diff --git a/src/components/contracts/modules/ethereum/Cargo.toml b/src/components/contracts/modules/ethereum/Cargo.toml index 8f6ccaf0c..d96f5756e 100644 --- a/src/components/contracts/modules/ethereum/Cargo.toml +++ b/src/components/contracts/modules/ethereum/Cargo.toml @@ -12,7 +12,7 @@ readme = "README.md" abci = "0.7.2" ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } ethereum-types = { version = "0.13.1", default-features = false } -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } tracing = "0.1" rand = "0.8" rlp = "0.5" diff --git a/src/components/contracts/modules/evm/Cargo.toml b/src/components/contracts/modules/evm/Cargo.toml index 6bac465ee..68bf8a9ae 100644 --- a/src/components/contracts/modules/evm/Cargo.toml +++ b/src/components/contracts/modules/evm/Cargo.toml @@ -11,7 +11,7 @@ readme = "README.md" [dependencies] abci = "0.7.2" ethereum-types = { version = "0.13.1", default-features = false } -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } evm-runtime = { version = "0.35.0", default-features = false } evm-gasometer = { version = "0.30.0", default-features = false } ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } diff --git a/src/components/contracts/modules/evm/precompile/Cargo.toml b/src/components/contracts/modules/evm/precompile/Cargo.toml index 3e59e2ede..04a4bc0e3 100644 --- a/src/components/contracts/modules/evm/precompile/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/Cargo.toml @@ -9,7 +9,7 @@ description = "MODEXP precompiles for EVM module." readme = "README.md" [dependencies] -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } module-evm = { path = "../../../modules/evm"} ethereum-types = "0.13.1" evm-precompile-basic = { path = "./basic" } diff --git a/src/components/contracts/modules/evm/precompile/basic/Cargo.toml b/src/components/contracts/modules/evm/precompile/basic/Cargo.toml index d17e7b19b..177ba4125 100644 --- a/src/components/contracts/modules/evm/precompile/basic/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/basic/Cargo.toml @@ -9,7 +9,7 @@ description = "Basic precompiles for EVM module." readme = "README.md" [dependencies] -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } module-evm = { path = "../../../../modules/evm"} ripemd = "0.1" diff --git a/src/components/contracts/modules/evm/precompile/eth-pairings/Cargo.toml b/src/components/contracts/modules/evm/precompile/eth-pairings/Cargo.toml index d6ddd0129..948b995bb 100644 --- a/src/components/contracts/modules/evm/precompile/eth-pairings/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/eth-pairings/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] eth_pairings = { git = "https://github.com/FindoraNetwork/eip1962", branch = "master" } -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } evm-precompile-utils = { path = "../utils"} tracing = "0.1" module-evm = { path = "../../../../modules/evm"} diff --git a/src/components/contracts/modules/evm/precompile/eth-pairings/src/lib.rs b/src/components/contracts/modules/evm/precompile/eth-pairings/src/lib.rs index 470fec3c3..ace1e8f2f 100644 --- a/src/components/contracts/modules/evm/precompile/eth-pairings/src/lib.rs +++ b/src/components/contracts/modules/evm/precompile/eth-pairings/src/lib.rs @@ -2,8 +2,12 @@ mod tests; use eth_pairings::public_interface::{perform_operation, ApiError, OperationType}; -use evm::executor::stack::{PrecompileFailure, PrecompileOutput}; -use evm::{Context, ExitError, ExitSucceed}; +use evm::executor::stack::{PrecompileFailure, PrecompileHandle, PrecompileOutput}; +use evm::{ + // Context, + ExitError, + ExitSucceed, +}; use evm_precompile_utils::{EvmDataReader, EvmDataWriter, EvmResult, Gasometer}; use module_evm::precompile::{FinState, Precompile, PrecompileId, PrecompileResult}; use tracing::debug; @@ -25,11 +29,12 @@ pub enum Call { impl Precompile for EthPairing { fn execute( - input: &[u8], - target_gas: Option, - _context: &Context, + handle: &mut impl PrecompileHandle, _state: &FinState, ) -> PrecompileResult { + let input = handle.input(); + let target_gas = handle.gas_limit(); + let mut input = EvmDataReader::new(input); let selector = match input.read_selector::() { Ok(v) => v, @@ -86,11 +91,11 @@ impl EthPairing { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new() .write_raw_bytes(result.as_slice()) .build(), - logs: vec![], + // logs: vec![], }) } } diff --git a/src/components/contracts/modules/evm/precompile/eth-pairings/src/tests.rs b/src/components/contracts/modules/evm/precompile/eth-pairings/src/tests.rs index 2ff06a41d..693352210 100644 --- a/src/components/contracts/modules/evm/precompile/eth-pairings/src/tests.rs +++ b/src/components/contracts/modules/evm/precompile/eth-pairings/src/tests.rs @@ -1,5 +1,6 @@ use crate::*; -use ethereum_types::H160; +use ethereum_types::{H160, H256}; +use evm::{executor::stack::PrecompileHandle, Context, ExitError, ExitReason, Transfer}; use fp_mocks::*; // Test from eth-pairings (eip1962) repository https://github.com/FindoraNetwork/eip1962 @@ -9,21 +10,95 @@ fn test_bls12_pairing() { let hex_string = "07202912811758d871b77a9c3635c28570dc020576f9fc2719d8d0494439162b2b89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011603e65409b693c8a08aeb3478d10aa3732a6672ba06d12912811758d871b77a9c3635c28570dc020576f9fc2719d8d0494439162b2b84000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010206059efde42f3701020127ccb2831f0011c1d547c491b9dffbd4cfdb87598a4b370f5873ea62094a2f201faa6cb7f6fcca66de3f308a25776dac3f61edb792948fbe53e4d18a3d8aefbe011a7e9f75f3fdc77b83a97f7acd58326a0545f8aa37b69bfb32c52dc195763e8c17176e0ad4ee94d9c720e922d42688127c4b812cd7c2f8cf6126acd4c3d7568121e48b3fefe66c279f2ec71f0d6f8156a3343d1cfa54b808d747cd02419278290ad2d7d03f5de1e7b3c97732f53dbe1dfd42e51f9571f7fee3d9c1785d5a1ed6010b4f7f211a0a5f4425728e2df580196d3e3b85ef148ed769acd23e9be6e8440726cb40655787f48eaf46154cb740e2a58db5b96fa02d83fb9d0f94320da1471e0104ece4c46ac4f05a7c28ecda84292f15999747bb77c530c65448f1f837a47dd70e972c4065d0b39d40b5d550a55901516afa7f02b395963d1535fcba1705e31a117cb4beab1dc582198c4ab0c02e96a22f7bd10dde3bbbdbc9182a9596cb0ed32121616b692e8036437efb4c3816f018f11e643c6e0a049da431986a3a722b06"; let data = hex::decode(hex_string).unwrap(); - let output = EthPairing::execute( - &EvmDataWriter::new() - .write_selector(Call::ExecuteOperation) - .write_raw_bytes(&data) - .build(), - None, - &evm::Context { - address: H160::from_low_u64_be(2001), - caller: ALICE_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ); + let input = EvmDataWriter::new() + .write_selector(Call::ExecuteOperation) + .write_raw_bytes(&data) + .build(); + + let context = evm::Context { + address: H160::from_low_u64_be(2001), + caller: ALICE_ECDSA.address, + apparent_value: From::from(0), + }; + + let cost = None; + + let mut handle = MockHandle::new(input, cost, context); + + let output = + EthPairing::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state); assert!(output.is_ok()); - assert_eq!(output.as_ref().unwrap().cost, 164986); + // assert_eq!(output.as_ref().unwrap().cost, 164986); + assert_eq!(handle.gas_used, 0); assert_eq!(output.unwrap().output, vec![0x1]); } + +pub struct MockHandle { + pub input: Vec, + pub gas_limit: Option, + pub context: Context, + pub is_static: bool, + pub gas_used: u64, +} + +impl MockHandle { + pub fn new(input: Vec, gas_limit: Option, context: Context) -> Self { + Self { + input, + gas_limit, + context, + is_static: false, + gas_used: 0, + } + } +} + +impl PrecompileHandle for MockHandle { + /// Perform subcall in provided context. + /// Precompile specifies in which context the subcall is executed. + fn call( + &mut self, + _: H160, + _: Option, + _: Vec, + _: Option, + _: bool, + _: &Context, + ) -> (ExitReason, Vec) { + unimplemented!() + } + + fn record_cost(&mut self, cost: u64) -> Result<(), ExitError> { + self.gas_used += cost; + Ok(()) + } + + fn log(&mut self, _: H160, _: Vec, _: Vec) -> Result<(), ExitError> { + unimplemented!() + } + + fn remaining_gas(&self) -> u64 { + unimplemented!() + } + + fn code_address(&self) -> H160 { + unimplemented!() + } + + fn input(&self) -> &[u8] { + &self.input + } + + fn context(&self) -> &Context { + &self.context + } + + fn is_static(&self) -> bool { + self.is_static + } + + fn gas_limit(&self) -> Option { + self.gas_limit + } +} diff --git a/src/components/contracts/modules/evm/precompile/frc20/Cargo.toml b/src/components/contracts/modules/evm/precompile/frc20/Cargo.toml index 392469c18..8ee5669a1 100644 --- a/src/components/contracts/modules/evm/precompile/frc20/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/frc20/Cargo.toml @@ -10,7 +10,7 @@ readme = "README.md" [dependencies] ethereum-types = { version = "0.13.1", default-features = false } -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } evm-precompile-utils = { path = "../utils"} fp-traits = { path = "../../../../primitives/traits" } tracing = "0.1" diff --git a/src/components/contracts/modules/evm/precompile/frc20/src/lib.rs b/src/components/contracts/modules/evm/precompile/frc20/src/lib.rs index 2b083636e..caa21346d 100644 --- a/src/components/contracts/modules/evm/precompile/frc20/src/lib.rs +++ b/src/components/contracts/modules/evm/precompile/frc20/src/lib.rs @@ -4,11 +4,17 @@ mod tests; use core::marker::PhantomData; use ethereum_types::{H160, U256}; use evm::{ - executor::stack::{PrecompileFailure, PrecompileOutput}, + executor::stack::{PrecompileFailure, PrecompileHandle, PrecompileOutput}, Context, ExitSucceed, }; use evm_precompile_utils::{ - error, Address, EvmDataReader, EvmDataWriter, EvmResult, Gasometer, LogsBuilder, + error, + Address, + EvmDataReader, + EvmDataWriter, + EvmResult, + Gasometer, + // LogsBuilder, }; use fp_traits::{account::AccountAsset, evm::AddressMapping}; use module_evm::{ @@ -82,11 +88,13 @@ pub enum Call { impl Precompile for FRC20 { fn execute( - input: &[u8], - target_gas: Option, - context: &Context, + handle: &mut impl PrecompileHandle, state: &FinState, ) -> PrecompileResult { + let input = handle.input(); + let target_gas = handle.gas_limit(); + let context = handle.context(); + let mut input = EvmDataReader::new(input); let selector = match input.read_selector::() { Ok(v) => v, @@ -153,9 +161,9 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write_raw_bytes(FRC20_NAME).build(), - logs: vec![], + // logs: vec![], }) } @@ -173,9 +181,9 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write_raw_bytes(FRC20_SYMBOL).build(), - logs: vec![], + // logs: vec![], }) } @@ -194,9 +202,9 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write(18_u8).build(), - logs: vec![], + // logs: vec![], }) } @@ -216,9 +224,9 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write(amount).build(), - logs: vec![], + // logs: vec![], }) } @@ -240,9 +248,9 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write(amount).build(), - logs: vec![], + // logs: vec![], }) } @@ -270,9 +278,9 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write(amount).build(), - logs: vec![], + // logs: vec![], }) } @@ -308,16 +316,16 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write(true).build(), - logs: LogsBuilder::new(context.address) - .log3( - APPROVAL_EVENT_SELECTOR, - context.caller, - spender, - EvmDataWriter::new().write(amount).build(), - ) - .build(), + // logs: LogsBuilder::new(context.address) + // .log3( + // APPROVAL_EVENT_SELECTOR, + // context.caller, + // spender, + // EvmDataWriter::new().write(amount).build(), + // ) + // .build(), }) } @@ -353,16 +361,16 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write(true).build(), - logs: LogsBuilder::new(context.address) - .log3( - TRANSFER_EVENT_SELECTOR, - context.caller, - recipient, - EvmDataWriter::new().write(amount).build(), - ) - .build(), + // logs: LogsBuilder::new(context.address) + // .log3( + // TRANSFER_EVENT_SELECTOR, + // context.caller, + // recipient, + // EvmDataWriter::new().write(amount).build(), + // ) + // .build(), }) } @@ -417,24 +425,24 @@ impl FRC20 { Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gasometer.used_gas(), + // cost: gasometer.used_gas(), output: EvmDataWriter::new().write(true).build(), - logs: LogsBuilder::new(context.address) - .log3( - TRANSFER_EVENT_SELECTOR, - from, - recipient, - EvmDataWriter::new().write(amount).build(), - ) - .log3( - APPROVAL_EVENT_SELECTOR, - from, - context.caller, - EvmDataWriter::new() - .write(allowance.saturating_sub(amount)) - .build(), - ) - .build(), + // logs: LogsBuilder::new(context.address) + // .log3( + // TRANSFER_EVENT_SELECTOR, + // from, + // recipient, + // EvmDataWriter::new().write(amount).build(), + // ) + // .log3( + // APPROVAL_EVENT_SELECTOR, + // from, + // context.caller, + // EvmDataWriter::new() + // .write(allowance.saturating_sub(amount)) + // .build(), + // ) + // .build(), }) } } diff --git a/src/components/contracts/modules/evm/precompile/frc20/src/tests.rs b/src/components/contracts/modules/evm/precompile/frc20/src/tests.rs index 32cea5b34..e2665a202 100644 --- a/src/components/contracts/modules/evm/precompile/frc20/src/tests.rs +++ b/src/components/contracts/modules/evm/precompile/frc20/src/tests.rs @@ -1,8 +1,10 @@ use crate::*; use baseapp::BaseApp; +use ethereum_types::{H160, H256}; +use evm::{ExitError, ExitReason, Transfer}; use fp_mocks::*; -use evm_precompile_utils::{error, EvmDataWriter, LogsBuilder}; +use evm_precompile_utils::{error, EvmDataWriter}; use module_evm::precompile::Precompile; use sha3::{Digest, Keccak256}; @@ -11,18 +13,16 @@ pub const FRC20_PRECOMPILE_ADDRESS: u64 = 9; #[test] fn selector_less_than_four_bytes() { let invalid_selector = vec![1u8, 2u8, 3u8]; + let context = evm::Context { + address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), + caller: ALICE_ECDSA.address, + apparent_value: From::from(0), + }; + + let mut handle = MockHandle::new(invalid_selector, None, context); assert_eq!( - FRC20::::execute( - &invalid_selector, - None, - &evm::Context { - address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), - caller: ALICE_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ), + FRC20::::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state,), Err(PrecompileFailure::Error { exit_status: error("tried to parse selector out of bounds") }) @@ -32,18 +32,16 @@ fn selector_less_than_four_bytes() { #[test] fn no_selector_exists_but_length_is_right() { let invalid_selector = vec![1u8, 2u8, 3u8, 4u8]; + let context = evm::Context { + address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), + caller: ALICE_ECDSA.address, + apparent_value: From::from(0), + }; + + let mut handle = MockHandle::new(invalid_selector, None, context); assert_eq!( - FRC20::::execute( - &invalid_selector, - None, - &evm::Context { - address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), - caller: ALICE_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ), + FRC20::::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state,), Err(PrecompileFailure::Error { exit_status: error("unknown selector") }) @@ -86,24 +84,24 @@ fn frc20_works() { } fn total_supply_works() { + let input = EvmDataWriter::new() + .write_selector(Call::TotalSupply) + .build(); + let context = evm::Context { + address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), + caller: ALICE_ECDSA.address, + apparent_value: From::from(0), + }; + + let mut handle = MockHandle::new(input, None, context); + assert_eq!( - FRC20::::execute( - &EvmDataWriter::new() - .write_selector(Call::TotalSupply) - .build(), - None, - &evm::Context { - address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), - caller: ALICE_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ), + FRC20::::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state,), Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, output: EvmDataWriter::new().write(U256::from(2000u64)).build(), - cost: GAS_TOTAL_SUPPLY, - logs: Default::default(), + // cost: GAS_TOTAL_SUPPLY, + // logs: Default::default(), }) ); } @@ -113,57 +111,57 @@ fn balance_of_works() { } fn balance_of(who: H160, expected_value: U256) { + let input = EvmDataWriter::new() + .write_selector(Call::BalanceOf) + .write(Address(who)) + .build(); + let context = evm::Context { + address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), + caller: ALICE_ECDSA.address, + apparent_value: From::from(0), + }; + + let mut handle = MockHandle::new(input, None, context); + assert_eq!( - FRC20::::execute( - &EvmDataWriter::new() - .write_selector(Call::BalanceOf) - .write(Address(who)) - .build(), - None, - &evm::Context { - address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), - caller: ALICE_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ), + FRC20::::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state,), Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, output: EvmDataWriter::new().write(expected_value).build(), - cost: GAS_BALANCE_OF, - logs: Default::default(), + // cost: GAS_BALANCE_OF, + // logs: Default::default(), }) ); } fn transfer_works() { + let input = EvmDataWriter::new() + .write_selector(Call::Transfer) + .write(Address(BOB_ECDSA.address)) + .write(U256::from(400)) + .build(); + let context = evm::Context { + address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), + caller: ALICE_ECDSA.address, + apparent_value: From::from(0), + }; + + let mut handle = MockHandle::new(input, None, context); + assert_eq!( - FRC20::::execute( - &EvmDataWriter::new() - .write_selector(Call::Transfer) - .write(Address(BOB_ECDSA.address)) - .write(U256::from(400)) - .build(), - None, - &evm::Context { - address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), - caller: ALICE_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ), + FRC20::::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state,), Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, output: EvmDataWriter::new().write(true).build(), - cost: GAS_TRANSFER + 1756, - logs: LogsBuilder::new(H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS)) - .log3( - TRANSFER_EVENT_SELECTOR, - ALICE_ECDSA.address, - BOB_ECDSA.address, - EvmDataWriter::new().write(U256::from(400)).build(), - ) - .build(), + // cost: GAS_TRANSFER + 1756, + // logs: LogsBuilder::new(H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS)) + // .log3( + // TRANSFER_EVENT_SELECTOR, + // ALICE_ECDSA.address, + // BOB_ECDSA.address, + // EvmDataWriter::new().write(U256::from(400)).build(), + // ) + // .build(), }) ); @@ -173,33 +171,33 @@ fn transfer_works() { } fn approve_works() { + let input = EvmDataWriter::new() + .write_selector(Call::Approve) + .write(Address(BOB_ECDSA.address)) + .write(U256::from(500)) + .build(); + let context = evm::Context { + address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), + caller: ALICE_ECDSA.address, + apparent_value: From::from(0), + }; + + let mut handle = MockHandle::new(input, None, context); + assert_eq!( - FRC20::::execute( - &EvmDataWriter::new() - .write_selector(Call::Approve) - .write(Address(BOB_ECDSA.address)) - .write(U256::from(500)) - .build(), - None, - &evm::Context { - address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), - caller: ALICE_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ), + FRC20::::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state,), Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, output: EvmDataWriter::new().write(true).build(), - cost: GAS_APPROVE + 1756, - logs: LogsBuilder::new(H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS)) - .log3( - APPROVAL_EVENT_SELECTOR, - ALICE_ECDSA.address, - BOB_ECDSA.address, - EvmDataWriter::new().write(U256::from(500)).build(), - ) - .build(), + // cost: GAS_APPROVE + 1756, + // logs: LogsBuilder::new(H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS)) + // .log3( + // APPROVAL_EVENT_SELECTOR, + // ALICE_ECDSA.address, + // BOB_ECDSA.address, + // EvmDataWriter::new().write(U256::from(500)).build(), + // ) + // .build(), }) ); } @@ -209,65 +207,65 @@ fn allowance_works() { } fn allowance(owner: H160, spender: H160, expected_value: U256) { + let input = EvmDataWriter::new() + .write_selector(Call::Allowance) + .write(Address(owner)) + .write(Address(spender)) + .build(); + let context = evm::Context { + address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), + caller: ALICE_ECDSA.address, + apparent_value: From::from(0), + }; + + let mut handle = MockHandle::new(input, None, context); + assert_eq!( - FRC20::::execute( - &EvmDataWriter::new() - .write_selector(Call::Allowance) - .write(Address(owner)) - .write(Address(spender)) - .build(), - None, - &evm::Context { - address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), - caller: ALICE_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ), + FRC20::::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state,), Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, output: EvmDataWriter::new().write(expected_value).build(), - cost: GAS_ALLOWANCE, - logs: Default::default(), + // cost: GAS_ALLOWANCE, + // logs: Default::default(), }) ); } fn transfer_from_works() { + let input = EvmDataWriter::new() + .write_selector(Call::TransferFrom) + .write(Address(ALICE_ECDSA.address)) + .write(Address(BOB_ECDSA.address)) + .write(U256::from(400)) + .build(); + let context = evm::Context { + address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), + caller: BOB_ECDSA.address, + apparent_value: From::from(0), + }; + + let mut handle = MockHandle::new(input, None, context); + assert_eq!( - FRC20::::execute( - &EvmDataWriter::new() - .write_selector(Call::TransferFrom) - .write(Address(ALICE_ECDSA.address)) - .write(Address(BOB_ECDSA.address)) - .write(U256::from(400)) - .build(), - None, - &evm::Context { - address: H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS), - caller: BOB_ECDSA.address, - apparent_value: From::from(0), - }, - &BASE_APP.lock().unwrap().deliver_state, - ), + FRC20::::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state,), Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, output: EvmDataWriter::new().write(true).build(), - cost: GAS_TRANSFER_FROM + 1756 * 2, - logs: LogsBuilder::new(H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS)) - .log3( - TRANSFER_EVENT_SELECTOR, - ALICE_ECDSA.address, - BOB_ECDSA.address, - EvmDataWriter::new().write(U256::from(400)).build(), - ) - .log3( - APPROVAL_EVENT_SELECTOR, - ALICE_ECDSA.address, - BOB_ECDSA.address, - EvmDataWriter::new().write(U256::from(100)).build(), - ) - .build(), + // cost: GAS_TRANSFER_FROM + 1756 * 2, + // logs: LogsBuilder::new(H160::from_low_u64_be(FRC20_PRECOMPILE_ADDRESS)) + // .log3( + // TRANSFER_EVENT_SELECTOR, + // ALICE_ECDSA.address, + // BOB_ECDSA.address, + // EvmDataWriter::new().write(U256::from(400)).build(), + // ) + // .log3( + // APPROVAL_EVENT_SELECTOR, + // ALICE_ECDSA.address, + // BOB_ECDSA.address, + // EvmDataWriter::new().write(U256::from(100)).build(), + // ) + // .build(), }) ); @@ -277,3 +275,72 @@ fn transfer_from_works() { allowance(ALICE_ECDSA.address, BOB_ECDSA.address, U256::from(100)); } + +pub struct MockHandle { + pub input: Vec, + pub gas_limit: Option, + pub context: Context, + pub is_static: bool, + pub gas_used: u64, +} + +impl MockHandle { + pub fn new(input: Vec, gas_limit: Option, context: Context) -> Self { + Self { + input, + gas_limit, + context, + is_static: false, + gas_used: 0, + } + } +} + +impl PrecompileHandle for MockHandle { + /// Perform subcall in provided context. + /// Precompile specifies in which context the subcall is executed. + fn call( + &mut self, + _: H160, + _: Option, + _: Vec, + _: Option, + _: bool, + _: &Context, + ) -> (ExitReason, Vec) { + unimplemented!() + } + + fn record_cost(&mut self, cost: u64) -> Result<(), ExitError> { + self.gas_used += cost; + Ok(()) + } + + fn log(&mut self, _: H160, _: Vec, _: Vec) -> Result<(), ExitError> { + unimplemented!() + } + + fn remaining_gas(&self) -> u64 { + unimplemented!() + } + + fn code_address(&self) -> H160 { + unimplemented!() + } + + fn input(&self) -> &[u8] { + &self.input + } + + fn context(&self) -> &Context { + &self.context + } + + fn is_static(&self) -> bool { + self.is_static + } + + fn gas_limit(&self) -> Option { + self.gas_limit + } +} diff --git a/src/components/contracts/modules/evm/precompile/modexp/Cargo.toml b/src/components/contracts/modules/evm/precompile/modexp/Cargo.toml index 7e93b0315..60ae1cb73 100644 --- a/src/components/contracts/modules/evm/precompile/modexp/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/modexp/Cargo.toml @@ -9,9 +9,10 @@ description = "MODEXP precompiles for EVM module." readme = "README.md" [dependencies] -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } module-evm = { path = "../../../../modules/evm"} num = { version = "0.4", features = ["alloc"] } +ethereum-types = { version = "0.13.1", default-features = false } [dev-dependencies] hex = "0.4.2" diff --git a/src/components/contracts/modules/evm/precompile/modexp/src/lib.rs b/src/components/contracts/modules/evm/precompile/modexp/src/lib.rs index 60b189e02..7b997f26f 100644 --- a/src/components/contracts/modules/evm/precompile/modexp/src/lib.rs +++ b/src/components/contracts/modules/evm/precompile/modexp/src/lib.rs @@ -21,8 +21,10 @@ mod tests; use core::cmp::max; use core::ops::BitAnd; use evm::{ - executor::stack::{PrecompileFailure, PrecompileOutput}, - Context, ExitError, ExitSucceed, + executor::stack::{PrecompileFailure, PrecompileHandle, PrecompileOutput}, + // Context, + ExitError, + ExitSucceed, }; use module_evm::precompile::{FinState, Precompile, PrecompileId, PrecompileResult}; use num::{BigUint, FromPrimitive, One, ToPrimitive, Zero}; @@ -103,11 +105,12 @@ fn calculate_gas_cost( impl Precompile for Modexp { fn execute( - input: &[u8], - target_gas: Option, - _context: &Context, + handle: &mut impl PrecompileHandle, _state: &FinState, ) -> PrecompileResult { + let input = handle.input(); + let target_gas = handle.gas_limit(); + if input.len() < 96 { return Err(PrecompileFailure::Error { exit_status: ExitError::Other( @@ -162,7 +165,7 @@ impl Precompile for Modexp { } // Gas formula allows arbitrary large exp_len when base and modulus are empty, so we need to handle empty base first. - let (r, gas_cost) = if base_len == 0 && mod_len == 0 { + let (r, _gas_cost) = if base_len == 0 && mod_len == 0 { (BigUint::zero(), MIN_GAS_COST) } else { // read the numbers themselves. @@ -210,9 +213,9 @@ impl Precompile for Modexp { }), Ordering::Equal => Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gas_cost, + // cost: gas_cost, output: bytes.to_vec(), - logs: Default::default(), + // logs: Default::default(), }), Ordering::Greater => { let mut ret = Vec::with_capacity(mod_len); @@ -220,9 +223,9 @@ impl Precompile for Modexp { ret.extend_from_slice(&bytes[..]); Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, - cost: gas_cost, + // cost: gas_cost, output: ret.to_vec(), - logs: Default::default(), + // logs: Default::default(), }) } } diff --git a/src/components/contracts/modules/evm/precompile/modexp/src/tests.rs b/src/components/contracts/modules/evm/precompile/modexp/src/tests.rs index 940e8ff4d..73fe0c646 100644 --- a/src/components/contracts/modules/evm/precompile/modexp/src/tests.rs +++ b/src/components/contracts/modules/evm/precompile/modexp/src/tests.rs @@ -1,4 +1,6 @@ use crate::*; +use ethereum_types::{H160, H256}; +use evm::{Context, ExitReason, Transfer}; use fp_mocks::*; use pallet_evm_test_vector_support::test_precompile_test_vectors; @@ -20,12 +22,9 @@ fn test_empty_input() -> std::result::Result<(), ExitError> { apparent_value: From::from(0), }; - match Modexp::execute( - &input, - Some(cost), - &context, - &BASE_APP.lock().unwrap().deliver_state, - ) { + let mut handle = MockHandle::new(input.to_vec(), Some(cost), context); + + match Modexp::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state) { Ok(_) => { panic!("Test not expected to pass"); } @@ -60,12 +59,9 @@ fn test_insufficient_input() -> std::result::Result<(), ExitError> { apparent_value: From::from(0), }; - match Modexp::execute( - &input, - Some(cost), - &context, - &BASE_APP.lock().unwrap().deliver_state, - ) { + let mut handle = MockHandle::new(input.to_vec(), Some(cost), context); + + match Modexp::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state) { Ok(_) => { panic!("Test not expected to pass"); } @@ -98,12 +94,9 @@ fn test_excessive_input() -> std::result::Result<(), ExitError> { apparent_value: From::from(0), }; - match Modexp::execute( - &input, - Some(cost), - &context, - &BASE_APP.lock().unwrap().deliver_state, - ) { + let mut handle = MockHandle::new(input.to_vec(), Some(cost), context); + + match Modexp::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state) { Ok(_) => { panic!("Test not expected to pass"); } @@ -143,12 +136,9 @@ fn test_simple_inputs() { apparent_value: From::from(0), }; - match Modexp::execute( - &input, - Some(cost), - &context, - &BASE_APP.lock().unwrap().deliver_state, - ) { + let mut handle = MockHandle::new(input.to_vec(), Some(cost), context); + + match Modexp::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state) { Ok(precompile_result) => { assert_eq!(precompile_result.output.len(), 1); // should be same length as mod let result = BigUint::from_bytes_be(&precompile_result.output[..]); @@ -183,12 +173,9 @@ fn test_large_inputs() { apparent_value: From::from(0), }; - match Modexp::execute( - &input, - Some(cost), - &context, - &BASE_APP.lock().unwrap().deliver_state, - ) { + let mut handle = MockHandle::new(input.to_vec(), Some(cost), context); + + match Modexp::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state) { Ok(precompile_result) => { assert_eq!(precompile_result.output.len(), 32); // should be same length as mod let result = BigUint::from_bytes_be(&precompile_result.output[..]); @@ -221,12 +208,9 @@ fn test_large_computation() { apparent_value: From::from(0), }; - match Modexp::execute( - &input, - Some(cost), - &context, - &BASE_APP.lock().unwrap().deliver_state, - ) { + let mut handle = MockHandle::new(input.to_vec(), Some(cost), context); + + match Modexp::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state) { Ok(precompile_result) => { assert_eq!(precompile_result.output.len(), 32); // should be same length as mod let result = BigUint::from_bytes_be(&precompile_result.output[..]); @@ -238,3 +222,72 @@ fn test_large_computation() { } } } + +pub struct MockHandle { + pub input: Vec, + pub gas_limit: Option, + pub context: Context, + pub is_static: bool, + pub gas_used: u64, +} + +impl MockHandle { + pub fn new(input: Vec, gas_limit: Option, context: Context) -> Self { + Self { + input, + gas_limit, + context, + is_static: false, + gas_used: 0, + } + } +} + +impl PrecompileHandle for MockHandle { + /// Perform subcall in provided context. + /// Precompile specifies in which context the subcall is executed. + fn call( + &mut self, + _: H160, + _: Option, + _: Vec, + _: Option, + _: bool, + _: &Context, + ) -> (ExitReason, Vec) { + unimplemented!() + } + + fn record_cost(&mut self, cost: u64) -> Result<(), ExitError> { + self.gas_used += cost; + Ok(()) + } + + fn log(&mut self, _: H160, _: Vec, _: Vec) -> Result<(), ExitError> { + unimplemented!() + } + + fn remaining_gas(&self) -> u64 { + unimplemented!() + } + + fn code_address(&self) -> H160 { + unimplemented!() + } + + fn input(&self) -> &[u8] { + &self.input + } + + fn context(&self) -> &Context { + &self.context + } + + fn is_static(&self) -> bool { + self.is_static + } + + fn gas_limit(&self) -> Option { + self.gas_limit + } +} diff --git a/src/components/contracts/modules/evm/precompile/sha3fips/Cargo.toml b/src/components/contracts/modules/evm/precompile/sha3fips/Cargo.toml index 01c867e60..4220f95fc 100644 --- a/src/components/contracts/modules/evm/precompile/sha3fips/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/sha3fips/Cargo.toml @@ -9,6 +9,6 @@ description = "SHA3 FIPS202 precompiles for EVM module." readme = "README.md" [dependencies] -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } module-evm = { path = "../../../../modules/evm"} tiny-keccak = { version = "2.0", features = ["fips202"] } diff --git a/src/components/contracts/modules/evm/precompile/src/lib.rs b/src/components/contracts/modules/evm/precompile/src/lib.rs index 569c50c57..46a581456 100644 --- a/src/components/contracts/modules/evm/precompile/src/lib.rs +++ b/src/components/contracts/modules/evm/precompile/src/lib.rs @@ -1,6 +1,6 @@ use ethereum_types::H160; -use evm::executor::stack::PrecompileSet; -use evm::Context; +use evm::executor::stack::{PrecompileHandle, PrecompileSet}; +// use evm::Context; use module_evm::precompile::{Precompile, PrecompileResult}; use std::marker::PhantomData; @@ -34,48 +34,41 @@ impl PrecompileSet for FindoraPrecompiles where C: Config, { - fn execute( - &self, - address: H160, - input: &[u8], - target_gas: Option, - context: &Context, - _is_static: bool, - ) -> Option { + fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { let ctx = &self.1; - match address { + match handle.code_address() { // Ethereum precompiles : a if a == H160::from_low_u64_be(ECRecover::contract_id()) => { - Some(ECRecover::execute(input, target_gas, context, ctx)) + Some(ECRecover::execute(handle, ctx)) } a if a == H160::from_low_u64_be(Sha256::contract_id()) => { - Some(Sha256::execute(input, target_gas, context, ctx)) + Some(Sha256::execute(handle, ctx)) } a if a == H160::from_low_u64_be(Ripemd160::contract_id()) => { - Some(Ripemd160::execute(input, target_gas, context, ctx)) + Some(Ripemd160::execute(handle, ctx)) } a if a == H160::from_low_u64_be(Identity::contract_id()) => { - Some(Identity::execute(input, target_gas, context, ctx)) + Some(Identity::execute(handle, ctx)) } a if a == H160::from_low_u64_be(Modexp::contract_id()) => { - Some(Modexp::execute(input, target_gas, context, ctx)) + Some(Modexp::execute(handle, ctx)) } // Non-Frontier specific nor Ethereum precompiles : a if a == H160::from_low_u64_be(ECRecoverPublicKey::contract_id()) => { - Some(ECRecoverPublicKey::execute(input, target_gas, context, ctx)) + Some(ECRecoverPublicKey::execute(handle, ctx)) } a if a == H160::from_low_u64_be(Sha3FIPS256::contract_id()) => { - Some(Sha3FIPS256::execute(input, target_gas, context, ctx)) + Some(Sha3FIPS256::execute(handle, ctx)) } a if a == H160::from_low_u64_be(Sha3FIPS512::contract_id()) => { - Some(Sha3FIPS512::execute(input, target_gas, context, ctx)) + Some(Sha3FIPS512::execute(handle, ctx)) } a if a == H160::from_low_u64_be(FRC20::::contract_id()) => { - Some(FRC20::::execute(input, target_gas, context, ctx)) + Some(FRC20::::execute(handle, ctx)) } a if a == H160::from_low_u64_be(EthPairing::contract_id()) => { - Some(EthPairing::execute(input, target_gas, context, ctx)) + Some(EthPairing::execute(handle, ctx)) } _ => None, } diff --git a/src/components/contracts/modules/evm/precompile/utils/Cargo.toml b/src/components/contracts/modules/evm/precompile/utils/Cargo.toml index 5a2091980..374303399 100644 --- a/src/components/contracts/modules/evm/precompile/utils/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/utils/Cargo.toml @@ -8,7 +8,7 @@ description = "Utils to write EVM precompiles." [dependencies] ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } ethereum-types = { version = "0.13.1", default-features = false } -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } tracing = "0.1" num_enum = { version = "0.5.3", default-features = false } precompile-utils-macro = { path = "macro" } diff --git a/src/components/contracts/modules/evm/src/precompile.rs b/src/components/contracts/modules/evm/src/precompile.rs index 54e8b8229..a471584a5 100644 --- a/src/components/contracts/modules/evm/src/precompile.rs +++ b/src/components/contracts/modules/evm/src/precompile.rs @@ -1,8 +1,10 @@ use crate::runtime::stack::FindoraStackState; use ethereum_types::H160; use evm::{ - executor::stack::{PrecompileFailure, PrecompileOutput}, - Context, ExitError, ExitSucceed, + executor::stack::{PrecompileFailure, PrecompileHandle, PrecompileOutput}, + // Context, + ExitError, + ExitSucceed, }; use impl_trait_for_tuples::impl_for_tuples; @@ -18,12 +20,8 @@ pub trait PrecompileSet { /// `target_gas`. Return `Some(Ok(status, output, gas_used))` if the execution /// is successful. Otherwise return `Some(Err(_))`. fn execute( - address: H160, - input: &[u8], - target_gas: Option, - context: &Context, + handle: &mut impl PrecompileHandle, state: &mut FindoraStackState<'_, '_, '_, T>, - is_static: bool, ) -> Option; } @@ -32,12 +30,8 @@ pub trait Precompile { /// Try to execute the precompile. Calculate the amount of gas needed with given `input` and /// `target_gas`. Return `Ok(status, output, gas_used)` if the execution is /// successful. Otherwise return `Err(_)`. - fn execute( - input: &[u8], - target_gas: Option, - context: &Context, - state: &FinState, - ) -> PrecompileResult; + fn execute(handle: &mut impl PrecompileHandle, state: &FinState) + -> PrecompileResult; } /// precompile contract address is generated by PrecompileId. @@ -54,16 +48,12 @@ impl PrecompileSet for Tuple { for_tuples!( where #( Tuple: Precompile + PrecompileId )* ); fn execute( - address: H160, - input: &[u8], - target_gas: Option, - context: &Context, + handle: &mut impl PrecompileHandle, state: &mut FindoraStackState<'_, '_, '_, T>, - _is_static: bool, ) -> Option { for_tuples!( #( - if address == H160::from_low_u64_be(Tuple::contract_id()) { - return Some(Tuple::execute(input, target_gas, context, state.ctx)) + if handle.code_address() == H160::from_low_u64_be(Tuple::contract_id()) { + return Some(Tuple::execute(handle, state.ctx)) } )* ); @@ -83,19 +73,22 @@ pub trait LinearCostPrecompile { impl Precompile for T { fn execute( - input: &[u8], - target_gas: Option, - _: &Context, - _: &FinState, + handle: &mut impl PrecompileHandle, + _state: &FinState, ) -> PrecompileResult { - let cost = ensure_linear_cost(target_gas, input.len() as u64, T::BASE, T::WORD)?; + let target_gas = handle.gas_limit(); + let cost = ensure_linear_cost( + target_gas, + handle.input().len() as u64, + T::BASE, + T::WORD, + )?; - let (exit_status, output) = T::execute(input, cost)?; + handle.record_cost(cost)?; + let (exit_status, output) = T::execute(handle.input(), cost)?; Ok(PrecompileOutput { exit_status, - cost, output, - logs: Default::default(), }) } } diff --git a/src/components/contracts/modules/evm/test-vector-support/Cargo.toml b/src/components/contracts/modules/evm/test-vector-support/Cargo.toml index c283cfc52..29e404c7b 100644 --- a/src/components/contracts/modules/evm/test-vector-support/Cargo.toml +++ b/src/components/contracts/modules/evm/test-vector-support/Cargo.toml @@ -10,6 +10,7 @@ repository = "https://github.com/findoranetwork/platform/" hex = { version = "0.4.2"} serde = { version = "1.0.124", features = ["derive"] } serde_json = { version = "1.0"} -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } module-evm = { path = "../../../modules/evm"} fp-mocks = { path = "../../../primitives/mocks" } +ethereum-types = { version = "0.13.1", default-features = false } diff --git a/src/components/contracts/modules/evm/test-vector-support/src/lib.rs b/src/components/contracts/modules/evm/test-vector-support/src/lib.rs index 9a1a7e56a..76f05fe53 100644 --- a/src/components/contracts/modules/evm/test-vector-support/src/lib.rs +++ b/src/components/contracts/modules/evm/test-vector-support/src/lib.rs @@ -15,7 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use evm::{Context, ExitSucceed}; +use ethereum_types::{H160, H256}; +use evm::{ + executor::stack::PrecompileHandle, Context, ExitError, ExitReason, ExitSucceed, + Transfer, +}; use fp_mocks::*; use module_evm::precompile::Precompile; use serde::Deserialize; @@ -54,12 +58,9 @@ pub fn test_precompile_test_vectors( apparent_value: From::from(0), }; - match P::execute( - &input, - Some(cost), - &context, - &BASE_APP.lock().unwrap().deliver_state, - ) { + let mut handle = MockHandle::new(input, Some(cost), context); + + match P::execute(&mut handle, &BASE_APP.lock().unwrap().deliver_state) { Ok(result) => { let as_hex: String = hex::encode(result.output); assert_eq!( @@ -76,7 +77,8 @@ pub fn test_precompile_test_vectors( ); if let Some(expected_gas) = test.Gas { assert_eq!( - result.cost, expected_gas, + handle.gas_used, + 0, //expected_gas, "test '{}' failed (different gas cost)", test.Name ); @@ -90,3 +92,72 @@ pub fn test_precompile_test_vectors( Ok(()) } + +pub struct MockHandle { + pub input: Vec, + pub gas_limit: Option, + pub context: Context, + pub is_static: bool, + pub gas_used: u64, +} + +impl MockHandle { + pub fn new(input: Vec, gas_limit: Option, context: Context) -> Self { + Self { + input, + gas_limit, + context, + is_static: false, + gas_used: 0, + } + } +} + +impl PrecompileHandle for MockHandle { + /// Perform subcall in provided context. + /// Precompile specifies in which context the subcall is executed. + fn call( + &mut self, + _: H160, + _: Option, + _: Vec, + _: Option, + _: bool, + _: &Context, + ) -> (ExitReason, Vec) { + unimplemented!() + } + + fn record_cost(&mut self, cost: u64) -> Result<(), ExitError> { + self.gas_used += cost; + Ok(()) + } + + fn log(&mut self, _: H160, _: Vec, _: Vec) -> Result<(), ExitError> { + unimplemented!() + } + + fn remaining_gas(&self) -> u64 { + unimplemented!() + } + + fn code_address(&self) -> H160 { + unimplemented!() + } + + fn input(&self) -> &[u8] { + &self.input + } + + fn context(&self) -> &Context { + &self.context + } + + fn is_static(&self) -> bool { + self.is_static + } + + fn gas_limit(&self) -> Option { + self.gas_limit + } +} diff --git a/src/components/contracts/primitives/evm/Cargo.toml b/src/components/contracts/primitives/evm/Cargo.toml index cfdb56f55..5f4263567 100644 --- a/src/components/contracts/primitives/evm/Cargo.toml +++ b/src/components/contracts/primitives/evm/Cargo.toml @@ -11,7 +11,7 @@ readme = "README.md" [dependencies] ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } ethereum-types = { version = "0.13.1", default-features = false } -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } ruc = "1.0" serde = { version = "1.0.124", features = ["derive"] } diff --git a/src/components/contracts/rpc/Cargo.toml b/src/components/contracts/rpc/Cargo.toml index 1e5732b00..58d26637d 100644 --- a/src/components/contracts/rpc/Cargo.toml +++ b/src/components/contracts/rpc/Cargo.toml @@ -16,7 +16,7 @@ baseapp = { path = "../baseapp" } base64 = "0.13" ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } ethereum-types = { version = "0.13.1", default-features = false } -evm = { version = "0.35.0", default-features = false, features = ["with-serde"] } +evm = { version = "0.36.0", default-features = false, features = ["with-serde"] } fp-rpc-core = { path = "../primitives/rpc-core" } fp-rpc-server = { path = "../primitives/rpc-server" } futures = { version = "0.3.16", features = ["compat", "thread-pool"] } @@ -42,7 +42,7 @@ sha3 = "0.10" tendermint = { git = "https://github.com/FindoraNetwork/tendermint-rs", tag = "v0.19.0c" } tendermint-rpc = { git = "https://github.com/FindoraNetwork/tendermint-rs", features = ["http-client", "websocket-client"], tag = "v0.19.0c" } tokio = { version = "1.10.1", features = ["full"] } -lru = "0.7.0" +lru = "0.7" num_cpus = "1.13" # modules