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