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