ink_sandbox/
lib.rs

1use core::any::Any;
2
3pub mod api;
4pub mod macros;
5
6pub use frame_metadata::RuntimeMetadataPrefixed;
7pub use frame_support::weights::Weight;
8use frame_support::{
9    sp_runtime::traits::Dispatchable,
10    traits::fungible::Inspect,
11};
12use frame_system::{
13    EventRecord,
14    pallet_prelude::{
15        BlockNumberFor,
16        OriginFor,
17    },
18};
19use ink_primitives::U256;
20pub use macros::{
21    BlockBuilder,
22    DefaultSandbox,
23};
24use pallet_revive::{
25    ContractResult,
26    ExecReturnValue,
27    InstantiateReturnValue,
28};
29use sp_core::Get;
30/// Export pallets that are used in [`crate::create_sandbox`]
31pub use {
32    frame_support::sp_runtime::testing::H256,
33    frame_support::{
34        self,
35        sp_runtime::{
36            AccountId32,
37            DispatchError,
38        },
39    },
40    frame_system,
41    pallet_balances,
42    pallet_revive,
43    pallet_timestamp,
44    paste,
45    sp_core::crypto::Ss58Codec,
46    sp_externalities::{
47        self,
48        Extension,
49    },
50    sp_io::TestExternalities,
51};
52
53/// A snapshot of the storage.
54#[derive(Clone, Debug)]
55pub struct Snapshot {
56    /// The storage raw key-value pairs.
57    pub storage: RawStorage,
58    /// The storage root hash.
59    pub storage_root: StorageRoot,
60}
61
62pub type RawStorage = Vec<(Vec<u8>, (Vec<u8>, i32))>;
63pub type StorageRoot = H256;
64
65/// Alias for the balance type.
66type BalanceOf<R> =
67    <<R as pallet_revive::Config>::Currency as Inspect<AccountIdFor<R>>>::Balance;
68
69/// Alias for the account ID type.
70pub type AccountIdFor<R> = <R as frame_system::Config>::AccountId;
71
72/// Alias for the runtime call type.
73pub type RuntimeCall<R> = <R as frame_system::Config>::RuntimeCall;
74
75/// Alias for the event record type.
76pub type EventRecordOf<Runtime> = EventRecord<
77    <Runtime as frame_system::Config>::RuntimeEvent,
78    <Runtime as frame_system::Config>::Hash,
79>;
80
81/// Alias for the contract instantiate result.
82pub type ContractInstantiateResultFor<Runtime> =
83    ContractResult<OriginFor<Runtime>, BalanceOf<Runtime>>;
84
85pub type ContractResultFor<Runtime> = ContractResult<Runtime, BalanceOf<Runtime>>;
86
87pub type ContractResultInstantiate<Runtime> =
88    ContractResult<InstantiateReturnValue, BalanceOf<Runtime>>;
89
90/// Alias for the contract exec result.
91pub type ContractExecResultFor<Runtime> =
92    ContractResult<ExecReturnValue, BalanceOf<Runtime>>;
93
94/// Alias for the `map_account` result.
95pub type MapAccountResultFor = Result<(), DispatchError>;
96
97/// Alias for the runtime of a sandbox.
98pub type RuntimeOf<S> = <S as Sandbox>::Runtime;
99
100/// Alias for the runtime event of a sandbox.
101pub type RuntimeEventOf<S> = <RuntimeOf<S> as frame_system::Config>::RuntimeEvent;
102
103/// Sandbox defines the API of a sandboxed runtime.
104pub trait Sandbox {
105    /// The runtime associated with the sandbox.
106    type Runtime: frame_system::Config;
107
108    /// Execute the given externalities.
109    fn execute_with<T>(&mut self, execute: impl FnOnce() -> T) -> T;
110
111    /// Dry run an action without modifying the storage.
112    fn dry_run<T>(&mut self, action: impl FnOnce(&mut Self) -> T) -> T;
113
114    /// Register an extension.
115    fn register_extension<E: Any + Extension>(&mut self, ext: E);
116
117    /// Initialize a new block at particular height.
118    fn initialize_block(
119        _height: BlockNumberFor<Self::Runtime>,
120        _parent_hash: <Self::Runtime as frame_system::Config>::Hash,
121    ) {
122    }
123
124    /// Finalize a block at particular height.
125    fn finalize_block(
126        _height: BlockNumberFor<Self::Runtime>,
127    ) -> <Self::Runtime as frame_system::Config>::Hash {
128        Default::default()
129    }
130
131    /// Default actor for the sandbox.
132    fn default_actor() -> AccountIdFor<Self::Runtime>;
133
134    fn default_gas_limit() -> Weight {
135        Weight::from_parts(100_000_000_000_000, 6 * 1024 * 1024)
136    }
137
138    /// Metadata of the runtime.
139    fn get_metadata() -> RuntimeMetadataPrefixed;
140
141    /// Convert an account to a call origin.
142    fn convert_account_to_origin(
143        account: AccountIdFor<Self::Runtime>,
144    ) -> <<Self::Runtime as frame_system::Config>::RuntimeCall as Dispatchable>::RuntimeOrigin;
145
146    /// Take a snapshot of the storage.
147    fn take_snapshot(&mut self) -> Snapshot;
148
149    /// Restore the storage from the given snapshot.
150    fn restore_snapshot(&mut self, snapshot: Snapshot);
151}
152
153/// Converts from the generic `Balance` type to the Ethereum native `U256`.
154///
155/// # Developer Note
156///
157/// `pallet-revive` uses both types, hence we have to convert in between them
158/// for certain functions. Notice that precision loss might occur when converting
159/// the other way (from `U256` to `Balance`).
160///
161/// See <https://github.com/paritytech/polkadot-sdk/pull/9101> for more details.
162pub fn balance_to_evm_value<R>(value: BalanceOf<R>) -> U256
163where
164    R: pallet_revive::Config,
165    BalanceOf<R>: Into<U256>,
166    U256: From<u32>,
167{
168    let native_to_eth_ratio: U256 =
169        <R as pallet_revive::Config>::NativeToEthRatio::get().into();
170    let evm_value: U256 = value.into();
171    native_to_eth_ratio.saturating_mul(evm_value)
172}