From 383550737edee0b722af8ddf5a20a9c32aa0547d Mon Sep 17 00:00:00 2001 From: PG Herveou <pgherveou@gmail.com> Date: Mon, 2 Sep 2024 21:10:24 +0200 Subject: [PATCH] [pallet-revive] Use address20 for contract's address (#5548) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Theißen <alex.theissen@me.com> Co-authored-by: command-bot <> --- Cargo.lock | 11 +- prdoc/pr_5548.prdoc | 16 + substrate/bin/node/runtime/src/lib.rs | 20 +- substrate/frame/revive/Cargo.toml | 12 +- substrate/frame/revive/fixtures/Cargo.toml | 10 +- .../frame/revive/fixtures/contracts/call.rs | 2 +- .../fixtures/contracts/call_return_code.rs | 2 +- .../contracts/call_runtime_and_call.rs | 2 +- .../contracts/call_with_flags_and_value.rs | 2 +- .../fixtures/contracts/call_with_limit.rs | 2 +- .../fixtures/contracts/caller_contract.rs | 6 +- .../contracts/create_storage_and_call.rs | 2 +- .../create_storage_and_instantiate.rs | 4 +- .../create_transient_storage_and_call.rs | 2 +- .../fixtures/contracts/delegate_call_lib.rs | 4 +- .../contracts/destroy_and_transfer.rs | 6 +- .../contracts/locking_delegate_dependency.rs | 4 +- .../fixtures/contracts/read_only_call.rs | 2 +- .../fixtures/contracts/self_destruct.rs | 6 +- substrate/frame/revive/fixtures/src/lib.rs | 12 +- .../src/parachain/contracts_config.rs | 2 +- substrate/frame/revive/src/address.rs | 145 ++- .../revive/src/benchmarking/call_builder.rs | 10 +- .../frame/revive/src/benchmarking/code.rs | 14 +- .../frame/revive/src/benchmarking/mod.rs | 119 +- substrate/frame/revive/src/debug.rs | 13 +- substrate/frame/revive/src/exec.rs | 896 +++++++------ substrate/frame/revive/src/lib.rs | 127 +- substrate/frame/revive/src/primitives.rs | 22 +- substrate/frame/revive/src/storage.rs | 23 +- substrate/frame/revive/src/storage/meter.rs | 12 +- substrate/frame/revive/src/test_utils.rs | 28 + .../frame/revive/src/test_utils/builder.rs | 47 +- substrate/frame/revive/src/tests.rs | 1146 +++++++++-------- .../frame/revive/src/tests/test_debug.rs | 47 +- substrate/frame/revive/src/wasm/mod.rs | 30 +- substrate/frame/revive/src/wasm/runtime.rs | 45 +- 37 files changed, 1522 insertions(+), 1331 deletions(-) create mode 100644 prdoc/pr_5548.prdoc diff --git a/Cargo.lock b/Cargo.lock index 2d4485c9221..0d41be5c9bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11472,6 +11472,7 @@ dependencies = [ "paste", "polkavm 0.10.0", "pretty_assertions", + "rlp", "scale-info", "serde", "sp-api", @@ -11494,6 +11495,8 @@ dependencies = [ "frame-system", "parity-wasm", "polkavm-linker 0.10.0", + "sp-core", + "sp-io", "sp-runtime", "tempfile", "toml 0.8.12", @@ -16924,9 +16927,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.11.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -16948,9 +16951,9 @@ dependencies = [ [[package]] name = "ruint-macro" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" [[package]] name = "rustc-demangle" diff --git a/prdoc/pr_5548.prdoc b/prdoc/pr_5548.prdoc new file mode 100644 index 00000000000..69e79213fa2 --- /dev/null +++ b/prdoc/pr_5548.prdoc @@ -0,0 +1,16 @@ +title: Use H160 when interfacing with contracts + +doc: + - audience: Runtime Dev + description: | + When interfacing with a contract we now use the native ethereum address + type and map it to AccountId32 when interfacing with the rest + of substrate. + +crates: + - name: pallet-revive + bump: major + - name: pallet-revive-fixtures + bump: major + - name: pallet-revive-mock-network + bump: major diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index ef5c52bf6e6..7ef0779dd9b 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -91,7 +91,7 @@ use sp_consensus_beefy::{ mmr::MmrLeafVersion, }; use sp_consensus_grandpa::AuthorityId as GrandpaId; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160}; use sp_inherents::{CheckInherentsResult, InherentData}; use sp_runtime::{ create_runtime_str, @@ -1392,7 +1392,7 @@ impl pallet_revive::Config for Runtime { type WeightPrice = pallet_transaction_payment::Pallet<Self>; type WeightInfo = pallet_revive::weights::SubstrateWeight<Self>; type ChainExtension = (); - type AddressGenerator = pallet_revive::DefaultAddressGenerator; + type AddressMapper = pallet_revive::DefaultAddressMapper; type MaxCodeLen = ConstU32<{ 123 * 1024 }>; type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>; type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>; @@ -2988,11 +2988,11 @@ impl_runtime_apis! { } } - impl pallet_revive::ReviveApi<Block, AccountId, Balance, BlockNumber, Hash, EventRecord> for Runtime + impl pallet_revive::ReviveApi<Block, AccountId, Balance, BlockNumber, EventRecord> for Runtime { fn call( origin: AccountId, - dest: AccountId, + dest: H160, value: Balance, gas_limit: Option<Weight>, storage_deposit_limit: Option<Balance>, @@ -3015,10 +3015,10 @@ impl_runtime_apis! { value: Balance, gas_limit: Option<Weight>, storage_deposit_limit: Option<Balance>, - code: pallet_revive::Code<Hash>, + code: pallet_revive::Code, data: Vec<u8>, - salt: Vec<u8>, - ) -> pallet_revive::ContractInstantiateResult<AccountId, Balance, EventRecord> + salt: [u8; 32], + ) -> pallet_revive::ContractInstantiateResult<Balance, EventRecord> { Revive::bare_instantiate( RuntimeOrigin::signed(origin), @@ -3037,7 +3037,7 @@ impl_runtime_apis! { origin: AccountId, code: Vec<u8>, storage_deposit_limit: Option<Balance>, - ) -> pallet_revive::CodeUploadResult<Hash, Balance> + ) -> pallet_revive::CodeUploadResult<Balance> { Revive::bare_upload_code( RuntimeOrigin::signed(origin), @@ -3047,8 +3047,8 @@ impl_runtime_apis! { } fn get_storage( - address: AccountId, - key: Vec<u8>, + address: H160, + key: [u8; 32], ) -> pallet_revive::GetStorageResult { Revive::get_storage( address, diff --git a/substrate/frame/revive/Cargo.toml b/substrate/frame/revive/Cargo.toml index 747c2283e21..6b7542e8920 100644 --- a/substrate/frame/revive/Cargo.toml +++ b/substrate/frame/revive/Cargo.toml @@ -18,6 +18,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] +environmental = { workspace = true } paste = { workspace = true } polkavm = { version = "0.10.0", default-features = false } bitflags = { workspace = true } @@ -29,9 +30,9 @@ scale-info = { features = ["derive"], workspace = true } log = { workspace = true } serde = { optional = true, features = ["derive"], workspace = true, default-features = true } impl-trait-for-tuples = { workspace = true } +rlp = { workspace = true } -# Substrate Dependencies -environmental = { workspace = true } +# Polkadot SDK Dependencies frame-benchmarking = { optional = true, workspace = true } frame-support = { workspace = true } frame-system = { workspace = true } @@ -54,10 +55,7 @@ pretty_assertions = { workspace = true } wat = { workspace = true } pallet-revive-fixtures = { workspace = true, default-features = true } -# Polkadot Dependencies -xcm-builder = { workspace = true, default-features = true } - -# Substrate Dependencies +# Polkadot SDK Dependencies pallet-balances = { workspace = true, default-features = true } pallet-timestamp = { workspace = true, default-features = true } pallet-message-queue = { workspace = true, default-features = true } @@ -66,6 +64,7 @@ pallet-assets = { workspace = true, default-features = true } pallet-proxy = { workspace = true, default-features = true } sp-keystore = { workspace = true, default-features = true } sp-tracing = { workspace = true, default-features = true } +xcm-builder = { workspace = true, default-features = true } [features] default = ["std"] @@ -86,6 +85,7 @@ std = [ "pallet-timestamp/std", "pallet-utility/std", "polkavm/std", + "rlp/std", "scale-info/std", "serde", "sp-api/std", diff --git a/substrate/frame/revive/fixtures/Cargo.toml b/substrate/frame/revive/fixtures/Cargo.toml index 9e54acdace7..db284c7cc06 100644 --- a/substrate/frame/revive/fixtures/Cargo.toml +++ b/substrate/frame/revive/fixtures/Cargo.toml @@ -12,15 +12,17 @@ workspace = true [dependencies] frame-system = { workspace = true, default-features = true, optional = true } +sp-core = { workspace = true, default-features = true, optional = true } +sp-io = { workspace = true, default-features = true, optional = true } sp-runtime = { workspace = true, default-features = true, optional = true } -anyhow = { workspace = true } +anyhow = { workspace = true, default-features = true, optional = true } [build-dependencies] parity-wasm = { workspace = true } tempfile = { workspace = true } toml = { workspace = true } polkavm-linker = { version = "0.10.0" } -anyhow = { workspace = true } +anyhow = { workspace = true, default-features = true } [features] default = ["std"] @@ -30,7 +32,9 @@ default = ["std"] riscv = [] # only when std is enabled all fixtures are available std = [ - "anyhow/std", + "anyhow", "frame-system", + "sp-core", + "sp-io", "sp-runtime", ] diff --git a/substrate/frame/revive/fixtures/contracts/call.rs b/substrate/frame/revive/fixtures/contracts/call.rs index a75aee65c20..73f427650c2 100644 --- a/substrate/frame/revive/fixtures/contracts/call.rs +++ b/substrate/frame/revive/fixtures/contracts/call.rs @@ -31,7 +31,7 @@ pub extern "C" fn deploy() {} pub extern "C" fn call() { input!( callee_input: [u8; 4], - callee_addr: [u8; 32], + callee_addr: [u8; 20], ); // Call the callee diff --git a/substrate/frame/revive/fixtures/contracts/call_return_code.rs b/substrate/frame/revive/fixtures/contracts/call_return_code.rs index 32654d59ef1..e8f995cffc7 100644 --- a/substrate/frame/revive/fixtures/contracts/call_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/call_return_code.rs @@ -33,7 +33,7 @@ pub extern "C" fn deploy() {} pub extern "C" fn call() { input!( 100, - callee_addr: [u8; 32], + callee_addr: [u8; 20], input: [u8], ); diff --git a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs index 1323c8c5d55..f3d2ece2132 100644 --- a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs @@ -31,7 +31,7 @@ pub extern "C" fn call() { input!( 512, callee_input: [u8; 4], - callee_addr: [u8; 32], + callee_addr: [u8; 20], call: [u8], ); diff --git a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs index a078162d799..15c1124eeae 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs @@ -31,7 +31,7 @@ pub extern "C" fn deploy() {} pub extern "C" fn call() { input!( 256, - callee_addr: [u8; 32], + callee_addr: [u8; 20], flags: u32, value: u64, forwarded_input: [u8], diff --git a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs index a5356924f24..985df672411 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs @@ -32,7 +32,7 @@ pub extern "C" fn deploy() {} pub extern "C" fn call() { input!( 256, - callee_addr: [u8; 32], + callee_addr: [u8; 20], ref_time: u64, proof_size: u64, forwarded_input: [u8], diff --git a/substrate/frame/revive/fixtures/contracts/caller_contract.rs b/substrate/frame/revive/fixtures/contracts/caller_contract.rs index 2fa11df82d0..dceab813f88 100644 --- a/substrate/frame/revive/fixtures/contracts/caller_contract.rs +++ b/substrate/frame/revive/fixtures/contracts/caller_contract.rs @@ -33,7 +33,7 @@ pub extern "C" fn call() { // The value to transfer on instantiation and calls. Chosen to be greater than existential // deposit. let value = 32768u64.to_le_bytes(); - let salt = [0u8; 0]; + let salt = [0u8; 32]; // Callee will use the first 4 bytes of the input to return an exit status. let input = [0u8, 1, 34, 51, 68, 85, 102, 119]; @@ -72,7 +72,7 @@ pub extern "C" fn call() { assert!(matches!(res, Err(ReturnErrorCode::CalleeTrapped))); // Deploy the contract successfully. - let mut callee = [0u8; 32]; + let mut callee = [0u8; 20]; let callee = &mut &mut callee[..]; api::instantiate( @@ -87,7 +87,7 @@ pub extern "C" fn call() { &salt, ) .unwrap(); - assert_eq!(callee.len(), 32); + assert_eq!(callee.len(), 20); // Call the new contract and expect it to return failing exit code. let res = api::call( diff --git a/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs index d0d3651dfe4..7a0b497079c 100644 --- a/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs @@ -32,7 +32,7 @@ pub extern "C" fn call() { input!( buffer, input: [u8; 4], - callee: [u8; 32], + callee: [u8; 20], deposit_limit: [u8; 8], ); diff --git a/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs b/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs index 918a4abe6b2..53b9afba778 100644 --- a/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs +++ b/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs @@ -36,8 +36,8 @@ pub extern "C" fn call() { ); let value = 10_000u64.to_le_bytes(); - let salt = [0u8; 0]; - let mut address = [0u8; 32]; + let salt = [0u8; 32]; + let mut address = [0u8; 20]; let address = &mut &mut address[..]; api::instantiate( diff --git a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs index a2a0e85bcf6..8788542a0c5 100644 --- a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs @@ -35,7 +35,7 @@ pub extern "C" fn call() { buffer, len: u32, input: [u8; 4], - callee: [u8; 32], + callee: [u8; 20], ); let rounds = len as usize / BUFFER.len(); diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call_lib.rs b/substrate/frame/revive/fixtures/contracts/delegate_call_lib.rs index 055760729bd..921543dced0 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_lib.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_lib.rs @@ -44,6 +44,6 @@ pub extern "C" fn call() { assert_eq!(value_transferred, 1337); // Assert that ALICE is the caller of the contract. - output!(caller, [0u8; 32], api::caller,); - assert_eq!(&caller[..], &[1u8; 32]); + output!(caller, [0u8; 20], api::caller,); + assert_eq!(&caller[..], &[1u8; 20]); } diff --git a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs index 8b74493a1e3..b86e761d53e 100644 --- a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs +++ b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs @@ -30,9 +30,9 @@ pub extern "C" fn deploy() { input!(code_hash: [u8; 32],); let input = [0u8; 0]; - let mut address = [0u8; 32]; + let mut address = [0u8; 20]; let address = &mut &mut address[..]; - let salt = [71u8, 17u8]; + let salt = [47u8; 32]; api::instantiate( code_hash, @@ -54,7 +54,7 @@ pub extern "C" fn deploy() { #[no_mangle] #[polkavm_derive::polkavm_export] pub extern "C" fn call() { - let mut callee_addr = [0u8; 32]; + let mut callee_addr = [0u8; 20]; let callee_addr = &mut &mut callee_addr[..]; api::get_storage(StorageFlags::empty(), &ADDRESS_KEY, callee_addr).unwrap(); diff --git a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs index 3ed886b4948..2f3e5ae148c 100644 --- a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs +++ b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs @@ -23,7 +23,7 @@ use common::input; use uapi::{HostFn, HostFnImpl as api}; -const ALICE: [u8; 32] = [1u8; 32]; +const ETH_ALICE: [u8; 20] = [1u8; 20]; /// Load input data and perform the action specified by the input. /// If `delegate_call` is true, then delegate call into the contract. @@ -44,7 +44,7 @@ fn load_input(delegate_call: bool) { }, // 3 = Terminate 3 => { - api::terminate(&ALICE); + api::terminate(Ð_ALICE); }, // Everything else is a noop _ => {}, diff --git a/substrate/frame/revive/fixtures/contracts/read_only_call.rs b/substrate/frame/revive/fixtures/contracts/read_only_call.rs index a62bb205039..ef8bc95f009 100644 --- a/substrate/frame/revive/fixtures/contracts/read_only_call.rs +++ b/substrate/frame/revive/fixtures/contracts/read_only_call.rs @@ -31,7 +31,7 @@ pub extern "C" fn deploy() {} pub extern "C" fn call() { input!( 256, - callee_addr: [u8; 32], + callee_addr: [u8; 20], callee_input: [u8], ); diff --git a/substrate/frame/revive/fixtures/contracts/self_destruct.rs b/substrate/frame/revive/fixtures/contracts/self_destruct.rs index 10f33226acf..b0e004018f1 100644 --- a/substrate/frame/revive/fixtures/contracts/self_destruct.rs +++ b/substrate/frame/revive/fixtures/contracts/self_destruct.rs @@ -21,7 +21,7 @@ use common::{input, output}; use uapi::{HostFn, HostFnImpl as api}; -const DJANGO: [u8; 32] = [4u8; 32]; +const ETH_DJANGO: [u8; 20] = [4u8; 20]; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -36,7 +36,7 @@ pub extern "C" fn call() { input!(input, 4,); if !input.is_empty() { - output!(addr, [0u8; 32], api::address,); + output!(addr, [0u8; 20], api::address,); api::call( uapi::CallFlags::ALLOW_REENTRY, addr, @@ -50,6 +50,6 @@ pub extern "C" fn call() { .unwrap(); } else { // Try to terminate and give balance to django. - api::terminate(&DJANGO); + api::terminate(Ð_DJANGO); } } diff --git a/substrate/frame/revive/fixtures/src/lib.rs b/substrate/frame/revive/fixtures/src/lib.rs index 1b6103f57ae..54e32130635 100644 --- a/substrate/frame/revive/fixtures/src/lib.rs +++ b/substrate/frame/revive/fixtures/src/lib.rs @@ -21,18 +21,12 @@ extern crate alloc; /// Load a given wasm module and returns a wasm binary contents along with it's hash. #[cfg(feature = "std")] -pub fn compile_module<T>( - fixture_name: &str, -) -> anyhow::Result<(Vec<u8>, <T::Hashing as sp_runtime::traits::Hash>::Output)> -where - T: frame_system::Config, -{ - use sp_runtime::traits::Hash; +pub fn compile_module(fixture_name: &str) -> anyhow::Result<(Vec<u8>, sp_core::H256)> { let out_dir: std::path::PathBuf = env!("OUT_DIR").into(); let fixture_path = out_dir.join(format!("{fixture_name}.polkavm")); let binary = std::fs::read(fixture_path)?; - let code_hash = T::Hashing::hash(&binary); - Ok((binary, code_hash)) + let code_hash = sp_io::hashing::keccak_256(&binary); + Ok((binary, sp_core::H256(code_hash))) } /// Fixtures used in runtime benchmarks. diff --git a/substrate/frame/revive/mock-network/src/parachain/contracts_config.rs b/substrate/frame/revive/mock-network/src/parachain/contracts_config.rs index 49f53ae5bc3..678e7a44490 100644 --- a/substrate/frame/revive/mock-network/src/parachain/contracts_config.rs +++ b/substrate/frame/revive/mock-network/src/parachain/contracts_config.rs @@ -20,7 +20,7 @@ use frame_support::derive_impl; #[derive_impl(pallet_revive::config_preludes::TestDefaultConfig)] impl pallet_revive::Config for Runtime { - type AddressGenerator = pallet_revive::DefaultAddressGenerator; + type AddressMapper = pallet_revive::DefaultAddressMapper; type Currency = Balances; type Time = super::Timestamp; type Xcm = pallet_xcm::Pallet<Self>; diff --git a/substrate/frame/revive/src/address.rs b/substrate/frame/revive/src/address.rs index 5758daf7b1f..f1bd36dcbba 100644 --- a/substrate/frame/revive/src/address.rs +++ b/substrate/frame/revive/src/address.rs @@ -15,54 +15,115 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Functions that deal with address derivation. +//! Functions that deal contract addresses. -use crate::{CodeHash, Config}; -use codec::{Decode, Encode}; -use sp_runtime::traits::{Hash, TrailingZeroInput}; +use alloc::vec::Vec; +use sp_core::H160; +use sp_io::hashing::keccak_256; +use sp_runtime::AccountId32; -/// Provides the contract address generation method. +/// Map between the native chain account id `T` and an Ethereum [`H160`]. /// -/// See [`DefaultAddressGenerator`] for the default implementation. +/// This trait exists only to emulate specialization for different concrete +/// native account ids. **Not** to make the mapping user configurable. Hence +/// the trait is `Sealed` and only one mandatory implementor [`DefaultAddressMapper`] +/// exists. /// -/// # Note for implementors -/// -/// 1. Make sure that there are no collisions, different inputs never lead to the same output. -/// 2. Make sure that the same inputs lead to the same output. -pub trait AddressGenerator<T: Config> { - /// The address of a contract based on the given instantiate parameters. +/// Please note that we assume that the native account is at least 20 bytes and +/// only implement this type for a `T` where this is the case. Luckily, this is the +/// case for all existing runtimes as of right now. Reasing is that this will allow +/// us to reverse an address -> account_id mapping by just stripping the prefix. +pub trait AddressMapper<T>: private::Sealed { + /// Convert an account id to an ethereum adress. + /// + /// This mapping is **not** required to be reversible. + fn to_address(account_id: &T) -> H160; + + /// Convert an ethereum address to a native account id. /// - /// Changing the formular for an already deployed chain is fine as long as no collisions - /// with the old formular. Changes only affect existing contracts. - fn contract_address( - deploying_address: &T::AccountId, - code_hash: &CodeHash<T>, - input_data: &[u8], - salt: &[u8], - ) -> T::AccountId; + /// This mapping is **required** to be reversible. + fn to_account_id(address: &H160) -> T; + + /// Same as [`Self::to_account_id`] but when we know the address is a contract. + /// + /// This is only the case when we just generated the new address. + fn to_account_id_contract(address: &H160) -> T; } -/// Default address generator. -/// -/// This is the default address generator used by contract instantiation. Its result -/// is only dependent on its inputs. It can therefore be used to reliably predict the -/// address of a contract. This is akin to the formula of eth's CREATE2 opcode. There -/// is no CREATE equivalent because CREATE2 is strictly more powerful. -/// Formula: -/// `hash("contract_addr_v1" ++ deploying_address ++ code_hash ++ input_data ++ salt)` -pub struct DefaultAddressGenerator; - -impl<T: Config> AddressGenerator<T> for DefaultAddressGenerator { - /// Formula: `hash("contract_addr_v1" ++ deploying_address ++ code_hash ++ input_data ++ salt)` - fn contract_address( - deploying_address: &T::AccountId, - code_hash: &CodeHash<T>, - input_data: &[u8], - salt: &[u8], - ) -> T::AccountId { - let entropy = (b"contract_addr_v1", deploying_address, code_hash, input_data, salt) - .using_encoded(T::Hashing::hash); - Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) - .expect("infinite length input; no invalid inputs for type; qed") +mod private { + pub trait Sealed {} + impl Sealed for super::DefaultAddressMapper {} +} + +/// The only implementor for `AddressMapper`. +pub enum DefaultAddressMapper {} + +impl AddressMapper<AccountId32> for DefaultAddressMapper { + fn to_address(account_id: &AccountId32) -> H160 { + H160::from_slice(&<AccountId32 as AsRef<[u8; 32]>>::as_ref(&account_id)[..20]) + } + + fn to_account_id(address: &H160) -> AccountId32 { + let mut account_id = AccountId32::new([0xEE; 32]); + <AccountId32 as AsMut<[u8; 32]>>::as_mut(&mut account_id)[..20] + .copy_from_slice(address.as_bytes()); + account_id + } + + fn to_account_id_contract(address: &H160) -> AccountId32 { + Self::to_account_id(address) + } +} + +/// Determine the address of a contract using CREATE semantics. +#[allow(dead_code)] +pub fn create1(deployer: &H160, nonce: u64) -> H160 { + let mut list = rlp::RlpStream::new_list(2); + list.append(&deployer.as_bytes()); + list.append(&nonce); + let hash = keccak_256(&list.out()); + H160::from_slice(&hash[12..]) +} + +/// Determine the address of a contract using the CREATE2 semantics. +pub fn create2(deployer: &H160, code: &[u8], input_data: &[u8], salt: &[u8; 32]) -> H160 { + let init_code_hash = { + let init_code: Vec<u8> = code.into_iter().chain(input_data).cloned().collect(); + keccak_256(init_code.as_ref()) + }; + let mut bytes = [0; 85]; + bytes[0] = 0xff; + bytes[1..21].copy_from_slice(deployer.as_bytes()); + bytes[21..53].copy_from_slice(salt); + bytes[53..85].copy_from_slice(&init_code_hash); + let hash = keccak_256(&bytes); + H160::from_slice(&hash[12..]) +} + +#[cfg(test)] +mod test { + use super::*; + use crate::test_utils::ALICE_ADDR; + use sp_core::{hex2array, H160}; + + #[test] + fn create1_works() { + assert_eq!( + create1(&ALICE_ADDR, 1u64), + H160(hex2array!("c851da37e4e8d3a20d8d56be2963934b4ad71c3b")), + ) + } + + #[test] + fn create2_works() { + assert_eq!( + create2( + &ALICE_ADDR, + &hex2array!("600060005560016000"), + &hex2array!("55"), + &hex2array!("1234567890123456789012345678901234567890123456789012345678901234") + ), + H160(hex2array!("7f31e795e5836a19a8f919ab5a9de9a197ecd2b6")), + ) } } diff --git a/substrate/frame/revive/src/benchmarking/call_builder.rs b/substrate/frame/revive/src/benchmarking/call_builder.rs index 654ba3de4f7..c000817a8a3 100644 --- a/substrate/frame/revive/src/benchmarking/call_builder.rs +++ b/substrate/frame/revive/src/benchmarking/call_builder.rs @@ -16,6 +16,7 @@ // limitations under the License. use crate::{ + address::AddressMapper, benchmarking::{default_deposit_limit, Contract, WasmModule}, exec::{ExportedFunction, Ext, Key, Stack}, storage::meter::Meter, @@ -59,7 +60,7 @@ where <BalanceOf<T> as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode, { /// Setup a new call for the given module. - pub fn new(module: WasmModule<T>) -> Self { + pub fn new(module: WasmModule) -> Self { let contract = Contract::<T>::new(module.clone(), vec![]).unwrap(); let dest = contract.account_id.clone(); let origin = Origin::from_account_id(contract.caller.clone()); @@ -74,7 +75,10 @@ where // Whitelist the contract's contractInfo as it is already accounted for in the call // benchmark benchmarking::add_to_whitelist( - crate::ContractInfoOf::<T>::hashed_key_for(&contract.account_id).into(), + crate::ContractInfoOf::<T>::hashed_key_for(&T::AddressMapper::to_address( + &contract.account_id, + )) + .into(), ); Self { @@ -138,7 +142,7 @@ where /// Build the call stack. pub fn ext(&mut self) -> (StackExt<'_, T>, WasmBlob<T>) { let mut ext = StackExt::bench_new_call( - self.dest.clone(), + T::AddressMapper::to_address(&self.dest), self.origin.clone(), &mut self.gas_meter, &mut self.storage_meter, diff --git a/substrate/frame/revive/src/benchmarking/code.rs b/substrate/frame/revive/src/benchmarking/code.rs index eba4710d8a2..ede3bb69b11 100644 --- a/substrate/frame/revive/src/benchmarking/code.rs +++ b/substrate/frame/revive/src/benchmarking/code.rs @@ -24,19 +24,19 @@ //! we define this simple definition of a contract that can be passed to `create_code` that //! compiles it down into a `WasmModule` that can be used as a contract's code. -use crate::Config; use alloc::vec::Vec; use pallet_revive_fixtures::bench as bench_fixtures; -use sp_runtime::traits::Hash; +use sp_core::H256; +use sp_io::hashing::keccak_256; /// A wasm module ready to be put on chain. #[derive(Clone)] -pub struct WasmModule<T: Config> { +pub struct WasmModule { pub code: Vec<u8>, - pub hash: <T::Hashing as Hash>::Output, + pub hash: H256, } -impl<T: Config> WasmModule<T> { +impl WasmModule { /// Return a contract code that does nothing. pub fn dummy() -> Self { Self::new(bench_fixtures::DUMMY.to_vec()) @@ -63,7 +63,7 @@ impl<T: Config> WasmModule<T> { } fn new(code: Vec<u8>) -> Self { - let hash = T::Hashing::hash(&code); - Self { code, hash } + let hash = keccak_256(&code); + Self { code, hash: H256(hash) } } } diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs index b4bd028d6f0..409d53b8a06 100644 --- a/substrate/frame/revive/src/benchmarking/mod.rs +++ b/substrate/frame/revive/src/benchmarking/mod.rs @@ -65,7 +65,7 @@ const UNBALANCED_TRIE_LAYERS: u32 = 20; struct Contract<T: Config> { caller: T::AccountId, account_id: T::AccountId, - addr: AccountIdLookupOf<T>, + addr: T::AccountId, } impl<T> Contract<T> @@ -74,14 +74,14 @@ where <BalanceOf<T> as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode, { /// Create new contract and use a default account id as instantiator. - fn new(module: WasmModule<T>, data: Vec<u8>) -> Result<Contract<T>, &'static str> { + fn new(module: WasmModule, data: Vec<u8>) -> Result<Contract<T>, &'static str> { Self::with_index(0, module, data) } /// Create new contract and use an account id derived from the supplied index as instantiator. fn with_index( index: u32, - module: WasmModule<T>, + module: WasmModule, data: Vec<u8>, ) -> Result<Contract<T>, &'static str> { Self::with_caller(account("instantiator", index, 0), module, data) @@ -90,11 +90,11 @@ where /// Create new contract and use the supplied `caller` as instantiator. fn with_caller( caller: T::AccountId, - module: WasmModule<T>, + module: WasmModule, data: Vec<u8>, ) -> Result<Contract<T>, &'static str> { T::Currency::set_balance(&caller, caller_funding::<T>()); - let salt = vec![0xff]; + let salt = [0xffu8; 32]; let outcome = Contracts::<T>::bare_instantiate( RawOrigin::Signed(caller.clone()).into(), @@ -108,20 +108,17 @@ where CollectEvents::Skip, ); - let addr = outcome.result?.account_id; - let result = Contract { caller, account_id: addr.clone(), addr: T::Lookup::unlookup(addr) }; + let address = outcome.result?.addr; + let account_id = T::AddressMapper::to_account_id_contract(&address); + let result = Contract { caller, account_id: account_id.clone(), addr: account_id }; - ContractInfoOf::<T>::insert(&result.account_id, result.info()?); + ContractInfoOf::<T>::insert(&address, result.info()?); Ok(result) } /// Create a new contract with the supplied storage item count and size each. - fn with_storage( - code: WasmModule<T>, - stor_num: u32, - stor_size: u32, - ) -> Result<Self, &'static str> { + fn with_storage(code: WasmModule, stor_num: u32, stor_size: u32) -> Result<Self, &'static str> { let contract = Contract::<T>::new(code, vec![])?; let storage_items = (0..stor_num) .map(|i| { @@ -143,12 +140,12 @@ where info.write(&Key::Fix(item.0), Some(item.1.clone()), None, false) .map_err(|_| "Failed to write storage to restoration dest")?; } - <ContractInfoOf<T>>::insert(&self.account_id, info); + <ContractInfoOf<T>>::insert(T::AddressMapper::to_address(&self.account_id), info); Ok(()) } /// Create a new contract with the specified unbalanced storage trie. - fn with_unbalanced_storage_trie(code: WasmModule<T>, key: &[u8]) -> Result<Self, &'static str> { + fn with_unbalanced_storage_trie(code: WasmModule, key: &[u8]) -> Result<Self, &'static str> { if (key.len() as u32) < (UNBALANCED_TRIE_LAYERS + 1) / 2 { return Err("Key size too small to create the specified trie"); } @@ -179,7 +176,8 @@ where /// Get the `ContractInfo` of the `addr` or an error if it no longer exists. fn address_info(addr: &T::AccountId) -> Result<ContractInfo<T>, &'static str> { - ContractInfoOf::<T>::get(addr).ok_or("Expected contract to exist at this point.") + ContractInfoOf::<T>::get(T::AddressMapper::to_address(addr)) + .ok_or("Expected contract to exist at this point.") } /// Get the `ContractInfo` of this contract or an error if it no longer exists. @@ -193,12 +191,12 @@ where } /// Returns `true` iff all storage entries related to code storage exist. - fn code_exists(hash: &CodeHash<T>) -> bool { + fn code_exists(hash: &sp_core::H256) -> bool { <PristineCode<T>>::contains_key(hash) && <CodeInfoOf<T>>::contains_key(&hash) } /// Returns `true` iff no storage entry related to code storage exist. - fn code_removed(hash: &CodeHash<T>) -> bool { + fn code_removed(hash: &sp_core::H256) -> bool { !<PristineCode<T>>::contains_key(hash) && !<CodeInfoOf<T>>::contains_key(&hash) } } @@ -328,7 +326,7 @@ mod benchmarks { let instance = Contract::<T>::with_caller(whitelisted_caller(), WasmModule::sized(c), vec![])?; let value = Pallet::<T>::min_balance(); - let callee = instance.addr; + let callee = T::AddressMapper::to_address(&instance.addr); let storage_deposit = default_deposit_limit::<T>(); #[extrinsic_call] @@ -351,22 +349,23 @@ mod benchmarks { fn instantiate_with_code( c: Linear<0, { T::MaxCodeLen::get() }>, i: Linear<0, { limits::MEMORY_BYTES }>, - s: Linear<0, { limits::MEMORY_BYTES }>, ) { let input = vec![42u8; i as usize]; - let salt = vec![42u8; s as usize]; + let salt = [42u8; 32]; let value = Pallet::<T>::min_balance(); let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::<T>()); - let WasmModule { code, hash, .. } = WasmModule::<T>::sized(c); + let WasmModule { code, .. } = WasmModule::sized(c); let origin = RawOrigin::Signed(caller.clone()); - let addr = Contracts::<T>::contract_address(&caller, &hash, &input, &salt); + let deployer = T::AddressMapper::to_address(&caller); + let addr = crate::address::create2(&deployer, &code, &input, &salt); + let account_id = T::AddressMapper::to_account_id_contract(&addr); let storage_deposit = default_deposit_limit::<T>(); #[extrinsic_call] _(origin, value, Weight::MAX, storage_deposit, code, input, salt); let deposit = - T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &addr); + T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account_id); // uploading the code reserves some balance in the callers account let code_deposit = T::Currency::balance_on_hold(&HoldReason::CodeUploadDepositReserve.into(), &caller); @@ -375,27 +374,26 @@ mod benchmarks { caller_funding::<T>() - value - deposit - code_deposit - Pallet::<T>::min_balance(), ); // contract has the full value - assert_eq!(T::Currency::balance(&addr), value + Pallet::<T>::min_balance()); + assert_eq!(T::Currency::balance(&account_id), value + Pallet::<T>::min_balance()); } // `i`: Size of the input in bytes. // `s`: Size of the salt in bytes. #[benchmark(pov_mode = Measured)] - fn instantiate( - i: Linear<0, { limits::MEMORY_BYTES }>, - s: Linear<0, { limits::MEMORY_BYTES }>, - ) -> Result<(), BenchmarkError> { + fn instantiate(i: Linear<0, { limits::MEMORY_BYTES }>) -> Result<(), BenchmarkError> { let input = vec![42u8; i as usize]; - let salt = vec![42u8; s as usize]; + let salt = [42u8; 32]; let value = Pallet::<T>::min_balance(); let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::<T>()); let origin = RawOrigin::Signed(caller.clone()); - let WasmModule { code, .. } = WasmModule::<T>::dummy(); + let WasmModule { code, .. } = WasmModule::dummy(); let storage_deposit = default_deposit_limit::<T>(); + let deployer = T::AddressMapper::to_address(&caller); + let addr = crate::address::create2(&deployer, &code, &input, &salt); let hash = Contracts::<T>::bare_upload_code(origin.into(), code, storage_deposit)?.code_hash; - let addr = Contracts::<T>::contract_address(&caller, &hash, &input, &salt); + let account_id = T::AddressMapper::to_account_id_contract(&addr); #[extrinsic_call] _( @@ -409,16 +407,16 @@ mod benchmarks { ); let deposit = - T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &addr); + T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account_id); let code_deposit = - T::Currency::balance_on_hold(&HoldReason::CodeUploadDepositReserve.into(), &caller); + T::Currency::balance_on_hold(&HoldReason::CodeUploadDepositReserve.into(), &account_id); // value was removed from the caller assert_eq!( - T::Currency::balance(&caller), + T::Currency::total_balance(&caller), caller_funding::<T>() - value - deposit - code_deposit - Pallet::<T>::min_balance(), ); // contract has the full value - assert_eq!(T::Currency::balance(&addr), value + Pallet::<T>::min_balance()); + assert_eq!(T::Currency::balance(&account_id), value + Pallet::<T>::min_balance()); Ok(()) } @@ -437,7 +435,7 @@ mod benchmarks { Contract::<T>::with_caller(whitelisted_caller(), WasmModule::dummy(), vec![])?; let value = Pallet::<T>::min_balance(); let origin = RawOrigin::Signed(instance.caller.clone()); - let callee = instance.addr.clone(); + let callee = T::AddressMapper::to_address(&instance.addr); let before = T::Currency::balance(&instance.account_id); let storage_deposit = default_deposit_limit::<T>(); #[extrinsic_call] @@ -470,7 +468,7 @@ mod benchmarks { fn upload_code(c: Linear<0, { T::MaxCodeLen::get() }>) { let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::<T>()); - let WasmModule { code, hash, .. } = WasmModule::<T>::sized(c); + let WasmModule { code, hash, .. } = WasmModule::sized(c); let origin = RawOrigin::Signed(caller.clone()); let storage_deposit = default_deposit_limit::<T>(); #[extrinsic_call] @@ -487,7 +485,7 @@ mod benchmarks { fn remove_code() -> Result<(), BenchmarkError> { let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::<T>()); - let WasmModule { code, hash, .. } = WasmModule::<T>::dummy(); + let WasmModule { code, hash, .. } = WasmModule::dummy(); let origin = RawOrigin::Signed(caller.clone()); let storage_deposit = default_deposit_limit::<T>(); let uploaded = @@ -508,12 +506,12 @@ mod benchmarks { let instance = <Contract<T>>::with_caller(whitelisted_caller(), WasmModule::dummy(), vec![])?; // we just add some bytes so that the code hash is different - let WasmModule { code, .. } = <WasmModule<T>>::dummy_unique(128); + let WasmModule { code, .. } = WasmModule::dummy_unique(128); let origin = RawOrigin::Signed(instance.caller.clone()); let storage_deposit = default_deposit_limit::<T>(); let hash = <Contracts<T>>::bare_upload_code(origin.into(), code, storage_deposit)?.code_hash; - let callee = instance.addr.clone(); + let callee = T::AddressMapper::to_address(&instance.addr); assert_ne!(instance.info()?.code_hash, hash); #[extrinsic_call] _(RawOrigin::Root, callee, hash); @@ -534,7 +532,7 @@ mod benchmarks { #[benchmark(pov_mode = Measured)] fn seal_caller() { - let len = <T::AccountId as MaxEncodedLen>::max_encoded_len() as u32; + let len = H160::len_bytes(); build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); let result; @@ -545,8 +543,8 @@ mod benchmarks { assert_ok!(result); assert_eq!( - &<T::AccountId as Decode>::decode(&mut &memory[4..]).unwrap(), - runtime.ext().caller().account_id().unwrap() + <H160 as Decode>::decode(&mut &memory[4..]).unwrap(), + T::AddressMapper::to_address(&runtime.ext().caller().account_id().unwrap()) ); } @@ -569,7 +567,7 @@ mod benchmarks { #[benchmark(pov_mode = Measured)] fn seal_code_hash() { let contract = Contract::<T>::with_index(1, WasmModule::dummy(), vec![]).unwrap(); - let len = <CodeHash<T> as MaxEncodedLen>::max_encoded_len() as u32; + let len = <sp_core::H256 as MaxEncodedLen>::max_encoded_len() as u32; build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], contract.account_id.encode(), ]); let result; @@ -580,14 +578,14 @@ mod benchmarks { assert_ok!(result); assert_eq!( - <CodeHash<T> as Decode>::decode(&mut &memory[4..]).unwrap(), + <sp_core::H256 as Decode>::decode(&mut &memory[4..]).unwrap(), contract.info().unwrap().code_hash ); } #[benchmark(pov_mode = Measured)] fn seal_own_code_hash() { - let len = <CodeHash<T> as MaxEncodedLen>::max_encoded_len() as u32; + let len = <sp_core::H256 as MaxEncodedLen>::max_encoded_len() as u32; build_runtime!(runtime, contract, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); let result; #[block] @@ -597,7 +595,7 @@ mod benchmarks { assert_ok!(result); assert_eq!( - <CodeHash<T> as Decode>::decode(&mut &memory[4..]).unwrap(), + <sp_core::H256 as Decode>::decode(&mut &memory[4..]).unwrap(), contract.info().unwrap().code_hash ); } @@ -631,7 +629,7 @@ mod benchmarks { #[benchmark(pov_mode = Measured)] fn seal_address() { - let len = <AccountIdOf<T> as MaxEncodedLen>::max_encoded_len() as u32; + let len = H160::len_bytes(); build_runtime!(runtime, memory: [len.to_le_bytes(), vec![0u8; len as _], ]); let result; @@ -640,10 +638,7 @@ mod benchmarks { result = runtime.bench_address(memory.as_mut_slice(), 4, 0); } assert_ok!(result); - assert_eq!( - &<T::AccountId as Decode>::decode(&mut &memory[4..]).unwrap(), - runtime.ext().address() - ); + assert_eq!(<H160 as Decode>::decode(&mut &memory[4..]).unwrap(), runtime.ext().address()); } #[benchmark(pov_mode = Measured)] @@ -809,7 +804,7 @@ mod benchmarks { build_runtime!(runtime, memory: [beneficiary.encode(),]); (0..n).for_each(|i| { - let new_code = WasmModule::<T>::dummy_unique(65 + i); + let new_code = WasmModule::dummy_unique(65 + i); Contracts::<T>::bare_upload_code(origin.clone().into(), new_code.code, storage_deposit) .unwrap(); runtime.ext().lock_delegate_dependency(new_code.hash).unwrap(); @@ -1536,10 +1531,8 @@ mod benchmarks { // i: size of input in bytes // s: size of salt in bytes #[benchmark(pov_mode = Measured)] - fn seal_instantiate( - i: Linear<0, { limits::MEMORY_BYTES }>, - s: Linear<0, { limits::MEMORY_BYTES }>, - ) -> Result<(), BenchmarkError> { + fn seal_instantiate(i: Linear<0, { limits::MEMORY_BYTES }>) -> Result<(), BenchmarkError> { + let code = WasmModule::dummy(); let hash = Contract::<T>::with_index(1, WasmModule::dummy(), vec![])?.info()?.code_hash; let hash_bytes = hash.encode(); let hash_len = hash_bytes.len() as u32; @@ -1561,8 +1554,10 @@ mod benchmarks { let mut runtime = crate::wasm::Runtime::<_, [u8]>::new(&mut ext, vec![]); let input = vec![42u8; i as _]; - let salt = vec![42u8; s as _]; - let addr = Contracts::<T>::contract_address(&account_id, &hash, &input, &salt); + let salt = [42u8; 32]; + let deployer = T::AddressMapper::to_address(&account_id); + let addr = crate::address::create2(&deployer, &code.code, &input, &salt); + let account_id = T::AddressMapper::to_account_id_contract(&addr); let mut memory = memory!(hash_bytes, deposit_bytes, value_bytes, input, salt,); let mut offset = { @@ -1592,13 +1587,13 @@ mod benchmarks { SENTINEL, // output_ptr 0, // output_len_ptr offset(i), // salt_ptr - s, // salt_len + 32, // salt_len ); } assert_ok!(result); assert!(ContractInfoOf::<T>::get(&addr).is_some()); - assert_eq!(T::Currency::balance(&addr), Pallet::<T>::min_balance() + value); + assert_eq!(T::Currency::balance(&account_id), Pallet::<T>::min_balance() + value); Ok(()) } diff --git a/substrate/frame/revive/src/debug.rs b/substrate/frame/revive/src/debug.rs index 467f4e1ad49..00e893b94f8 100644 --- a/substrate/frame/revive/src/debug.rs +++ b/substrate/frame/revive/src/debug.rs @@ -20,6 +20,7 @@ pub use crate::{ primitives::ExecReturnValue, }; use crate::{Config, LOG_TARGET}; +use sp_core::H160; /// Umbrella trait for all interfaces that serves for debugging. pub trait Debugger<T: Config>: Tracing<T> + CallInterceptor<T> {} @@ -43,7 +44,7 @@ pub trait Tracing<T: Config> { /// * `entry_point` - Describes whether the call is the constructor or a regular call. /// * `input_data` - The raw input data of the call. fn new_call_span( - contract_address: &T::AccountId, + contract_address: &H160, entry_point: ExportedFunction, input_data: &[u8], ) -> Self::CallSpan; @@ -62,11 +63,7 @@ pub trait CallSpan { impl<T: Config> Tracing<T> for () { type CallSpan = (); - fn new_call_span( - contract_address: &T::AccountId, - entry_point: ExportedFunction, - input_data: &[u8], - ) { + fn new_call_span(contract_address: &H160, entry_point: ExportedFunction, input_data: &[u8]) { log::trace!(target: LOG_TARGET, "call {entry_point:?} account: {contract_address:?}, input_data: {input_data:?}") } } @@ -95,7 +92,7 @@ pub trait CallInterceptor<T: Config> { /// is returned. /// * `None` - otherwise, i.e. the call should be executed normally. fn intercept_call( - contract_address: &T::AccountId, + contract_address: &H160, entry_point: ExportedFunction, input_data: &[u8], ) -> Option<ExecResult>; @@ -103,7 +100,7 @@ pub trait CallInterceptor<T: Config> { impl<T: Config> CallInterceptor<T> for () { fn intercept_call( - _contract_address: &T::AccountId, + _contract_address: &H160, _entry_point: ExportedFunction, _input_data: &[u8], ) -> Option<ExecResult> { diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 9740707ae70..54019a6ba99 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -16,6 +16,7 @@ // limitations under the License. use crate::{ + address::{self, AddressMapper}, debug::{CallInterceptor, CallSpan, Tracing}, gas::GasMeter, limits, @@ -23,8 +24,8 @@ use crate::{ runtime_decl_for_revive_api::{Decode, Encode, RuntimeDebugNoBound, TypeInfo}, storage::{self, meter::Diff, WriteOutcome}, transient_storage::TransientStorage, - BalanceOf, CodeHash, CodeInfo, CodeInfoOf, Config, ContractInfo, ContractInfoOf, DebugBuffer, - Error, Event, Pallet as Contracts, LOG_TARGET, + BalanceOf, CodeInfo, CodeInfoOf, Config, ContractInfo, ContractInfoOf, DebugBuffer, Error, + Event, Pallet as Contracts, LOG_TARGET, }; use alloc::vec::Vec; use core::{fmt::Debug, marker::PhantomData, mem}; @@ -48,7 +49,7 @@ use frame_system::{ use sp_core::{ ecdsa::Public as ECDSAPublic, sr25519::{Public as SR25519Public, Signature as SR25519Signature}, - ConstU32, Get, + ConstU32, Get, H160, H256, }; use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256}; use sp_runtime::{ @@ -184,7 +185,7 @@ pub trait Ext: sealing::Sealed { &mut self, gas_limit: Weight, deposit_limit: BalanceOf<Self::T>, - to: AccountIdOf<Self::T>, + to: &H160, value: BalanceOf<Self::T>, input_data: Vec<u8>, allows_reentry: bool, @@ -196,7 +197,7 @@ pub trait Ext: sealing::Sealed { /// Returns the code size of the called contract. fn delegate_call( &mut self, - code: CodeHash<Self::T>, + code: H256, input_data: Vec<u8>, ) -> Result<ExecReturnValue, ExecError>; @@ -209,11 +210,11 @@ pub trait Ext: sealing::Sealed { &mut self, gas_limit: Weight, deposit_limit: BalanceOf<Self::T>, - code: CodeHash<Self::T>, + code: H256, value: BalanceOf<Self::T>, input_data: Vec<u8>, - salt: &[u8], - ) -> Result<(AccountIdOf<Self::T>, ExecReturnValue), ExecError>; + salt: &[u8; 32], + ) -> Result<(H160, ExecReturnValue), ExecError>; /// Transfer all funds to `beneficiary` and delete the contract. /// @@ -222,10 +223,10 @@ pub trait Ext: sealing::Sealed { /// /// This function will fail if the same contract is present on the contract /// call stack. - fn terminate(&mut self, beneficiary: &AccountIdOf<Self::T>) -> DispatchResult; + fn terminate(&mut self, beneficiary: &H160) -> DispatchResult; /// Transfer some amount of funds into the specified account. - fn transfer(&mut self, to: &AccountIdOf<Self::T>, value: BalanceOf<Self::T>) -> DispatchResult; + fn transfer(&mut self, to: &H160, value: BalanceOf<Self::T>) -> DispatchResult; /// Returns the storage entry of the executing account by the given `key`. /// @@ -273,15 +274,15 @@ pub trait Ext: sealing::Sealed { fn caller(&self) -> Origin<Self::T>; /// Check if a contract lives at the specified `address`. - fn is_contract(&self, address: &AccountIdOf<Self::T>) -> bool; + fn is_contract(&self, address: &H160) -> bool; /// Returns the code hash of the contract for the given `address`. /// /// Returns `None` if the `address` does not belong to a contract. - fn code_hash(&self, address: &AccountIdOf<Self::T>) -> Option<CodeHash<Self::T>>; + fn code_hash(&self, address: &H160) -> Option<H256>; /// Returns the code hash of the contract being executed. - fn own_code_hash(&mut self) -> &CodeHash<Self::T>; + fn own_code_hash(&mut self) -> &H256; /// Check if the caller of the current contract is the origin of the whole call stack. /// @@ -293,7 +294,12 @@ pub trait Ext: sealing::Sealed { fn caller_is_root(&self) -> bool; /// Returns a reference to the account id of the current contract. - fn address(&self) -> &AccountIdOf<Self::T>; + fn account_id(&self) -> &AccountIdOf<Self::T>; + + /// Returns a reference to the [`H160`] address of the current contract. + fn address(&self) -> H160 { + <Self::T as Config>::AddressMapper::to_address(self.account_id()) + } /// Returns the balance of the current contract. /// @@ -368,7 +374,7 @@ pub trait Ext: sealing::Sealed { fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>; /// Sets new code hash for existing contract. - fn set_code_hash(&mut self, hash: CodeHash<Self::T>) -> DispatchResult; + fn set_code_hash(&mut self, hash: H256) -> DispatchResult; /// Returns the number of times the specified contract exists on the call stack. Delegated calls /// Increment the reference count of a of a stored code by one. @@ -377,7 +383,7 @@ pub trait Ext: sealing::Sealed { /// /// [`Error::CodeNotFound`] is returned if no stored code found having the specified /// `code_hash`. - fn increment_refcount(code_hash: CodeHash<Self::T>) -> DispatchResult; + fn increment_refcount(code_hash: H256) -> DispatchResult; /// Decrement the reference count of a stored code by one. /// @@ -385,7 +391,7 @@ pub trait Ext: sealing::Sealed { /// /// A contract whose reference count dropped to zero isn't automatically removed. A /// `remove_code` transaction must be submitted by the original uploader to do so. - fn decrement_refcount(code_hash: CodeHash<Self::T>); + fn decrement_refcount(code_hash: H256); /// Adds a delegate dependency to [`ContractInfo`]'s `delegate_dependencies` field. /// @@ -398,7 +404,7 @@ pub trait Ext: sealing::Sealed { /// - [`Error::MaxDelegateDependenciesReached`] /// - [`Error::CannotAddSelfAsDelegateDependency`] /// - [`Error::DelegateDependencyAlreadyExists`] - fn lock_delegate_dependency(&mut self, code_hash: CodeHash<Self::T>) -> DispatchResult; + fn lock_delegate_dependency(&mut self, code_hash: H256) -> DispatchResult; /// Removes a delegate dependency from [`ContractInfo`]'s `delegate_dependencies` field. /// @@ -408,7 +414,7 @@ pub trait Ext: sealing::Sealed { /// # Errors /// /// - [`Error::DelegateDependencyNotFound`] - fn unlock_delegate_dependency(&mut self, code_hash: &CodeHash<Self::T>) -> DispatchResult; + fn unlock_delegate_dependency(&mut self, code_hash: &H256) -> DispatchResult; /// Returns the number of locked delegate dependencies. /// @@ -447,10 +453,7 @@ pub trait Executable<T: Config>: Sized { /// /// # Note /// Charges size base load weight from the gas meter. - fn from_storage( - code_hash: CodeHash<T>, - gas_meter: &mut GasMeter<T>, - ) -> Result<Self, DispatchError>; + fn from_storage(code_hash: H256, gas_meter: &mut GasMeter<T>) -> Result<Self, DispatchError>; /// Execute the specified exported function and return the result. /// @@ -471,8 +474,11 @@ pub trait Executable<T: Config>: Sized { /// The code info of the executable. fn code_info(&self) -> &CodeInfo<T>; + /// The raw code of the executable. + fn code(&self) -> &[u8]; + /// The code hash of the executable. - fn code_hash(&self) -> &CodeHash<T>; + fn code_hash(&self) -> &H256; } /// The complete call stack of a contract execution. @@ -519,7 +525,7 @@ pub struct Stack<'a, T: Config, E> { /// For each nested contract call or instantiate one frame is created. It holds specific /// information for the said call and caches the in-storage `ContractInfo` data structure. struct Frame<T: Config> { - /// The account id of the executing contract. + /// The address of the executing contract. account_id: T::AccountId, /// The cached in-storage data of the contract. contract_info: CachedContract<T>, @@ -567,7 +573,7 @@ enum FrameArgs<'a, T: Config, E> { /// The executable whose `deploy` function is run. executable: E, /// A salt used in the contract address derivation of the new contract. - salt: &'a [u8], + salt: &'a [u8; 32], /// The input data is used in the contract address derivation of the new contract. input_data: &'a [u8], }, @@ -668,7 +674,7 @@ impl<T: Config> CachedContract<T> { /// Load the `contract_info` from storage if necessary. fn load(&mut self, account_id: &T::AccountId) { if let CachedContract::Invalidated = self { - let contract = <ContractInfoOf<T>>::get(&account_id); + let contract = <ContractInfoOf<T>>::get(T::AddressMapper::to_address(account_id)); if let Some(contract) = contract { *self = CachedContract::Cached(contract); } @@ -705,7 +711,7 @@ where /// Result<(ExecReturnValue, CodeSize), (ExecError, CodeSize)> pub fn run_call( origin: Origin<T>, - dest: T::AccountId, + dest: H160, gas_meter: &'a mut GasMeter<T>, storage_meter: &'a mut storage::meter::Meter<T>, value: BalanceOf<T>, @@ -713,7 +719,11 @@ where debug_message: Option<&'a mut DebugBuffer>, ) -> Result<ExecReturnValue, ExecError> { let (mut stack, executable) = Self::new( - FrameArgs::Call { dest, cached_info: None, delegated_call: None }, + FrameArgs::Call { + dest: T::AddressMapper::to_account_id(&dest), + cached_info: None, + delegated_call: None, + }, origin, gas_meter, storage_meter, @@ -740,9 +750,9 @@ where storage_meter: &'a mut storage::meter::Meter<T>, value: BalanceOf<T>, input_data: Vec<u8>, - salt: &[u8], + salt: &[u8; 32], debug_message: Option<&'a mut DebugBuffer>, - ) -> Result<(T::AccountId, ExecReturnValue), ExecError> { + ) -> Result<(H160, ExecReturnValue), ExecError> { let (mut stack, executable) = Self::new( FrameArgs::Instantiate { sender: origin.clone(), @@ -756,13 +766,13 @@ where value, debug_message, )?; - let account_id = stack.top_frame().account_id.clone(); - stack.run(executable, input_data).map(|ret| (account_id, ret)) + let address = T::AddressMapper::to_address(&stack.top_frame().account_id); + stack.run(executable, input_data).map(|ret| (address, ret)) } #[cfg(all(feature = "runtime-benchmarks", feature = "riscv"))] pub fn bench_new_call( - dest: T::AccountId, + dest: H160, origin: Origin<T>, gas_meter: &'a mut GasMeter<T>, storage_meter: &'a mut storage::meter::Meter<T>, @@ -770,7 +780,11 @@ where debug_message: Option<&'a mut DebugBuffer>, ) -> (Self, E) { Self::new( - FrameArgs::Call { dest, cached_info: None, delegated_call: None }, + FrameArgs::Call { + dest: T::AddressMapper::to_account_id(&dest), + cached_info: None, + delegated_call: None, + }, origin, gas_meter, storage_meter, @@ -834,7 +848,8 @@ where let contract = if let Some(contract) = cached_info { contract } else { - <ContractInfoOf<T>>::get(&dest).ok_or(<Error<T>>::ContractNotFound)? + <ContractInfoOf<T>>::get(T::AddressMapper::to_address(&dest)) + .ok_or(<Error<T>>::ContractNotFound)? }; let (executable, delegate_caller) = @@ -847,18 +862,20 @@ where (dest, contract, executable, delegate_caller, ExportedFunction::Call) }, FrameArgs::Instantiate { sender, executable, salt, input_data } => { - let account_id = Contracts::<T>::contract_address( - &sender, - &executable.code_hash(), - input_data, - salt, - ); + let deployer = T::AddressMapper::to_address(&sender); + let address = address::create2(&deployer, executable.code(), input_data, salt); let contract = ContractInfo::new( - &account_id, + &address, <System<T>>::account_nonce(&sender), *executable.code_hash(), )?; - (account_id, contract, executable, None, ExportedFunction::Constructor) + ( + T::AddressMapper::to_account_id_contract(&address), + contract, + executable, + None, + ExportedFunction::Constructor, + ) }, }; @@ -887,7 +904,7 @@ where read_only: bool, ) -> Result<E, ExecError> { if self.frames.len() as u32 == limits::CALL_STACK_DEPTH { - return Err(Error::<T>::MaxCallDepthReached.into()) + return Err(Error::<T>::MaxCallDepthReached.into()); } // We need to make sure that changes made to the contract info are not discarded. @@ -898,7 +915,10 @@ where if let (CachedContract::Cached(contract), ExportedFunction::Call) = (&frame.contract_info, frame.entry_point) { - <ContractInfoOf<T>>::insert(frame.account_id.clone(), contract.clone()); + <ContractInfoOf<T>>::insert( + T::AddressMapper::to_address(&frame.account_id), + contract.clone(), + ); } let frame = top_frame_mut!(self); @@ -950,11 +970,11 @@ where // Every non delegate call or instantiate also optionally transfers the balance. self.initial_transfer()?; - let contract_address = &top_frame!(self).account_id; + let contract_address = T::AddressMapper::to_address(&top_frame!(self).account_id); - let call_span = T::Debug::new_call_span(contract_address, entry_point, &input_data); + let call_span = T::Debug::new_call_span(&contract_address, entry_point, &input_data); - let output = T::Debug::intercept_call(contract_address, entry_point, &input_data) + let output = T::Debug::intercept_call(&contract_address, entry_point, &input_data) .unwrap_or_else(|| { executable .execute(self, entry_point, input_data) @@ -965,7 +985,7 @@ where // Avoid useless work that would be reverted anyways. if output.did_revert() { - return Ok(output) + return Ok(output); } // Storage limit is normally enforced as late as possible (when the last frame returns) @@ -980,12 +1000,12 @@ where } let frame = self.top_frame(); - let account_id = &frame.account_id.clone(); + let account_id = T::AddressMapper::to_address(&frame.account_id); match (entry_point, delegated_code_hash) { (ExportedFunction::Constructor, _) => { // It is not allowed to terminate a contract inside its constructor. if matches!(frame.contract_info, CachedContract::Terminated) { - return Err(Error::<T>::TerminatedInConstructor.into()) + return Err(Error::<T>::TerminatedInConstructor.into()); } // If a special limit was set for the sub-call, we enforce it here. @@ -995,17 +1015,17 @@ where let contract = frame.contract_info.as_contract(); frame.nested_storage.enforce_subcall_limit(contract)?; - let caller = self.caller().account_id()?.clone(); + let caller = T::AddressMapper::to_address(self.caller().account_id()?); // Deposit an instantiation event. Contracts::<T>::deposit_event(Event::Instantiated { deployer: caller, - contract: account_id.clone(), + contract: account_id, }); }, (ExportedFunction::Call, Some(code_hash)) => { Contracts::<T>::deposit_event(Event::DelegateCalled { - contract: account_id.clone(), + contract: account_id, code_hash, }); }, @@ -1019,7 +1039,7 @@ where let caller = self.caller(); Contracts::<T>::deposit_event(Event::Called { caller: caller.clone(), - contract: account_id.clone(), + contract: account_id, }); }, } @@ -1081,7 +1101,7 @@ where // Only gas counter changes are persisted in case of a failure. if !persist { - return + return; } // Record the storage meter changes of the nested call into the parent meter. @@ -1100,7 +1120,7 @@ where // trigger a rollback. if prev.account_id == *account_id { prev.contract_info = CachedContract::Cached(contract); - return + return; } // Predecessor is a different contract: We persist the info and invalidate the first @@ -1108,7 +1128,7 @@ where // because that case is already handled by the optimization above. Only the first // cache needs to be invalidated because that one will invalidate the next cache // when it is popped from the stack. - <ContractInfoOf<T>>::insert(account_id, contract); + <ContractInfoOf<T>>::insert(T::AddressMapper::to_address(account_id), contract); if let Some(c) = self.frames_mut().skip(1).find(|f| f.account_id == *account_id) { c.contract_info = CachedContract::Invalidated; } @@ -1123,7 +1143,7 @@ where } self.gas_meter.absorb_nested(mem::take(&mut self.first_frame.nested_gas)); if !persist { - return + return; } let mut contract = self.first_frame.contract_info.as_contract(); self.storage_meter.absorb( @@ -1132,7 +1152,10 @@ where contract.as_deref_mut(), ); if let Some(contract) = contract { - <ContractInfoOf<T>>::insert(&self.first_frame.account_id, contract); + <ContractInfoOf<T>>::insert( + T::AddressMapper::to_address(&self.first_frame.account_id), + contract, + ); } } } @@ -1158,7 +1181,7 @@ where // If it is a delegate call, then we've already transferred tokens in the // last non-delegate frame. if frame.delegate_caller.is_some() { - return Ok(()) + return Ok(()); } let value = frame.value_transferred; @@ -1203,7 +1226,7 @@ where } /// Returns whether the specified contract allows to be reentered right now. - fn allows_reentry(&self, id: &AccountIdOf<T>) -> bool { + fn allows_reentry(&self, id: &T::AccountId) -> bool { !self.frames().any(|f| &f.account_id == id && !f.allows_reentry) } } @@ -1219,7 +1242,7 @@ where &mut self, gas_limit: Weight, deposit_limit: BalanceOf<T>, - to: T::AccountId, + dest: &H160, value: BalanceOf<T>, input_data: Vec<u8>, allows_reentry: bool, @@ -1230,9 +1253,11 @@ where // is caught by it. self.top_frame_mut().allows_reentry = allows_reentry; + let dest = T::AddressMapper::to_account_id(dest); + let try_call = || { - if !self.allows_reentry(&to) { - return Err(<Error<T>>::ReentranceDenied.into()) + if !self.allows_reentry(&dest) { + return Err(<Error<T>>::ReentranceDenied.into()); } // We ignore instantiate frames in our search for a cached contract. @@ -1240,13 +1265,13 @@ where // constructor: We disallow calling not fully constructed contracts. let cached_info = self .frames() - .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == to) + .find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest) .and_then(|f| match &f.contract_info { CachedContract::Cached(contract) => Some(contract.clone()), _ => None, }); let executable = self.push_frame( - FrameArgs::Call { dest: to, cached_info, delegated_call: None }, + FrameArgs::Call { dest, cached_info, delegated_call: None }, value, gas_limit, deposit_limit, @@ -1267,7 +1292,7 @@ where fn delegate_call( &mut self, - code_hash: CodeHash<Self::T>, + code_hash: H256, input_data: Vec<u8>, ) -> Result<ExecReturnValue, ExecError> { let executable = E::from_storage(code_hash, self.gas_meter_mut())?; @@ -1293,11 +1318,11 @@ where &mut self, gas_limit: Weight, deposit_limit: BalanceOf<Self::T>, - code_hash: CodeHash<T>, + code_hash: H256, value: BalanceOf<T>, input_data: Vec<u8>, - salt: &[u8], - ) -> Result<(AccountIdOf<T>, ExecReturnValue), ExecError> { + salt: &[u8; 32], + ) -> Result<(H160, ExecReturnValue), ExecError> { let executable = E::from_storage(code_hash, self.gas_meter_mut())?; let sender = &self.top_frame().account_id; let executable = self.push_frame( @@ -1312,20 +1337,22 @@ where deposit_limit, self.is_read_only(), )?; - let account_id = self.top_frame().account_id.clone(); - self.run(executable, input_data).map(|ret| (account_id, ret)) + let address = T::AddressMapper::to_address(&self.top_frame().account_id); + self.run(executable, input_data).map(|ret| (address, ret)) } - fn terminate(&mut self, beneficiary: &AccountIdOf<Self::T>) -> DispatchResult { + fn terminate(&mut self, beneficiary: &H160) -> DispatchResult { if self.is_recursive() { - return Err(Error::<T>::TerminatedWhileReentrant.into()) + return Err(Error::<T>::TerminatedWhileReentrant.into()); } let frame = self.top_frame_mut(); let info = frame.terminate(); - frame.nested_storage.terminate(&info, beneficiary.clone()); + let beneficiary_account = T::AddressMapper::to_account_id(beneficiary); + frame.nested_storage.terminate(&info, beneficiary_account); info.queue_trie_for_deletion(); - ContractInfoOf::<T>::remove(&frame.account_id); + let account_address = T::AddressMapper::to_address(&frame.account_id); + ContractInfoOf::<T>::remove(&account_address); Self::decrement_refcount(info.code_hash); for (code_hash, deposit) in info.delegate_dependencies() { @@ -1336,14 +1363,19 @@ where } Contracts::<T>::deposit_event(Event::Terminated { - contract: frame.account_id.clone(), - beneficiary: beneficiary.clone(), + contract: account_address, + beneficiary: *beneficiary, }); Ok(()) } - fn transfer(&mut self, to: &T::AccountId, value: BalanceOf<T>) -> DispatchResult { - Self::transfer(Preservation::Preserve, &self.top_frame().account_id, to, value) + fn transfer(&mut self, to: &H160, value: BalanceOf<T>) -> DispatchResult { + Self::transfer( + Preservation::Preserve, + &self.top_frame().account_id, + &T::AddressMapper::to_account_id(to), + value, + ) } fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> { @@ -1370,11 +1402,13 @@ where } fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> { - self.transient_storage.read(self.address(), key) + self.transient_storage.read(self.account_id(), key) } fn get_transient_storage_size(&self, key: &Key) -> Option<u32> { - self.transient_storage.read(self.address(), key).map(|value| value.len() as _) + self.transient_storage + .read(self.account_id(), key) + .map(|value| value.len() as _) } fn set_transient_storage( @@ -1383,11 +1417,11 @@ where value: Option<Vec<u8>>, take_old: bool, ) -> Result<WriteOutcome, DispatchError> { - let account_id = self.address().clone(); + let account_id = self.account_id().clone(); self.transient_storage.write(&account_id, key, value, take_old) } - fn address(&self) -> &T::AccountId { + fn account_id(&self) -> &T::AccountId { &self.top_frame().account_id } @@ -1402,15 +1436,15 @@ where } } - fn is_contract(&self, address: &T::AccountId) -> bool { + fn is_contract(&self, address: &H160) -> bool { ContractInfoOf::<T>::contains_key(&address) } - fn code_hash(&self, address: &T::AccountId) -> Option<CodeHash<Self::T>> { + fn code_hash(&self, address: &H160) -> Option<H256> { <ContractInfoOf<T>>::get(&address).map(|contract| contract.code_hash) } - fn own_code_hash(&mut self) -> &CodeHash<Self::T> { + fn own_code_hash(&mut self) -> &H256 { &self.top_frame_mut().contract_info().code_hash } @@ -1446,7 +1480,10 @@ where fn deposit_event(&mut self, topics: Vec<T::Hash>, data: Vec<u8>) { Contracts::<Self::T>::deposit_indexed_event( topics, - Event::ContractEmitted { contract: self.top_frame().account_id.clone(), data }, + Event::ContractEmitted { + contract: T::AddressMapper::to_address(self.account_id()), + data, + }, ); } @@ -1497,7 +1534,7 @@ where } fn call_runtime(&self, call: <Self::T as Config>::RuntimeCall) -> DispatchResultWithPostInfo { - let mut origin: T::RuntimeOrigin = RawOrigin::Signed(self.address().clone()).into(); + let mut origin: T::RuntimeOrigin = RawOrigin::Signed(self.account_id().clone()).into(); origin.add_filter(T::CallFilter::contains); call.dispatch(origin) } @@ -1528,7 +1565,7 @@ where &mut self.transient_storage } - fn set_code_hash(&mut self, hash: CodeHash<Self::T>) -> DispatchResult { + fn set_code_hash(&mut self, hash: H256) -> DispatchResult { let frame = top_frame_mut!(self); let info = frame.contract_info(); @@ -1548,14 +1585,14 @@ where Self::increment_refcount(hash)?; Self::decrement_refcount(prev_hash); Contracts::<Self::T>::deposit_event(Event::ContractCodeUpdated { - contract: frame.account_id.clone(), + contract: T::AddressMapper::to_address(&frame.account_id), new_code_hash: hash, old_code_hash: prev_hash, }); Ok(()) } - fn increment_refcount(code_hash: CodeHash<Self::T>) -> DispatchResult { + fn increment_refcount(code_hash: H256) -> DispatchResult { <CodeInfoOf<Self::T>>::mutate(code_hash, |existing| -> Result<(), DispatchError> { if let Some(info) = existing { *info.refcount_mut() = info.refcount().saturating_add(1); @@ -1566,7 +1603,7 @@ where }) } - fn decrement_refcount(code_hash: CodeHash<T>) { + fn decrement_refcount(code_hash: H256) { <CodeInfoOf<T>>::mutate(code_hash, |existing| { if let Some(info) = existing { *info.refcount_mut() = info.refcount().saturating_sub(1); @@ -1574,7 +1611,7 @@ where }); } - fn lock_delegate_dependency(&mut self, code_hash: CodeHash<Self::T>) -> DispatchResult { + fn lock_delegate_dependency(&mut self, code_hash: H256) -> DispatchResult { let frame = self.top_frame_mut(); let info = frame.contract_info.get(&frame.account_id); ensure!(code_hash != info.code_hash, Error::<T>::CannotAddSelfAsDelegateDependency); @@ -1590,7 +1627,7 @@ where Ok(()) } - fn unlock_delegate_dependency(&mut self, code_hash: &CodeHash<Self::T>) -> DispatchResult { + fn unlock_delegate_dependency(&mut self, code_hash: &H256) -> DispatchResult { let frame = self.top_frame_mut(); let info = frame.contract_info.get(&frame.account_id); @@ -1635,10 +1672,9 @@ mod tests { test_utils::{get_balance, place_contract, set_balance}, ExtBuilder, RuntimeCall, RuntimeEvent as MetaEvent, Test, TestFilter, }, - Error, + AddressMapper, Error, }; use assert_matches::assert_matches; - use codec::{Decode, Encode}; use frame_support::{assert_err, assert_ok, parameter_types}; use frame_system::{EventRecord, Phase}; use pallet_revive_uapi::ReturnFlags; @@ -1673,25 +1709,25 @@ mod tests { struct MockExecutable { func: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>, func_type: ExportedFunction, - code_hash: CodeHash<Test>, + code_hash: H256, code_info: CodeInfo<Test>, } #[derive(Default, Clone)] pub struct MockLoader { - map: HashMap<CodeHash<Test>, MockExecutable>, + map: HashMap<H256, MockExecutable>, counter: u64, } impl MockLoader { - fn code_hashes() -> Vec<CodeHash<Test>> { + fn code_hashes() -> Vec<H256> { Loader::get().map.keys().copied().collect() } fn insert( func_type: ExportedFunction, f: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static, - ) -> CodeHash<Test> { + ) -> H256 { Loader::mutate(|loader| { // Generate code hashes as monotonically increasing values. let hash = <Test as frame_system::Config>::Hash::from_low_u64_be(loader.counter); @@ -1712,7 +1748,7 @@ mod tests { impl Executable<Test> for MockExecutable { fn from_storage( - code_hash: CodeHash<Test>, + code_hash: H256, _gas_meter: &mut GasMeter<Test>, ) -> Result<Self, DispatchError> { Loader::mutate(|loader| { @@ -1746,7 +1782,12 @@ mod tests { } } - fn code_hash(&self) -> &CodeHash<Test> { + fn code(&self) -> &[u8] { + // The mock executable doesn't have code", so we return the code hash. + self.code_hash.as_ref() + } + + fn code_hash(&self) -> &H256 { &self.code_hash } @@ -1784,7 +1825,7 @@ mod tests { assert_matches!( MockStack::run_call( Origin::from_account_id(ALICE), - BOB, + BOB_ADDR, &mut gas_meter, &mut storage_meter, value, @@ -1802,24 +1843,19 @@ mod tests { fn transfer_works() { // This test verifies that a contract is able to transfer // some funds to another account. - let origin = ALICE; - let dest = BOB; - ExtBuilder::default().build().execute_with(|| { - set_balance(&origin, 100); - set_balance(&dest, 0); + set_balance(&ALICE, 100); + set_balance(&BOB, 0); - MockStack::transfer(Preservation::Preserve, &origin, &dest, 55).unwrap(); + MockStack::transfer(Preservation::Preserve, &ALICE, &BOB, 55).unwrap(); - assert_eq!(get_balance(&origin), 45); - assert_eq!(get_balance(&dest), 55); + assert_eq!(get_balance(&ALICE), 45); + assert_eq!(get_balance(&BOB), 55); }); } #[test] fn correct_transfer_on_call() { - let origin = ALICE; - let dest = BOB; let value = 55; let success_ch = MockLoader::insert(Call, move |ctx, _| { @@ -1828,15 +1864,15 @@ mod tests { }); ExtBuilder::default().build().execute_with(|| { - place_contract(&dest, success_ch); - set_balance(&origin, 100); - let balance = get_balance(&dest); - let contract_origin = Origin::from_account_id(origin.clone()); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, value).unwrap(); + place_contract(&BOB, success_ch); + set_balance(&ALICE, 100); + let balance = get_balance(&BOB_CONTRACT_ID); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, value).unwrap(); let _ = MockStack::run_call( - contract_origin.clone(), - dest.clone(), + origin.clone(), + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, value, @@ -1845,15 +1881,13 @@ mod tests { ) .unwrap(); - assert_eq!(get_balance(&origin), 100 - value); - assert_eq!(get_balance(&dest), balance + value); + assert_eq!(get_balance(&ALICE), 100 - value); + assert_eq!(get_balance(&BOB_CONTRACT_ID), balance + value); }); } #[test] fn correct_transfer_on_delegate_call() { - let origin = ALICE; - let dest = BOB; let value = 35; let success_ch = MockLoader::insert(Call, move |ctx, _| { @@ -1868,15 +1902,15 @@ mod tests { }); ExtBuilder::default().build().execute_with(|| { - place_contract(&dest, delegate_ch); - set_balance(&origin, 100); - let balance = get_balance(&dest); - let contract_origin = Origin::from_account_id(origin.clone()); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 55).unwrap(); + place_contract(&BOB, delegate_ch); + set_balance(&ALICE, 100); + let balance = get_balance(&BOB_CONTRACT_ID); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap(); let _ = MockStack::run_call( - contract_origin.clone(), - dest.clone(), + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, value, @@ -1885,8 +1919,8 @@ mod tests { ) .unwrap(); - assert_eq!(get_balance(&origin), 100 - value); - assert_eq!(get_balance(&dest), balance + value); + assert_eq!(get_balance(&ALICE), 100 - value); + assert_eq!(get_balance(&BOB_CONTRACT_ID), balance + value); }); } @@ -1894,23 +1928,21 @@ mod tests { fn changes_are_reverted_on_failing_call() { // This test verifies that changes are reverted on a call which fails (or equally, returns // a non-zero status code). - let origin = ALICE; - let dest = BOB; let return_ch = MockLoader::insert(Call, |_, _| { Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Vec::new() }) }); ExtBuilder::default().build().execute_with(|| { - place_contract(&dest, return_ch); - set_balance(&origin, 100); - let balance = get_balance(&dest); - let contract_origin = Origin::from_account_id(origin.clone()); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 55).unwrap(); + place_contract(&BOB, return_ch); + set_balance(&ALICE, 100); + let balance = get_balance(&BOB); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap(); let output = MockStack::run_call( - contract_origin.clone(), - dest.clone(), + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 55, @@ -1920,8 +1952,8 @@ mod tests { .unwrap(); assert!(output.did_revert()); - assert_eq!(get_balance(&origin), 100); - assert_eq!(get_balance(&dest), balance); + assert_eq!(get_balance(&ALICE), 100); + assert_eq!(get_balance(&BOB), balance); }); } @@ -1947,20 +1979,18 @@ mod tests { fn output_is_returned_on_success() { // Verifies that if a contract returns data with a successful exit status, this data // is returned from the execution context. - let origin = ALICE; - let dest = BOB; let return_ch = MockLoader::insert(Call, |_, _| { Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] }) }); ExtBuilder::default().build().execute_with(|| { - let contract_origin = Origin::from_account_id(origin); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); place_contract(&BOB, return_ch); let result = MockStack::run_call( - contract_origin, - dest, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -1978,20 +2008,18 @@ mod tests { fn output_is_returned_on_failure() { // Verifies that if a contract returns data with a failing exit status, this data // is returned from the execution context. - let origin = ALICE; - let dest = BOB; let return_ch = MockLoader::insert(Call, |_, _| { Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1, 2, 3, 4] }) }); ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, return_ch); - let contract_origin = Origin::from_account_id(origin); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - dest, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2015,12 +2043,12 @@ mod tests { // This one tests passing the input data into a contract via call. ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, input_data_ch); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2048,13 +2076,10 @@ mod tests { let executable = MockExecutable::from_storage(input_data_ch, &mut gas_meter).unwrap(); set_balance(&ALICE, min_balance * 10_000); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new( - &contract_origin, - deposit_limit::<Test>(), - min_balance, - ) - .unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance) + .unwrap(); let result = MockStack::run_instantiate( ALICE, @@ -2063,7 +2088,7 @@ mod tests { &mut storage_meter, min_balance, vec![1, 2, 3, 4], - &[], + &[0; 32], None, ); assert_matches!(result, Ok(_)); @@ -2083,7 +2108,7 @@ mod tests { let r = ctx.ext.call( Weight::zero(), BalanceOf::<Test>::zero(), - BOB, + &BOB_ADDR, 0, vec![], true, @@ -2108,12 +2133,12 @@ mod tests { ExtBuilder::default().build().execute_with(|| { set_balance(&BOB, 1); place_contract(&BOB, recurse_ch); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, value).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, value).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, value, @@ -2127,18 +2152,18 @@ mod tests { #[test] fn caller_returns_proper_values() { - let origin = ALICE; - let dest = BOB; - parameter_types! { - static WitnessedCallerBob: Option<AccountIdOf<Test>> = None; - static WitnessedCallerCharlie: Option<AccountIdOf<Test>> = None; + static WitnessedCallerBob: Option<H160> = None; + static WitnessedCallerCharlie: Option<H160> = None; } let bob_ch = MockLoader::insert(Call, |ctx, _| { // Record the caller for bob. WitnessedCallerBob::mutate(|caller| { - *caller = Some(ctx.ext.caller().account_id().unwrap().clone()) + let origin = ctx.ext.caller(); + *caller = Some(<Test as Config>::AddressMapper::to_address( + &origin.account_id().unwrap(), + )); }); // Call into CHARLIE contract. @@ -2146,7 +2171,7 @@ mod tests { ctx.ext.call( Weight::zero(), BalanceOf::<Test>::zero(), - CHARLIE, + &CHARLIE_ADDR, 0, vec![], true, @@ -2159,20 +2184,23 @@ mod tests { let charlie_ch = MockLoader::insert(Call, |ctx, _| { // Record the caller for charlie. WitnessedCallerCharlie::mutate(|caller| { - *caller = Some(ctx.ext.caller().account_id().unwrap().clone()) + let origin = ctx.ext.caller(); + *caller = Some(<Test as Config>::AddressMapper::to_address( + &origin.account_id().unwrap(), + )); }); exec_success() }); ExtBuilder::default().build().execute_with(|| { - place_contract(&dest, bob_ch); + place_contract(&BOB, bob_ch); place_contract(&CHARLIE, charlie_ch); - let contract_origin = Origin::from_account_id(origin.clone()); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin.clone(), - dest.clone(), + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2183,28 +2211,28 @@ mod tests { assert_matches!(result, Ok(_)); }); - assert_eq!(WitnessedCallerBob::get(), Some(origin)); - assert_eq!(WitnessedCallerCharlie::get(), Some(dest)); + assert_eq!(WitnessedCallerBob::get(), Some(ALICE_ADDR)); + assert_eq!(WitnessedCallerCharlie::get(), Some(BOB_ADDR)); } #[test] fn is_contract_returns_proper_values() { let bob_ch = MockLoader::insert(Call, |ctx, _| { // Verify that BOB is a contract - assert!(ctx.ext.is_contract(&BOB)); + assert!(ctx.ext.is_contract(&BOB_ADDR)); // Verify that ALICE is not a contract - assert!(!ctx.ext.is_contract(&ALICE)); + assert!(!ctx.ext.is_contract(&ALICE_ADDR)); exec_success() }); ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, bob_ch); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2219,20 +2247,20 @@ mod tests { fn code_hash_returns_proper_values() { let code_bob = MockLoader::insert(Call, |ctx, _| { // ALICE is not a contract and hence they do not have a code_hash - assert!(ctx.ext.code_hash(&ALICE).is_none()); + assert!(ctx.ext.code_hash(&ALICE_ADDR).is_none()); // BOB is a contract and hence it has a code_hash - assert!(ctx.ext.code_hash(&BOB).is_some()); + assert!(ctx.ext.code_hash(&BOB_ADDR).is_some()); exec_success() }); ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); // ALICE (not contract) -> BOB (contract) let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2246,19 +2274,19 @@ mod tests { #[test] fn own_code_hash_returns_proper_values() { let bob_ch = MockLoader::insert(Call, |ctx, _| { - let code_hash = ctx.ext.code_hash(&BOB).unwrap(); + let code_hash = ctx.ext.code_hash(&BOB_ADDR).unwrap(); assert_eq!(*ctx.ext.own_code_hash(), code_hash); exec_success() }); ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, bob_ch); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); // ALICE (not contract) -> BOB (contract) let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2281,19 +2309,26 @@ mod tests { // ALICE is the origin of the call stack assert!(ctx.ext.caller_is_origin()); // BOB calls CHARLIE - ctx.ext - .call(Weight::zero(), BalanceOf::<Test>::zero(), CHARLIE, 0, vec![], true, false) + ctx.ext.call( + Weight::zero(), + BalanceOf::<Test>::zero(), + &CHARLIE_ADDR, + 0, + vec![], + true, + false, + ) }); ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); // ALICE -> BOB (caller is origin) -> CHARLIE (caller is not origin) let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2314,12 +2349,12 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); - let contract_origin = Origin::Root; - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::Root; + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); // root -> BOB (caller is root) let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2340,12 +2375,12 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); - let contract_origin = Origin::Root; - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::Root; + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); // root -> BOB (caller is root) let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 1, @@ -2368,19 +2403,26 @@ mod tests { // root is the origin of the call stack. assert!(ctx.ext.caller_is_root()); // BOB calls CHARLIE. - ctx.ext - .call(Weight::zero(), BalanceOf::<Test>::zero(), CHARLIE, 0, vec![], true, false) + ctx.ext.call( + Weight::zero(), + BalanceOf::<Test>::zero(), + &CHARLIE_ADDR, + 0, + vec![], + true, + false, + ) }); ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); - let contract_origin = Origin::Root; - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::Root; + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); // root -> BOB (caller is root) -> CHARLIE (caller is not root) let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2395,14 +2437,14 @@ mod tests { fn address_returns_proper_values() { let bob_ch = MockLoader::insert(Call, |ctx, _| { // Verify that address matches BOB. - assert_eq!(*ctx.ext.address(), BOB); + assert_eq!(ctx.ext.address(), BOB_ADDR); // Call into charlie contract. assert_matches!( ctx.ext.call( Weight::zero(), BalanceOf::<Test>::zero(), - CHARLIE, + &CHARLIE_ADDR, 0, vec![], true, @@ -2413,19 +2455,19 @@ mod tests { exec_success() }); let charlie_ch = MockLoader::insert(Call, |ctx, _| { - assert_eq!(*ctx.ext.address(), CHARLIE); + assert_eq!(ctx.ext.address(), CHARLIE_ADDR); exec_success() }); ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, bob_ch); place_contract(&CHARLIE, charlie_ch); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2444,8 +2486,8 @@ mod tests { ExtBuilder::default().existential_deposit(15).build().execute_with(|| { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap(); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); assert_matches!( MockStack::run_instantiate( @@ -2455,7 +2497,7 @@ mod tests { &mut storage_meter, 0, // <- zero value vec![], - &[], + &[0; 32], None, ), Err(_) @@ -2478,10 +2520,9 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap(); set_balance(&ALICE, min_balance * 1000); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, min_balance * 100, min_balance) - .unwrap(); + storage::meter::Meter::new(&origin, min_balance * 100, min_balance).unwrap(); let instantiated_contract_address = assert_matches!( MockStack::run_instantiate( @@ -2492,22 +2533,26 @@ mod tests { min_balance, vec![], - &[], + &[0;32], None, ), Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address ); + let instantiated_contract_id = + <Test as Config>::AddressMapper::to_account_id_contract( + &instantiated_contract_address, + ); // Check that the newly created account has the expected code hash and // there are instantiation event. assert_eq!( - ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(), + ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).unwrap(), dummy_ch ); assert_eq!( &events(), &[Event::Instantiated { - deployer: ALICE, + deployer: ALICE_ADDR, contract: instantiated_contract_address }] ); @@ -2529,10 +2574,9 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap(); set_balance(&ALICE, min_balance * 1000); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, min_balance * 100, min_balance) - .unwrap(); + storage::meter::Meter::new(&origin, min_balance * 100, min_balance).unwrap(); let instantiated_contract_address = assert_matches!( MockStack::run_instantiate( @@ -2543,16 +2587,19 @@ mod tests { min_balance, vec![], - &[], + &[0;32], None, ), Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address ); + let instantiated_contract_id = + <Test as Config>::AddressMapper::to_account_id_contract( + &instantiated_contract_address, + ); + // Check that the account has not been created. - assert!( - ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).is_none() - ); + assert!(ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).is_none()); assert!(events().is_empty()); }); } @@ -2560,7 +2607,7 @@ mod tests { #[test] fn instantiation_from_contract() { let dummy_ch = MockLoader::insert(Call, |_, _| exec_success()); - let instantiated_contract_address = Rc::new(RefCell::new(None::<AccountIdOf<Test>>)); + let instantiated_contract_address = Rc::new(RefCell::new(None::<H160>)); let instantiator_ch = MockLoader::insert(Call, { let instantiated_contract_address = Rc::clone(&instantiated_contract_address); move |ctx, _| { @@ -2573,11 +2620,11 @@ mod tests { dummy_ch, <Test as Config>::Currency::minimum_balance(), vec![], - &[48, 49, 50], + &[48; 32], ) .unwrap(); - *instantiated_contract_address.borrow_mut() = address.into(); + *instantiated_contract_address.borrow_mut() = Some(address); Ok(output) } }); @@ -2590,18 +2637,15 @@ mod tests { let min_balance = <Test as Config>::Currency::minimum_balance(); set_balance(&ALICE, min_balance * 100); place_contract(&BOB, instantiator_ch); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new( - &contract_origin, - min_balance * 10, - min_balance * 10, - ) - .unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = + storage::meter::Meter::new(&origin, min_balance * 10, min_balance * 10) + .unwrap(); assert_matches!( MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, min_balance * 10, @@ -2612,22 +2656,30 @@ mod tests { ); let instantiated_contract_address = - instantiated_contract_address.borrow().as_ref().unwrap().clone(); + *instantiated_contract_address.borrow().as_ref().unwrap(); + + let instantiated_contract_id = + <Test as Config>::AddressMapper::to_account_id_contract( + &instantiated_contract_address, + ); // Check that the newly created account has the expected code hash and // there are instantiation event. assert_eq!( - ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(), + ContractInfo::<Test>::load_code_hash(&instantiated_contract_id).unwrap(), dummy_ch ); assert_eq!( &events(), &[ Event::Instantiated { - deployer: BOB, + deployer: BOB_ADDR, contract: instantiated_contract_address }, - Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB }, + Event::Called { + caller: Origin::from_account_id(ALICE), + contract: BOB_ADDR + }, ] ); }); @@ -2646,7 +2698,7 @@ mod tests { dummy_ch, <Test as Config>::Currency::minimum_balance(), vec![], - &[], + &[0; 32], ), Err(ExecError { error: DispatchError::Other("It's a trap!"), @@ -2664,16 +2716,15 @@ mod tests { .build() .execute_with(|| { set_balance(&ALICE, 1000); - set_balance(&BOB, 100); + set_balance(&BOB_CONTRACT_ID, 100); place_contract(&BOB, instantiator_ch); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = - storage::meter::Meter::new(&contract_origin, 200, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap(); assert_matches!( MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2687,7 +2738,7 @@ mod tests { // event here. assert_eq!( &events(), - &[Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },] + &[Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB_ADDR },] ); }); } @@ -2695,7 +2746,7 @@ mod tests { #[test] fn termination_from_instantiate_fails() { let terminate_ch = MockLoader::insert(Constructor, |ctx, _| { - ctx.ext.terminate(&ALICE).unwrap(); + ctx.ext.terminate(&ALICE_ADDR).unwrap(); exec_success() }); @@ -2708,10 +2759,9 @@ mod tests { let executable = MockExecutable::from_storage(terminate_ch, &mut gas_meter).unwrap(); set_balance(&ALICE, 10_000); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, deposit_limit::<Test>(), 100) - .unwrap(); + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 100).unwrap(); assert_eq!( MockStack::run_instantiate( @@ -2721,7 +2771,7 @@ mod tests { &mut storage_meter, 100, vec![], - &[], + &[0; 32], None, ), Err(Error::<Test>::TerminatedInConstructor.into()) @@ -2750,7 +2800,7 @@ mod tests { ctx.ext.call( Weight::zero(), BalanceOf::<Test>::zero(), - CHARLIE, + &CHARLIE_ADDR, 0, vec![], true, @@ -2765,7 +2815,15 @@ mod tests { let code_charlie = MockLoader::insert(Call, |ctx, _| { assert!(ctx .ext - .call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false) + .call( + Weight::zero(), + BalanceOf::<Test>::zero(), + &BOB_ADDR, + 0, + vec![99], + true, + false + ) .is_ok()); exec_trapped() }); @@ -2774,12 +2832,12 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -2793,10 +2851,13 @@ mod tests { #[test] fn recursive_call_during_constructor_fails() { let code = MockLoader::insert(Constructor, |ctx, _| { + let account_id = ctx.ext.account_id().clone(); + let addr = <Test as Config>::AddressMapper::to_address(&account_id); + assert_matches!( - ctx.ext.call(Weight::zero(), BalanceOf::<Test>::zero(), ctx.ext.address().clone(), 0, vec![], true, false), - Err(ExecError{error, ..}) if error == <Error<Test>>::ContractNotFound.into() - ); + ctx.ext.call(Weight::zero(), BalanceOf::<Test>::zero(), &addr, 0, vec![], + true, false), Err(ExecError{error, ..}) if error == <Error<Test>>::ContractNotFound.into() + ); exec_success() }); @@ -2809,13 +2870,10 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); let executable = MockExecutable::from_storage(code, &mut gas_meter).unwrap(); set_balance(&ALICE, min_balance * 10_000); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new( - &contract_origin, - deposit_limit::<Test>(), - min_balance, - ) - .unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance) + .unwrap(); let result = MockStack::run_instantiate( ALICE, @@ -2824,7 +2882,7 @@ mod tests { &mut storage_meter, min_balance, vec![], - &[], + &[0; 32], None, ); assert_matches!(result, Ok(_)); @@ -2847,11 +2905,11 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -2880,11 +2938,11 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -2913,11 +2971,11 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -2933,9 +2991,9 @@ mod tests { fn call_reentry_direct_recursion() { // call the contract passed as input with disabled reentry let code_bob = MockLoader::insert(Call, |ctx, _| { - let dest = Decode::decode(&mut ctx.input_data.as_ref()).unwrap(); + let dest = H160::from_slice(ctx.input_data.as_ref()); ctx.ext - .call(Weight::zero(), BalanceOf::<Test>::zero(), dest, 0, vec![], false, false) + .call(Weight::zero(), BalanceOf::<Test>::zero(), &dest, 0, vec![], false, false) }); let code_charlie = MockLoader::insert(Call, |_, _| exec_success()); @@ -2943,29 +3001,29 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); // Calling another contract should succeed assert_ok!(MockStack::run_call( - contract_origin.clone(), - BOB, + origin.clone(), + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, - CHARLIE.encode(), + CHARLIE_ADDR.as_bytes().to_vec(), None, )); // Calling into oneself fails assert_err!( MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, - BOB.encode(), + BOB_ADDR.as_bytes().to_vec(), None, ) .map_err(|e| e.error), @@ -2981,7 +3039,7 @@ mod tests { ctx.ext.call( Weight::zero(), BalanceOf::<Test>::zero(), - CHARLIE, + &CHARLIE_ADDR, 0, vec![], false, @@ -2994,21 +3052,28 @@ mod tests { // call BOB with input set to '1' let code_charlie = MockLoader::insert(Call, |ctx, _| { - ctx.ext - .call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![1], true, false) + ctx.ext.call( + Weight::zero(), + BalanceOf::<Test>::zero(), + &BOB_ADDR, + 0, + vec![1], + true, + false, + ) }); ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); // BOB -> CHARLIE -> BOB fails as BOB denies reentry. assert_err!( MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -3037,12 +3102,12 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); System::reset_events(); MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -3058,7 +3123,7 @@ mod tests { EventRecord { phase: Phase::Initialization, event: MetaEvent::System(frame_system::Event::Remarked { - sender: BOB, + sender: BOB_CONTRACT_ID, hash: remark_hash }), topics: vec![], @@ -3067,7 +3132,7 @@ mod tests { phase: Phase::Initialization, event: MetaEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: BOB, + contract: BOB_ADDR, }), topics: vec![], }, @@ -3121,12 +3186,12 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); System::reset_events(); MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -3142,7 +3207,7 @@ mod tests { EventRecord { phase: Phase::Initialization, event: MetaEvent::System(frame_system::Event::Remarked { - sender: BOB, + sender: BOB_CONTRACT_ID, hash: remark_hash }), topics: vec![], @@ -3164,7 +3229,7 @@ mod tests { phase: Phase::Initialization, event: MetaEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: BOB, + contract: BOB_ADDR, }), topics: vec![], }, @@ -3185,16 +3250,16 @@ mod tests { fail_code, ctx.ext.minimum_balance() * 100, vec![], - &[], + &[0; 32], ) .ok(); exec_success() }); let succ_succ_code = MockLoader::insert(Constructor, move |ctx, _| { let alice_nonce = System::account_nonce(&ALICE); - assert_eq!(System::account_nonce(ctx.ext.address()), 0); + assert_eq!(System::account_nonce(ctx.ext.account_id()), 0); assert_eq!(ctx.ext.caller().account_id().unwrap(), &ALICE); - let (account_id, _) = ctx + let (addr, _) = ctx .ext .instantiate( Weight::zero(), @@ -3202,29 +3267,23 @@ mod tests { success_code, ctx.ext.minimum_balance() * 100, vec![], - &[], + &[0; 32], ) .unwrap(); + let account_id = <Test as Config>::AddressMapper::to_account_id_contract(&addr); + assert_eq!(System::account_nonce(&ALICE), alice_nonce); - assert_eq!(System::account_nonce(ctx.ext.address()), 1); + assert_eq!(System::account_nonce(ctx.ext.account_id()), 1); assert_eq!(System::account_nonce(&account_id), 0); // a plain call should not influence the account counter ctx.ext - .call( - Weight::zero(), - BalanceOf::<Test>::zero(), - account_id.clone(), - 0, - vec![], - false, - false, - ) + .call(Weight::zero(), BalanceOf::<Test>::zero(), &addr, 0, vec![], false, false) .unwrap(); assert_eq!(System::account_nonce(ALICE), alice_nonce); - assert_eq!(System::account_nonce(ctx.ext.address()), 1); + assert_eq!(System::account_nonce(ctx.ext.account_id()), 1); assert_eq!(System::account_nonce(&account_id), 0); exec_success() @@ -3246,13 +3305,10 @@ mod tests { MockExecutable::from_storage(succ_succ_code, &mut gas_meter).unwrap(); set_balance(&ALICE, min_balance * 10_000); set_balance(&BOB, min_balance * 10_000); - let contract_origin = Origin::from_account_id(BOB); - let mut storage_meter = storage::meter::Meter::new( - &contract_origin, - deposit_limit::<Test>(), - min_balance * 100, - ) - .unwrap(); + let origin = Origin::from_account_id(BOB); + let mut storage_meter = + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), min_balance * 100) + .unwrap(); // fail should not increment MockStack::run_instantiate( @@ -3262,7 +3318,7 @@ mod tests { &mut storage_meter, min_balance * 100, vec![], - &[], + &[0; 32], None, ) .ok(); @@ -3275,7 +3331,7 @@ mod tests { &mut storage_meter, min_balance * 100, vec![], - &[], + &[0; 32], None, )); assert_eq!(System::account_nonce(&ALICE), 1); @@ -3287,7 +3343,7 @@ mod tests { &mut storage_meter, min_balance * 200, vec![], - &[], + &[0; 32], None, )); assert_eq!(System::account_nonce(&ALICE), 2); @@ -3299,7 +3355,7 @@ mod tests { &mut storage_meter, min_balance * 200, vec![], - &[], + &[0; 32], None, )); assert_eq!(System::account_nonce(&ALICE), 3); @@ -3358,12 +3414,12 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 1000); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, deposit_limit::<Test>(), 0).unwrap(); + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap(); assert_ok!(MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -3469,12 +3525,12 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 1000); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, deposit_limit::<Test>(), 0).unwrap(); + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap(); assert_ok!(MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -3508,12 +3564,12 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 1000); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, deposit_limit::<Test>(), 0).unwrap(); + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap(); assert_ok!(MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -3547,12 +3603,12 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 1000); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, deposit_limit::<Test>(), 0).unwrap(); + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap(); assert_ok!(MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -3600,12 +3656,12 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 1000); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, deposit_limit::<Test>(), 0).unwrap(); + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap(); assert_ok!(MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -3656,12 +3712,12 @@ mod tests { let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 1000); place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, deposit_limit::<Test>(), 0).unwrap(); + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap(); assert_ok!(MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut gas_meter, &mut storage_meter, 0, @@ -3731,12 +3787,12 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); + let origin = Origin::from_account_id(ALICE); let mut storage_meter = - storage::meter::Meter::new(&contract_origin, deposit_limit::<Test>(), 0).unwrap(); + storage::meter::Meter::new(&origin, deposit_limit::<Test>(), 0).unwrap(); assert_ok!(MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -3762,7 +3818,7 @@ mod tests { ctx.ext.call( Weight::zero(), BalanceOf::<Test>::zero(), - CHARLIE, + &CHARLIE_ADDR, 0, vec![], true, @@ -3788,7 +3844,15 @@ mod tests { let code_charlie = MockLoader::insert(Call, |ctx, _| { assert!(ctx .ext - .call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false) + .call( + Weight::zero(), + BalanceOf::<Test>::zero(), + &BOB_ADDR, + 0, + vec![99], + true, + false + ) .is_ok()); // CHARLIE can not read BOB`s storage. assert_eq!(ctx.ext.get_transient_storage(storage_key_1), None); @@ -3799,12 +3863,12 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -3838,11 +3902,11 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_hash); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); assert_ok!(MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -3866,7 +3930,7 @@ mod tests { ctx.ext.call( Weight::zero(), BalanceOf::<Test>::zero(), - CHARLIE, + &CHARLIE_ADDR, 0, vec![], true, @@ -3888,7 +3952,15 @@ mod tests { let code_charlie = MockLoader::insert(Call, |ctx, _| { assert!(ctx .ext - .call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false) + .call( + Weight::zero(), + BalanceOf::<Test>::zero(), + &BOB_ADDR, + 0, + vec![99], + true, + false + ) .is_ok()); exec_trapped() }); @@ -3897,12 +3969,12 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, @@ -3931,11 +4003,11 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, bob_ch); - let contract_origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(&contract_origin, 0, 0).unwrap(); + let origin = Origin::from_account_id(ALICE); + let mut storage_meter = storage::meter::Meter::new(&origin, 0, 0).unwrap(); let result = MockStack::run_call( - contract_origin, - BOB, + origin, + BOB_ADDR, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, 0, diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 303c649bc8c..359434b9abd 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -70,13 +70,14 @@ use frame_system::{ EventRecord, Pallet as System, }; use scale_info::TypeInfo; +use sp_core::{H160, H256}; use sp_runtime::{ - traits::{BadOrigin, Convert, Dispatchable, Saturating, StaticLookup}, + traits::{BadOrigin, Convert, Dispatchable, Saturating}, DispatchError, }; pub use crate::{ - address::{AddressGenerator, DefaultAddressGenerator}, + address::{AddressMapper, DefaultAddressMapper}, debug::Tracing, migration::{MigrateSequence, Migration, NoopMigration}, pallet::*, @@ -86,12 +87,10 @@ pub use weights::WeightInfo; #[cfg(doc)] pub use crate::wasm::SyscallDoc; -type CodeHash<T> = <T as frame_system::Config>::Hash; type TrieId = BoundedVec<u8, ConstU32<128>>; type BalanceOf<T> = <<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance; type CodeVec<T> = BoundedVec<u8, <T as Config>::MaxCodeLen>; -type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source; type EventRecordOf<T> = EventRecord<<T as frame_system::Config>::RuntimeEvent, <T as frame_system::Config>::Hash>; type DebugBuffer = BoundedVec<u8, ConstU32<{ limits::DEBUG_BUFFER_BYTES }>>; @@ -228,9 +227,9 @@ pub mod pallet { #[pallet::constant] type CodeHashLockupDepositPercent: Get<Perbill>; - /// The address generator used to generate the addresses of contracts. + /// Only valid type is [`DefaultAddressMapper`]. #[pallet::no_default_bounds] - type AddressGenerator: AddressGenerator<Self>; + type AddressMapper: AddressMapper<AccountIdOf<Self>>; /// The maximum length of a contract code in bytes. /// @@ -376,8 +375,7 @@ pub mod pallet { #[inject_runtime_type] type RuntimeCall = (); - - type AddressGenerator = DefaultAddressGenerator; + type AddressMapper = DefaultAddressMapper; type CallFilter = (); type ChainExtension = (); type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; @@ -401,7 +399,7 @@ pub mod pallet { #[pallet::event] pub enum Event<T: Config> { /// Contract deployed by address at the specified address. - Instantiated { deployer: T::AccountId, contract: T::AccountId }, + Instantiated { deployer: H160, contract: H160 }, /// Contract has been removed. /// @@ -411,34 +409,34 @@ pub mod pallet { /// `seal_terminate`. Terminated { /// The contract that was terminated. - contract: T::AccountId, + contract: H160, /// The account that received the contracts remaining balance - beneficiary: T::AccountId, + beneficiary: H160, }, /// Code with the specified hash has been stored. - CodeStored { code_hash: T::Hash, deposit_held: BalanceOf<T>, uploader: T::AccountId }, + CodeStored { code_hash: H256, deposit_held: BalanceOf<T>, uploader: H160 }, /// A custom event emitted by the contract. ContractEmitted { /// The contract that emitted the event. - contract: T::AccountId, + contract: H160, /// Data supplied by the contract. Metadata generated during contract compilation /// is needed to decode it. data: Vec<u8>, }, /// A code with the specified hash was removed. - CodeRemoved { code_hash: T::Hash, deposit_released: BalanceOf<T>, remover: T::AccountId }, + CodeRemoved { code_hash: H256, deposit_released: BalanceOf<T>, remover: H160 }, /// A contract's code was updated. ContractCodeUpdated { /// The contract that has been updated. - contract: T::AccountId, + contract: H160, /// New code hash that was set for the contract. - new_code_hash: T::Hash, + new_code_hash: H256, /// Previous code hash of the contract. - old_code_hash: T::Hash, + old_code_hash: H256, }, /// A contract was called either by a plain account or another contract. @@ -452,7 +450,7 @@ pub mod pallet { /// The caller of the `contract`. caller: Origin<T>, /// The contract that was called. - contract: T::AccountId, + contract: H160, }, /// A contract delegate called a code hash. @@ -465,24 +463,16 @@ pub mod pallet { DelegateCalled { /// The contract that performed the delegate call and hence in whose context /// the `code_hash` is executed. - contract: T::AccountId, + contract: H160, /// The code hash that was delegate called. - code_hash: CodeHash<T>, + code_hash: H256, }, /// Some funds have been transferred and held as storage deposit. - StorageDepositTransferredAndHeld { - from: T::AccountId, - to: T::AccountId, - amount: BalanceOf<T>, - }, + StorageDepositTransferredAndHeld { from: H160, to: H160, amount: BalanceOf<T> }, /// Some storage deposit funds have been transferred and released. - StorageDepositTransferredAndReleased { - from: T::AccountId, - to: T::AccountId, - amount: BalanceOf<T>, - }, + StorageDepositTransferredAndReleased { from: H160, to: H160, amount: BalanceOf<T> }, } #[pallet::error] @@ -592,16 +582,15 @@ pub mod pallet { /// A mapping from a contract's code hash to its code. #[pallet::storage] - pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, CodeHash<T>, CodeVec<T>>; + pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, H256, CodeVec<T>>; /// A mapping from a contract's code hash to its code info. #[pallet::storage] - pub(crate) type CodeInfoOf<T: Config> = StorageMap<_, Identity, CodeHash<T>, CodeInfo<T>>; + pub(crate) type CodeInfoOf<T: Config> = StorageMap<_, Identity, H256, CodeInfo<T>>; /// The code associated with a given account. #[pallet::storage] - pub(crate) type ContractInfoOf<T: Config> = - StorageMap<_, Identity, T::AccountId, ContractInfo<T>>; + pub(crate) type ContractInfoOf<T: Config> = StorageMap<_, Identity, H160, ContractInfo<T>>; /// Evicted contracts that await child trie deletion. /// @@ -804,13 +793,12 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::call().saturating_add(*gas_limit))] pub fn call( origin: OriginFor<T>, - dest: AccountIdLookupOf<T>, + dest: H160, #[pallet::compact] value: BalanceOf<T>, gas_limit: Weight, #[pallet::compact] storage_deposit_limit: BalanceOf<T>, data: Vec<u8>, ) -> DispatchResultWithPostInfo { - let dest = T::Lookup::lookup(dest)?; let mut output = Self::bare_call( origin, dest, @@ -843,9 +831,9 @@ pub mod pallet { #[pallet::compact] value: BalanceOf<T>, gas_limit: Weight, #[pallet::compact] storage_deposit_limit: BalanceOf<T>, - code_hash: CodeHash<T>, + code_hash: sp_core::H256, data: Vec<u8>, - salt: Vec<u8>, + salt: [u8; 32], ) -> DispatchResultWithPostInfo { let data_len = data.len() as u32; let salt_len = salt.len() as u32; @@ -887,7 +875,7 @@ pub mod pallet { /// from the caller to pay for the storage consumed. /// * `code`: The contract code to deploy in raw bytes. /// * `data`: The input data to pass to the contract constructor. - /// * `salt`: Used for the address derivation. See [`Pallet::contract_address`]. + /// * `salt`: Used for the address derivation. See [`crate::address::create2`]. /// /// Instantiation is executed as follows: /// @@ -909,7 +897,7 @@ pub mod pallet { #[pallet::compact] storage_deposit_limit: BalanceOf<T>, code: Vec<u8>, data: Vec<u8>, - salt: Vec<u8>, + salt: [u8; 32], ) -> DispatchResultWithPostInfo { let code_len = code.len() as u32; let data_len = data.len() as u32; @@ -967,7 +955,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::remove_code())] pub fn remove_code( origin: OriginFor<T>, - code_hash: CodeHash<T>, + code_hash: sp_core::H256, ) -> DispatchResultWithPostInfo { Migration::<T>::ensure_migrated()?; let origin = ensure_signed(origin)?; @@ -990,12 +978,11 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_code())] pub fn set_code( origin: OriginFor<T>, - dest: AccountIdLookupOf<T>, - code_hash: CodeHash<T>, + dest: H160, + code_hash: sp_core::H256, ) -> DispatchResult { Migration::<T>::ensure_migrated()?; ensure_root(origin)?; - let dest = T::Lookup::lookup(dest)?; <ContractInfoOf<T>>::try_mutate(&dest, |contract| { let contract = if let Some(contract) = contract { contract @@ -1005,7 +992,7 @@ pub mod pallet { <ExecStack<T, WasmBlob<T>>>::increment_refcount(code_hash)?; <ExecStack<T, WasmBlob<T>>>::decrement_refcount(contract.code_hash); Self::deposit_event(Event::ContractCodeUpdated { - contract: dest.clone(), + contract: dest, new_code_hash: code_hash, old_code_hash: contract.code_hash, }); @@ -1075,7 +1062,7 @@ impl<T: Config> Pallet<T> { /// collection). pub fn bare_call( origin: OriginFor<T>, - dest: T::AccountId, + dest: H160, value: BalanceOf<T>, gas_limit: Weight, storage_deposit_limit: BalanceOf<T>, @@ -1133,12 +1120,12 @@ impl<T: Config> Pallet<T> { value: BalanceOf<T>, gas_limit: Weight, mut storage_deposit_limit: BalanceOf<T>, - code: Code<CodeHash<T>>, + code: Code, data: Vec<u8>, - salt: Vec<u8>, + salt: [u8; 32], debug: DebugInfo, collect_events: CollectEvents, - ) -> ContractInstantiateResult<T::AccountId, BalanceOf<T>, EventRecordOf<T>> { + ) -> ContractInstantiateResult<BalanceOf<T>, EventRecordOf<T>> { let mut gas_meter = GasMeter::new(gas_limit); let mut storage_deposit = Default::default(); let mut debug_message = @@ -1187,7 +1174,7 @@ impl<T: Config> Pallet<T> { }; ContractInstantiateResult { result: output - .map(|(account_id, result)| InstantiateReturnValue { result, account_id }) + .map(|(addr, result)| InstantiateReturnValue { result, addr }) .map_err(|e| e.error), gas_consumed: gas_meter.gas_consumed(), gas_required: gas_meter.gas_required(), @@ -1204,7 +1191,7 @@ impl<T: Config> Pallet<T> { origin: OriginFor<T>, code: Vec<u8>, storage_deposit_limit: BalanceOf<T>, - ) -> CodeUploadResult<CodeHash<T>, BalanceOf<T>> { + ) -> CodeUploadResult<BalanceOf<T>> { Migration::<T>::ensure_migrated()?; let origin = T::UploadOrigin::ensure_origin(origin)?; let (module, deposit) = Self::try_upload_code(origin, code, storage_deposit_limit, None)?; @@ -1212,34 +1199,17 @@ impl<T: Config> Pallet<T> { } /// Query storage of a specified contract under a specified key. - pub fn get_storage(address: T::AccountId, key: Vec<u8>) -> GetStorageResult { + pub fn get_storage(address: H160, key: [u8; 32]) -> GetStorageResult { if Migration::<T>::in_progress() { return Err(ContractAccessError::MigrationInProgress) } let contract_info = ContractInfoOf::<T>::get(&address).ok_or(ContractAccessError::DoesntExist)?; - let maybe_value = contract_info.read( - &Key::try_from_var(key) - .map_err(|_| ContractAccessError::KeyDecodingFailed)? - .into(), - ); + let maybe_value = contract_info.read(&Key::from_fixed(key)); Ok(maybe_value) } - /// Determine the address of a contract. - /// - /// This is the address generation function used by contract instantiation. See - /// [`DefaultAddressGenerator`] for the default implementation. - pub fn contract_address( - deploying_address: &T::AccountId, - code_hash: &CodeHash<T>, - input_data: &[u8], - salt: &[u8], - ) -> T::AccountId { - T::AddressGenerator::contract_address(deploying_address, code_hash, input_data, salt) - } - /// Uploads new code and returns the Wasm blob and deposit amount collected. fn try_upload_code( origin: T::AccountId, @@ -1300,11 +1270,10 @@ environmental!(executing_contract: bool); sp_api::decl_runtime_apis! { /// The API used to dry-run contract interactions. #[api_version(1)] - pub trait ReviveApi<AccountId, Balance, BlockNumber, Hash, EventRecord> where + pub trait ReviveApi<AccountId, Balance, BlockNumber, EventRecord> where AccountId: Codec, Balance: Codec, BlockNumber: Codec, - Hash: Codec, EventRecord: Codec, { /// Perform a call from a specified account to a given contract. @@ -1312,7 +1281,7 @@ sp_api::decl_runtime_apis! { /// See [`crate::Pallet::bare_call`]. fn call( origin: AccountId, - dest: AccountId, + dest: H160, value: Balance, gas_limit: Option<Weight>, storage_deposit_limit: Option<Balance>, @@ -1327,10 +1296,10 @@ sp_api::decl_runtime_apis! { value: Balance, gas_limit: Option<Weight>, storage_deposit_limit: Option<Balance>, - code: Code<Hash>, + code: Code, data: Vec<u8>, - salt: Vec<u8>, - ) -> ContractInstantiateResult<AccountId, Balance, EventRecord>; + salt: [u8; 32], + ) -> ContractInstantiateResult<Balance, EventRecord>; /// Upload new code without instantiating a contract from it. /// @@ -1339,7 +1308,7 @@ sp_api::decl_runtime_apis! { origin: AccountId, code: Vec<u8>, storage_deposit_limit: Option<Balance>, - ) -> CodeUploadResult<Hash, Balance>; + ) -> CodeUploadResult<Balance>; /// Query a given storage key in a given contract. /// @@ -1347,8 +1316,8 @@ sp_api::decl_runtime_apis! { /// specified account and `Ok(None)` if it doesn't. If the account specified by the address /// doesn't exist, or doesn't have a contract then `Err` is returned. fn get_storage( - address: AccountId, - key: Vec<u8>, + address: H160, + key: [u8; 32], ) -> GetStorageResult; } } diff --git a/substrate/frame/revive/src/primitives.rs b/substrate/frame/revive/src/primitives.rs index a4a1133b710..98e8879457b 100644 --- a/substrate/frame/revive/src/primitives.rs +++ b/substrate/frame/revive/src/primitives.rs @@ -17,6 +17,7 @@ //! A crate that hosts a common definitions that are relevant for the pallet-revive. +use crate::H160; use alloc::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::weights::Weight; @@ -86,12 +87,11 @@ pub type ContractExecResult<Balance, EventRecord> = ContractResult<Result<ExecReturnValue, DispatchError>, Balance, EventRecord>; /// Result type of a `bare_instantiate` call as well as `ContractsApi::instantiate`. -pub type ContractInstantiateResult<AccountId, Balance, EventRecord> = - ContractResult<Result<InstantiateReturnValue<AccountId>, DispatchError>, Balance, EventRecord>; +pub type ContractInstantiateResult<Balance, EventRecord> = + ContractResult<Result<InstantiateReturnValue, DispatchError>, Balance, EventRecord>; /// Result type of a `bare_code_upload` call. -pub type CodeUploadResult<CodeHash, Balance> = - Result<CodeUploadReturnValue<CodeHash, Balance>, DispatchError>; +pub type CodeUploadResult<Balance> = Result<CodeUploadReturnValue<Balance>, DispatchError>; /// Result type of a `get_storage` call. pub type GetStorageResult = Result<Option<Vec<u8>>, ContractAccessError>; @@ -125,29 +125,29 @@ impl ExecReturnValue { /// The result of a successful contract instantiation. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct InstantiateReturnValue<AccountId> { +pub struct InstantiateReturnValue { /// The output of the called constructor. pub result: ExecReturnValue, - /// The account id of the new contract. - pub account_id: AccountId, + /// The address of the new contract. + pub addr: H160, } /// The result of successfully uploading a contract. #[derive(Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)] -pub struct CodeUploadReturnValue<CodeHash, Balance> { +pub struct CodeUploadReturnValue<Balance> { /// The key under which the new code is stored. - pub code_hash: CodeHash, + pub code_hash: sp_core::H256, /// The deposit that was reserved at the caller. Is zero when the code already existed. pub deposit: Balance, } /// Reference to an existing code hash or a new wasm module. #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub enum Code<Hash> { +pub enum Code { /// A wasm module as raw bytes. Upload(Vec<u8>), /// The code hash of an on-chain wasm blob. - Existing(Hash), + Existing(sp_core::H256), } /// The amount of balance that was either charged or refunded in order to pay for storage. diff --git a/substrate/frame/revive/src/storage.rs b/substrate/frame/revive/src/storage.rs index 87274ce407f..91b7b904d2b 100644 --- a/substrate/frame/revive/src/storage.rs +++ b/substrate/frame/revive/src/storage.rs @@ -20,12 +20,13 @@ pub mod meter; use crate::{ + address::AddressMapper, exec::{AccountIdOf, Key}, limits, storage::meter::Diff, weights::WeightInfo, - BalanceOf, CodeHash, CodeInfo, Config, ContractInfoOf, DeletionQueue, DeletionQueueCounter, - Error, TrieId, SENTINEL, + BalanceOf, CodeInfo, Config, ContractInfoOf, DeletionQueue, DeletionQueueCounter, Error, + TrieId, SENTINEL, }; use alloc::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; @@ -36,7 +37,7 @@ use frame_support::{ CloneNoBound, DefaultNoBound, }; use scale_info::TypeInfo; -use sp_core::{ConstU32, Get}; +use sp_core::{ConstU32, Get, H160}; use sp_io::KillStorageResult; use sp_runtime::{ traits::{Hash, Saturating, Zero}, @@ -44,7 +45,7 @@ use sp_runtime::{ }; type DelegateDependencyMap<T> = - BoundedBTreeMap<CodeHash<T>, BalanceOf<T>, ConstU32<{ limits::DELEGATE_DEPENDENCIES }>>; + BoundedBTreeMap<sp_core::H256, BalanceOf<T>, ConstU32<{ limits::DELEGATE_DEPENDENCIES }>>; /// Information for managing an account and its sub trie abstraction. /// This is the required info to cache for an account. @@ -54,7 +55,7 @@ pub struct ContractInfo<T: Config> { /// Unique ID for the subtree encoded as a bytes vector. pub trie_id: TrieId, /// The code associated with a given account. - pub code_hash: CodeHash<T>, + pub code_hash: sp_core::H256, /// How many bytes of storage are accumulated in this contract's child trie. storage_bytes: u32, /// How many items of storage are accumulated in this contract's child trie. @@ -82,9 +83,9 @@ impl<T: Config> ContractInfo<T> { /// This returns an `Err` if an contract with the supplied `account` already exists /// in storage. pub fn new( - account: &AccountIdOf<T>, + account: &H160, nonce: T::Nonce, - code_hash: CodeHash<T>, + code_hash: sp_core::H256, ) -> Result<Self, DispatchError> { if <ContractInfoOf<T>>::contains_key(account) { return Err(Error::<T>::DuplicateContract.into()) @@ -259,7 +260,7 @@ impl<T: Config> ContractInfo<T> { /// the delegate dependency already exists. pub fn lock_delegate_dependency( &mut self, - code_hash: CodeHash<T>, + code_hash: sp_core::H256, amount: BalanceOf<T>, ) -> DispatchResult { self.delegate_dependencies @@ -275,7 +276,7 @@ impl<T: Config> ContractInfo<T> { /// Returns an error if the entry doesn't exist. pub fn unlock_delegate_dependency( &mut self, - code_hash: &CodeHash<T>, + code_hash: &sp_core::H256, ) -> Result<BalanceOf<T>, DispatchError> { self.delegate_dependencies .remove(code_hash) @@ -352,8 +353,8 @@ impl<T: Config> ContractInfo<T> { } /// Returns the code hash of the contract specified by `account` ID. - pub fn load_code_hash(account: &AccountIdOf<T>) -> Option<CodeHash<T>> { - <ContractInfoOf<T>>::get(account).map(|i| i.code_hash) + pub fn load_code_hash(account: &AccountIdOf<T>) -> Option<sp_core::H256> { + <ContractInfoOf<T>>::get(&T::AddressMapper::to_address(account)).map(|i| i.code_hash) } } diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 8735aa82342..f6ad4c5fc34 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -18,8 +18,8 @@ //! This module contains functions to meter the storage deposit. use crate::{ - storage::ContractInfo, AccountIdOf, BalanceOf, CodeInfo, Config, Error, Event, HoldReason, - Inspect, Origin, Pallet, StorageDeposit as Deposit, System, LOG_TARGET, + address::AddressMapper, storage::ContractInfo, AccountIdOf, BalanceOf, CodeInfo, Config, Error, + Event, HoldReason, Inspect, Origin, Pallet, StorageDeposit as Deposit, System, LOG_TARGET, }; use alloc::vec::Vec; @@ -537,8 +537,8 @@ impl<T: Config> Ext<T> for ReservingExt { )?; Pallet::<T>::deposit_event(Event::StorageDepositTransferredAndHeld { - from: origin.clone(), - to: contract.clone(), + from: T::AddressMapper::to_address(origin), + to: T::AddressMapper::to_address(contract), amount: *amount, }); }, @@ -554,8 +554,8 @@ impl<T: Config> Ext<T> for ReservingExt { )?; Pallet::<T>::deposit_event(Event::StorageDepositTransferredAndReleased { - from: contract.clone(), - to: origin.clone(), + from: T::AddressMapper::to_address(contract), + to: T::AddressMapper::to_address(origin), amount: transferred, }); diff --git a/substrate/frame/revive/src/test_utils.rs b/substrate/frame/revive/src/test_utils.rs index 2bfe754f86c..671efebdf4b 100644 --- a/substrate/frame/revive/src/test_utils.rs +++ b/substrate/frame/revive/src/test_utils.rs @@ -24,12 +24,40 @@ pub mod builder; use crate::{BalanceOf, Config}; use frame_support::weights::Weight; +use sp_core::H160; pub use sp_runtime::AccountId32; +const fn ee_suffix(addr: H160) -> AccountId32 { + let mut id = [0u8; 32]; + let mut i = 0; + while i < 20 { + id[i] = addr.0[i]; + i += 1; + } + + let mut j = 20; + while j < 32 { + id[j] = 0xee; + j += 1; + } + + AccountId32::new(id) +} + pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); +pub const ALICE_ADDR: H160 = H160([1u8; 20]); +pub const ETH_ALICE: AccountId32 = ee_suffix(ALICE_ADDR); + pub const BOB: AccountId32 = AccountId32::new([2u8; 32]); +pub const BOB_ADDR: H160 = H160([2u8; 20]); +pub const BOB_CONTRACT_ID: AccountId32 = ee_suffix(BOB_ADDR); + pub const CHARLIE: AccountId32 = AccountId32::new([3u8; 32]); +pub const CHARLIE_ADDR: H160 = H160([3u8; 20]); + pub const DJANGO: AccountId32 = AccountId32::new([4u8; 32]); +pub const DJANGO_ADDR: H160 = H160([4u8; 20]); +pub const ETH_DJANGO: AccountId32 = ee_suffix(DJANGO_ADDR); pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); diff --git a/substrate/frame/revive/src/test_utils/builder.rs b/substrate/frame/revive/src/test_utils/builder.rs index bf8cbcd5a01..76b4c98d4cb 100644 --- a/substrate/frame/revive/src/test_utils/builder.rs +++ b/substrate/frame/revive/src/test_utils/builder.rs @@ -17,7 +17,7 @@ use super::{deposit_limit, GAS_LIMIT}; use crate::{ - AccountIdLookupOf, AccountIdOf, BalanceOf, Code, CodeHash, CollectEvents, Config, + address::AddressMapper, AccountIdOf, BalanceOf, Code, CollectEvents, Config, ContractExecResult, ContractInstantiateResult, DebugInfo, EventRecordOf, ExecReturnValue, InstantiateReturnValue, OriginFor, Pallet, Weight, }; @@ -26,6 +26,7 @@ use core::fmt::Debug; use frame_support::pallet_prelude::DispatchResultWithPostInfo; use paste::paste; use scale_info::TypeInfo; +use sp_core::H160; /// Helper macro to generate a builder for contract API calls. macro_rules! builder { @@ -74,6 +75,11 @@ macro_rules! builder { } } +pub struct Contract<T: Config> { + pub account_id: AccountIdOf<T>, + pub addr: H160, +} + builder!( instantiate_with_code( origin: OriginFor<T>, @@ -82,7 +88,7 @@ builder!( storage_deposit_limit: BalanceOf<T>, code: Vec<u8>, data: Vec<u8>, - salt: Vec<u8>, + salt: [u8; 32], ) -> DispatchResultWithPostInfo; /// Create an [`InstantiateWithCodeBuilder`] with default values. @@ -94,7 +100,7 @@ builder!( storage_deposit_limit: deposit_limit::<T>(), code, data: vec![], - salt: vec![], + salt: [0; 32], } } ); @@ -105,13 +111,13 @@ builder!( value: BalanceOf<T>, gas_limit: Weight, storage_deposit_limit: BalanceOf<T>, - code_hash: CodeHash<T>, + code_hash: sp_core::H256, data: Vec<u8>, - salt: Vec<u8>, + salt: [u8; 32], ) -> DispatchResultWithPostInfo; /// Create an [`InstantiateBuilder`] with default values. - pub fn instantiate(origin: OriginFor<T>, code_hash: CodeHash<T>) -> Self { + pub fn instantiate(origin: OriginFor<T>, code_hash: sp_core::H256) -> Self { Self { origin, value: 0u32.into(), @@ -119,7 +125,7 @@ builder!( storage_deposit_limit: deposit_limit::<T>(), code_hash, data: vec![], - salt: vec![], + salt: [0; 32], } } ); @@ -130,24 +136,27 @@ builder!( value: BalanceOf<T>, gas_limit: Weight, storage_deposit_limit: BalanceOf<T>, - code: Code<CodeHash<T>>, + code: Code, data: Vec<u8>, - salt: Vec<u8>, + salt: [u8; 32], debug: DebugInfo, collect_events: CollectEvents, - ) -> ContractInstantiateResult<AccountIdOf<T>, BalanceOf<T>, EventRecordOf<T>>; + ) -> ContractInstantiateResult<BalanceOf<T>, EventRecordOf<T>>; /// Build the instantiate call and unwrap the result. - pub fn build_and_unwrap_result(self) -> InstantiateReturnValue<AccountIdOf<T>> { + pub fn build_and_unwrap_result(self) -> InstantiateReturnValue { self.build().result.unwrap() } /// Build the instantiate call and unwrap the account id. - pub fn build_and_unwrap_account_id(self) -> AccountIdOf<T> { - self.build().result.unwrap().account_id + pub fn build_and_unwrap_contract(self) -> Contract<T> { + let addr = self.build().result.unwrap().addr; + let account_id = T::AddressMapper::to_account_id(&addr); + Contract{ account_id, addr } } - pub fn bare_instantiate(origin: OriginFor<T>, code: Code<CodeHash<T>>) -> Self { + /// Create a [`BareInstantiateBuilder`] with default values. + pub fn bare_instantiate(origin: OriginFor<T>, code: Code) -> Self { Self { origin, value: 0u32.into(), @@ -155,7 +164,7 @@ builder!( storage_deposit_limit: deposit_limit::<T>(), code, data: vec![], - salt: vec![], + salt: [0; 32], debug: DebugInfo::UnsafeDebug, collect_events: CollectEvents::Skip, } @@ -165,7 +174,7 @@ builder!( builder!( call( origin: OriginFor<T>, - dest: AccountIdLookupOf<T>, + dest: H160, value: BalanceOf<T>, gas_limit: Weight, storage_deposit_limit: BalanceOf<T>, @@ -173,7 +182,7 @@ builder!( ) -> DispatchResultWithPostInfo; /// Create a [`CallBuilder`] with default values. - pub fn call(origin: OriginFor<T>, dest: AccountIdLookupOf<T>) -> Self { + pub fn call(origin: OriginFor<T>, dest: H160) -> Self { CallBuilder { origin, dest, @@ -188,7 +197,7 @@ builder!( builder!( bare_call( origin: OriginFor<T>, - dest: AccountIdOf<T>, + dest: H160, value: BalanceOf<T>, gas_limit: Weight, storage_deposit_limit: BalanceOf<T>, @@ -203,7 +212,7 @@ builder!( } /// Create a [`BareCallBuilder`] with default values. - pub fn bare_call(origin: OriginFor<T>, dest: AccountIdOf<T>) -> Self { + pub fn bare_call(origin: OriginFor<T>, dest: H160) -> Self { Self { origin, dest, diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index 52ee7b31054..a37e9842a2c 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -26,6 +26,7 @@ use self::{ }; use crate::{ self as pallet_revive, + address::AddressMapper, chain_extension::{ ChainExtension, Environment, Ext, RegisteredChainExtension, Result as ExtensionResult, RetVal, ReturnFlags, @@ -39,10 +40,12 @@ use crate::{ tests::test_utils::{get_contract, get_contract_checked}, wasm::Memory, weights::WeightInfo, - BalanceOf, Code, CodeHash, CodeInfoOf, CollectEvents, Config, ContractInfo, ContractInfoOf, - DebugInfo, DefaultAddressGenerator, DeletionQueueCounter, Error, HoldReason, - MigrationInProgress, Origin, Pallet, PristineCode, + BalanceOf, Code, CodeInfoOf, CollectEvents, Config, ContractInfo, ContractInfoOf, DebugInfo, + DefaultAddressMapper, DeletionQueueCounter, Error, HoldReason, MigrationInProgress, Origin, + Pallet, PristineCode, H160, }; + +use crate::test_utils::builder::Contract; use assert_matches::assert_matches; use codec::{Decode, Encode}; use frame_support::{ @@ -62,12 +65,11 @@ use frame_support::{ use frame_system::{EventRecord, Phase}; use pallet_revive_fixtures::{bench::dummy_unique, compile_module}; use pallet_revive_uapi::ReturnErrorCode as RuntimeReturnCode; -use sp_core::ByteArray; use sp_io::hashing::blake2_256; use sp_keystore::{testing::MemoryKeystore, KeystoreExt}; use sp_runtime::{ testing::H256, - traits::{BlakeTwo256, Convert, Hash, IdentityLookup}, + traits::{BlakeTwo256, Convert, IdentityLookup}, AccountId32, BuildStorage, DispatchError, Perbill, TokenError, }; @@ -102,15 +104,17 @@ macro_rules! assert_refcount { pub mod test_utils { use super::{Contracts, DepositPerByte, DepositPerItem, Test}; use crate::{ - exec::AccountIdOf, BalanceOf, CodeHash, CodeInfo, CodeInfoOf, Config, ContractInfo, - ContractInfoOf, PristineCode, + address::AddressMapper, exec::AccountIdOf, BalanceOf, CodeInfo, CodeInfoOf, Config, + ContractInfo, ContractInfoOf, PristineCode, }; use codec::{Encode, MaxEncodedLen}; use frame_support::traits::fungible::{InspectHold, Mutate}; + use sp_core::H160; - pub fn place_contract(address: &AccountIdOf<Test>, code_hash: CodeHash<Test>) { + pub fn place_contract(address: &AccountIdOf<Test>, code_hash: sp_core::H256) { set_balance(address, Contracts::min_balance() * 10); <CodeInfoOf<Test>>::insert(code_hash, CodeInfo::new(address.clone())); + let address = <Test as Config>::AddressMapper::to_address(&address); let contract = <ContractInfo<Test>>::new(&address, 0, code_hash).unwrap(); <ContractInfoOf<Test>>::insert(address, contract); } @@ -126,18 +130,16 @@ pub mod test_utils { ) -> u64 { <Test as Config>::Currency::balance_on_hold(reason.into(), who) } - pub fn get_contract(addr: &AccountIdOf<Test>) -> ContractInfo<Test> { + pub fn get_contract(addr: &H160) -> ContractInfo<Test> { get_contract_checked(addr).unwrap() } - pub fn get_contract_checked(addr: &AccountIdOf<Test>) -> Option<ContractInfo<Test>> { + pub fn get_contract_checked(addr: &H160) -> Option<ContractInfo<Test>> { ContractInfoOf::<Test>::get(addr) } - pub fn get_code_deposit(code_hash: &CodeHash<Test>) -> BalanceOf<Test> { + pub fn get_code_deposit(code_hash: &sp_core::H256) -> BalanceOf<Test> { crate::CodeInfoOf::<Test>::get(code_hash).unwrap().deposit() } - pub fn contract_info_storage_deposit( - addr: &<Test as frame_system::Config>::AccountId, - ) -> BalanceOf<Test> { + pub fn contract_info_storage_deposit(addr: &H160) -> BalanceOf<Test> { let contract_info = self::get_contract(&addr); let info_size = contract_info.encoded_size() as u64; DepositPerByte::get() @@ -152,7 +154,7 @@ pub mod test_utils { DepositPerByte::get().saturating_mul(code_len as u64 + code_info_len) + DepositPerItem::get().saturating_mul(2) } - pub fn ensure_stored(code_hash: CodeHash<Test>) -> usize { + pub fn ensure_stored(code_hash: sp_core::H256) -> usize { // Assert that code_info is stored assert!(CodeInfoOf::<Test>::contains_key(&code_hash)); // Assert that contract code is stored, and get its size. @@ -163,16 +165,17 @@ pub mod test_utils { mod builder { use super::Test; use crate::{ - test_utils::{builder::*, AccountId32, ALICE}, + test_utils::{builder::*, ALICE}, tests::RuntimeOrigin, - AccountIdLookupOf, Code, CodeHash, + Code, }; + use sp_core::{H160, H256}; - pub fn bare_instantiate(code: Code<CodeHash<Test>>) -> BareInstantiateBuilder<Test> { + pub fn bare_instantiate(code: Code) -> BareInstantiateBuilder<Test> { BareInstantiateBuilder::<Test>::bare_instantiate(RuntimeOrigin::signed(ALICE), code) } - pub fn bare_call(dest: AccountId32) -> BareCallBuilder<Test> { + pub fn bare_call(dest: H160) -> BareCallBuilder<Test> { BareCallBuilder::<Test>::bare_call(RuntimeOrigin::signed(ALICE), dest) } @@ -183,11 +186,11 @@ mod builder { ) } - pub fn instantiate(code_hash: CodeHash<Test>) -> InstantiateBuilder<Test> { + pub fn instantiate(code_hash: H256) -> InstantiateBuilder<Test> { InstantiateBuilder::<Test>::instantiate(RuntimeOrigin::signed(ALICE), code_hash) } - pub fn call(dest: AccountIdLookupOf<Test>) -> CallBuilder<Test> { + pub fn call(dest: H160) -> CallBuilder<Test> { CallBuilder::<Test>::call(RuntimeOrigin::signed(ALICE), dest) } } @@ -483,7 +486,7 @@ impl Config for Test { (TestExtension, DisabledExtension, RevertingExtension, TempStorageExtension); type DepositPerByte = DepositPerByte; type DepositPerItem = DepositPerItem; - type AddressGenerator = DefaultAddressGenerator; + type AddressMapper = DefaultAddressMapper; type UnsafeUnstableInterface = UnstableInterface; type UploadOrigin = EnsureAccount<Self, UploadAccount>; type InstantiateOrigin = EnsureAccount<Self, InstantiateAccount>; @@ -495,7 +498,7 @@ impl Config for Test { pub struct ExtBuilder { existential_deposit: u64, storage_version: Option<StorageVersion>, - code_hashes: Vec<CodeHash<Test>>, + code_hashes: Vec<sp_core::H256>, } impl Default for ExtBuilder { @@ -513,7 +516,7 @@ impl ExtBuilder { self.existential_deposit = existential_deposit; self } - pub fn with_code_hashes(mut self, code_hashes: Vec<CodeHash<Test>>) -> Self { + pub fn with_code_hashes(mut self, code_hashes: Vec<sp_core::H256>) -> Self { self.code_hashes = code_hashes; self } @@ -601,7 +604,7 @@ mod run_tests { let base_cost = <<Test as Config>::WeightInfo as WeightInfo>::call(); assert_eq!( - builder::call(BOB).build(), + builder::call(BOB_ADDR).build(), Err(DispatchErrorWithPostInfo { error: Error::<Test>::ContractNotFound.into(), post_info: PostDispatchInfo { @@ -636,7 +639,7 @@ mod run_tests { #[test] fn migration_in_progress_works() { - let (wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(1).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -655,11 +658,11 @@ mod run_tests { Error::<Test>::MigrationInProgress, ); assert_err!( - Contracts::set_code(RuntimeOrigin::signed(ALICE), BOB.clone(), code_hash), + Contracts::set_code(RuntimeOrigin::signed(ALICE), BOB_ADDR, code_hash), Error::<Test>::MigrationInProgress, ); assert_err_ignore_postinfo!( - builder::call(BOB).build(), + builder::call(BOB_ADDR).build(), Error::<Test>::MigrationInProgress ); assert_err_ignore_postinfo!( @@ -675,7 +678,7 @@ mod run_tests { #[test] fn instantiate_and_call_and_deposit_event() { - let (wasm, code_hash) = compile_module::<Test>("event_and_return_on_deploy").unwrap(); + let (wasm, code_hash) = compile_module("event_and_return_on_deploy").unwrap(); ExtBuilder::default().existential_deposit(1).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -694,9 +697,10 @@ mod run_tests { initialize_block(2); // Check at the end to get hash on error easily - let addr = builder::bare_instantiate(Code::Existing(code_hash)) - .value(value) - .build_and_unwrap_account_id(); + let Contract { addr, account_id } = + builder::bare_instantiate(Code::Existing(code_hash)) + .value(value) + .build_and_unwrap_contract(); assert!(ContractInfoOf::<Test>::contains_key(&addr)); assert_eq!( @@ -705,14 +709,14 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::System(frame_system::Event::NewAccount { - account: addr.clone() + account: account_id.clone() }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Endowed { - account: addr.clone(), + account: account_id.clone(), free_balance: min_balance, }), topics: vec![], @@ -721,7 +725,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { from: ALICE, - to: addr.clone(), + to: account_id.clone(), amount: min_balance, }), topics: vec![], @@ -730,7 +734,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { from: ALICE, - to: addr.clone(), + to: account_id.clone(), amount: value, }), topics: vec![], @@ -738,7 +742,7 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::ContractEmitted { - contract: addr.clone(), + contract: addr, data: vec![1, 2, 3, 4] }), topics: vec![], @@ -746,8 +750,8 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Instantiated { - deployer: ALICE, - contract: addr.clone() + deployer: ALICE_ADDR, + contract: addr }), topics: vec![], }, @@ -755,8 +759,8 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts( pallet_revive::Event::StorageDepositTransferredAndHeld { - from: ALICE, - to: addr.clone(), + from: ALICE_ADDR, + to: addr, amount: test_utils::contract_info_storage_deposit(&addr), } ), @@ -769,17 +773,17 @@ mod run_tests { #[test] fn deposit_event_max_value_limit() { - let (wasm, _code_hash) = compile_module::<Test>("event_size").unwrap(); + let (wasm, _code_hash) = compile_module("event_size").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { // Create let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(30_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Call contract with allowed storage value. - assert_ok!(builder::call(addr.clone()) + assert_ok!(builder::call(addr) .gas_limit(GAS_LIMIT.set_ref_time(GAS_LIMIT.ref_time() * 2)) // we are copying a huge buffer, .data(limits::PAYLOAD_BYTES.encode()) .build()); @@ -795,14 +799,14 @@ mod run_tests { // Fail out of fuel (ref_time weight) in the engine. #[test] fn run_out_of_fuel_engine() { - let (wasm, _code_hash) = compile_module::<Test>("run_out_of_gas").unwrap(); + let (wasm, _code_hash) = compile_module("run_out_of_gas").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(100 * min_balance) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Call the contract with a fixed gas limit. It must run out of gas because it just // loops forever. @@ -818,19 +822,19 @@ mod run_tests { // Fail out of fuel (ref_time weight) in the host. #[test] fn run_out_of_fuel_host() { - let (code, _hash) = compile_module::<Test>("chain_extension").unwrap(); + let (code, _hash) = compile_module("chain_extension").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(code)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); let gas_limit = Weight::from_parts(u32::MAX as u64, GAS_LIMIT.proof_size()); // Use chain extension to charge more ref_time than it is available. - let result = builder::bare_call(addr.clone()) + let result = builder::bare_call(addr) .gas_limit(gas_limit) .data( ExtensionInput { extension_id: 0, func_id: 2, extra: &u32::MAX.encode() } @@ -844,16 +848,17 @@ mod run_tests { #[test] fn gas_syncs_work() { - let (code, _code_hash) = compile_module::<Test>("caller_is_origin_n").unwrap(); + let (code, _code_hash) = compile_module("caller_is_origin_n").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_account_id(); + let contract = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); - let result = builder::bare_call(addr.clone()).data(0u32.encode()).build(); + let result = builder::bare_call(contract.addr).data(0u32.encode()).build(); assert_ok!(result.result); let engine_consumed_noop = result.gas_consumed.ref_time(); - let result = builder::bare_call(addr.clone()).data(1u32.encode()).build(); + let result = builder::bare_call(contract.addr).data(1u32.encode()).build(); assert_ok!(result.result); let gas_consumed_once = result.gas_consumed.ref_time(); let host_consumed_once = @@ -861,7 +866,7 @@ mod run_tests { let engine_consumed_once = gas_consumed_once - host_consumed_once - engine_consumed_noop; - let result = builder::bare_call(addr).data(2u32.encode()).build(); + let result = builder::bare_call(contract.addr).data(2u32.encode()).build(); assert_ok!(result.result); let gas_consumed_twice = result.gas_consumed.ref_time(); let host_consumed_twice = host_consumed_once * 2; @@ -878,7 +883,7 @@ mod run_tests { /// Check the `Nonce` storage item for more information. #[test] fn instantiate_unique_trie_id() { - let (wasm, code_hash) = compile_module::<Test>("self_destruct").unwrap(); + let (wasm, code_hash) = compile_module("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(500).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -886,8 +891,8 @@ mod run_tests { .unwrap(); // Instantiate the contract and store its trie id for later comparison. - let addr = - builder::bare_instantiate(Code::Existing(code_hash)).build_and_unwrap_account_id(); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Existing(code_hash)).build_and_unwrap_contract(); let trie_id = get_contract(&addr).trie_id; // Try to instantiate it again without termination should yield an error. @@ -897,7 +902,7 @@ mod run_tests { ); // Terminate the contract. - assert_ok!(builder::call(addr.clone()).build()); + assert_ok!(builder::call(addr).build()); // Re-Instantiate after termination. assert_ok!(builder::instantiate(code_hash).build()); @@ -909,14 +914,14 @@ mod run_tests { #[test] fn storage_work() { - let (code, _code_hash) = compile_module::<Test>("storage").unwrap(); + let (code, _code_hash) = compile_module("storage").unwrap(); ExtBuilder::default().build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); - let addr = builder::bare_instantiate(Code::Upload(code)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); builder::bare_call(addr).build_and_unwrap_result(); }); @@ -924,18 +929,18 @@ mod run_tests { #[test] fn storage_max_value_limit() { - let (wasm, _code_hash) = compile_module::<Test>("storage_size").unwrap(); + let (wasm, _code_hash) = compile_module("storage_size").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { // Create let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(30_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); get_contract(&addr); // Call contract with allowed storage value. - assert_ok!(builder::call(addr.clone()) + assert_ok!(builder::call(addr) .gas_limit(GAS_LIMIT.set_ref_time(GAS_LIMIT.ref_time() * 2)) // we are copying a huge buffer .data(limits::PAYLOAD_BYTES.encode()) .build()); @@ -950,14 +955,14 @@ mod run_tests { #[test] fn transient_storage_work() { - let (code, _code_hash) = compile_module::<Test>("transient_storage").unwrap(); + let (code, _code_hash) = compile_module("transient_storage").unwrap(); ExtBuilder::default().build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); - let addr = builder::bare_instantiate(Code::Upload(code)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); builder::bare_call(addr).build_and_unwrap_result(); }); @@ -966,28 +971,27 @@ mod run_tests { #[test] fn transient_storage_limit_in_call() { let (wasm_caller, _code_hash_caller) = - compile_module::<Test>("create_transient_storage_and_call").unwrap(); - let (wasm_callee, _code_hash_callee) = - compile_module::<Test>("set_transient_storage").unwrap(); + compile_module("create_transient_storage_and_call").unwrap(); + let (wasm_callee, _code_hash_callee) = compile_module("set_transient_storage").unwrap(); ExtBuilder::default().build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Create both contracts: Constructors do nothing. - let addr_caller = - builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_account_id(); - let addr_callee = - builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_contract(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_contract(); // Call contracts with storage values within the limit. // Caller and Callee contracts each set a transient storage value of size 100. - assert_ok!(builder::call(addr_caller.clone()) + assert_ok!(builder::call(addr_caller) .data((100u32, 100u32, &addr_callee).encode()) .build(),); // Call a contract with a storage value that is too large. // Limit exceeded in the caller contract. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .data((4u32 * 1024u32, 200u32, &addr_callee).encode()) .build(), <Error<Test>>::OutOfTransientStorage, @@ -1006,17 +1010,27 @@ mod run_tests { #[test] fn deploy_and_call_other_contract() { - let (caller_wasm, _caller_code_hash) = compile_module::<Test>("caller_contract").unwrap(); - let (callee_wasm, callee_code_hash) = compile_module::<Test>("return_with_data").unwrap(); + let (caller_wasm, _caller_code_hash) = compile_module("caller_contract").unwrap(); + let (callee_wasm, callee_code_hash) = compile_module("return_with_data").unwrap(); ExtBuilder::default().existential_deposit(1).build().execute_with(|| { let min_balance = Contracts::min_balance(); // Create let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let caller_addr = builder::bare_instantiate(Code::Upload(caller_wasm)) - .value(100_000) - .build_and_unwrap_account_id(); + let Contract { addr: caller_addr, account_id: caller_account } = + builder::bare_instantiate(Code::Upload(caller_wasm)) + .value(100_000) + .build_and_unwrap_contract(); + + let callee_addr = crate::address::create2( + &caller_addr, + &callee_wasm, + &[0, 1, 34, 51, 68, 85, 102, 119], // hard coded in wasm + &[0u8; 32], + ); + let callee_account = <Test as Config>::AddressMapper::to_account_id(&callee_addr); + Contracts::upload_code( RuntimeOrigin::signed(ALICE), callee_wasm, @@ -1024,21 +1038,12 @@ mod run_tests { ) .unwrap(); - let callee_addr = Contracts::contract_address( - &caller_addr, - &callee_code_hash, - &[0, 1, 34, 51, 68, 85, 102, 119], // hard coded in wasm - &[], - ); - // Drop previous events initialize_block(2); // Call BOB contract, which attempts to instantiate and call the callee contract and // makes various assertions on the results from those calls. - assert_ok!(builder::call(caller_addr.clone()) - .data(callee_code_hash.as_ref().to_vec()) - .build()); + assert_ok!(builder::call(caller_addr).data(callee_code_hash.as_ref().to_vec()).build()); assert_eq!( System::events(), @@ -1046,14 +1051,14 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::System(frame_system::Event::NewAccount { - account: callee_addr.clone() + account: callee_account.clone() }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Endowed { - account: callee_addr.clone(), + account: callee_account.clone(), free_balance: min_balance, }), topics: vec![], @@ -1062,7 +1067,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { from: ALICE, - to: callee_addr.clone(), + to: callee_account.clone(), amount: min_balance, }), topics: vec![], @@ -1070,8 +1075,8 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { - from: caller_addr.clone(), - to: callee_addr.clone(), + from: caller_account.clone(), + to: callee_account.clone(), amount: 32768 // hardcoded in wasm }), topics: vec![], @@ -1079,16 +1084,16 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Instantiated { - deployer: caller_addr.clone(), - contract: callee_addr.clone(), + deployer: caller_addr, + contract: callee_addr, }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { - from: caller_addr.clone(), - to: callee_addr.clone(), + from: caller_account.clone(), + to: callee_account.clone(), amount: 32768, }), topics: vec![], @@ -1096,8 +1101,8 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Called { - caller: Origin::from_account_id(caller_addr.clone()), - contract: callee_addr.clone(), + caller: Origin::from_account_id(caller_account.clone()), + contract: callee_addr, }), topics: vec![], }, @@ -1105,7 +1110,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: caller_addr.clone(), + contract: caller_addr, }), topics: vec![], }, @@ -1113,8 +1118,8 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts( pallet_revive::Event::StorageDepositTransferredAndHeld { - from: ALICE, - to: callee_addr.clone(), + from: ALICE_ADDR, + to: callee_addr, amount: test_utils::contract_info_storage_deposit(&callee_addr), } ), @@ -1127,20 +1132,21 @@ mod run_tests { #[test] fn delegate_call() { - let (caller_wasm, _caller_code_hash) = compile_module::<Test>("delegate_call").unwrap(); - let (callee_wasm, callee_code_hash) = compile_module::<Test>("delegate_call_lib").unwrap(); + let (caller_wasm, _caller_code_hash) = compile_module("delegate_call").unwrap(); + let (callee_wasm, callee_code_hash) = compile_module("delegate_call_lib").unwrap(); ExtBuilder::default().existential_deposit(500).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate the 'caller' - let caller_addr = builder::bare_instantiate(Code::Upload(caller_wasm)) - .value(300_000) - .build_and_unwrap_account_id(); + let Contract { addr: caller_addr, .. } = + builder::bare_instantiate(Code::Upload(caller_wasm)) + .value(300_000) + .build_and_unwrap_contract(); // Only upload 'callee' code assert_ok!(Contracts::upload_code(RuntimeOrigin::signed(ALICE), callee_wasm, 100_000,)); - assert_ok!(builder::call(caller_addr.clone()) + assert_ok!(builder::call(caller_addr) .value(1337) .data(callee_code_hash.as_ref().to_vec()) .build()); @@ -1149,29 +1155,33 @@ mod run_tests { #[test] fn transfer_expendable_cannot_kill_account() { - let (wasm, _code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(1_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Check that the BOB contract has been instantiated. get_contract(&addr); - let total_balance = <Test as Config>::Currency::total_balance(&addr); + let account = <Test as Config>::AddressMapper::to_account_id(&addr); + let total_balance = <Test as Config>::Currency::total_balance(&account); assert_eq!( - test_utils::get_balance_on_hold(&HoldReason::StorageDepositReserve.into(), &addr), + test_utils::get_balance_on_hold( + &HoldReason::StorageDepositReserve.into(), + &account + ), test_utils::contract_info_storage_deposit(&addr) ); // Some ot the total balance is held, so it can't be transferred. assert_err!( <<Test as Config>::Currency as Mutate<AccountId32>>::transfer( - &addr, + &account, &ALICE, total_balance, Preservation::Expendable, @@ -1179,33 +1189,34 @@ mod run_tests { TokenError::FundsUnavailable, ); - assert_eq!(<Test as Config>::Currency::total_balance(&addr), total_balance); + assert_eq!(<Test as Config>::Currency::total_balance(&account), total_balance); }); } #[test] fn cannot_self_destruct_through_draining() { - let (wasm, _code_hash) = compile_module::<Test>("drain").unwrap(); + let (wasm, _code_hash) = compile_module("drain").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let value = 1_000; let min_balance = Contracts::min_balance(); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(value) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); + let account = <Test as Config>::AddressMapper::to_account_id(&addr); // Check that the BOB contract has been instantiated. get_contract(&addr); // Call BOB which makes it send all funds to the zero address // The contract code asserts that the transfer fails with the correct error code - assert_ok!(builder::call(addr.clone()).build()); + assert_ok!(builder::call(addr).build()); // Make sure the account wasn't remove by sending all free balance away. assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&account), value + test_utils::contract_info_storage_deposit(&addr) + min_balance, ); }); @@ -1213,54 +1224,54 @@ mod run_tests { #[test] fn cannot_self_destruct_through_storage_refund_after_price_change() { - let (wasm, _code_hash) = compile_module::<Test>("store_call").unwrap(); + let (wasm, _code_hash) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); - - let info_deposit = test_utils::contract_info_storage_deposit(&addr); + let contract = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); + let info_deposit = test_utils::contract_info_storage_deposit(&contract.addr); // Check that the contract has been instantiated and has the minimum balance - assert_eq!(get_contract(&addr).total_deposit(), info_deposit); - assert_eq!(get_contract(&addr).extra_deposit(), 0); + assert_eq!(get_contract(&contract.addr).total_deposit(), info_deposit); + assert_eq!(get_contract(&contract.addr).extra_deposit(), 0); assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&contract.account_id), info_deposit + min_balance ); // Create 100 bytes of storage with a price of per byte and a single storage item of // price 2 - assert_ok!(builder::call(addr.clone()).data(100u32.to_le_bytes().to_vec()).build()); - assert_eq!(get_contract(&addr).total_deposit(), info_deposit + 102); + assert_ok!(builder::call(contract.addr).data(100u32.to_le_bytes().to_vec()).build()); + assert_eq!(get_contract(&contract.addr).total_deposit(), info_deposit + 102); // Increase the byte price and trigger a refund. This should not have any influence // because the removal is pro rata and exactly those 100 bytes should have been // removed. DEPOSIT_PER_BYTE.with(|c| *c.borrow_mut() = 500); - assert_ok!(builder::call(addr.clone()).data(0u32.to_le_bytes().to_vec()).build()); + assert_ok!(builder::call(contract.addr).data(0u32.to_le_bytes().to_vec()).build()); // Make sure the account wasn't removed by the refund assert_eq!( - <Test as Config>::Currency::total_balance(&addr), - get_contract(&addr).total_deposit() + min_balance, + <Test as Config>::Currency::total_balance(&contract.account_id), + get_contract(&contract.addr).total_deposit() + min_balance, ); - assert_eq!(get_contract(&addr).extra_deposit(), 2); + assert_eq!(get_contract(&contract.addr).extra_deposit(), 2); }); } #[test] fn cannot_self_destruct_while_live() { - let (wasm, _code_hash) = compile_module::<Test>("self_destruct").unwrap(); + let (wasm, _code_hash) = compile_module("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(100_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Check that the BOB contract has been instantiated. get_contract(&addr); @@ -1268,7 +1279,7 @@ mod run_tests { // Call BOB with input data, forcing it make a recursive call to itself to // self-destruct, resulting in a trap. assert_err_ignore_postinfo!( - builder::call(addr.clone()).data(vec![0]).build(), + builder::call(addr).data(vec![0]).build(), Error::<Test>::ContractTrapped, ); @@ -1279,38 +1290,38 @@ mod run_tests { #[test] fn self_destruct_works() { - let (wasm, code_hash) = compile_module::<Test>("self_destruct").unwrap(); + let (wasm, code_hash) = compile_module("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(1_000).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let _ = <Test as Config>::Currency::set_balance(&DJANGO, 1_000_000); + let _ = <Test as Config>::Currency::set_balance(Ð_DJANGO, 1_000_000); let min_balance = Contracts::min_balance(); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let contract = builder::bare_instantiate(Code::Upload(wasm)) .value(100_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Check that the BOB contract has been instantiated. - let _ = get_contract(&addr); + let _ = get_contract(&contract.addr); - let info_deposit = test_utils::contract_info_storage_deposit(&addr); + let info_deposit = test_utils::contract_info_storage_deposit(&contract.addr); // Drop all previous events initialize_block(2); // Call BOB without input data which triggers termination. - assert_matches!(builder::call(addr.clone()).build(), Ok(_)); + assert_matches!(builder::call(contract.addr).build(), Ok(_)); // Check that code is still there but refcount dropped to zero. assert_refcount!(&code_hash, 0); // Check that account is gone - assert!(get_contract_checked(&addr).is_none()); - assert_eq!(<Test as Config>::Currency::total_balance(&addr), 0); + assert!(get_contract_checked(&contract.addr).is_none()); + assert_eq!(<Test as Config>::Currency::total_balance(&contract.account_id), 0); // Check that the beneficiary (django) got remaining balance. assert_eq!( - <Test as Config>::Currency::free_balance(DJANGO), + <Test as Config>::Currency::free_balance(ETH_DJANGO), 1_000_000 + 100_000 + min_balance ); @@ -1327,8 +1338,8 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Terminated { - contract: addr.clone(), - beneficiary: DJANGO + contract: contract.addr, + beneficiary: DJANGO_ADDR, }), topics: vec![], }, @@ -1336,7 +1347,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: addr.clone(), + contract: contract.addr, }), topics: vec![], }, @@ -1344,8 +1355,8 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts( pallet_revive::Event::StorageDepositTransferredAndReleased { - from: addr.clone(), - to: ALICE, + from: contract.addr, + to: ALICE_ADDR, amount: info_deposit, } ), @@ -1354,15 +1365,15 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::System(frame_system::Event::KilledAccount { - account: addr.clone() + account: contract.account_id.clone() }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { - from: addr.clone(), - to: DJANGO, + from: contract.account_id.clone(), + to: ETH_DJANGO, amount: 100_000 + min_balance, }), topics: vec![], @@ -1376,30 +1387,30 @@ mod run_tests { // additional funds after it has been drained. #[test] fn destroy_contract_and_transfer_funds() { - let (callee_wasm, callee_code_hash) = compile_module::<Test>("self_destruct").unwrap(); - let (caller_wasm, _caller_code_hash) = - compile_module::<Test>("destroy_and_transfer").unwrap(); + let (callee_wasm, callee_code_hash) = compile_module("self_destruct").unwrap(); + let (caller_wasm, _caller_code_hash) = compile_module("destroy_and_transfer").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { // Create code hash for bob to instantiate let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); Contracts::upload_code( RuntimeOrigin::signed(ALICE), - callee_wasm, + callee_wasm.clone(), deposit_limit::<Test>(), ) .unwrap(); // This deploys the BOB contract, which in turn deploys the CHARLIE contract during // construction. - let addr_bob = builder::bare_instantiate(Code::Upload(caller_wasm)) - .value(200_000) - .data(callee_code_hash.as_ref().to_vec()) - .build_and_unwrap_account_id(); + let Contract { addr: addr_bob, .. } = + builder::bare_instantiate(Code::Upload(caller_wasm)) + .value(200_000) + .data(callee_code_hash.as_ref().to_vec()) + .build_and_unwrap_contract(); // Check that the CHARLIE contract has been instantiated. - let addr_charlie = - Contracts::contract_address(&addr_bob, &callee_code_hash, &[], &[0x47, 0x11]); + let salt = [47; 32]; // hard coded in fixture. + let addr_charlie = crate::address::create2(&addr_bob, &callee_wasm, &[], &salt); get_contract(&addr_charlie); // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. @@ -1412,7 +1423,7 @@ mod run_tests { #[test] fn cannot_self_destruct_in_constructor() { - let (wasm, _) = compile_module::<Test>("self_destructing_constructor").unwrap(); + let (wasm, _) = compile_module("self_destructing_constructor").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -1426,15 +1437,15 @@ mod run_tests { #[test] fn crypto_hashes() { - let (wasm, _code_hash) = compile_module::<Test>("crypto_hashes").unwrap(); + let (wasm, _code_hash) = compile_module("crypto_hashes").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate the CRYPTO_HASHES contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(100_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Perform the call. let input = b"_DEAD_BEEF"; use sp_io::hashing::*; @@ -1456,8 +1467,7 @@ mod run_tests { // We offset data in the contract tables by 1. let mut params = vec![(n + 1) as u8]; params.extend_from_slice(input); - let result = - builder::bare_call(addr.clone()).data(params).build_and_unwrap_result(); + let result = builder::bare_call(addr).data(params).build_and_unwrap_result(); assert!(!result.did_revert()); let expected = hash_fn(input.as_ref()); assert_eq!(&result.data[..*expected_size], &*expected); @@ -1467,54 +1477,54 @@ mod run_tests { #[test] fn transfer_return_code() { - let (wasm, _code_hash) = compile_module::<Test>("transfer_return_code").unwrap(); + let (wasm, _code_hash) = compile_module("transfer_return_code").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let contract = builder::bare_instantiate(Code::Upload(wasm)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Contract has only the minimal balance so any transfer will fail. - <Test as Config>::Currency::set_balance(&addr, min_balance); - let result = builder::bare_call(addr.clone()).build_and_unwrap_result(); + <Test as Config>::Currency::set_balance(&contract.account_id, min_balance); + let result = builder::bare_call(contract.addr).build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::TransferFailed); }); } #[test] fn call_return_code() { - let (caller_code, _caller_hash) = compile_module::<Test>("call_return_code").unwrap(); - let (callee_code, _callee_hash) = compile_module::<Test>("ok_trap_revert").unwrap(); + let (caller_code, _caller_hash) = compile_module("call_return_code").unwrap(); + let (callee_code, _callee_hash) = compile_module("ok_trap_revert").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); let _ = <Test as Config>::Currency::set_balance(&CHARLIE, 1000 * min_balance); - let addr_bob = builder::bare_instantiate(Code::Upload(caller_code)) + let bob = builder::bare_instantiate(Code::Upload(caller_code)) .value(min_balance * 100) .data(vec![0]) - .build_and_unwrap_account_id(); - <Test as Config>::Currency::set_balance(&addr_bob, min_balance); + .build_and_unwrap_contract(); + <Test as Config>::Currency::set_balance(&bob.account_id, min_balance); // Contract calls into Django which is no valid contract - let result = builder::bare_call(addr_bob.clone()) + let result = builder::bare_call(bob.addr) .data(AsRef::<[u8]>::as_ref(&DJANGO).to_vec()) .build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::NotCallable); - let addr_django = builder::bare_instantiate(Code::Upload(callee_code)) + let django = builder::bare_instantiate(Code::Upload(callee_code)) .origin(RuntimeOrigin::signed(CHARLIE)) .value(min_balance * 100) .data(vec![0]) - .build_and_unwrap_account_id(); - <Test as Config>::Currency::set_balance(&addr_django, min_balance); + .build_and_unwrap_contract(); + <Test as Config>::Currency::set_balance(&django.account_id, min_balance); // Contract has only the minimal balance so any transfer will fail. - let result = builder::bare_call(addr_bob.clone()) + let result = builder::bare_call(bob.addr) .data( - AsRef::<[u8]>::as_ref(&addr_django) + AsRef::<[u8]>::as_ref(&django.addr) .iter() .chain(&0u32.to_le_bytes()) .cloned() @@ -1524,10 +1534,10 @@ mod run_tests { assert_return_code!(result, RuntimeReturnCode::TransferFailed); // Contract has enough balance but callee reverts because "1" is passed. - <Test as Config>::Currency::set_balance(&addr_bob, min_balance + 1000); - let result = builder::bare_call(addr_bob.clone()) + <Test as Config>::Currency::set_balance(&bob.account_id, min_balance + 1000); + let result = builder::bare_call(bob.addr) .data( - AsRef::<[u8]>::as_ref(&addr_django) + AsRef::<[u8]>::as_ref(&django.addr) .iter() .chain(&1u32.to_le_bytes()) .cloned() @@ -1537,9 +1547,9 @@ mod run_tests { assert_return_code!(result, RuntimeReturnCode::CalleeReverted); // Contract has enough balance but callee traps because "2" is passed. - let result = builder::bare_call(addr_bob) + let result = builder::bare_call(bob.addr) .data( - AsRef::<[u8]>::as_ref(&addr_django) + AsRef::<[u8]>::as_ref(&django.addr) .iter() .chain(&2u32.to_le_bytes()) .cloned() @@ -1552,9 +1562,8 @@ mod run_tests { #[test] fn instantiate_return_code() { - let (caller_code, _caller_hash) = - compile_module::<Test>("instantiate_return_code").unwrap(); - let (callee_code, callee_hash) = compile_module::<Test>("ok_trap_revert").unwrap(); + let (caller_code, _caller_hash) = compile_module("instantiate_return_code").unwrap(); + let (callee_code, callee_hash) = compile_module("ok_trap_revert").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); @@ -1565,31 +1574,31 @@ mod run_tests { .value(min_balance * 100) .build()); - let addr = builder::bare_instantiate(Code::Upload(caller_code)) + let contract = builder::bare_instantiate(Code::Upload(caller_code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Contract has only the minimal balance so any transfer will fail. - <Test as Config>::Currency::set_balance(&addr, min_balance); - let result = builder::bare_call(addr.clone()) + <Test as Config>::Currency::set_balance(&contract.account_id, min_balance); + let result = builder::bare_call(contract.addr) .data(callee_hash.clone()) .build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::TransferFailed); // Contract has enough balance but the passed code hash is invalid - <Test as Config>::Currency::set_balance(&addr, min_balance + 10_000); + <Test as Config>::Currency::set_balance(&contract.account_id, min_balance + 10_000); let result = - builder::bare_call(addr.clone()).data(vec![0; 33]).build_and_unwrap_result(); + builder::bare_call(contract.addr).data(vec![0; 33]).build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::CodeNotFound); // Contract has enough balance but callee reverts because "1" is passed. - let result = builder::bare_call(addr.clone()) + let result = builder::bare_call(contract.addr) .data(callee_hash.iter().chain(&1u32.to_le_bytes()).cloned().collect()) .build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::CalleeReverted); // Contract has enough balance but callee traps because "2" is passed. - let result = builder::bare_call(addr) + let result = builder::bare_call(contract.addr) .data(callee_hash.iter().chain(&2u32.to_le_bytes()).cloned().collect()) .build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::CalleeTrapped); @@ -1598,16 +1607,16 @@ mod run_tests { #[test] fn disabled_chain_extension_errors_on_call() { - let (code, _hash) = compile_module::<Test>("chain_extension").unwrap(); + let (code, _hash) = compile_module("chain_extension").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(code)) + let contract = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); TestExtension::disable(); assert_err_ignore_postinfo!( - builder::call(addr.clone()).data(vec![7u8; 8]).build(), + builder::call(contract.addr).data(vec![7u8; 8]).build(), Error::<Test>::NoChainExtension, ); }); @@ -1615,46 +1624,46 @@ mod run_tests { #[test] fn chain_extension_works() { - let (code, _hash) = compile_module::<Test>("chain_extension").unwrap(); + let (code, _hash) = compile_module("chain_extension").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(code)) + let contract = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // 0 = read input buffer and pass it through as output let input: Vec<u8> = ExtensionInput { extension_id: 0, func_id: 0, extra: &[99] }.into(); - let result = builder::bare_call(addr.clone()).data(input.clone()).build(); + let result = builder::bare_call(contract.addr).data(input.clone()).build(); assert_eq!(TestExtension::last_seen_buffer(), input); assert_eq!(result.result.unwrap().data, input); // 1 = treat inputs as integer primitives and store the supplied integers - builder::bare_call(addr.clone()) + builder::bare_call(contract.addr) .data(ExtensionInput { extension_id: 0, func_id: 1, extra: &[] }.into()) .build_and_unwrap_result(); assert_eq!(TestExtension::last_seen_input_len(), 4); // 2 = charge some extra weight (amount supplied in the fifth byte) - let result = builder::bare_call(addr.clone()) + let result = builder::bare_call(contract.addr) .data(ExtensionInput { extension_id: 0, func_id: 2, extra: &0u32.encode() }.into()) .build(); assert_ok!(result.result); let gas_consumed = result.gas_consumed; - let result = builder::bare_call(addr.clone()) + let result = builder::bare_call(contract.addr) .data(ExtensionInput { extension_id: 0, func_id: 2, extra: &42u32.encode() }.into()) .build(); assert_ok!(result.result); assert_eq!(result.gas_consumed.ref_time(), gas_consumed.ref_time() + 42); - let result = builder::bare_call(addr.clone()) + let result = builder::bare_call(contract.addr) .data(ExtensionInput { extension_id: 0, func_id: 2, extra: &95u32.encode() }.into()) .build(); assert_ok!(result.result); assert_eq!(result.gas_consumed.ref_time(), gas_consumed.ref_time() + 95); // 3 = diverging chain extension call that sets flags to 0x1 and returns a fixed buffer - let result = builder::bare_call(addr.clone()) + let result = builder::bare_call(contract.addr) .data(ExtensionInput { extension_id: 0, func_id: 3, extra: &[] }.into()) .build_and_unwrap_result(); assert_eq!(result.flags, ReturnFlags::REVERT); @@ -1663,7 +1672,7 @@ mod run_tests { // diverging to second chain extension that sets flags to 0x1 and returns a fixed buffer // We set the MSB part to 1 (instead of 0) which routes the request into the second // extension - let result = builder::bare_call(addr.clone()) + let result = builder::bare_call(contract.addr) .data(ExtensionInput { extension_id: 1, func_id: 0, extra: &[] }.into()) .build_and_unwrap_result(); assert_eq!(result.flags, ReturnFlags::REVERT); @@ -1673,7 +1682,7 @@ mod run_tests { // We set the MSB part to 2 (instead of 0) which routes the request into the third // extension assert_err_ignore_postinfo!( - builder::call(addr.clone()) + builder::call(contract.addr) .data(ExtensionInput { extension_id: 2, func_id: 0, extra: &[] }.into()) .build(), Error::<Test>::NoChainExtension, @@ -1683,13 +1692,13 @@ mod run_tests { #[test] fn chain_extension_temp_storage_works() { - let (code, _hash) = compile_module::<Test>("chain_extension_temp_storage").unwrap(); + let (code, _hash) = compile_module("chain_extension_temp_storage").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(code)) + let contract = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Call func 0 and func 1 back to back. let stop_recursion = 0u8; @@ -1701,32 +1710,32 @@ mod run_tests { .as_ref(), ); - assert_ok!(builder::bare_call(addr.clone()).data(input.clone()).build().result); + assert_ok!(builder::bare_call(contract.addr).data(input.clone()).build().result); }) } #[test] fn lazy_removal_works() { - let (code, _hash) = compile_module::<Test>("self_destruct").unwrap(); + let (code, _hash) = compile_module("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(code)) + let contract = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); - let info = get_contract(&addr); + let info = get_contract(&contract.addr); let trie = &info.child_trie_info(); // Put value into the contracts child trie child::put(trie, &[99], &42); // Terminate the contract - assert_ok!(builder::call(addr.clone()).build()); + assert_ok!(builder::call(contract.addr).build()); // Contract info should be gone - assert!(!<ContractInfoOf::<Test>>::contains_key(&addr)); + assert!(!<ContractInfoOf::<Test>>::contains_key(&contract.addr)); // But value should be still there as the lazy removal did not run, yet. assert_matches!(child::get(trie, &[99]), Some(42)); @@ -1741,19 +1750,19 @@ mod run_tests { #[test] fn lazy_batch_removal_works() { - let (code, _hash) = compile_module::<Test>("self_destruct").unwrap(); + let (code, _hash) = compile_module("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); let mut tries: Vec<child::ChildInfo> = vec![]; for i in 0..3u8 { - let addr = builder::bare_instantiate(Code::Upload(code.clone())) + let contract = builder::bare_instantiate(Code::Upload(code.clone())) .value(min_balance * 100) - .salt(vec![i]) - .build_and_unwrap_account_id(); + .salt([i; 32]) + .build_and_unwrap_contract(); - let info = get_contract(&addr); + let info = get_contract(&contract.addr); let trie = &info.child_trie_info(); // Put value into the contracts child trie @@ -1761,9 +1770,9 @@ mod run_tests { // Terminate the contract. Contract info should be gone, but value should be still // there as the lazy removal did not run, yet. - assert_ok!(builder::call(addr.clone()).build()); + assert_ok!(builder::call(contract.addr).build()); - assert!(!<ContractInfoOf::<Test>>::contains_key(&addr)); + assert!(!<ContractInfoOf::<Test>>::contains_key(&contract.addr)); assert_matches!(child::get(trie, &[99]), Some(42)); tries.push(trie.clone()) @@ -1781,7 +1790,7 @@ mod run_tests { #[test] fn lazy_removal_partial_remove_works() { - let (code, _hash) = compile_module::<Test>("self_destruct").unwrap(); + let (code, _hash) = compile_module("self_destruct").unwrap(); // We create a contract with some extra keys above the weight limit let extra_keys = 7u32; @@ -1797,9 +1806,9 @@ mod run_tests { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(code)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); let info = get_contract(&addr); @@ -1810,7 +1819,7 @@ mod run_tests { <ContractInfoOf<Test>>::insert(&addr, info.clone()); // Terminate the contract - assert_ok!(builder::call(addr.clone()).build()); + assert_ok!(builder::call(addr).build()); // Contract info should be gone assert!(!<ContractInfoOf::<Test>>::contains_key(&addr)); @@ -1856,14 +1865,14 @@ mod run_tests { #[test] fn lazy_removal_does_no_run_on_low_remaining_weight() { - let (code, _hash) = compile_module::<Test>("self_destruct").unwrap(); + let (code, _hash) = compile_module("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(code)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); let info = get_contract(&addr); let trie = &info.child_trie_info(); @@ -1872,7 +1881,7 @@ mod run_tests { child::put(trie, &[99], &42); // Terminate the contract - assert_ok!(builder::call(addr.clone()).build()); + assert_ok!(builder::call(addr).build()); // Contract info should be gone assert!(!<ContractInfoOf::<Test>>::contains_key(&addr)); @@ -1906,7 +1915,7 @@ mod run_tests { #[test] fn lazy_removal_does_not_use_all_weight() { - let (code, _hash) = compile_module::<Test>("self_destruct").unwrap(); + let (code, _hash) = compile_module("self_destruct").unwrap(); let mut meter = WeightMeter::with_limit(Weight::from_parts(5_000_000_000, 100 * 1024)); let mut ext = ExtBuilder::default().existential_deposit(50).build(); @@ -1915,9 +1924,9 @@ mod run_tests { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(code)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); let info = get_contract(&addr); let (weight_per_key, max_keys) = ContractInfo::<Test>::deletion_budget(&meter); @@ -1935,7 +1944,7 @@ mod run_tests { <ContractInfoOf<Test>>::insert(&addr, info.clone()); // Terminate the contract - assert_ok!(builder::call(addr.clone()).build()); + assert_ok!(builder::call(addr).build()); // Contract info should be gone assert!(!<ContractInfoOf::<Test>>::contains_key(&addr)); @@ -1970,7 +1979,7 @@ mod run_tests { #[test] fn deletion_queue_ring_buffer_overflow() { - let (code, _hash) = compile_module::<Test>("self_destruct").unwrap(); + let (code, _hash) = compile_module("self_destruct").unwrap(); let mut ext = ExtBuilder::default().existential_deposit(50).build(); // setup the deletion queue with custom counters @@ -1989,10 +1998,10 @@ mod run_tests { // add 3 contracts to the deletion queue for i in 0..3u8 { - let addr = builder::bare_instantiate(Code::Upload(code.clone())) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code.clone())) .value(min_balance * 100) - .salt(vec![i]) - .build_and_unwrap_account_id(); + .salt([i; 32]) + .build_and_unwrap_contract(); let info = get_contract(&addr); let trie = &info.child_trie_info(); @@ -2002,7 +2011,7 @@ mod run_tests { // Terminate the contract. Contract info should be gone, but value should be still // there as the lazy removal did not run, yet. - assert_ok!(builder::call(addr.clone()).build()); + assert_ok!(builder::call(addr).build()); assert!(!<ContractInfoOf::<Test>>::contains_key(&addr)); assert_matches!(child::get(trie, &[99]), Some(42)); @@ -2024,27 +2033,29 @@ mod run_tests { } #[test] fn refcounter() { - let (wasm, code_hash) = compile_module::<Test>("self_destruct").unwrap(); + let (wasm, code_hash) = compile_module("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); // Create two contracts with the same code and check that they do in fact share it. - let addr0 = builder::bare_instantiate(Code::Upload(wasm.clone())) - .value(min_balance * 100) - .salt(vec![0]) - .build_and_unwrap_account_id(); - let addr1 = builder::bare_instantiate(Code::Upload(wasm.clone())) - .value(min_balance * 100) - .salt(vec![1]) - .build_and_unwrap_account_id(); + let Contract { addr: addr0, .. } = + builder::bare_instantiate(Code::Upload(wasm.clone())) + .value(min_balance * 100) + .salt([0; 32]) + .build_and_unwrap_contract(); + let Contract { addr: addr1, .. } = + builder::bare_instantiate(Code::Upload(wasm.clone())) + .value(min_balance * 100) + .salt([1; 32]) + .build_and_unwrap_contract(); assert_refcount!(code_hash, 2); // Sharing should also work with the usual instantiate call - let addr2 = builder::bare_instantiate(Code::Existing(code_hash)) + let Contract { addr: addr2, .. } = builder::bare_instantiate(Code::Existing(code_hash)) .value(min_balance * 100) - .salt(vec![2]) - .build_and_unwrap_account_id(); + .salt([2; 32]) + .build_and_unwrap_contract(); assert_refcount!(code_hash, 3); // Terminating one contract should decrement the refcount @@ -2069,13 +2080,13 @@ mod run_tests { #[test] fn debug_message_works() { - let (wasm, _code_hash) = compile_module::<Test>("debug_message_works").unwrap(); + let (wasm, _code_hash) = compile_module("debug_message_works").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(30_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); let result = builder::bare_call(addr).debug(DebugInfo::UnsafeDebug).build(); assert_matches!(result.result, Ok(_)); @@ -2085,13 +2096,13 @@ mod run_tests { #[test] fn debug_message_logging_disabled() { - let (wasm, _code_hash) = compile_module::<Test>("debug_message_logging_disabled").unwrap(); + let (wasm, _code_hash) = compile_module("debug_message_logging_disabled").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(30_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // the dispatchables always run without debugging assert_ok!(Contracts::call( RuntimeOrigin::signed(ALICE), @@ -2106,13 +2117,13 @@ mod run_tests { #[test] fn debug_message_invalid_utf8() { - let (wasm, _code_hash) = compile_module::<Test>("debug_message_invalid_utf8").unwrap(); + let (wasm, _code_hash) = compile_module("debug_message_invalid_utf8").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(30_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); let result = builder::bare_call(addr).debug(DebugInfo::UnsafeDebug).build(); assert_ok!(result.result); assert!(result.debug_message.is_empty()); @@ -2121,24 +2132,27 @@ mod run_tests { #[test] fn gas_estimation_for_subcalls() { - let (caller_code, _caller_hash) = compile_module::<Test>("call_with_limit").unwrap(); - let (call_runtime_code, _caller_hash) = compile_module::<Test>("call_runtime").unwrap(); - let (dummy_code, _callee_hash) = compile_module::<Test>("dummy").unwrap(); + let (caller_code, _caller_hash) = compile_module("call_with_limit").unwrap(); + let (call_runtime_code, _caller_hash) = compile_module("call_runtime").unwrap(); + let (dummy_code, _callee_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 2_000 * min_balance); - let addr_caller = builder::bare_instantiate(Code::Upload(caller_code)) - .value(min_balance * 100) - .build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(caller_code)) + .value(min_balance * 100) + .build_and_unwrap_contract(); - let addr_dummy = builder::bare_instantiate(Code::Upload(dummy_code)) - .value(min_balance * 100) - .build_and_unwrap_account_id(); + let Contract { addr: addr_dummy, .. } = + builder::bare_instantiate(Code::Upload(dummy_code)) + .value(min_balance * 100) + .build_and_unwrap_contract(); - let addr_call_runtime = builder::bare_instantiate(Code::Upload(call_runtime_code)) - .value(min_balance * 100) - .build_and_unwrap_account_id(); + let Contract { addr: addr_call_runtime, .. } = + builder::bare_instantiate(Code::Upload(call_runtime_code)) + .value(min_balance * 100) + .build_and_unwrap_contract(); // Run the test for all of those weight limits for the subcall let weights = [ @@ -2174,8 +2188,7 @@ mod run_tests { .collect(); // Call in order to determine the gas that is required for this call - let result_orig = - builder::bare_call(addr_caller.clone()).data(input.clone()).build(); + let result_orig = builder::bare_call(addr_caller).data(input.clone()).build(); assert_ok!(&result_orig.result); // If the out of gas happens in the subcall the caller contract @@ -2190,7 +2203,7 @@ mod run_tests { }; // Make the same call using the estimated gas. Should succeed. - let result = builder::bare_call(addr_caller.clone()) + let result = builder::bare_call(addr_caller) .gas_limit(result_orig.gas_required) .storage_deposit_limit(result_orig.storage_deposit.charge_or_zero()) .data(input.clone()) @@ -2198,7 +2211,7 @@ mod run_tests { assert_ok!(&result.result); // Check that it fails with too little ref_time - let result = builder::bare_call(addr_caller.clone()) + let result = builder::bare_call(addr_caller) .gas_limit(result_orig.gas_required.sub_ref_time(1)) .storage_deposit_limit(result_orig.storage_deposit.charge_or_zero()) .data(input.clone()) @@ -2206,7 +2219,7 @@ mod run_tests { assert_err!(result.result, error); // Check that it fails with too little proof_size - let result = builder::bare_call(addr_caller.clone()) + let result = builder::bare_call(addr_caller) .gas_limit(result_orig.gas_required.sub_proof_size(1)) .storage_deposit_limit(result_orig.storage_deposit.charge_or_zero()) .data(input.clone()) @@ -2219,16 +2232,17 @@ mod run_tests { #[test] fn gas_estimation_call_runtime() { - let (caller_code, _caller_hash) = compile_module::<Test>("call_runtime").unwrap(); + let (caller_code, _caller_hash) = compile_module("call_runtime").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); let _ = <Test as Config>::Currency::set_balance(&CHARLIE, 1000 * min_balance); - let addr_caller = builder::bare_instantiate(Code::Upload(caller_code)) - .value(min_balance * 100) - .salt(vec![0]) - .build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(caller_code)) + .value(min_balance * 100) + .salt([0; 32]) + .build_and_unwrap_contract(); // Call something trivial with a huge gas limit so that we can observe the effects // of pre-charging. This should create a difference between consumed and required. @@ -2236,7 +2250,7 @@ mod run_tests { pre_charge: Weight::from_parts(10_000_000, 1_000), actual_weight: Weight::from_parts(100, 100), }); - let result = builder::bare_call(addr_caller.clone()).data(call.encode()).build(); + let result = builder::bare_call(addr_caller).data(call.encode()).build(); // contract encodes the result of the dispatch runtime let outcome = u32::decode(&mut result.result.unwrap().data.as_ref()).unwrap(); assert_eq!(outcome, 0); @@ -2255,22 +2269,24 @@ mod run_tests { #[test] fn call_runtime_reentrancy_guarded() { - let (caller_code, _caller_hash) = compile_module::<Test>("call_runtime").unwrap(); - let (callee_code, _callee_hash) = compile_module::<Test>("dummy").unwrap(); + let (caller_code, _caller_hash) = compile_module("call_runtime").unwrap(); + let (callee_code, _callee_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); let _ = <Test as Config>::Currency::set_balance(&CHARLIE, 1000 * min_balance); - let addr_caller = builder::bare_instantiate(Code::Upload(caller_code)) - .value(min_balance * 100) - .salt(vec![0]) - .build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(caller_code)) + .value(min_balance * 100) + .salt([0; 32]) + .build_and_unwrap_contract(); - let addr_callee = builder::bare_instantiate(Code::Upload(callee_code)) - .value(min_balance * 100) - .salt(vec![1]) - .build_and_unwrap_account_id(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(callee_code)) + .value(min_balance * 100) + .salt([1; 32]) + .build_and_unwrap_contract(); // Call pallet_revive call() dispatchable let call = RuntimeCall::Contracts(crate::Call::call { @@ -2283,9 +2299,8 @@ mod run_tests { // Call runtime to re-enter back to contracts engine by // calling dummy contract - let result = builder::bare_call(addr_caller.clone()) - .data(call.encode()) - .build_and_unwrap_result(); + let result = + builder::bare_call(addr_caller).data(call.encode()).build_and_unwrap_result(); // Call to runtime should fail because of the re-entrancy guard assert_return_code!(result, RuntimeReturnCode::CallRuntimeFailed); }); @@ -2293,15 +2308,15 @@ mod run_tests { #[test] fn ecdsa_recover() { - let (wasm, _code_hash) = compile_module::<Test>("ecdsa_recover").unwrap(); + let (wasm, _code_hash) = compile_module("ecdsa_recover").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate the ecdsa_recover contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(100_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); #[rustfmt::skip] let signature: [u8; 65] = [ @@ -2326,7 +2341,7 @@ mod run_tests { params.extend_from_slice(&signature); params.extend_from_slice(&message_hash); assert!(params.len() == 65 + 32); - let result = builder::bare_call(addr.clone()).data(params).build_and_unwrap_result(); + let result = builder::bare_call(addr).data(params).build_and_unwrap_result(); assert!(!result.did_revert()); assert_eq!(result.data, EXPECTED_COMPRESSED_PUBLIC_KEY); }) @@ -2334,7 +2349,7 @@ mod run_tests { #[test] fn bare_instantiate_returns_events() { - let (wasm, _code_hash) = compile_module::<Test>("transfer_return_code").unwrap(); + let (wasm, _code_hash) = compile_module("transfer_return_code").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); @@ -2352,7 +2367,7 @@ mod run_tests { #[test] fn bare_instantiate_does_not_return_events() { - let (wasm, _code_hash) = compile_module::<Test>("transfer_return_code").unwrap(); + let (wasm, _code_hash) = compile_module("transfer_return_code").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); @@ -2368,18 +2383,17 @@ mod run_tests { #[test] fn bare_call_returns_events() { - let (wasm, _code_hash) = compile_module::<Test>("transfer_return_code").unwrap(); + let (wasm, _code_hash) = compile_module("transfer_return_code").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); - let result = builder::bare_call(addr.clone()) - .collect_events(CollectEvents::UnsafeCollect) - .build(); + let result = + builder::bare_call(addr).collect_events(CollectEvents::UnsafeCollect).build(); let events = result.events.unwrap(); assert_return_code!(&result.result.unwrap(), RuntimeReturnCode::Success); @@ -2390,16 +2404,16 @@ mod run_tests { #[test] fn bare_call_does_not_return_events() { - let (wasm, _code_hash) = compile_module::<Test>("transfer_return_code").unwrap(); + let (wasm, _code_hash) = compile_module("transfer_return_code").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let min_balance = Contracts::min_balance(); let _ = <Test as Config>::Currency::set_balance(&ALICE, 1000 * min_balance); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(min_balance * 100) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); - let result = builder::bare_call(addr.clone()).build(); + let result = builder::bare_call(addr).build(); let events = result.events; assert_return_code!(&result.result.unwrap(), RuntimeReturnCode::Success); @@ -2410,15 +2424,15 @@ mod run_tests { #[test] fn sr25519_verify() { - let (wasm, _code_hash) = compile_module::<Test>("sr25519_verify").unwrap(); + let (wasm, _code_hash) = compile_module("sr25519_verify").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate the sr25519_verify contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm)) .value(100_000) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); let call_with = |message: &[u8; 11]| { // Alice's signature for "hello world" @@ -2442,7 +2456,7 @@ mod run_tests { params.extend_from_slice(&public_key); params.extend_from_slice(message); - builder::bare_call(addr.clone()).data(params).build_and_unwrap_result() + builder::bare_call(addr).data(params).build_and_unwrap_result() }; // verification should succeed for "hello world" @@ -2455,8 +2469,8 @@ mod run_tests { #[test] fn failed_deposit_charge_should_roll_back_call() { - let (wasm_caller, _) = compile_module::<Test>("call_runtime_and_call").unwrap(); - let (wasm_callee, _) = compile_module::<Test>("store_call").unwrap(); + let (wasm_caller, _) = compile_module("call_runtime_and_call").unwrap(); + let (wasm_callee, _) = compile_module("store_call").unwrap(); const ED: u64 = 200; let execute = || { @@ -2464,15 +2478,16 @@ mod run_tests { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate both contracts. - let addr_caller = builder::bare_instantiate(Code::Upload(wasm_caller.clone())) - .build_and_unwrap_account_id(); - let addr_callee = builder::bare_instantiate(Code::Upload(wasm_callee.clone())) - .build_and_unwrap_account_id(); + let caller = builder::bare_instantiate(Code::Upload(wasm_caller.clone())) + .build_and_unwrap_contract(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(wasm_callee.clone())) + .build_and_unwrap_contract(); // Give caller proxy access to Alice. assert_ok!(Proxy::add_proxy( RuntimeOrigin::signed(ALICE), - addr_caller.clone(), + caller.account_id.clone(), (), 0 )); @@ -2497,7 +2512,7 @@ mod run_tests { transfer_proxy_call, ); - builder::call(addr_caller).data(data.encode()).build() + builder::call(caller.addr).data(data.encode()).build() }) }; @@ -2511,7 +2526,7 @@ mod run_tests { #[test] fn upload_code_works() { - let (wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -2532,7 +2547,7 @@ mod run_tests { event: RuntimeEvent::Contracts(crate::Event::CodeStored { code_hash, deposit_held: deposit_expected, - uploader: ALICE + uploader: ALICE_ADDR }), topics: vec![], },] @@ -2542,7 +2557,7 @@ mod run_tests { #[test] fn upload_code_limit_too_low() { - let (wasm, _code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _code_hash) = compile_module("dummy").unwrap(); let deposit_expected = expected_deposit(wasm.len()); let deposit_insufficient = deposit_expected.saturating_sub(1); @@ -2563,7 +2578,7 @@ mod run_tests { #[test] fn upload_code_not_enough_balance() { - let (wasm, _code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _code_hash) = compile_module("dummy").unwrap(); let deposit_expected = expected_deposit(wasm.len()); let deposit_insufficient = deposit_expected.saturating_sub(1); @@ -2584,7 +2599,7 @@ mod run_tests { #[test] fn remove_code_works() { - let (wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -2605,7 +2620,7 @@ mod run_tests { event: RuntimeEvent::Contracts(crate::Event::CodeStored { code_hash, deposit_held: deposit_expected, - uploader: ALICE + uploader: ALICE_ADDR }), topics: vec![], }, @@ -2614,7 +2629,7 @@ mod run_tests { event: RuntimeEvent::Contracts(crate::Event::CodeRemoved { code_hash, deposit_released: deposit_expected, - remover: ALICE + remover: ALICE_ADDR }), topics: vec![], }, @@ -2625,7 +2640,7 @@ mod run_tests { #[test] fn remove_code_wrong_origin() { - let (wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -2649,7 +2664,7 @@ mod run_tests { event: RuntimeEvent::Contracts(crate::Event::CodeStored { code_hash, deposit_held: deposit_expected, - uploader: ALICE + uploader: ALICE_ADDR }), topics: vec![], },] @@ -2659,7 +2674,7 @@ mod run_tests { #[test] fn remove_code_in_use() { - let (wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -2680,7 +2695,7 @@ mod run_tests { #[test] fn remove_code_not_found() { - let (_wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (_wasm, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -2699,7 +2714,7 @@ mod run_tests { #[test] fn instantiate_with_zero_balance_works() { - let (wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); @@ -2708,15 +2723,16 @@ mod run_tests { initialize_block(2); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); + let Contract { addr, account_id } = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); // Ensure the contract was stored and get expected deposit amount to be reserved. let deposit_expected = expected_deposit(ensure_stored(code_hash)); // Make sure the account exists even though no free balance was send - assert_eq!(<Test as Config>::Currency::free_balance(&addr), min_balance); + assert_eq!(<Test as Config>::Currency::free_balance(&account_id), min_balance); assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&account_id), min_balance + test_utils::contract_info_storage_deposit(&addr) ); @@ -2728,21 +2744,21 @@ mod run_tests { event: RuntimeEvent::Contracts(crate::Event::CodeStored { code_hash, deposit_held: deposit_expected, - uploader: ALICE + uploader: ALICE_ADDR }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: RuntimeEvent::System(frame_system::Event::NewAccount { - account: addr.clone(), + account: account_id.clone(), }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Endowed { - account: addr.clone(), + account: account_id.clone(), free_balance: min_balance, }), topics: vec![], @@ -2751,7 +2767,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { from: ALICE, - to: addr.clone(), + to: account_id, amount: min_balance, }), topics: vec![], @@ -2759,8 +2775,8 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Instantiated { - deployer: ALICE, - contract: addr.clone(), + deployer: ALICE_ADDR, + contract: addr, }), topics: vec![], }, @@ -2768,8 +2784,8 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts( pallet_revive::Event::StorageDepositTransferredAndHeld { - from: ALICE, - to: addr.clone(), + from: ALICE_ADDR, + to: addr, amount: test_utils::contract_info_storage_deposit(&addr), } ), @@ -2782,7 +2798,7 @@ mod run_tests { #[test] fn instantiate_with_below_existential_deposit_works() { - let (wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); @@ -2792,16 +2808,16 @@ mod run_tests { initialize_block(2); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(wasm)) .value(value) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Ensure the contract was stored and get expected deposit amount to be reserved. let deposit_expected = expected_deposit(ensure_stored(code_hash)); // Make sure the account exists even though not enough free balance was send - assert_eq!(<Test as Config>::Currency::free_balance(&addr), min_balance + value); + assert_eq!(<Test as Config>::Currency::free_balance(&account_id), min_balance + value); assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&account_id), min_balance + value + test_utils::contract_info_storage_deposit(&addr) ); @@ -2813,21 +2829,21 @@ mod run_tests { event: RuntimeEvent::Contracts(crate::Event::CodeStored { code_hash, deposit_held: deposit_expected, - uploader: ALICE + uploader: ALICE_ADDR }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: RuntimeEvent::System(frame_system::Event::NewAccount { - account: addr.clone() + account: account_id.clone() }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Endowed { - account: addr.clone(), + account: account_id.clone(), free_balance: min_balance, }), topics: vec![], @@ -2836,7 +2852,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { from: ALICE, - to: addr.clone(), + to: account_id.clone(), amount: min_balance, }), topics: vec![], @@ -2845,7 +2861,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { from: ALICE, - to: addr.clone(), + to: account_id.clone(), amount: 50, }), topics: vec![], @@ -2853,8 +2869,8 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Instantiated { - deployer: ALICE, - contract: addr.clone(), + deployer: ALICE_ADDR, + contract: addr, }), topics: vec![], }, @@ -2862,8 +2878,8 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts( pallet_revive::Event::StorageDepositTransferredAndHeld { - from: ALICE, - to: addr.clone(), + from: ALICE_ADDR, + to: addr, amount: test_utils::contract_info_storage_deposit(&addr), } ), @@ -2876,11 +2892,12 @@ mod run_tests { #[test] fn storage_deposit_works() { - let (wasm, _code_hash) = compile_module::<Test>("multi_store").unwrap(); + let (wasm, _code_hash) = compile_module("multi_store").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); + let Contract { addr, account_id } = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); let mut deposit = test_utils::contract_info_storage_deposit(&addr); @@ -2888,20 +2905,20 @@ mod run_tests { initialize_block(2); // Create storage - assert_ok!(builder::call(addr.clone()).value(42).data((50u32, 20u32).encode()).build()); + assert_ok!(builder::call(addr).value(42).data((50u32, 20u32).encode()).build()); // 4 is for creating 2 storage items let charged0 = 4 + 50 + 20; deposit += charged0; assert_eq!(get_contract(&addr).total_deposit(), deposit); // Add more storage (but also remove some) - assert_ok!(builder::call(addr.clone()).data((100u32, 10u32).encode()).build()); + assert_ok!(builder::call(addr).data((100u32, 10u32).encode()).build()); let charged1 = 50 - 10; deposit += charged1; assert_eq!(get_contract(&addr).total_deposit(), deposit); // Remove more storage (but also add some) - assert_ok!(builder::call(addr.clone()).data((10u32, 20u32).encode()).build()); + assert_ok!(builder::call(addr).data((10u32, 20u32).encode()).build()); // -1 for numeric instability let refunded0 = 90 - 10 - 1; deposit -= refunded0; @@ -2914,7 +2931,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { from: ALICE, - to: addr.clone(), + to: account_id.clone(), amount: 42, }), topics: vec![], @@ -2923,7 +2940,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: addr.clone(), + contract: addr, }), topics: vec![], }, @@ -2931,8 +2948,8 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts( pallet_revive::Event::StorageDepositTransferredAndHeld { - from: ALICE, - to: addr.clone(), + from: ALICE_ADDR, + to: addr, amount: charged0, } ), @@ -2942,7 +2959,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: addr.clone(), + contract: addr, }), topics: vec![], }, @@ -2950,8 +2967,8 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts( pallet_revive::Event::StorageDepositTransferredAndHeld { - from: ALICE, - to: addr.clone(), + from: ALICE_ADDR, + to: addr, amount: charged1, } ), @@ -2961,7 +2978,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: addr.clone(), + contract: addr, }), topics: vec![], }, @@ -2969,8 +2986,8 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts( pallet_revive::Event::StorageDepositTransferredAndReleased { - from: addr.clone(), - to: ALICE, + from: addr, + to: ALICE_ADDR, amount: refunded0, } ), @@ -2983,24 +3000,24 @@ mod run_tests { #[test] fn storage_deposit_callee_works() { - let (wasm_caller, _code_hash_caller) = compile_module::<Test>("call").unwrap(); - let (wasm_callee, _code_hash_callee) = compile_module::<Test>("store_call").unwrap(); + let (wasm_caller, _code_hash_caller) = compile_module("call").unwrap(); + let (wasm_callee, _code_hash_callee) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); // Create both contracts: Constructors do nothing. - let addr_caller = - builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_account_id(); - let addr_callee = - builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_contract(); + let Contract { addr: addr_callee, account_id } = + builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_contract(); assert_ok!(builder::call(addr_caller).data((100u32, &addr_callee).encode()).build()); let callee = get_contract(&addr_callee); let deposit = DepositPerByte::get() * 100 + DepositPerItem::get() * 1; - assert_eq!(test_utils::get_balance(&addr_callee), min_balance); + assert_eq!(test_utils::get_balance(&account_id), min_balance); assert_eq!( callee.total_deposit(), deposit + test_utils::contract_info_storage_deposit(&addr_callee) @@ -3010,15 +3027,16 @@ mod run_tests { #[test] fn set_code_extrinsic() { - let (wasm, code_hash) = compile_module::<Test>("dummy").unwrap(); - let (new_wasm, new_code_hash) = compile_module::<Test>("crypto_hashes").unwrap(); + let (wasm, code_hash) = compile_module("dummy").unwrap(); + let (new_wasm, new_code_hash) = compile_module("crypto_hashes").unwrap(); assert_ne!(code_hash, new_code_hash); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); assert_ok!(Contracts::upload_code( RuntimeOrigin::signed(ALICE), @@ -3035,7 +3053,7 @@ mod run_tests { // only root can execute this extrinsic assert_noop!( - Contracts::set_code(RuntimeOrigin::signed(ALICE), addr.clone(), new_code_hash), + Contracts::set_code(RuntimeOrigin::signed(ALICE), addr, new_code_hash), sp_runtime::traits::BadOrigin, ); assert_eq!(get_contract(&addr).code_hash, code_hash); @@ -3045,7 +3063,7 @@ mod run_tests { // contract must exist assert_noop!( - Contracts::set_code(RuntimeOrigin::root(), BOB, new_code_hash), + Contracts::set_code(RuntimeOrigin::root(), BOB_ADDR, new_code_hash), <Error<Test>>::ContractNotFound, ); assert_eq!(get_contract(&addr).code_hash, code_hash); @@ -3055,7 +3073,7 @@ mod run_tests { // new code hash must exist assert_noop!( - Contracts::set_code(RuntimeOrigin::root(), addr.clone(), Default::default()), + Contracts::set_code(RuntimeOrigin::root(), addr, Default::default()), <Error<Test>>::CodeNotFound, ); assert_eq!(get_contract(&addr).code_hash, code_hash); @@ -3064,7 +3082,7 @@ mod run_tests { assert_eq!(System::events(), vec![]); // successful call - assert_ok!(Contracts::set_code(RuntimeOrigin::root(), addr.clone(), new_code_hash)); + assert_ok!(Contracts::set_code(RuntimeOrigin::root(), addr, new_code_hash)); assert_eq!(get_contract(&addr).code_hash, new_code_hash); assert_refcount!(&code_hash, 0); assert_refcount!(&new_code_hash, 1); @@ -3073,7 +3091,7 @@ mod run_tests { vec![EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(pallet_revive::Event::ContractCodeUpdated { - contract: addr.clone(), + contract: addr, new_code_hash, old_code_hash: code_hash, }), @@ -3085,15 +3103,15 @@ mod run_tests { #[test] fn slash_cannot_kill_account() { - let (wasm, _code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let value = 700; let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); - let addr = builder::bare_instantiate(Code::Upload(wasm)) + let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(wasm)) .value(value) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Drop previous events initialize_block(2); @@ -3101,12 +3119,15 @@ mod run_tests { let info_deposit = test_utils::contract_info_storage_deposit(&addr); assert_eq!( - test_utils::get_balance_on_hold(&HoldReason::StorageDepositReserve.into(), &addr), + test_utils::get_balance_on_hold( + &HoldReason::StorageDepositReserve.into(), + &account_id + ), info_deposit ); assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&account_id), info_deposit + value + min_balance ); @@ -3116,18 +3137,18 @@ mod run_tests { // in staking. let _ = <Test as Config>::Currency::slash( &HoldReason::StorageDepositReserve.into(), - &addr, - <Test as Config>::Currency::total_balance(&addr), + &account_id, + <Test as Config>::Currency::total_balance(&account_id), ); // Slashing only removed the balance held. - assert_eq!(<Test as Config>::Currency::total_balance(&addr), value + min_balance); + assert_eq!(<Test as Config>::Currency::total_balance(&account_id), value + min_balance); }); } #[test] fn contract_reverted() { - let (wasm, code_hash) = compile_module::<Test>("return_with_data").unwrap(); + let (wasm, code_hash) = compile_module("return_with_data").unwrap(); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -3163,21 +3184,21 @@ mod run_tests { .build_and_unwrap_result(); assert_eq!(result.result.flags, flags); assert_eq!(result.result.data, buffer); - assert!(!<ContractInfoOf<Test>>::contains_key(result.account_id)); + assert!(!<ContractInfoOf<Test>>::contains_key(result.addr)); // Pass empty flags and therefore successfully instantiate the contract for later use. - let addr = builder::bare_instantiate(Code::Existing(code_hash)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Existing(code_hash)) .data(ReturnFlags::empty().bits().encode()) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); // Calling extrinsic: revert leads to an error assert_err_ignore_postinfo!( - builder::call(addr.clone()).data(input.clone()).build(), + builder::call(addr).data(input.clone()).build(), <Error<Test>>::ContractReverted, ); // Calling directly: revert leads to success but the flags indicate the error - let result = builder::bare_call(addr.clone()).data(input).build_and_unwrap_result(); + let result = builder::bare_call(addr).data(input).build_and_unwrap_result(); assert_eq!(result.flags, flags); assert_eq!(result.data, buffer); }); @@ -3185,17 +3206,17 @@ mod run_tests { #[test] fn set_code_hash() { - let (wasm, code_hash) = compile_module::<Test>("set_code_hash").unwrap(); - let (new_wasm, new_code_hash) = - compile_module::<Test>("new_set_code_hash_contract").unwrap(); + let (wasm, code_hash) = compile_module("set_code_hash").unwrap(); + let (new_wasm, new_code_hash) = compile_module("new_set_code_hash_contract").unwrap(); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate the 'caller' - let contract_addr = builder::bare_instantiate(Code::Upload(wasm)) - .value(300_000) - .build_and_unwrap_account_id(); + let Contract { addr: contract_addr, .. } = + builder::bare_instantiate(Code::Upload(wasm)) + .value(300_000) + .build_and_unwrap_contract(); // upload new code assert_ok!(Contracts::upload_code( RuntimeOrigin::signed(ALICE), @@ -3206,14 +3227,14 @@ mod run_tests { System::reset_events(); // First call sets new code_hash and returns 1 - let result = builder::bare_call(contract_addr.clone()) + let result = builder::bare_call(contract_addr) .data(new_code_hash.as_ref().to_vec()) .debug(DebugInfo::UnsafeDebug) .build_and_unwrap_result(); assert_return_code!(result, 1); // Second calls new contract code that returns 2 - let result = builder::bare_call(contract_addr.clone()) + let result = builder::bare_call(contract_addr) .debug(DebugInfo::UnsafeDebug) .build_and_unwrap_result(); assert_return_code!(result, 2); @@ -3225,7 +3246,7 @@ mod run_tests { EventRecord { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::ContractCodeUpdated { - contract: contract_addr.clone(), + contract: contract_addr, new_code_hash, old_code_hash: code_hash, }), @@ -3235,7 +3256,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: contract_addr.clone(), + contract: contract_addr, }), topics: vec![], }, @@ -3243,7 +3264,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Contracts(crate::Event::Called { caller: Origin::from_account_id(ALICE), - contract: contract_addr.clone(), + contract: contract_addr, }), topics: vec![], }, @@ -3254,7 +3275,7 @@ mod run_tests { #[test] fn storage_deposit_limit_is_enforced() { - let (wasm, _code_hash) = compile_module::<Test>("store_call").unwrap(); + let (wasm, _code_hash) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); @@ -3270,13 +3291,14 @@ mod run_tests { ); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); + let Contract { addr, account_id } = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); let info_deposit = test_utils::contract_info_storage_deposit(&addr); // Check that the BOB contract has been instantiated and has the minimum balance assert_eq!(get_contract(&addr).total_deposit(), info_deposit); assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&account_id), info_deposit + min_balance ); @@ -3284,7 +3306,7 @@ mod run_tests { // setting insufficient deposit limit, as it requires 3 Balance: // 2 for the item added + 1 for the new storage item. assert_err_ignore_postinfo!( - builder::call(addr.clone()) + builder::call(addr) .storage_deposit_limit(2) .data(1u32.to_le_bytes().to_vec()) .build(), @@ -3294,7 +3316,7 @@ mod run_tests { // Create 1 byte of storage, should cost 3 Balance: // 2 for the item added + 1 for the new storage item. // Should pass as it fallbacks to DefaultDepositLimit. - assert_ok!(builder::call(addr.clone()) + assert_ok!(builder::call(addr) .storage_deposit_limit(3) .data(1u32.to_le_bytes().to_vec()) .build()); @@ -3302,7 +3324,7 @@ mod run_tests { // Use 4 more bytes of the storage for the same item, which requires 4 Balance. // Should fail as DefaultDepositLimit is 3 and hence isn't enough. assert_err_ignore_postinfo!( - builder::call(addr.clone()) + builder::call(addr) .storage_deposit_limit(3) .data(5u32.to_le_bytes().to_vec()) .build(), @@ -3313,21 +3335,20 @@ mod run_tests { #[test] fn deposit_limit_in_nested_calls() { - let (wasm_caller, _code_hash_caller) = - compile_module::<Test>("create_storage_and_call").unwrap(); - let (wasm_callee, _code_hash_callee) = compile_module::<Test>("store_call").unwrap(); + let (wasm_caller, _code_hash_caller) = compile_module("create_storage_and_call").unwrap(); + let (wasm_callee, _code_hash_callee) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Create both contracts: Constructors do nothing. - let addr_caller = - builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_account_id(); - let addr_callee = - builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_contract(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_contract(); // Create 100 bytes of storage with a price of per byte // This is 100 Balance + 2 Balance for the item - assert_ok!(builder::call(addr_callee.clone()) + assert_ok!(builder::call(addr_callee) .storage_deposit_limit(102) .data(100u32.to_le_bytes().to_vec()) .build()); @@ -3338,7 +3359,7 @@ mod run_tests { // This should fail as the specified parent's limit is less than the cost: 13 < // 14. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .storage_deposit_limit(13) .data((100u32, &addr_callee, 0u64).encode()) .build(), @@ -3352,7 +3373,7 @@ mod run_tests { // This should fail as the specified parent's limit is less than the cost: 14 // < 15. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .storage_deposit_limit(14) .data((101u32, &addr_callee, 0u64).encode()) .build(), @@ -3365,7 +3386,7 @@ mod run_tests { // that the nested call should have a deposit limit of at least 2 Balance. The // sub-call should be rolled back, which is covered by the next test case. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .storage_deposit_limit(16) .data((102u32, &addr_callee, 1u64).encode()) .build(), @@ -3376,7 +3397,7 @@ mod run_tests { // caller. Note that if previous sub-call wouldn't roll back, this call would pass // making the test case fail. We don't set a special limit for the nested call here. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .storage_deposit_limit(0) .data((87u32, &addr_callee, 0u64).encode()) .build(), @@ -3388,16 +3409,14 @@ mod run_tests { // Require more than the sender's balance. // We don't set a special limit for the nested call. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) - .data((512u32, &addr_callee, 1u64).encode()) - .build(), + builder::call(addr_caller).data((512u32, &addr_callee, 1u64).encode()).build(), <Error<Test>>::StorageDepositLimitExhausted, ); // Same as above but allow for the additional deposit of 1 Balance in parent. // We set the special deposit limit of 1 Balance for the nested call, which isn't // enforced as callee frees up storage. This should pass. - assert_ok!(builder::call(addr_caller.clone()) + assert_ok!(builder::call(addr_caller) .storage_deposit_limit(1) .data((87u32, &addr_callee, 1u64).encode()) .build()); @@ -3407,20 +3426,21 @@ mod run_tests { #[test] fn deposit_limit_in_nested_instantiate() { let (wasm_caller, _code_hash_caller) = - compile_module::<Test>("create_storage_and_instantiate").unwrap(); - let (wasm_callee, code_hash_callee) = compile_module::<Test>("store_deploy").unwrap(); + compile_module("create_storage_and_instantiate").unwrap(); + let (wasm_callee, code_hash_callee) = compile_module("store_deploy").unwrap(); const ED: u64 = 5; ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let _ = <Test as Config>::Currency::set_balance(&BOB, 1_000_000); // Create caller contract - let addr_caller = builder::bare_instantiate(Code::Upload(wasm_caller)) - .value(10_000u64) // this balance is later passed to the deployed contract - .build_and_unwrap_account_id(); + let Contract { addr: addr_caller, account_id: caller_id } = + builder::bare_instantiate(Code::Upload(wasm_caller)) + .value(10_000u64) // this balance is later passed to the deployed contract + .build_and_unwrap_contract(); // Deploy a contract to get its occupied storage size - let addr = builder::bare_instantiate(Code::Upload(wasm_callee)) + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm_callee)) .data(vec![0, 0, 0, 0]) - .build_and_unwrap_account_id(); + .build_and_unwrap_contract(); let callee_info_len = ContractInfoOf::<Test>::get(&addr).unwrap().encoded_size() as u64; @@ -3436,7 +3456,7 @@ mod run_tests { // Provided the limit is set to be 1 Balance less, // this call should fail on the return from the caller contract. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(callee_info_len + 2 + ED + 1) .data((0u32, &code_hash_callee, 0u64).encode()) @@ -3450,7 +3470,7 @@ mod run_tests { // byte in the constructor. Hence +1 Balance to the limit is needed. This should fail on // the return from constructor. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(callee_info_len + 2 + ED + 2) .data((1u32, &code_hash_callee, 0u64).encode()) @@ -3464,7 +3484,7 @@ mod run_tests { // instantiate. This should fail during the charging for the instantiation in // `RawMeter::charge_instantiate()` assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(callee_info_len + 2 + ED + 2) .data((0u32, &code_hash_callee, callee_info_len + 2 + ED + 1).encode()) @@ -3479,7 +3499,7 @@ mod run_tests { // Now we set enough limit for the parent call, but insufficient limit for child // instantiate. This should fail right after the constructor execution. assert_err_ignore_postinfo!( - builder::call(addr_caller.clone()) + builder::call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(callee_info_len + 2 + ED + 3) // enough parent limit .data((1u32, &code_hash_callee, callee_info_len + 2 + ED + 2).encode()) @@ -3490,7 +3510,7 @@ mod run_tests { assert_eq!(<Test as Config>::Currency::free_balance(&BOB), 1_000_000); // Set enough deposit limit for the child instantiate. This should succeed. - let result = builder::bare_call(addr_caller.clone()) + let result = builder::bare_call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(callee_info_len + 2 + ED + 4) .data((1u32, &code_hash_callee, callee_info_len + 2 + ED + 3).encode()) @@ -3499,12 +3519,13 @@ mod run_tests { let returned = result.result.unwrap(); // All balance of the caller except ED has been transferred to the callee. // No deposit has been taken from it. - assert_eq!(<Test as Config>::Currency::free_balance(&addr_caller), ED); + assert_eq!(<Test as Config>::Currency::free_balance(&caller_id), ED); // Get address of the deployed contract. - let addr_callee = AccountId32::from_slice(&returned.data[0..32]).unwrap(); + let addr_callee = H160::from_slice(&returned.data[0..20]); + let callee_account_id = <Test as Config>::AddressMapper::to_account_id(&addr_callee); // 10_000 should be sent to callee from the caller contract, plus ED to be sent from the // origin. - assert_eq!(<Test as Config>::Currency::free_balance(&addr_callee), 10_000 + ED); + assert_eq!(<Test as Config>::Currency::free_balance(&callee_account_id), 10_000 + ED); // The origin should be charged with: // - callee instantiation deposit = (callee_info_len + 2) // - callee account ED @@ -3520,7 +3541,7 @@ mod run_tests { #[test] fn deposit_limit_honors_liquidity_restrictions() { - let (wasm, _code_hash) = compile_module::<Test>("store_call").unwrap(); + let (wasm, _code_hash) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let bobs_balance = 1_000; let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); @@ -3528,13 +3549,14 @@ mod run_tests { let min_balance = Contracts::min_balance(); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); + let Contract { addr, account_id } = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); let info_deposit = test_utils::contract_info_storage_deposit(&addr); // Check that the contract has been instantiated and has the minimum balance assert_eq!(get_contract(&addr).total_deposit(), info_deposit); assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&account_id), info_deposit + min_balance ); @@ -3546,7 +3568,7 @@ mod run_tests { ) .unwrap(); assert_err_ignore_postinfo!( - builder::call(addr.clone()) + builder::call(addr) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(10_000) .data(100u32.to_le_bytes().to_vec()) @@ -3559,27 +3581,28 @@ mod run_tests { #[test] fn deposit_limit_honors_existential_deposit() { - let (wasm, _code_hash) = compile_module::<Test>("store_call").unwrap(); + let (wasm, _code_hash) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let _ = <Test as Config>::Currency::set_balance(&BOB, 300); let min_balance = Contracts::min_balance(); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); + let Contract { addr, account_id } = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); let info_deposit = test_utils::contract_info_storage_deposit(&addr); // Check that the contract has been instantiated and has the minimum balance assert_eq!(get_contract(&addr).total_deposit(), info_deposit); assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&account_id), min_balance + info_deposit ); // check that the deposit can't bring the account below the existential deposit assert_err_ignore_postinfo!( - builder::call(addr.clone()) + builder::call(addr) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(10_000) .data(100u32.to_le_bytes().to_vec()) @@ -3592,14 +3615,15 @@ mod run_tests { #[test] fn deposit_limit_honors_min_leftover() { - let (wasm, _code_hash) = compile_module::<Test>("store_call").unwrap(); + let (wasm, _code_hash) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); let _ = <Test as Config>::Currency::set_balance(&BOB, 1_000); let min_balance = Contracts::min_balance(); // Instantiate the BOB contract. - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); + let Contract { addr, account_id } = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); let info_deposit = test_utils::contract_info_storage_deposit(&addr); @@ -3607,7 +3631,7 @@ mod run_tests { // storage deposit assert_eq!(get_contract(&addr).total_deposit(), info_deposit); assert_eq!( - <Test as Config>::Currency::total_balance(&addr), + <Test as Config>::Currency::total_balance(&account_id), info_deposit + min_balance ); @@ -3616,7 +3640,7 @@ mod run_tests { // 50 for the storage deposit. Which is not enough to store the 50 bytes // as we also need 2 bytes for the item assert_err_ignore_postinfo!( - builder::call(addr.clone()) + builder::call(addr) .origin(RuntimeOrigin::signed(BOB)) .value(750) .storage_deposit_limit(10_000) @@ -3633,13 +3657,12 @@ mod run_tests { // set hash lock up deposit to 30%, to test deposit calculation. CODE_HASH_LOCKUP_DEPOSIT_PERCENT.with(|c| *c.borrow_mut() = Perbill::from_percent(30)); - let (wasm_caller, self_code_hash) = - compile_module::<Test>("locking_delegate_dependency").unwrap(); + let (wasm_caller, self_code_hash) = compile_module("locking_delegate_dependency").unwrap(); let callee_codes: Vec<_> = (0..limits::DELEGATE_DEPENDENCIES + 1).map(|idx| dummy_unique(idx)).collect(); let callee_hashes: Vec<_> = callee_codes .iter() - .map(|c| <Test as frame_system::Config>::Hashing::hash(c)) + .map(|c| sp_core::H256(sp_io::hashing::keccak_256(c))) .collect(); // Define inputs with various actions to test locking / unlocking delegate_dependencies. @@ -3652,17 +3675,21 @@ mod run_tests { // Instantiate the caller contract with the given input. let instantiate = |input: &(u32, H256)| { builder::bare_instantiate(Code::Upload(wasm_caller.clone())) + .origin(RuntimeOrigin::signed(ETH_ALICE)) .data(input.encode()) .build() }; // Call contract with the given input. - let call = |addr_caller: &AccountId32, input: &(u32, H256)| { - builder::bare_call(addr_caller.clone()).data(input.encode()).build() + let call = |addr_caller: &H160, input: &(u32, H256)| { + builder::bare_call(*addr_caller) + .origin(RuntimeOrigin::signed(ETH_ALICE)) + .data(input.encode()) + .build() }; const ED: u64 = 2000; ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let _ = Balances::set_balance(&ALICE, 1_000_000); + let _ = Balances::set_balance(Ð_ALICE, 1_000_000); // Instantiate with lock_delegate_dependency should fail since the code is not yet on // chain. @@ -3676,7 +3703,7 @@ mod run_tests { for code in callee_codes.iter() { let CodeUploadReturnValue { deposit: deposit_per_code, .. } = Contracts::bare_upload_code( - RuntimeOrigin::signed(ALICE), + RuntimeOrigin::signed(ETH_ALICE), code.clone(), deposit_limit::<Test>(), ) @@ -3685,8 +3712,8 @@ mod run_tests { } // Instantiate should now work. - let addr_caller = - instantiate(&lock_delegate_dependency_input).result.unwrap().account_id; + let addr_caller = instantiate(&lock_delegate_dependency_input).result.unwrap().addr; + let caller_account_id = <Test as Config>::AddressMapper::to_account_id(&addr_caller); // There should be a dependency and a deposit. let contract = test_utils::get_contract(&addr_caller); @@ -3699,14 +3726,14 @@ mod run_tests { assert_eq!( test_utils::get_balance_on_hold( &HoldReason::StorageDepositReserve.into(), - &addr_caller + &caller_account_id ), dependency_deposit + contract.storage_base_deposit() ); // Removing the code should fail, since we have added a dependency. assert_err!( - Contracts::remove_code(RuntimeOrigin::signed(ALICE), callee_hashes[0]), + Contracts::remove_code(RuntimeOrigin::signed(ETH_ALICE), callee_hashes[0]), <Error<Test>>::CodeInUse ); @@ -3742,7 +3769,7 @@ mod run_tests { assert_eq!( test_utils::get_balance_on_hold( &HoldReason::StorageDepositReserve.into(), - &addr_caller + &caller_account_id ), contract.storage_base_deposit() ); @@ -3755,7 +3782,7 @@ mod run_tests { // Locking a dependency with a storage limit too low should fail. assert_err!( - builder::bare_call(addr_caller.clone()) + builder::bare_call(addr_caller) .storage_deposit_limit(dependency_deposit - 1) .data(lock_delegate_dependency_input.encode()) .build() @@ -3764,14 +3791,14 @@ mod run_tests { ); // Since we unlocked the dependency we should now be able to remove the code. - assert_ok!(Contracts::remove_code(RuntimeOrigin::signed(ALICE), callee_hashes[0])); + assert_ok!(Contracts::remove_code(RuntimeOrigin::signed(ETH_ALICE), callee_hashes[0])); // Calling should fail since the delegated contract is not on chain anymore. assert_err!(call(&addr_caller, &noop_input).result, Error::<Test>::ContractTrapped); // Add the dependency back. Contracts::upload_code( - RuntimeOrigin::signed(ALICE), + RuntimeOrigin::signed(ETH_ALICE), callee_codes[0].clone(), deposit_limit::<Test>(), ) @@ -3779,22 +3806,22 @@ mod run_tests { call(&addr_caller, &lock_delegate_dependency_input).result.unwrap(); // Call terminate should work, and return the deposit. - let balance_before = test_utils::get_balance(&ALICE); + let balance_before = test_utils::get_balance(Ð_ALICE); assert_ok!(call(&addr_caller, &terminate_input).result); assert_eq!( - test_utils::get_balance(&ALICE), + test_utils::get_balance(Ð_ALICE), ED + balance_before + contract.storage_base_deposit() + dependency_deposit ); // Terminate should also remove the dependency, so we can remove the code. - assert_ok!(Contracts::remove_code(RuntimeOrigin::signed(ALICE), callee_hashes[0])); + assert_ok!(Contracts::remove_code(RuntimeOrigin::signed(ETH_ALICE), callee_hashes[0])); }); } #[test] fn native_dependency_deposit_works() { - let (wasm, code_hash) = compile_module::<Test>("set_code_hash").unwrap(); - let (dummy_wasm, dummy_code_hash) = compile_module::<Test>("dummy").unwrap(); + let (wasm, code_hash) = compile_module("set_code_hash").unwrap(); + let (dummy_wasm, dummy_code_hash) = compile_module("dummy").unwrap(); // Set hash lock up deposit to 30%, to test deposit calculation. CODE_HASH_LOCKUP_DEPOSIT_PERCENT.with(|c| *c.borrow_mut() = Perbill::from_percent(30)); @@ -3830,7 +3857,8 @@ mod run_tests { // Instantiate the set_code_hash contract. let res = builder::bare_instantiate(code).build(); - let addr = res.result.unwrap().account_id; + let addr = res.result.unwrap().addr; + let account_id = <Test as Config>::AddressMapper::to_account_id(&addr); let base_deposit = test_utils::contract_info_storage_deposit(&addr); let upload_deposit = test_utils::get_code_deposit(&code_hash); let extra_deposit = add_upload_deposit.then(|| upload_deposit).unwrap_or_default(); @@ -3846,7 +3874,7 @@ mod run_tests { ); // call set_code_hash - builder::bare_call(addr.clone()) + builder::bare_call(addr) .data(dummy_code_hash.encode()) .build_and_unwrap_result(); @@ -3858,7 +3886,7 @@ mod run_tests { assert_eq!( test_utils::get_balance_on_hold( &HoldReason::StorageDepositReserve.into(), - &addr + &account_id ), deposit ); @@ -3868,7 +3896,7 @@ mod run_tests { #[test] fn root_cannot_upload_code() { - let (wasm, _) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _) = compile_module("dummy").unwrap(); ExtBuilder::default().build().execute_with(|| { assert_noop!( @@ -3880,7 +3908,7 @@ mod run_tests { #[test] fn root_cannot_remove_code() { - let (_, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (_, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().build().execute_with(|| { assert_noop!( @@ -3892,11 +3920,11 @@ mod run_tests { #[test] fn signed_cannot_set_code() { - let (_, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (_, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().build().execute_with(|| { assert_noop!( - Contracts::set_code(RuntimeOrigin::signed(ALICE), BOB, code_hash), + Contracts::set_code(RuntimeOrigin::signed(ALICE), BOB_ADDR, code_hash), DispatchError::BadOrigin, ); }); @@ -3906,7 +3934,7 @@ mod run_tests { fn none_cannot_call_code() { ExtBuilder::default().build().execute_with(|| { assert_err_ignore_postinfo!( - builder::call(BOB).origin(RuntimeOrigin::none()).build(), + builder::call(BOB_ADDR).origin(RuntimeOrigin::none()).build(), DispatchError::BadOrigin, ); }); @@ -3914,21 +3942,22 @@ mod run_tests { #[test] fn root_can_call() { - let (wasm, _) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(100).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_account_id(); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); // Call the contract. - assert_ok!(builder::call(addr.clone()).origin(RuntimeOrigin::root()).build()); + assert_ok!(builder::call(addr).origin(RuntimeOrigin::root()).build()); }); } #[test] fn root_cannot_instantiate_with_code() { - let (wasm, _) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _) = compile_module("dummy").unwrap(); ExtBuilder::default().build().execute_with(|| { assert_err_ignore_postinfo!( @@ -3940,7 +3969,7 @@ mod run_tests { #[test] fn root_cannot_instantiate() { - let (_, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (_, code_hash) = compile_module("dummy").unwrap(); ExtBuilder::default().build().execute_with(|| { assert_err_ignore_postinfo!( @@ -3952,7 +3981,7 @@ mod run_tests { #[test] fn only_upload_origin_can_upload() { - let (wasm, _) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _) = compile_module("dummy").unwrap(); UploadAccount::set(Some(ALICE)); ExtBuilder::default().build().execute_with(|| { let _ = Balances::set_balance(&ALICE, 1_000_000); @@ -3987,7 +4016,7 @@ mod run_tests { #[test] fn only_instantiation_origin_can_instantiate() { - let (code, code_hash) = compile_module::<Test>("dummy").unwrap(); + let (code, code_hash) = compile_module("dummy").unwrap(); InstantiateAccount::set(Some(ALICE)); ExtBuilder::default().build().execute_with(|| { let _ = Balances::set_balance(&ALICE, 1_000_000); @@ -4020,23 +4049,23 @@ mod run_tests { #[test] fn balance_api_returns_free_balance() { - let (wasm, _code_hash) = compile_module::<Test>("balance").unwrap(); + let (wasm, _code_hash) = compile_module("balance").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Instantiate the BOB contract without any extra balance. - let addr = builder::bare_instantiate(Code::Upload(wasm.to_vec())) - .build_and_unwrap_account_id(); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(wasm.to_vec())).build_and_unwrap_contract(); let value = 0; // Call BOB which makes it call the balance runtime API. // The contract code asserts that the returned balance is 0. - assert_ok!(builder::call(addr.clone()).value(value).build()); + assert_ok!(builder::call(addr).value(value).build()); let value = 1; // Calling with value will trap the contract. assert_err_ignore_postinfo!( - builder::call(addr.clone()).value(value).build(), + builder::call(addr).value(value).build(), <Error<Test>>::ContractTrapped ); }); @@ -4044,17 +4073,18 @@ mod run_tests { #[test] fn gas_consumed_is_linear_for_nested_calls() { - let (code, _code_hash) = compile_module::<Test>("recurse").unwrap(); + let (code, _code_hash) = compile_module("recurse").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); - let addr = builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_account_id(); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); let [gas_0, gas_1, gas_2, gas_max] = { [0u32, 1u32, 2u32, limits::CALL_STACK_DEPTH] .iter() .map(|i| { - let result = builder::bare_call(addr.clone()).data(i.encode()).build(); + let result = builder::bare_call(addr).data(i.encode()).build(); assert_ok!(result.result); result.gas_consumed }) @@ -4070,16 +4100,16 @@ mod run_tests { #[test] fn read_only_call_cannot_store() { - let (wasm_caller, _code_hash_caller) = compile_module::<Test>("read_only_call").unwrap(); - let (wasm_callee, _code_hash_callee) = compile_module::<Test>("store_call").unwrap(); + let (wasm_caller, _code_hash_caller) = compile_module("read_only_call").unwrap(); + let (wasm_callee, _code_hash_callee) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Create both contracts: Constructors do nothing. - let addr_caller = - builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_account_id(); - let addr_callee = - builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_contract(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_contract(); // Read-only call fails when modifying storage. assert_err_ignore_postinfo!( @@ -4091,17 +4121,16 @@ mod run_tests { #[test] fn read_only_call_cannot_transfer() { - let (wasm_caller, _code_hash_caller) = - compile_module::<Test>("call_with_flags_and_value").unwrap(); - let (wasm_callee, _code_hash_callee) = compile_module::<Test>("dummy").unwrap(); + let (wasm_caller, _code_hash_caller) = compile_module("call_with_flags_and_value").unwrap(); + let (wasm_callee, _code_hash_callee) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Create both contracts: Constructors do nothing. - let addr_caller = - builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_account_id(); - let addr_callee = - builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_contract(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_contract(); // Read-only call fails when a non-zero value is set. assert_err_ignore_postinfo!( @@ -4118,21 +4147,20 @@ mod run_tests { #[test] fn read_only_subsequent_call_cannot_store() { - let (wasm_read_only_caller, _code_hash_caller) = - compile_module::<Test>("read_only_call").unwrap(); - let (wasm_caller, _code_hash_caller) = - compile_module::<Test>("call_with_flags_and_value").unwrap(); - let (wasm_callee, _code_hash_callee) = compile_module::<Test>("store_call").unwrap(); + let (wasm_read_only_caller, _code_hash_caller) = compile_module("read_only_call").unwrap(); + let (wasm_caller, _code_hash_caller) = compile_module("call_with_flags_and_value").unwrap(); + let (wasm_callee, _code_hash_callee) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Create contracts: Constructors do nothing. - let addr_caller = builder::bare_instantiate(Code::Upload(wasm_read_only_caller)) - .build_and_unwrap_account_id(); - let addr_subsequent_caller = - builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_account_id(); - let addr_callee = - builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(wasm_read_only_caller)) + .build_and_unwrap_contract(); + let Contract { addr: addr_subsequent_caller, .. } = + builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_contract(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_contract(); // Subsequent call input. let input = (&addr_callee, pallet_revive_uapi::CallFlags::empty().bits(), 0u64, 100u32); @@ -4149,18 +4177,18 @@ mod run_tests { #[test] fn read_only_call_works() { - let (wasm_caller, _code_hash_caller) = compile_module::<Test>("read_only_call").unwrap(); - let (wasm_callee, _code_hash_callee) = compile_module::<Test>("dummy").unwrap(); + let (wasm_caller, _code_hash_caller) = compile_module("read_only_call").unwrap(); + let (wasm_callee, _code_hash_callee) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); // Create both contracts: Constructors do nothing. - let addr_caller = - builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_account_id(); - let addr_callee = - builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_account_id(); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(wasm_caller)).build_and_unwrap_contract(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(wasm_callee)).build_and_unwrap_contract(); - assert_ok!(builder::call(addr_caller.clone()).data(addr_callee.encode()).build()); + assert_ok!(builder::call(addr_caller).data(addr_callee.encode()).build()); }); } } diff --git a/substrate/frame/revive/src/tests/test_debug.rs b/substrate/frame/revive/src/tests/test_debug.rs index 166a0a8606a..e3571b7f21e 100644 --- a/substrate/frame/revive/src/tests/test_debug.rs +++ b/substrate/frame/revive/src/tests/test_debug.rs @@ -16,18 +16,19 @@ // limitations under the License. use super::*; + use crate::{ debug::{CallInterceptor, CallSpan, ExecResult, ExportedFunction, Tracing}, primitives::ExecReturnValue, test_utils::*, - AccountIdOf, }; use frame_support::traits::Currency; +use sp_core::H160; use std::cell::RefCell; #[derive(Clone, PartialEq, Eq, Debug)] struct DebugFrame { - contract_account: AccountId32, + contract_account: sp_core::H160, call: ExportedFunction, input: Vec<u8>, result: Option<Vec<u8>>, @@ -35,12 +36,12 @@ struct DebugFrame { thread_local! { static DEBUG_EXECUTION_TRACE: RefCell<Vec<DebugFrame>> = RefCell::new(Vec::new()); - static INTERCEPTED_ADDRESS: RefCell<Option<AccountId32>> = RefCell::new(None); + static INTERCEPTED_ADDRESS: RefCell<Option<sp_core::H160>> = RefCell::new(None); } pub struct TestDebug; pub struct TestCallSpan { - contract_account: AccountId32, + contract_account: sp_core::H160, call: ExportedFunction, input: Vec<u8>, } @@ -49,20 +50,20 @@ impl Tracing<Test> for TestDebug { type CallSpan = TestCallSpan; fn new_call_span( - contract_account: &AccountIdOf<Test>, + contract_account: &crate::H160, entry_point: ExportedFunction, input_data: &[u8], ) -> TestCallSpan { DEBUG_EXECUTION_TRACE.with(|d| { d.borrow_mut().push(DebugFrame { - contract_account: contract_account.clone(), + contract_account: *contract_account, call: entry_point, input: input_data.to_vec(), result: None, }) }); TestCallSpan { - contract_account: contract_account.clone(), + contract_account: *contract_account, call: entry_point, input: input_data.to_vec(), } @@ -71,7 +72,7 @@ impl Tracing<Test> for TestDebug { impl CallInterceptor<Test> for TestDebug { fn intercept_call( - contract_address: &<Test as frame_system::Config>::AccountId, + contract_address: &sp_core::H160, _entry_point: ExportedFunction, _input_data: &[u8], ) -> Option<ExecResult> { @@ -106,14 +107,14 @@ mod run_tests { #[test] fn debugging_works() { - let (wasm_caller, _) = compile_module::<Test>("call").unwrap(); - let (wasm_callee, _) = compile_module::<Test>("store_call").unwrap(); + let (wasm_caller, _) = compile_module("call").unwrap(); + let (wasm_callee, _) = compile_module("store_call").unwrap(); fn current_stack() -> Vec<DebugFrame> { DEBUG_EXECUTION_TRACE.with(|stack| stack.borrow().clone()) } - fn deploy(wasm: Vec<u8>) -> AccountId32 { + fn deploy(wasm: Vec<u8>) -> H160 { Contracts::bare_instantiate( RuntimeOrigin::signed(ALICE), 0, @@ -121,27 +122,27 @@ mod run_tests { deposit_limit::<Test>(), Code::Upload(wasm), vec![], - vec![], + [0u8; 32], DebugInfo::Skip, CollectEvents::Skip, ) .result .unwrap() - .account_id + .addr } - fn constructor_frame(contract_account: &AccountId32, after: bool) -> DebugFrame { + fn constructor_frame(contract_account: &H160, after: bool) -> DebugFrame { DebugFrame { - contract_account: contract_account.clone(), + contract_account: *contract_account, call: ExportedFunction::Constructor, input: vec![], result: if after { Some(vec![]) } else { None }, } } - fn call_frame(contract_account: &AccountId32, args: Vec<u8>, after: bool) -> DebugFrame { + fn call_frame(contract_account: &H160, args: Vec<u8>, after: bool) -> DebugFrame { DebugFrame { - contract_account: contract_account.clone(), + contract_account: *contract_account, call: ExportedFunction::Call, input: args, result: if after { Some(vec![]) } else { None }, @@ -171,7 +172,7 @@ mod run_tests { assert_ok!(Contracts::call( RuntimeOrigin::signed(ALICE), - addr_caller.clone(), + addr_caller, 0, GAS_LIMIT, deposit_limit::<Test>(), @@ -193,7 +194,7 @@ mod run_tests { #[test] fn call_interception_works() { - let (wasm, _) = compile_module::<Test>("dummy").unwrap(); + let (wasm, _) = compile_module("dummy").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = Balances::deposit_creating(&ALICE, 1_000_000); @@ -206,18 +207,18 @@ mod run_tests { Code::Upload(wasm), vec![], // some salt to ensure that the address of this contract is unique among all tests - vec![0x41, 0x41, 0x41, 0x41], + [0x41; 32], DebugInfo::Skip, CollectEvents::Skip, ) .result .unwrap() - .account_id; + .addr; // no interception yet assert_ok!(Contracts::call( RuntimeOrigin::signed(ALICE), - account_id.clone(), + account_id, 0, GAS_LIMIT, deposit_limit::<Test>(), @@ -225,7 +226,7 @@ mod run_tests { )); // intercept calls to this contract - INTERCEPTED_ADDRESS.with(|i| *i.borrow_mut() = Some(account_id.clone())); + INTERCEPTED_ADDRESS.with(|i| *i.borrow_mut() = Some(account_id)); assert_err_ignore_postinfo!( Contracts::call( diff --git a/substrate/frame/revive/src/wasm/mod.rs b/substrate/frame/revive/src/wasm/mod.rs index 784993ca793..9024390fd24 100644 --- a/substrate/frame/revive/src/wasm/mod.rs +++ b/substrate/frame/revive/src/wasm/mod.rs @@ -32,12 +32,13 @@ pub use crate::wasm::runtime::{ReturnData, TrapReason}; pub use crate::wasm::runtime::{ApiVersion, Memory, Runtime, RuntimeCosts}; use crate::{ + address::AddressMapper, exec::{ExecResult, Executable, ExportedFunction, Ext}, gas::{GasMeter, Token}, storage::meter::Diff, weights::WeightInfo, - AccountIdOf, BadOrigin, BalanceOf, CodeHash, CodeInfoOf, CodeVec, Config, Error, Event, - ExecError, HoldReason, Pallet, PristineCode, Weight, API_VERSION, LOG_TARGET, + AccountIdOf, BadOrigin, BalanceOf, CodeInfoOf, CodeVec, Config, Error, Event, ExecError, + HoldReason, Pallet, PristineCode, Weight, API_VERSION, LOG_TARGET, }; use alloc::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; @@ -47,7 +48,7 @@ use frame_support::{ traits::{fungible::MutateHold, tokens::Precision::BestEffort}, }; use sp_core::Get; -use sp_runtime::{traits::Hash, DispatchError}; +use sp_runtime::DispatchError; /// Validated Wasm module ready for execution. /// This data structure is immutable once created and stored. @@ -61,7 +62,7 @@ pub struct WasmBlob<T: Config> { code_info: CodeInfo<T>, // This is for not calculating the hash every time we need it. #[codec(skip)] - code_hash: CodeHash<T>, + code_hash: sp_core::H256, } /// Contract code related data, such as: @@ -143,14 +144,14 @@ impl<T: Config> WasmBlob<T> { api_version: API_VERSION, behaviour_version: Default::default(), }; - let code_hash = T::Hashing::hash(&code); + let code_hash = sp_core::H256(sp_io::hashing::keccak_256(&code)); Ok(WasmBlob { code, code_info, code_hash }) } /// Remove the code from storage and refund the deposit to its owner. /// /// Applies all necessary checks before removing the code. - pub fn remove(origin: &T::AccountId, code_hash: CodeHash<T>) -> DispatchResult { + pub fn remove(origin: &T::AccountId, code_hash: sp_core::H256) -> DispatchResult { <CodeInfoOf<T>>::try_mutate_exists(&code_hash, |existing| { if let Some(code_info) = existing { ensure!(code_info.refcount == 0, <Error<T>>::CodeInUse); @@ -162,7 +163,7 @@ impl<T: Config> WasmBlob<T> { BestEffort, ); let deposit_released = code_info.deposit; - let remover = code_info.owner.clone(); + let remover = T::AddressMapper::to_address(&code_info.owner); *existing = None; <PristineCode<T>>::remove(&code_hash); @@ -201,10 +202,11 @@ impl<T: Config> WasmBlob<T> { self.code_info.refcount = 0; <PristineCode<T>>::insert(code_hash, &self.code); *stored_code_info = Some(self.code_info.clone()); + let uploader = T::AddressMapper::to_address(&self.code_info.owner); <Pallet<T>>::deposit_event(Event::CodeStored { code_hash, deposit_held: deposit, - uploader: self.code_info.owner.clone(), + uploader, }); Ok(deposit) }, @@ -315,7 +317,7 @@ impl<T: Config> WasmBlob<T> { impl<T: Config> Executable<T> for WasmBlob<T> { fn from_storage( - code_hash: CodeHash<T>, + code_hash: sp_core::H256, gas_meter: &mut GasMeter<T>, ) -> Result<Self, DispatchError> { let code_info = <CodeInfoOf<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?; @@ -340,11 +342,15 @@ impl<T: Config> Executable<T> for WasmBlob<T> { prepared_call.call() } - fn code_info(&self) -> &CodeInfo<T> { - &self.code_info + fn code(&self) -> &[u8] { + self.code.as_ref() } - fn code_hash(&self) -> &CodeHash<T> { + fn code_hash(&self) -> &sp_core::H256 { &self.code_hash } + + fn code_info(&self) -> &CodeInfo<T> { + &self.code_info + } } diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index de910e79e73..70d405da989 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -18,12 +18,13 @@ //! Environment definition of the wasm smart-contract runtime. use crate::{ + address::AddressMapper, exec::{ExecError, ExecResult, Ext, Key, TopicOf}, gas::{ChargedAmount, Token}, limits, primitives::ExecReturnValue, weights::WeightInfo, - BalanceOf, CodeHash, Config, Error, LOG_TARGET, SENTINEL, + BalanceOf, Config, Error, LOG_TARGET, SENTINEL, }; use alloc::{boxed::Box, vec, vec::Vec}; use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; @@ -34,6 +35,7 @@ use frame_support::{ }; use pallet_revive_proc_macro::define_env; use pallet_revive_uapi::{CallFlags, ReturnErrorCode, ReturnFlags, StorageFlags}; +use sp_core::{H160, H256}; use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256}; use sp_runtime::{traits::Zero, DispatchError, RuntimeDebug}; @@ -939,8 +941,8 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> { let call_outcome = match call_type { CallType::Call { callee_ptr, value_ptr, deposit_ptr, weight } => { - let callee: <<E as Ext>::T as frame_system::Config>::AccountId = - memory.read_as(callee_ptr)?; + let mut callee = H160::zero(); + memory.read_into_buf(callee_ptr, callee.as_bytes_mut())?; let deposit_limit: BalanceOf<<E as Ext>::T> = if deposit_ptr == SENTINEL { BalanceOf::<<E as Ext>::T>::zero() } else { @@ -959,7 +961,7 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> { self.ext.call( weight, deposit_limit, - callee, + &callee, value, input_data, flags.contains(CallFlags::ALLOW_REENTRY), @@ -1022,9 +1024,10 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> { memory.read_as(deposit_ptr)? }; let value: BalanceOf<<E as Ext>::T> = memory.read_as(value_ptr)?; - let code_hash: CodeHash<<E as Ext>::T> = memory.read_as(code_hash_ptr)?; + let code_hash: H256 = memory.read_as(code_hash_ptr)?; let input_data = memory.read(input_data_ptr, input_data_len)?; - let salt = memory.read(salt_ptr, salt_len)?; + let mut salt = [0u8; 32]; + memory.read_into_buf(salt_ptr, salt.as_mut_slice())?; let instantiate_outcome = self.ext.instantiate(weight, deposit_limit, code_hash, value, input_data, &salt); if let Ok((address, output)) = &instantiate_outcome { @@ -1054,8 +1057,8 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> { let count = self.ext.locked_delegate_dependencies_count() as _; self.charge_gas(RuntimeCosts::Terminate(count))?; - let beneficiary: <<E as Ext>::T as frame_system::Config>::AccountId = - memory.read_as(beneficiary_ptr)?; + let mut beneficiary = H160::zero(); + memory.read_into_buf(beneficiary_ptr, beneficiary.as_bytes_mut())?; self.ext.terminate(&beneficiary)?; Err(TrapReason::Termination) } @@ -1161,8 +1164,8 @@ pub mod env { value_ptr: u32, ) -> Result<ReturnErrorCode, TrapReason> { self.charge_gas(RuntimeCosts::Transfer)?; - let callee: <<E as Ext>::T as frame_system::Config>::AccountId = - memory.read_as(account_ptr)?; + let mut callee = H160::zero(); + memory.read_into_buf(account_ptr, callee.as_bytes_mut())?; let value: BalanceOf<<E as Ext>::T> = memory.read_as(value_ptr)?; let result = self.ext.transfer(&callee, value); match result { @@ -1311,12 +1314,12 @@ pub mod env { #[api_version(0)] fn caller(&mut self, memory: &mut M, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> { self.charge_gas(RuntimeCosts::Caller)?; - let caller = self.ext.caller().account_id()?.clone(); + let caller = <E::T as Config>::AddressMapper::to_address(self.ext.caller().account_id()?); Ok(self.write_sandbox_output( memory, out_ptr, out_len_ptr, - &caller.encode(), + caller.as_bytes(), false, already_charged, )?) @@ -1327,9 +1330,8 @@ pub mod env { #[api_version(0)] fn is_contract(&mut self, memory: &mut M, account_ptr: u32) -> Result<u32, TrapReason> { self.charge_gas(RuntimeCosts::IsContract)?; - let address: <<E as Ext>::T as frame_system::Config>::AccountId = - memory.read_as(account_ptr)?; - + let mut address = H160::zero(); + memory.read_into_buf(account_ptr, address.as_bytes_mut())?; Ok(self.ext.is_contract(&address) as u32) } @@ -1344,8 +1346,8 @@ pub mod env { out_len_ptr: u32, ) -> Result<ReturnErrorCode, TrapReason> { self.charge_gas(RuntimeCosts::CodeHash)?; - let address: <<E as Ext>::T as frame_system::Config>::AccountId = - memory.read_as(account_ptr)?; + let mut address = H160::zero(); + memory.read_into_buf(account_ptr, address.as_bytes_mut())?; if let Some(value) = self.ext.code_hash(&address) { self.write_sandbox_output( memory, @@ -1408,11 +1410,12 @@ pub mod env { out_len_ptr: u32, ) -> Result<(), TrapReason> { self.charge_gas(RuntimeCosts::Address)?; + let address = self.ext.address(); Ok(self.write_sandbox_output( memory, out_ptr, out_len_ptr, - &self.ext.address().encode(), + address.as_bytes(), false, already_charged, )?) @@ -1754,7 +1757,7 @@ pub mod env { dispatch_info, RuntimeCosts::CallXcmExecute, |runtime| { - let origin = crate::RawOrigin::Signed(runtime.ext.address().clone()).into(); + let origin = crate::RawOrigin::Signed(runtime.ext.account_id().clone()).into(); let weight_used = <<E::T as Config>::Xcm>::execute( origin, Box::new(message), @@ -1786,7 +1789,7 @@ pub mod env { let message: VersionedXcm<()> = memory.read_as_unbounded(msg_ptr, msg_len)?; let weight = <<E::T as Config>::Xcm as SendController<_>>::WeightInfo::send(); self.charge_gas(RuntimeCosts::CallRuntime(weight))?; - let origin = crate::RawOrigin::Signed(self.ext.address().clone()).into(); + let origin = crate::RawOrigin::Signed(self.ext.account_id().clone()).into(); match <<E::T as Config>::Xcm>::send(origin, dest.into(), message.into()) { Ok(message_id) => { @@ -1872,7 +1875,7 @@ pub mod env { code_hash_ptr: u32, ) -> Result<ReturnErrorCode, TrapReason> { self.charge_gas(RuntimeCosts::SetCodeHash)?; - let code_hash: CodeHash<<E as Ext>::T> = memory.read_as(code_hash_ptr)?; + let code_hash: H256 = memory.read_as(code_hash_ptr)?; match self.ext.set_code_hash(code_hash) { Err(err) => { let code = Self::err_into_return_code(err)?; -- GitLab