1use soroban_sdk::{contracttype, Address, Env, Symbol};
2
3use super::error::StandardsError;
4
5const OWNER_PREFIX: &str = "std_owner";
6const PENDING_OWNER_PREFIX: &str = "std_powner";
7
8#[derive(Clone, Debug)]
10pub struct Ownable {
11 id: Symbol,
12}
13
14#[derive(Clone, Debug)]
16pub struct Ownable2Step {
17 inner: Ownable,
18}
19
20#[contracttype]
21#[derive(Clone, Debug, Eq, PartialEq)]
22pub struct OwnershipTransferredEvent {
23 pub previous_owner: Option<Address>,
24 pub new_owner: Option<Address>,
25}
26
27#[contracttype]
28#[derive(Clone, Debug, Eq, PartialEq)]
29pub struct OwnershipTransferStartedEvent {
30 pub owner: Address,
31 pub pending_owner: Address,
32}
33
34#[contracttype]
35#[derive(Clone, Debug, Eq, PartialEq)]
36pub struct OwnershipTransferCancelledEvent {
37 pub owner: Address,
38 pub pending_owner: Address,
39}
40
41impl Ownable {
42 pub fn new(id: Symbol) -> Self {
43 Self { id }
44 }
45
46 pub fn initialize(
47 &self,
48 env: &Env,
49 owner: &Address,
50 ) -> Result<OwnershipTransferredEvent, StandardsError> {
51 if self.owner(env).is_some() {
52 return Err(StandardsError::AlreadyInitialized);
53 }
54
55 env.storage().persistent().set(&self.owner_key(env), owner);
56 env.storage()
57 .persistent()
58 .remove(&self.pending_owner_key(env));
59
60 Ok(OwnershipTransferredEvent {
61 previous_owner: None,
62 new_owner: Some(owner.clone()),
63 })
64 }
65
66 pub fn owner(&self, env: &Env) -> Option<Address> {
67 env.storage().persistent().get(&self.owner_key(env))
68 }
69
70 pub fn pending_owner(&self, env: &Env) -> Option<Address> {
71 env.storage().persistent().get(&self.pending_owner_key(env))
72 }
73
74 pub fn require_owner(&self, env: &Env, caller: &Address) -> Result<(), StandardsError> {
75 let owner = self.owner(env).ok_or(StandardsError::OwnerNotSet)?;
76 if owner != *caller {
77 return Err(StandardsError::Unauthorized);
78 }
79 Ok(())
80 }
81
82 pub fn transfer_ownership(
83 &self,
84 env: &Env,
85 caller: &Address,
86 new_owner: &Address,
87 ) -> Result<OwnershipTransferredEvent, StandardsError> {
88 self.require_owner(env, caller)?;
89 let previous_owner = self.owner(env);
90 env.storage()
91 .persistent()
92 .set(&self.owner_key(env), new_owner);
93 env.storage()
94 .persistent()
95 .remove(&self.pending_owner_key(env));
96
97 Ok(OwnershipTransferredEvent {
98 previous_owner,
99 new_owner: Some(new_owner.clone()),
100 })
101 }
102
103 pub fn renounce_ownership(
104 &self,
105 env: &Env,
106 caller: &Address,
107 ) -> Result<OwnershipTransferredEvent, StandardsError> {
108 self.require_owner(env, caller)?;
109 let previous_owner = self.owner(env);
110 env.storage().persistent().remove(&self.owner_key(env));
111 env.storage()
112 .persistent()
113 .remove(&self.pending_owner_key(env));
114
115 Ok(OwnershipTransferredEvent {
116 previous_owner,
117 new_owner: None,
118 })
119 }
120
121 fn owner_key(&self, env: &Env) -> (Symbol, Symbol) {
122 (Symbol::new(env, OWNER_PREFIX), self.id.clone())
123 }
124
125 fn pending_owner_key(&self, env: &Env) -> (Symbol, Symbol) {
126 (Symbol::new(env, PENDING_OWNER_PREFIX), self.id.clone())
127 }
128}
129
130impl Ownable2Step {
131 pub fn new(id: Symbol) -> Self {
132 Self {
133 inner: Ownable::new(id),
134 }
135 }
136
137 pub fn initialize(
138 &self,
139 env: &Env,
140 owner: &Address,
141 ) -> Result<OwnershipTransferredEvent, StandardsError> {
142 self.inner.initialize(env, owner)
143 }
144
145 pub fn owner(&self, env: &Env) -> Option<Address> {
146 self.inner.owner(env)
147 }
148
149 pub fn pending_owner(&self, env: &Env) -> Option<Address> {
150 self.inner.pending_owner(env)
151 }
152
153 pub fn require_owner(&self, env: &Env, caller: &Address) -> Result<(), StandardsError> {
154 self.inner.require_owner(env, caller)
155 }
156
157 pub fn begin_transfer(
158 &self,
159 env: &Env,
160 caller: &Address,
161 pending_owner: &Address,
162 ) -> Result<OwnershipTransferStartedEvent, StandardsError> {
163 self.inner.require_owner(env, caller)?;
164 env.storage()
165 .persistent()
166 .set(&self.inner.pending_owner_key(env), pending_owner);
167
168 Ok(OwnershipTransferStartedEvent {
169 owner: caller.clone(),
170 pending_owner: pending_owner.clone(),
171 })
172 }
173
174 pub fn accept_transfer(
175 &self,
176 env: &Env,
177 caller: &Address,
178 ) -> Result<OwnershipTransferredEvent, StandardsError> {
179 let pending_owner = self
180 .pending_owner(env)
181 .ok_or(StandardsError::PendingOwnerNotSet)?;
182 if pending_owner != *caller {
183 return Err(StandardsError::PendingOwnerMismatch);
184 }
185
186 let previous_owner = self.owner(env);
187 env.storage()
188 .persistent()
189 .set(&self.inner.owner_key(env), caller);
190 env.storage()
191 .persistent()
192 .remove(&self.inner.pending_owner_key(env));
193
194 Ok(OwnershipTransferredEvent {
195 previous_owner,
196 new_owner: Some(caller.clone()),
197 })
198 }
199
200 pub fn cancel_transfer(
201 &self,
202 env: &Env,
203 caller: &Address,
204 ) -> Result<OwnershipTransferCancelledEvent, StandardsError> {
205 self.inner.require_owner(env, caller)?;
206 let pending_owner = self
207 .pending_owner(env)
208 .ok_or(StandardsError::PendingOwnerNotSet)?;
209 env.storage()
210 .persistent()
211 .remove(&self.inner.pending_owner_key(env));
212
213 Ok(OwnershipTransferCancelledEvent {
214 owner: caller.clone(),
215 pending_owner,
216 })
217 }
218}