1use core::any::Any;
2
3pub mod api;
4pub mod client;
5mod error;
6pub mod macros;
7
8pub use frame_metadata::RuntimeMetadataPrefixed;
9pub use frame_support::weights::Weight;
10use frame_support::{
11 sp_runtime::traits::Dispatchable,
12 traits::fungible::Inspect,
13};
14use frame_system::{
15 EventRecord,
16 pallet_prelude::{
17 BlockNumberFor,
18 OriginFor,
19 },
20};
21use ink_primitives::U256;
22use ink_revive_types::{
23 Bytes,
24 evm::{
25 CallLog,
26 CallTrace,
27 },
28};
29pub use macros::{
30 BlockBuilder,
31 DefaultSandbox,
32};
33use pallet_revive::{
34 ContractResult,
35 ExecReturnValue,
36 InstantiateReturnValue,
37};
38use sp_core::Get;
39pub use {
41 frame_support::sp_runtime::testing::H256,
42 frame_support::{
43 self,
44 sp_runtime::{
45 AccountId32,
46 DispatchError,
47 },
48 },
49 frame_system,
50 pallet_balances,
51 pallet_revive,
52 pallet_timestamp,
53 pallet_transaction_payment,
54 paste,
55 sp_core::crypto::Ss58Codec,
56 sp_externalities::{
57 self,
58 Extension,
59 },
60 sp_io::TestExternalities,
61};
62
63pub use client::{
64 Client as SandboxClient,
65 preset,
66};
67pub use ink_e2e_macro::test;
68
69#[derive(Clone, Debug)]
71pub struct Snapshot {
72 pub storage: RawStorage,
74 pub storage_root: StorageRoot,
76}
77
78pub type RawStorage = Vec<(Vec<u8>, (Vec<u8>, i32))>;
79pub type StorageRoot = H256;
80
81type BalanceOf<R> =
83 <<R as pallet_revive::Config>::Currency as Inspect<AccountIdFor<R>>>::Balance;
84
85pub type AccountIdFor<R> = <R as frame_system::Config>::AccountId;
87
88pub type RuntimeCall<R> = <R as frame_system::Config>::RuntimeCall;
90
91pub type EventRecordOf<Runtime> = EventRecord<
93 <Runtime as frame_system::Config>::RuntimeEvent,
94 <Runtime as frame_system::Config>::Hash,
95>;
96
97pub type ContractInstantiateResultFor<Runtime> =
99 ContractResult<OriginFor<Runtime>, BalanceOf<Runtime>>;
100
101pub type ContractResultFor<Runtime> = ContractResult<Runtime, BalanceOf<Runtime>>;
102
103pub type ContractResultInstantiate<Runtime> =
104 ContractResult<InstantiateReturnValue, BalanceOf<Runtime>>;
105
106pub type ContractExecResultFor<Runtime> =
108 ContractResult<ExecReturnValue, BalanceOf<Runtime>>;
109
110pub type MapAccountResultFor = Result<(), DispatchError>;
112
113pub type RuntimeOf<S> = <S as Sandbox>::Runtime;
115
116pub type RuntimeEventOf<S> = <RuntimeOf<S> as frame_system::Config>::RuntimeEvent;
118
119pub trait Sandbox {
121 type Runtime: frame_system::Config;
123
124 fn execute_with<T>(&mut self, execute: impl FnOnce() -> T) -> T;
126
127 fn dry_run<T>(&mut self, action: impl FnOnce(&mut Self) -> T) -> T;
129
130 fn register_extension<E: Any + Extension>(&mut self, ext: E);
132
133 fn initialize_block(
135 _height: BlockNumberFor<Self::Runtime>,
136 _parent_hash: <Self::Runtime as frame_system::Config>::Hash,
137 ) {
138 }
139
140 fn finalize_block(
142 _height: BlockNumberFor<Self::Runtime>,
143 ) -> <Self::Runtime as frame_system::Config>::Hash {
144 Default::default()
145 }
146
147 fn default_actor() -> AccountIdFor<Self::Runtime>;
149
150 fn default_gas_limit() -> Weight {
151 Weight::from_parts(100_000_000_000_000, 6 * 1024 * 1024)
152 }
153
154 fn get_metadata() -> RuntimeMetadataPrefixed;
156
157 fn convert_account_to_origin(
159 account: AccountIdFor<Self::Runtime>,
160 ) -> <<Self::Runtime as frame_system::Config>::RuntimeCall as Dispatchable>::RuntimeOrigin;
161
162 fn take_snapshot(&mut self) -> Snapshot;
164
165 fn restore_snapshot(&mut self, snapshot: Snapshot);
167}
168
169pub fn balance_to_evm_value<R>(value: BalanceOf<R>) -> U256
179where
180 R: pallet_revive::Config,
181 BalanceOf<R>: Into<U256>,
182 U256: From<u32>,
183{
184 let native_to_eth_ratio: U256 =
185 <R as pallet_revive::Config>::NativeToEthRatio::get().into();
186 let evm_value: U256 = value.into();
187 native_to_eth_ratio.saturating_mul(evm_value)
188}
189
190pub fn to_revive_trace(t: pallet_revive::evm::CallTrace) -> CallTrace {
193 CallTrace {
194 from: t.from,
195 gas: t.gas,
196 gas_used: t.gas_used,
197 to: t.to,
198 input: Bytes(t.input.0),
199 output: Bytes(t.output.0),
200 error: t.error,
201 revert_reason: t.revert_reason,
202 calls: t.calls.into_iter().map(to_revive_trace).collect(),
203 logs: t
204 .logs
205 .into_iter()
206 .map(|log| {
207 CallLog {
208 address: log.address,
209 topics: log.topics,
210 data: log.data.0,
211 ..Default::default()
212 }
213 })
214 .collect(),
215 value: t.value,
216 call_type: to_revive_call_type(t.call_type),
217 child_call_count: t.child_call_count,
218 }
219}
220
221fn to_revive_call_type(
223 ct: pallet_revive::evm::CallType,
224) -> ink_revive_types::evm::CallType {
225 match ct {
226 pallet_revive::evm::CallType::Call => ink_revive_types::evm::CallType::Call,
227 pallet_revive::evm::CallType::StaticCall => {
228 ink_revive_types::evm::CallType::StaticCall
229 }
230 pallet_revive::evm::CallType::DelegateCall => {
231 ink_revive_types::evm::CallType::DelegateCall
232 }
233 pallet_revive::evm::CallType::Create => ink_revive_types::evm::CallType::Create,
234 pallet_revive::evm::CallType::Create2 => ink_revive_types::evm::CallType::Create2,
235 }
236}
237
238pub fn to_revive_storage_deposit<B>(
240 sd: pallet_revive::StorageDeposit<B>,
241) -> ink_revive_types::StorageDeposit<B> {
242 match sd {
243 pallet_revive::StorageDeposit::Charge(b) => {
244 ink_revive_types::StorageDeposit::Charge(b)
245 }
246 pallet_revive::StorageDeposit::Refund(b) => {
247 ink_revive_types::StorageDeposit::Refund(b)
248 }
249 }
250}