ab_system_contract_simple_wallet_base/
utils.rs1use crate::{SimpleWalletBaseExt, WalletState};
2use ab_contracts_common::ContractError;
3use ab_contracts_common::env::{Env, MethodContext};
4use ab_contracts_standards::tx_handler::{TxHandlerPayload, TxHandlerSeal, TxHandlerSlots};
5use ab_core_primitives::address::Address;
6use ab_core_primitives::transaction::TransactionHeader;
7use ab_io_type::IoType;
8use ab_io_type::trivial_type::TrivialType;
9use ab_io_type::variable_bytes::VariableBytes;
10use ab_system_contract_state::StateExt;
11use core::mem::MaybeUninit;
12
13#[inline(always)]
15#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
16pub fn initialize_state(env: &mut Env<'_>, public_key: &[u8; 32]) -> Result<(), ContractError> {
17 {
19 let state =
20 env.simple_wallet_base_initialize(Address::SYSTEM_SIMPLE_WALLET_BASE, public_key)?;
21
22 env.state_initialize(
23 MethodContext::Reset,
24 Address::SYSTEM_STATE,
25 &env.own_address(),
26 &VariableBytes::from_buffer(state.as_bytes(), &state.size()),
27 )
28 }
29}
30
31#[inline(always)]
33#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
34pub fn authorize(
35 env: &Env<'_>,
36 header: &TransactionHeader,
37 read_slots: &TxHandlerSlots,
38 write_slots: &TxHandlerSlots,
39 payload: &TxHandlerPayload,
40 seal: &TxHandlerSeal,
41) -> Result<(), ContractError> {
42 let state = load_current_state(env)?;
43
44 env.simple_wallet_base_authorize(
45 Address::SYSTEM_SIMPLE_WALLET_BASE,
46 &state,
47 header,
48 read_slots,
49 write_slots,
50 payload,
51 seal,
52 )
53}
54
55#[inline(always)]
58#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
59pub fn execute(
60 env: &mut Env<'_>,
61 header: &TransactionHeader,
62 read_slots: &TxHandlerSlots,
63 write_slots: &TxHandlerSlots,
64 payload: &TxHandlerPayload,
65 seal: &TxHandlerSeal,
66) -> Result<(), ContractError> {
67 if env.caller() != Address::NULL {
69 return Err(ContractError::Forbidden);
70 }
71
72 let old_state = load_current_state(env)?;
74
75 env.simple_wallet_base_execute(
76 MethodContext::Replace,
77 Address::SYSTEM_SIMPLE_WALLET_BASE,
78 header,
79 read_slots,
80 write_slots,
81 payload,
82 seal,
83 )?;
84
85 {
88 let new_state =
90 env.simple_wallet_base_increase_nonce(Address::SYSTEM_SIMPLE_WALLET_BASE, &old_state)?;
91 env.state_compare_and_write(
93 MethodContext::Reset,
94 Address::SYSTEM_STATE,
95 &env.own_address(),
96 &VariableBytes::from_buffer(old_state.as_bytes(), &old_state.size()),
97 &VariableBytes::from_buffer(new_state.as_bytes(), &new_state.size()),
98 )
99 .map(|_| ())
100 }
101}
102
103#[inline(always)]
105#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
106pub fn change_public_key(env: &mut Env<'_>, public_key: &[u8; 32]) -> Result<(), ContractError> {
107 {
109 if !(env.context() == env.own_address()
112 && env.caller() == Address::SYSTEM_SIMPLE_WALLET_BASE)
113 {
114 return Err(ContractError::Forbidden);
115 }
116
117 let old_state = load_current_state(env)?;
119 let new_state = env.simple_wallet_base_change_public_key(
121 Address::SYSTEM_SIMPLE_WALLET_BASE,
122 &old_state,
123 public_key,
124 )?;
125 env.state_write(
127 MethodContext::Reset,
128 Address::SYSTEM_STATE,
129 &env.own_address(),
130 &VariableBytes::from_buffer(new_state.as_bytes(), &new_state.size()),
131 )
132 }
133}
134
135#[inline(always)]
136#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
137fn load_current_state(env: &Env<'_>) -> Result<WalletState, ContractError> {
138 let current_state = {
139 let mut current_state = MaybeUninit::<WalletState>::uninit();
140 let mut current_state_size = 0;
141 env.state_read(
142 Address::SYSTEM_STATE,
143 &env.own_address(),
144 &mut VariableBytes::from_uninit(current_state.as_bytes_mut(), &mut current_state_size),
145 )?;
146 if current_state_size != WalletState::SIZE {
147 return Err(ContractError::BadOutput);
148 }
149 unsafe { current_state.assume_init() }
151 };
152
153 Ok(current_state)
154}