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