1#[cfg(feature = "abi")]
2mod abi;
3mod accounts;
4mod admin;
5pub mod config;
6mod events;
7mod fees;
8mod garbage_collector;
9mod intents;
10mod salts;
11mod state;
12mod tokens;
13mod upgrade;
14mod versioned;
15
16use core::iter;
17
18use borsh::{BorshDeserialize, BorshSerialize};
19use defuse_borsh_utils::As;
20use defuse_core::Result;
21use impl_tools::autoimpl;
22use near_plugins::{AccessControlRole, AccessControllable, Pausable, access_control};
23use near_sdk::{BorshStorageKey, IntoStorageKey, PanicOnDefault, near, require, store::LookupSet};
24use serde::{Deserialize, Serialize};
25use versioned::MaybeVersionedContractStorage;
26
27use crate::{Defuse, contract::events::PostponedMtBurnEvents};
28
29use self::{
30 accounts::Accounts,
31 config::{DefuseConfig, RolesConfig},
32 state::ContractState,
33};
34
35#[cfg_attr(feature = "abi", derive(::schemars::JsonSchema))]
36#[derive(
37 Debug,
38 Clone,
39 Copy,
40 PartialEq,
41 Eq,
42 PartialOrd,
43 Ord,
44 Hash,
45 Serialize,
46 Deserialize,
47 AccessControlRole,
48)]
49pub enum Role {
50 DAO,
51
52 FeesManager,
53 RelayerKeysManager,
54
55 UnrestrictedWithdrawer,
56
57 PauseManager,
58 Upgrader,
59 UnpauseManager,
60
61 UnrestrictedAccountLocker,
62 UnrestrictedAccountUnlocker,
63
64 SaltManager,
65
66 GarbageCollector,
67
68 UnrestrictedAccountManager,
69}
70
71#[access_control(role_type(Role))]
72#[derive(Pausable, PanicOnDefault)]
73#[pausable(
74 pause_roles(Role::DAO, Role::PauseManager),
75 unpause_roles(Role::DAO, Role::UnpauseManager)
76)]
77#[near(
78 contract_state,
79 contract_metadata(
80 standard(standard = "dip4", version = "0.1.0"),
81 standard(standard = "nep245", version = "1.0.0"),
82 )
83)]
84#[autoimpl(Deref using self.storage)]
85#[autoimpl(DerefMut using self.storage)]
86pub struct Contract {
87 #[borsh(
88 deserialize_with = "As::<MaybeVersionedContractStorage>::deserialize",
89 serialize_with = "As::<MaybeVersionedContractStorage>::serialize"
90 )]
91 storage: ContractStorage,
92
93 #[borsh(skip)]
94 runtime: Runtime,
95}
96
97#[autoimpl(Deref using self.state)]
98#[autoimpl(DerefMut using self.state)]
99#[cfg_attr(feature = "abi", derive(::borsh::BorshSchema))]
100#[derive(Debug, BorshSerialize, BorshDeserialize)]
101pub struct ContractStorage {
102 accounts: Accounts,
103
104 state: ContractState,
105
106 relayer_keys: LookupSet<near_sdk::PublicKey>,
107}
108
109#[derive(Debug, Default)]
110pub struct Runtime {
111 pub postponed_burns: PostponedMtBurnEvents,
112}
113
114#[near]
115impl Contract {
116 #[must_use]
117 #[init]
118 #[allow(clippy::use_self)] pub fn new(config: DefuseConfig) -> Self {
120 let mut contract = Self {
121 storage: ContractStorage {
122 accounts: Accounts::new(Prefix::Accounts),
123 state: ContractState::new(Prefix::State, config.wnear_id, config.fees),
124 relayer_keys: LookupSet::new(Prefix::RelayerKeys),
125 },
126 runtime: Runtime::default(),
127 };
128 contract.init_acl(config.roles);
129 contract
130 }
131
132 fn init_acl(&mut self, roles: RolesConfig) {
133 let mut acl = self.acl_get_or_init();
134 require!(
135 roles
136 .super_admins
137 .into_iter()
138 .all(|super_admin| acl.add_super_admin_unchecked(&super_admin))
139 && roles
140 .admins
141 .into_iter()
142 .flat_map(|(role, admins)| iter::repeat(role).zip(admins))
143 .all(|(role, admin)| acl.add_admin_unchecked(role, &admin))
144 && roles
145 .grantees
146 .into_iter()
147 .flat_map(|(role, grantees)| iter::repeat(role).zip(grantees))
148 .all(|(role, grantee)| acl.grant_role_unchecked(role, &grantee)),
149 "failed to set roles"
150 );
151 }
152}
153
154#[near]
155impl Defuse for Contract {}
156
157#[cfg_attr(feature = "abi", derive(::borsh::BorshSchema))]
158#[derive(BorshSerialize, BorshDeserialize, BorshStorageKey)]
159enum Prefix {
160 Accounts,
161 State,
162 RelayerKeys,
163}
164
165pub trait MigrateStorageWithPrefix<T>: Sized {
166 fn migrate<S>(val: T, prefix: S) -> Self
167 where
168 S: IntoStorageKey;
169}