diff --git a/.github/workflows/tests-evm.yml b/.github/workflows/tests-evm.yml index bfb55a460b274..41f75cf57dbe8 100644 --- a/.github/workflows/tests-evm.yml +++ b/.github/workflows/tests-evm.yml @@ -37,13 +37,13 @@ jobs: - name: script run: | forklift cargo build --locked --profile production -p pallet-revive-eth-rpc --bin eth-rpc - forklift cargo build --bin substrate-node + forklift cargo build -p staging-node-cli --bin substrate-node - name: Checkout evm-tests uses: actions/checkout@v4 with: repository: paritytech/evm-test-suite - ref: 737881404f7c5d32e53565ff19e94c21b79d498d + ref: 72d1dace20c8fea4c2404383cc422299b26f1961 path: evm-test-suite - uses: actions/setup-node@v4 @@ -58,7 +58,7 @@ jobs: echo "Change to the evm-test-suite directory" cd evm-test-suite echo "Download the resolc binary" - wget https://github.com/paritytech/revive/releases/download/v0.1.0-dev.9/resolc -q + wget -O resolc https://github.com/paritytech/revive/releases/download/v0.3.0/resolc-x86_64-unknown-linux-musl -q chmod +x resolc mv resolc /usr/local/bin resolc --version @@ -74,7 +74,7 @@ jobs: # cat matter-labs-tests/hardhat.config.ts | grep batchSize echo "Installing solc" - wget https://github.com/ethereum/solidity/releases/download/v0.8.28/solc-static-linux -q + wget https://github.com/ethereum/solidity/releases/download/v0.8.30/solc-static-linux -q chmod +x solc-static-linux mv solc-static-linux /usr/local/bin/solc echo "Run the tests" diff --git a/prdoc/pr_9001.prdoc b/prdoc/pr_9001.prdoc new file mode 100644 index 0000000000000..3a8b348230b1d --- /dev/null +++ b/prdoc/pr_9001.prdoc @@ -0,0 +1,30 @@ +title: 'revive: Precompiles should return dummy code when queried' +doc: +- audience: Runtime Dev + description: |- + Fixes https://github.com/paritytech/contract-issues/issues/111 + + This fixes both the RPC and the opcodes `EXTCODESIZE` and `EXTCODEHASH`. + + Also removed the disabled host function `is_contract`. Contracts do use `EXTCODESIZE` to determine if something is a contract exclusively. + + Need to add some differential tests to our test suite to make sure that the RPC matches geth behaviour: + + On kitchensink: + + ```shell + # primitive precompiles should not return error but 0x + $ cast code 0x0000000000000000000000000000000000000001 + 0x + + # this is the erc pre-compile + $ cast code 0x0000000000000000000000000000000000010000 + 0x60006000fd + ``` +crates: +- name: pallet-revive + bump: major +- name: pallet-revive-uapi + bump: major +- name: pallet-revive-eth-rpc + bump: major diff --git a/substrate/frame/revive/rpc/revive_chain.metadata b/substrate/frame/revive/rpc/revive_chain.metadata index 343d4c6a8fce1..4c4148fa0b7cf 100644 Binary files a/substrate/frame/revive/rpc/revive_chain.metadata and b/substrate/frame/revive/rpc/revive_chain.metadata differ diff --git a/substrate/frame/revive/rpc/src/client/runtime_api.rs b/substrate/frame/revive/rpc/src/client/runtime_api.rs index d78f29346811d..f42c805fb5f61 100644 --- a/substrate/frame/revive/rpc/src/client/runtime_api.rs +++ b/substrate/frame/revive/rpc/src/client/runtime_api.rs @@ -154,4 +154,11 @@ impl RuntimeApi { let trace = self.0.call(payload).await?.map_err(|err| ClientError::TransactError(err.0))?; Ok(trace.0) } + + /// Get the code of the given address. + pub async fn code(&self, address: H160) -> Result, ClientError> { + let payload = subxt_client::apis().revive_api().code(address); + let code = self.0.call(payload).await?; + Ok(code) + } } diff --git a/substrate/frame/revive/rpc/src/client/storage_api.rs b/substrate/frame/revive/rpc/src/client/storage_api.rs index d75d75bca6f63..db053751d5f32 100644 --- a/substrate/frame/revive/rpc/src/client/storage_api.rs +++ b/substrate/frame/revive/rpc/src/client/storage_api.rs @@ -47,17 +47,6 @@ impl StorageApi { Ok(info) } - /// Get the contract code for the given contract address. - pub async fn get_contract_code( - &self, - contract_address: &H160, - ) -> Result>, ClientError> { - let ContractInfo { code_hash, .. } = self.get_contract_info(contract_address).await?; - let query = subxt_client::storage().revive().pristine_code(code_hash); - let result = self.0.fetch(&query).await?.map(|v| v.0); - Ok(result) - } - /// Get the contract trie id for the given contract address. pub async fn get_contract_trie_id(&self, address: &H160) -> Result, ClientError> { let ContractInfo { trie_id, .. } = self.get_contract_info(address).await?; diff --git a/substrate/frame/revive/rpc/src/lib.rs b/substrate/frame/revive/rpc/src/lib.rs index 2ad2894b814f0..3cdb55f6f081a 100644 --- a/substrate/frame/revive/rpc/src/lib.rs +++ b/substrate/frame/revive/rpc/src/lib.rs @@ -246,8 +246,8 @@ impl EthRpcServer for EthRpcServerImpl { async fn get_code(&self, address: H160, block: BlockNumberOrTagOrHash) -> RpcResult { let hash = self.client.block_hash_for_tag(block).await?; - let code = self.client.storage_api(hash).get_contract_code(&address).await?; - Ok(code.unwrap_or_default().into()) + let code = self.client.runtime_api(hash).code(address).await?; + Ok(code.into()) } async fn accounts(&self) -> RpcResult> { diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index 93e698a0082cb..ed426967ea009 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -445,22 +445,6 @@ mod benchmarks { ); } - #[benchmark(pov_mode = Measured)] - fn seal_is_contract() { - let Contract { account_id, .. } = - Contract::::with_index(1, VmBinaryModule::dummy(), vec![]).unwrap(); - - build_runtime!(runtime, memory: [account_id.encode(), ]); - - let result; - #[block] - { - result = runtime.bench_is_contract(memory.as_mut_slice(), 0); - } - - assert_eq!(result.unwrap(), 1); - } - #[benchmark(pov_mode = Measured)] fn seal_to_account_id() { // use a mapped address for the benchmark, to ensure that we bench the worst diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 8e0657f00b123..339e888b5aaba 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -323,9 +323,6 @@ pub trait PrecompileExt: sealing::Sealed { /// Return the origin of the whole call stack. fn origin(&self) -> &Origin; - /// Check if a contract lives at the specified `address`. - fn is_contract(&self, address: &H160) -> bool; - /// Returns the account id for the given `address`. fn to_account_id(&self, address: &H160) -> AccountIdOf; @@ -337,9 +334,6 @@ pub trait PrecompileExt: sealing::Sealed { fn code_size(&self, address: &H160) -> u64; /// Check if the caller of the current contract is the origin of the whole call stack. - /// - /// This can be checked with `is_contract(self.caller())` as well. - /// However, this function does not require any storage lookup and therefore uses less weight. fn caller_is_origin(&self) -> bool; /// Check if the caller is origin, and this origin is root. @@ -1854,15 +1848,14 @@ where &self.origin } - fn is_contract(&self, address: &H160) -> bool { - ContractInfoOf::::contains_key(&address) - } - fn to_account_id(&self, address: &H160) -> T::AccountId { T::AddressMapper::to_account_id(address) } fn code_hash(&self, address: &H160) -> H256 { + if let Some(code) = >::code(address.as_fixed_bytes()) { + return sp_io::hashing::keccak_256(code).into() + } >::get(&address) .map(|contract| contract.code_hash) .unwrap_or_else(|| { @@ -1874,6 +1867,9 @@ where } fn code_size(&self, address: &H160) -> u64 { + if let Some(code) = >::code(address.as_fixed_bytes()) { + return code.len() as u64 + } >::get(&address) .and_then(|contract| CodeInfoOf::::get(contract.code_hash)) .map(|info| info.code_len()) diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index 9fe6caf24796b..d6249fea6eadd 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -782,34 +782,6 @@ fn origin_returns_proper_values() { assert_eq!(WitnessedCallerCharlie::get(), Some(ALICE_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_ADDR)); - // Verify that ALICE is not a contract - assert!(!ctx.ext.is_contract(&ALICE_ADDR)); - exec_success() - }); - - ExtBuilder::default().build().execute_with(|| { - place_contract(&BOB, bob_ch); - - let origin = Origin::from_account_id(ALICE); - let mut storage_meter = storage::meter::Meter::new(0); - let result = MockStack::run_call( - origin, - BOB_ADDR, - &mut GasMeter::::new(GAS_LIMIT), - &mut storage_meter, - U256::zero(), - vec![], - false, - ); - assert_matches!(result, Ok(_)); - }); -} - #[test] fn to_account_id_returns_proper_values() { let bob_code_hash = MockLoader::insert(Call, |ctx, _| { diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index ce7106d69327a..243d7b6fcad62 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -1603,6 +1603,20 @@ impl Pallet { let account_id = T::FindAuthor::find_author(pre_runtime_digests)?; Some(T::AddressMapper::to_address(&account_id)) } + + /// Returns the code at `address`. + /// + /// This takes pre-compiles into account. + pub fn code(address: &H160) -> Vec { + use precompiles::{All, Precompiles}; + if let Some(code) = >::code(address.as_fixed_bytes()) { + return code.into() + } + >::get(&address) + .and_then(|contract| >::get(contract.code_hash)) + .map(|code| code.into()) + .unwrap_or_default() + } } /// The address used to call the runtime's pallets dispatchables @@ -1729,6 +1743,9 @@ sp_api::decl_runtime_apis! { /// The address used to call the runtime's pallets dispatchables fn runtime_pallets_address() -> H160; + + /// The code at the specified address taking pre-compiles into account. + fn code(address: H160) -> Vec; } } @@ -1947,6 +1964,9 @@ macro_rules! impl_runtime_apis_plus_revive { $crate::RUNTIME_PALLETS_ADDR } + fn code(address: $crate::H160) -> Vec { + $crate::Pallet::::code(&address) + } } } }; diff --git a/substrate/frame/revive/src/precompiles.rs b/substrate/frame/revive/src/precompiles.rs index 6ad14f6a43fac..8eae8ef6375e7 100644 --- a/substrate/frame/revive/src/precompiles.rs +++ b/substrate/frame/revive/src/precompiles.rs @@ -54,6 +54,9 @@ pub(crate) use builtin::{IBenchmarking, NoInfo as BenchmarkNoInfo, WithInfo as B const UNIMPLEMENTED: &str = "A precompile must either implement `call` or `call_with_info`"; +/// A minimal EVM bytecode to be returned when a pre-compile is queried for its code. +pub(crate) const EVM_REVERT: [u8; 5] = sp_core::hex2array!("60006000fd"); + /// The composition of all available pre-compiles. /// /// This is how the rest of the pallet discovers and calls pre-compiles. @@ -227,6 +230,7 @@ pub(crate) trait BuiltinPrecompile { type Interface: SolInterface; const MATCHER: BuiltinAddressMatcher; const HAS_CONTRACT_INFO: bool; + const CODE: &[u8] = &EVM_REVERT; fn call( _address: &[u8; 20], @@ -245,7 +249,7 @@ pub(crate) trait BuiltinPrecompile { } } -/// A low level pre-compile that does use Solidity ABI. +/// A low level pre-compile that does not use Solidity ABI. /// /// It is used to implement the original Ethereum pre-compiles which do not /// use Solidity ABI but just encode inputs and outputs packed in memory. @@ -256,6 +260,7 @@ pub(crate) trait PrimitivePrecompile { type T: Config; const MATCHER: BuiltinAddressMatcher; const HAS_CONTRACT_INFO: bool; + const CODE: &[u8] = &[]; fn call( _address: &[u8; 20], @@ -315,6 +320,13 @@ pub(crate) trait Precompiles { /// range by accident. const USES_EXTERNAL_RANGE: bool; + /// Returns the code of the pre-compile. + /// + /// Just used when queried by `EXTCODESIZE` or the RPC. It is just + /// a bogus code that is never executed. Returns None if no pre-compile + /// exists at the specified address. + fn code(address: &[u8; 20]) -> Option<&'static [u8]>; + /// Get a reference to a specific pre-compile. /// /// Returns `None` if no pre-compile exists at `address`. @@ -348,6 +360,7 @@ impl PrimitivePrecompile for P { type T = ::T; const MATCHER: BuiltinAddressMatcher = P::MATCHER; const HAS_CONTRACT_INFO: bool = P::HAS_CONTRACT_INFO; + const CODE: &[u8] = P::CODE; fn call( address: &[u8; 20], @@ -398,24 +411,40 @@ impl Precompiles for Tuple { uses_external }; + fn code(address: &[u8; 20]) -> Option<&'static [u8]> { + for_tuples!( + #( + if Tuple::MATCHER.matches(address) { + return Some(Tuple::CODE) + } + )* + ); + None + } + fn get>(address: &[u8; 20]) -> Option> { let _ = >::CHECK_COLLISION; - let mut has_contract_info = false; - let mut function: Option, &mut E) -> Result, Error>> = None; + let mut instance: Option> = None; for_tuples!( #( if Tuple::MATCHER.matches(address) { if Tuple::HAS_CONTRACT_INFO { - has_contract_info = true; - function = Some(Tuple::call_with_info); + instance = Some(Instance { + address: *address, + has_contract_info: true, + function: Tuple::call_with_info, + }) } else { - has_contract_info = false; - function = Some(Tuple::call); + instance = Some(Instance { + address: *address, + has_contract_info: false, + function: Tuple::call, + }) } } )* ); - function.map(|function| Instance { has_contract_info, address: *address, function }) + instance } } @@ -428,6 +457,10 @@ impl Precompiles for (Builtin, ::Precompiles) { }; const USES_EXTERNAL_RANGE: bool = { ::Precompiles::USES_EXTERNAL_RANGE }; + fn code(address: &[u8; 20]) -> Option<&'static [u8]> { + >::code(address).or_else(|| ::Precompiles::code(address)) + } + fn get>(address: &[u8; 20]) -> Option> { let _ = >::CHECK_COLLISION; >::get(address).or_else(|| ::Precompiles::get(address)) diff --git a/substrate/frame/revive/src/precompiles/builtin.rs b/substrate/frame/revive/src/precompiles/builtin.rs index 7cf854ca4c052..2c33718bc7d24 100644 --- a/substrate/frame/revive/src/precompiles/builtin.rs +++ b/substrate/frame/revive/src/precompiles/builtin.rs @@ -64,6 +64,10 @@ impl Precompiles for (Production, Benchmarking) { const USES_EXTERNAL_RANGE: bool = Production::::USES_EXTERNAL_RANGE || Benchmarking::::USES_EXTERNAL_RANGE; + fn code(address: &[u8; 20]) -> Option<&'static [u8]> { + >::code(address).or_else(|| Benchmarking::::code(address)) + } + fn get>(address: &[u8; 20]) -> Option> { let _ = >::CHECK_COLLISION; >::get(address).or_else(|| Benchmarking::::get(address)) diff --git a/substrate/frame/revive/src/precompiles/tests.rs b/substrate/frame/revive/src/precompiles/tests.rs index eed520d3b135d..8acf049eda659 100644 --- a/substrate/frame/revive/src/precompiles/tests.rs +++ b/substrate/frame/revive/src/precompiles/tests.rs @@ -254,3 +254,19 @@ fn public_matching_works() { assert_eq!(matcher_prefix.base_address(), hex!("0000000000000000000000000000000000080000")); assert_eq!(matcher_prefix.highest_address(), hex!("FFFFFFFF00000000000000000000000000080000")); } + +#[test] +fn primitives_have_no_code() { + for i in 0x01..0x0A { + let address = H160::from_low_u64_be(i).to_fixed_bytes(); + let code = >::code(&address).unwrap(); + assert_eq!(code, &[0u8; 0]); + } +} + +#[cfg(feature = "runtime-benchmarks")] +#[test] +fn benchmarking_precompile_has_code() { + let code = >::code(&hex!("000000000000000000000000000000000000FFFF")).unwrap(); + assert_eq!(code, EVM_REVERT); +} diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index b99b587f7d596..a41d3afa5f21b 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -3719,6 +3719,12 @@ fn to_account_id_works() { #[test] fn code_hash_works() { + use crate::precompiles::{Precompile, EVM_REVERT}; + use precompiles::NoInfo; + + let builtin_precompile = H160(NoInfo::::MATCHER.base_address()); + let primitive_precompile = H160::from_low_u64_be(1); + let (code_hash_code, self_code_hash) = compile_module("code_hash").unwrap(); let (dummy_code, code_hash) = compile_module("dummy").unwrap(); @@ -3732,8 +3738,16 @@ fn code_hash_works() { // code hash of dummy contract assert_ok!(builder::call(addr).data((dummy_addr, code_hash).encode()).build()); - // code has of itself + // code hash of itself assert_ok!(builder::call(addr).data((addr, self_code_hash).encode()).build()); + // code hash of primitive pre-compile (exist but have no bytecode) + assert_ok!(builder::call(addr) + .data((primitive_precompile, crate::exec::EMPTY_CODE_HASH).encode()) + .build()); + // code hash of normal pre-compile (do have a bytecode) + assert_ok!(builder::call(addr) + .data((builtin_precompile, sp_io::hashing::keccak_256(&EVM_REVERT)).encode()) + .build()); // EOA doesn't exists assert_err!( @@ -4768,3 +4782,30 @@ fn bump_nonce_once_works() { assert_eq!(err, >::DuplicateContract.into()); }); } + +#[test] +fn code_size_for_precompiles_works() { + use crate::precompiles::Precompile; + use precompiles::NoInfo; + + let builtin_precompile = H160(NoInfo::::MATCHER.base_address()); + let primitive_precompile = H160::from_low_u64_be(1); + + let (code, _code_hash) = compile_module("extcodesize").unwrap(); + ExtBuilder::default().build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); + let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) + .value(1000) + .build_and_unwrap_contract(); + + // the primitive pre-compiles return 0 code size on eth + builder::bare_call(addr) + .data((&primitive_precompile, 0u64).encode()) + .build_and_unwrap_result(); + + // other precompiles should return the minimal evm revert code + builder::bare_call(addr) + .data((&builtin_precompile, 5u64).encode()) + .build_and_unwrap_result(); + }); +} diff --git a/substrate/frame/revive/src/vm/runtime.rs b/substrate/frame/revive/src/vm/runtime.rs index 8db4c965bc768..5a18d909c421b 100644 --- a/substrate/frame/revive/src/vm/runtime.rs +++ b/substrate/frame/revive/src/vm/runtime.rs @@ -266,8 +266,6 @@ pub enum RuntimeCosts { ToAccountId, /// Weight of calling `seal_origin`. Origin, - /// Weight of calling `seal_is_contract`. - IsContract, /// Weight of calling `seal_code_hash`. CodeHash, /// Weight of calling `seal_own_code_hash`. @@ -447,7 +445,6 @@ impl Token for RuntimeCosts { CallDataCopy(len) => T::WeightInfo::seal_call_data_copy(len), Caller => T::WeightInfo::seal_caller(), Origin => T::WeightInfo::seal_origin(), - IsContract => T::WeightInfo::seal_is_contract(), ToAccountId => T::WeightInfo::seal_to_account_id(), CodeHash => T::WeightInfo::seal_code_hash(), CodeSize => T::WeightInfo::seal_code_size(), @@ -1975,14 +1972,6 @@ pub mod env { )?) } - /// Checks whether a specified address belongs to a contract. - /// See [`pallet_revive_uapi::HostFn::is_contract`]. - fn is_contract(&mut self, memory: &mut M, account_ptr: u32) -> Result { - self.charge_gas(RuntimeCosts::IsContract)?; - let address = memory.read_h160(account_ptr)?; - Ok(self.ext.is_contract(&address) as u32) - } - /// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer. /// See [`pallet_revive_uapi::HostFn::minimum_balance`]. fn minimum_balance(&mut self, memory: &mut M, out_ptr: u32) -> Result<(), TrapReason> { diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index 602fc7057b86a..1c0a94336d14a 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -87,7 +87,6 @@ pub trait WeightInfo { fn noop_host_fn(r: u32, ) -> Weight; fn seal_caller() -> Weight; fn seal_origin() -> Weight; - fn seal_is_contract() -> Weight; fn seal_to_account_id() -> Weight; fn seal_code_hash() -> Weight; fn seal_own_code_hash() -> Weight; @@ -423,16 +422,6 @@ impl WeightInfo for SubstrateWeight { // Minimum execution time: 184_000 picoseconds. Weight::from_parts(206_000, 0) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) - fn seal_is_contract() -> Weight { - // Proof Size summary in bytes: - // Measured: `306` - // Estimated: `3771` - // Minimum execution time: 8_270_000 picoseconds. - Weight::from_parts(8_700_000, 3771) - .saturating_add(T::DbWeight::get().reads(1_u64)) - } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) fn seal_to_account_id() -> Weight { @@ -1410,16 +1399,6 @@ impl WeightInfo for () { // Minimum execution time: 184_000 picoseconds. Weight::from_parts(206_000, 0) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) - fn seal_is_contract() -> Weight { - // Proof Size summary in bytes: - // Measured: `306` - // Estimated: `3771` - // Minimum execution time: 8_270_000 picoseconds. - Weight::from_parts(8_700_000, 3771) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) fn seal_to_account_id() -> Weight { diff --git a/substrate/frame/revive/uapi/src/host.rs b/substrate/frame/revive/uapi/src/host.rs index ac4e2cab791b2..7b11e12990d2e 100644 --- a/substrate/frame/revive/uapi/src/host.rs +++ b/substrate/frame/revive/uapi/src/host.rs @@ -482,9 +482,6 @@ pub trait HostFn: private::Sealed { /// Checks whether the caller of the current contract is the origin of the whole call stack. /// - /// Prefer this over [`is_contract()`][`Self::is_contract`] when checking whether your contract - /// is being called by a contract or a plain account. The reason is that it performs better - /// since it does not need to do any storage lookups. /// /// # Return /// @@ -569,18 +566,6 @@ pub trait HostFn: private::Sealed { #[unstable_hostfn] fn hash_blake2_128(input: &[u8], output: &mut [u8; 16]); - /// Checks whether a specified address belongs to a contract. - /// - /// # Parameters - /// - /// - `address`: The address to check - /// - /// # Return - /// - /// Returns `true` if the address belongs to a contract. - #[unstable_hostfn] - fn is_contract(address: &[u8; 20]) -> bool; - /// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer. /// /// # Parameters diff --git a/substrate/frame/revive/uapi/src/host/riscv64.rs b/substrate/frame/revive/uapi/src/host/riscv64.rs index 45da03e604720..4ca1c27c1732f 100644 --- a/substrate/frame/revive/uapi/src/host/riscv64.rs +++ b/substrate/frame/revive/uapi/src/host/riscv64.rs @@ -95,7 +95,6 @@ mod sys { pub fn seal_return(flags: u32, data_ptr: *const u8, data_len: u32); pub fn caller(out_ptr: *mut u8); pub fn origin(out_ptr: *mut u8); - pub fn is_contract(account_ptr: *const u8) -> ReturnCode; pub fn to_account_id(address_ptr: *const u8, out_ptr: *mut u8); pub fn code_hash(address_ptr: *const u8, out_ptr: *mut u8); pub fn code_size(address_ptr: *const u8) -> u64; @@ -526,12 +525,6 @@ impl HostFn for HostFnImpl { unsafe { sys::hash_blake2_128(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) } } - #[unstable_hostfn] - fn is_contract(address: &[u8; 20]) -> bool { - let ret_val = unsafe { sys::is_contract(address.as_ptr()) }; - ret_val.into_bool() - } - #[unstable_hostfn] fn minimum_balance(output: &mut [u8; 32]) { unsafe { sys::minimum_balance(output.as_mut_ptr()) }