From abff5cf6ac48effc85b5e541dec1d9e725abb21a Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Thu, 16 Sep 2021 07:56:51 -0400 Subject: [PATCH 1/9] Test for 1inch liquidity protocol (#274) * A test showing a 1inch liquidity pool working * Add some modules to organize 1inch code * Reorganize code; add gas value asserts * Avoid some code duplication --- src/test_utils/erc20.rs | 18 ++ src/test_utils/mod.rs | 37 ++- src/test_utils/one_inch/liquidity_protocol.rs | 262 ++++++++++++++++++ src/test_utils/one_inch/mod.rs | 46 +++ src/test_utils/solidity.rs | 6 +- src/tests/one_inch.rs | 117 +++++--- 6 files changed, 440 insertions(+), 46 deletions(-) create mode 100644 src/test_utils/one_inch/liquidity_protocol.rs create mode 100644 src/test_utils/one_inch/mod.rs diff --git a/src/test_utils/erc20.rs b/src/test_utils/erc20.rs index fcc7568d7..b48dff9ab 100644 --- a/src/test_utils/erc20.rs +++ b/src/test_utils/erc20.rs @@ -115,6 +115,24 @@ impl ERC20 { } } + pub fn approve(&self, spender: Address, amount: U256, nonce: U256) -> LegacyEthTransaction { + let data = self + .0 + .abi + .function("approve") + .unwrap() + .encode_input(&[ethabi::Token::Address(spender), ethabi::Token::Uint(amount)]) + .unwrap(); + LegacyEthTransaction { + nonce, + gas_price: Default::default(), + gas: u64::MAX.into(), + to: Some(self.0.address), + value: Default::default(), + data, + } + } + pub fn balance_of(&self, address: Address, nonce: U256) -> LegacyEthTransaction { let data = self .0 diff --git a/src/test_utils/mod.rs b/src/test_utils/mod.rs index cc58df7bf..e8b807335 100644 --- a/src/test_utils/mod.rs +++ b/src/test_utils/mod.rs @@ -34,6 +34,7 @@ pub(crate) const SUBMIT: &str = "submit"; pub(crate) mod erc20; pub(crate) mod exit_precompile; +pub(crate) mod one_inch; pub(crate) mod self_destruct; pub(crate) mod solidity; pub(crate) mod standard_precompiles; @@ -144,7 +145,7 @@ impl AuroraRunner { input: Vec, ) { context.block_index += 1; - context.block_timestamp += 100; + context.block_timestamp += 1_000_000_000; context.input = input; context.signer_account_id = as_account_id(signer_account_id); context.predecessor_account_id = as_account_id(caller_account_id); @@ -223,9 +224,18 @@ impl AuroraRunner { signer: &mut Signer, make_tx: F, ) -> Result { + self.submit_with_signer_profiled(signer, make_tx) + .map(|(result, _)| result) + } + + pub fn submit_with_signer_profiled LegacyEthTransaction>( + &mut self, + signer: &mut Signer, + make_tx: F, + ) -> Result<(SubmitResult, ExecutionProfile), VMError> { let nonce = signer.use_nonce(); let tx = make_tx(nonce.into()); - self.submit_transaction(&signer.secret_key, tx) + self.submit_transaction_profiled(&signer.secret_key, tx) } pub fn submit_transaction( @@ -233,6 +243,15 @@ impl AuroraRunner { account: &SecretKey, transaction: LegacyEthTransaction, ) -> Result { + self.submit_transaction_profiled(account, transaction) + .map(|(result, _)| result) + } + + pub fn submit_transaction_profiled( + &mut self, + account: &SecretKey, + transaction: LegacyEthTransaction, + ) -> Result<(SubmitResult, ExecutionProfile), VMError> { let calling_account_id = "some-account.near"; let signed_tx = sign_transaction(transaction, Some(self.chain_id), account); @@ -242,10 +261,11 @@ impl AuroraRunner { if let Some(err) = maybe_err { Err(err) } else { + let output = output.unwrap(); + let profile = ExecutionProfile::new(&output); let submit_result = - SubmitResult::try_from_slice(&output.unwrap().return_data.as_value().unwrap()) - .unwrap(); - Ok(submit_result) + SubmitResult::try_from_slice(&output.return_data.as_value().unwrap()).unwrap(); + Ok((submit_result, profile)) } } @@ -562,6 +582,13 @@ pub fn unwrap_success(result: SubmitResult) -> Vec { } } +pub fn unwrap_success_slice(result: &SubmitResult) -> &[u8] { + match &result.status { + TransactionStatus::Succeed(ret) => &ret, + other => panic!("Unexpected status: {:?}", other), + } +} + pub fn unwrap_revert(result: SubmitResult) -> Vec { match result.status { TransactionStatus::Revert(ret) => ret, diff --git a/src/test_utils/one_inch/liquidity_protocol.rs b/src/test_utils/one_inch/liquidity_protocol.rs new file mode 100644 index 000000000..e9ce72a89 --- /dev/null +++ b/src/test_utils/one_inch/liquidity_protocol.rs @@ -0,0 +1,262 @@ +use crate::parameters::SubmitResult; +use crate::prelude::{Address, U256}; +use crate::test_utils::{self, solidity, ExecutionProfile}; +use std::path::PathBuf; +use std::sync::Once; + +static DOWNLOAD_ONCE: Once = Once::new(); +static COMPILE_ONCE: Once = Once::new(); + +pub(crate) struct Helper<'a> { + pub runner: &'a mut test_utils::AuroraRunner, + pub signer: &'a mut test_utils::Signer, +} + +impl<'a> Helper<'a> { + pub(crate) fn create_mooniswap_deployer( + &mut self, + ) -> (SubmitResult, ExecutionProfile, PoolDeployer) { + let artifacts_path = download_and_compile_solidity_sources(); + let deployer_constructor = + test_utils::solidity::ContractConstructor::compile_from_extended_json( + artifacts_path.join("MooniswapDeployer.sol/MooniswapDeployer.json"), + ); + let data = deployer_constructor.code; + let abi = deployer_constructor.abi; + + let (result, profile) = self + .runner + .submit_with_signer_profiled(self.signer, |nonce| { + crate::transaction::LegacyEthTransaction { + nonce, + gas_price: Default::default(), + gas: u64::MAX.into(), + to: None, + value: Default::default(), + data, + } + }) + .unwrap(); + + let deployer_address = Address::from_slice(test_utils::unwrap_success_slice(&result)); + let deployer = PoolDeployer(solidity::DeployedContract { + abi, + address: deployer_address, + }); + + (result, profile, deployer) + } + + pub(crate) fn create_pool_factory( + &mut self, + pool_deployer: &PoolDeployer, + ) -> (SubmitResult, ExecutionProfile, PoolFactory) { + let artifacts_path = download_and_compile_solidity_sources(); + let constructor = test_utils::solidity::ContractConstructor::compile_from_extended_json( + artifacts_path.join("MooniswapFactory.sol/MooniswapFactory.json"), + ); + + let signer_address = test_utils::address_from_secret_key(&self.signer.secret_key); + let (result, profile) = self + .runner + .submit_with_signer_profiled(self.signer, |nonce| { + constructor.deploy_with_args( + nonce, + &[ + ethabi::Token::Address(signer_address), + ethabi::Token::Address(pool_deployer.0.address), + ethabi::Token::Address(signer_address), + ], + ) + }) + .unwrap(); + + let address = Address::from_slice(test_utils::unwrap_success_slice(&result)); + let pool_factory = PoolFactory(constructor.deployed_at(address)); + + (result, profile, pool_factory) + } + + pub(crate) fn create_pool( + &mut self, + pool_factory: &PoolFactory, + token_a: Address, + token_b: Address, + ) -> (SubmitResult, ExecutionProfile, Pool) { + let artifacts_path = download_and_compile_solidity_sources(); + let constructor = test_utils::solidity::ContractConstructor::compile_from_extended_json( + artifacts_path.join("Mooniswap.sol/Mooniswap.json"), + ); + + let (result, profile) = self + .runner + .submit_with_signer_profiled(self.signer, |nonce| { + pool_factory.0.call_method_with_args( + "deploy", + &[ + ethabi::Token::Address(token_a), + ethabi::Token::Address(token_b), + ], + nonce, + ) + }) + .unwrap(); + + let address = Address::from_slice(&test_utils::unwrap_success_slice(&result)[12..32]); + let pool = Pool(constructor.deployed_at(address)); + + (result, profile, pool) + } + + pub(crate) fn create_erc20(&mut self, name: &str, symbol: &str) -> test_utils::erc20::ERC20 { + let constructor = test_utils::erc20::ERC20Constructor::load(); + let nonce = self.signer.use_nonce(); + test_utils::erc20::ERC20(self.runner.deploy_contract( + &self.signer.secret_key, + |c| c.deploy(name, symbol, nonce.into()), + constructor, + )) + } + + pub(crate) fn mint_erc20_tokens( + &mut self, + token: &test_utils::erc20::ERC20, + dest: Address, + ) -> SubmitResult { + let result = self + .runner + .submit_with_signer(self.signer, |nonce| { + token.mint(dest, 1_000_000.into(), nonce) + }) + .unwrap(); + assert!(result.status.is_ok()); + result + } + + pub(crate) fn approve_erc20_tokens( + &mut self, + token: &test_utils::erc20::ERC20, + dest: Address, + ) -> SubmitResult { + let result = self + .runner + .submit_with_signer(self.signer, |nonce| { + token.approve(dest, 1_000_000.into(), nonce) + }) + .unwrap(); + assert!(result.status.is_ok()); + result + } + + pub(crate) fn pool_deposit( + &mut self, + pool: &Pool, + args: DepositArgs, + ) -> (SubmitResult, ExecutionProfile) { + self.pool_call( + pool, + "deposit", + &[ + ethabi::Token::FixedArray(vec![ + ethabi::Token::Uint(args.max_token_a), + ethabi::Token::Uint(args.max_token_b), + ]), + ethabi::Token::FixedArray(vec![ + ethabi::Token::Uint(args.min_token_a), + ethabi::Token::Uint(args.min_token_b), + ]), + ], + ) + } + + pub(crate) fn pool_swap( + &mut self, + pool: &Pool, + args: SwapArgs, + ) -> (SubmitResult, ExecutionProfile) { + self.pool_call( + pool, + "swap", + &[ + ethabi::Token::Address(args.src_token), + ethabi::Token::Address(args.dst_token), + ethabi::Token::Uint(args.amount), + ethabi::Token::Uint(args.min_amount), + ethabi::Token::Address(args.referral), + ], + ) + } + + pub(crate) fn pool_withdraw( + &mut self, + pool: &Pool, + args: WithdrawArgs, + ) -> (SubmitResult, ExecutionProfile) { + self.pool_call( + pool, + "withdraw", + &[ + ethabi::Token::Uint(args.amount), + ethabi::Token::Array(vec![ + ethabi::Token::Uint(args.min_token_a), + ethabi::Token::Uint(args.min_token_b), + ]), + ], + ) + } + + fn pool_call( + &mut self, + pool: &Pool, + method_name: &str, + args: &[ethabi::Token], + ) -> (SubmitResult, ExecutionProfile) { + let (result, profile) = self + .runner + .submit_with_signer_profiled(self.signer, |nonce| { + pool.0.call_method_with_args(method_name, args, nonce) + }) + .unwrap(); + assert!(result.status.is_ok()); + (result, profile) + } +} + +pub(crate) struct PoolDeployer(solidity::DeployedContract); +pub(crate) struct PoolFactory(solidity::DeployedContract); +pub(crate) struct Pool(solidity::DeployedContract); + +pub(crate) struct DepositArgs { + pub min_token_a: U256, + pub min_token_b: U256, + pub max_token_a: U256, + pub max_token_b: U256, +} + +pub(crate) struct SwapArgs { + pub src_token: Address, + pub dst_token: Address, + pub amount: U256, + pub min_amount: U256, + pub referral: Address, +} + +pub(crate) struct WithdrawArgs { + pub amount: U256, + pub min_token_a: U256, + pub min_token_b: U256, +} + +impl Pool { + pub fn address(&self) -> Address { + self.0.address + } +} + +fn download_and_compile_solidity_sources() -> PathBuf { + super::download_and_compile_solidity_sources( + "liquidity-protocol", + &DOWNLOAD_ONCE, + &COMPILE_ONCE, + ) +} diff --git a/src/test_utils/one_inch/mod.rs b/src/test_utils/one_inch/mod.rs new file mode 100644 index 000000000..5e3f35b63 --- /dev/null +++ b/src/test_utils/one_inch/mod.rs @@ -0,0 +1,46 @@ +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::sync::Once; + +pub(crate) mod liquidity_protocol; + +pub(crate) fn download_and_compile_solidity_sources( + repo_name: &str, + download_once: &'static Once, + compile_once: &'static Once, +) -> PathBuf { + let sources_dir = Path::new("target").join(repo_name); + if !sources_dir.exists() { + // Contracts not already present, so download them (but only once, even + // if multiple tests running in parallel saw `contracts_dir` does not exist). + download_once.call_once(|| { + let url = format!("https://github.com/1inch/{}", repo_name); + git2::Repository::clone(&url, &sources_dir).unwrap(); + }); + } + + compile_once.call_once(|| { + // install packages + let status = Command::new("/usr/bin/env") + .current_dir(&sources_dir) + .args(["yarn", "install"]) + .status() + .unwrap(); + assert!(status.success()); + + let hardhat = |command: &str| { + let status = Command::new("/usr/bin/env") + .current_dir(&sources_dir) + .args(["node_modules/hardhat/internal/cli/cli.js", command]) + .status() + .unwrap(); + assert!(status.success()); + }; + + // clean and compile + hardhat("clean"); + hardhat("compile"); + }); + + sources_dir.join("artifacts/contracts") +} diff --git a/src/test_utils/solidity.rs b/src/test_utils/solidity.rs index 70c642def..6e68c17a6 100644 --- a/src/test_utils/solidity.rs +++ b/src/test_utils/solidity.rs @@ -75,11 +75,15 @@ impl ContractConstructor { } pub fn deploy_without_args(&self, nonce: U256) -> LegacyEthTransaction { + self.deploy_with_args(nonce, &[]) + } + + pub fn deploy_with_args(&self, nonce: U256, args: &[ethabi::Token]) -> LegacyEthTransaction { let data = self .abi .constructor() .unwrap() - .encode_input(self.code.clone(), &[]) + .encode_input(self.code.clone(), args) .unwrap(); LegacyEthTransaction { nonce, diff --git a/src/tests/one_inch.rs b/src/tests/one_inch.rs index dffa169b1..bf454793a 100644 --- a/src/tests/one_inch.rs +++ b/src/tests/one_inch.rs @@ -1,11 +1,11 @@ use crate::parameters::SubmitResult; +use crate::prelude::U256; use crate::test_utils; +use crate::test_utils::one_inch::liquidity_protocol; use crate::types::Wei; use borsh::BorshDeserialize; use near_vm_logic::VMOutcome; use secp256k1::SecretKey; -use std::path::{Path, PathBuf}; -use std::process::Command; use std::sync::Once; const INITIAL_BALANCE: Wei = Wei::new_u64(1_000_000); @@ -14,6 +14,75 @@ const INITIAL_NONCE: u64 = 0; static DOWNLOAD_ONCE: Once = Once::new(); static COMPILE_ONCE: Once = Once::new(); +#[test] +fn test_1inch_liquidity_protocol() { + let (mut runner, mut source_account) = initialize(); + let mut helper = liquidity_protocol::Helper { + runner: &mut runner, + signer: &mut source_account, + }; + + let (result, profile, deployer_address) = helper.create_mooniswap_deployer(); + assert!(result.gas_used >= 5_100_000); // more than 5.1M EVM gas used + assert!(profile.all_gas() <= 43_000_000_000_000); // less than 43 NEAR Tgas used + + let (result, profile, pool_factory) = helper.create_pool_factory(&deployer_address); + assert!(result.gas_used >= 2_800_000); // more than 2.8M EVM gas used + assert!(profile.all_gas() <= 32_000_000_000_000); // less than 32 NEAR Tgas used + + // create some ERC-20 tokens to have a liquidity pool for + let signer_address = test_utils::address_from_secret_key(&helper.signer.secret_key); + let token_a = helper.create_erc20("TokenA", "AAA"); + let token_b = helper.create_erc20("TokenB", "BBB"); + helper.mint_erc20_tokens(&token_a, signer_address); + helper.mint_erc20_tokens(&token_b, signer_address); + + let (result, profile, pool) = + helper.create_pool(&pool_factory, token_a.0.address, token_b.0.address); + assert!(result.gas_used >= 4_500_000); // more than 4.5M EVM gas used + assert!(profile.all_gas() <= 103_000_000_000_000); // less than 103 NEAR Tgas used + + // Approve giving ERC-20 tokens to the pool + helper.approve_erc20_tokens(&token_a, pool.address()); + helper.approve_erc20_tokens(&token_b, pool.address()); + + let (result, profile) = helper.pool_deposit( + &pool, + liquidity_protocol::DepositArgs { + min_token_a: U256::zero(), + min_token_b: U256::zero(), + max_token_a: 10_000.into(), + max_token_b: 10_000.into(), + }, + ); + assert!(result.gas_used >= 302_000); // more than 302k EVM gas used + assert!(profile.all_gas() <= 117_000_000_000_000); // less than 117 NEAR Tgas used + + let (result, profile) = helper.pool_swap( + &pool, + liquidity_protocol::SwapArgs { + src_token: token_a.0.address, + dst_token: token_b.0.address, + amount: 1000.into(), + min_amount: U256::one(), + referral: signer_address, + }, + ); + assert!(result.gas_used >= 210_000); // more than 210k EVM gas used + assert!(profile.all_gas() <= 136_000_000_000_000); // less than 136 NEAR Tgas used + + let (result, profile) = helper.pool_withdraw( + &pool, + liquidity_protocol::WithdrawArgs { + amount: 100.into(), + min_token_a: U256::one(), + min_token_b: U256::one(), + }, + ); + assert!(result.gas_used >= 150_000); // more than 150k EVM gas used + assert!(profile.all_gas() <= 102_000_000_000_000); // less than 102 NEAR Tgas used +} + #[test] fn test_1_inch_limit_order_deploy() { // set up Aurora runner and accounts @@ -37,7 +106,12 @@ fn deploy_1_inch_limit_order_contract( runner: &mut test_utils::AuroraRunner, signer: &mut test_utils::Signer, ) -> VMOutcome { - let contract_path = download_and_compile_solidity_sources(); + let artifacts_path = test_utils::one_inch::download_and_compile_solidity_sources( + "limit-order-protocol", + &DOWNLOAD_ONCE, + &COMPILE_ONCE, + ); + let contract_path = artifacts_path.join("LimitOrderProtocol.sol/LimitOrderProtocol.json"); let constructor = test_utils::solidity::ContractConstructor::compile_from_extended_json(contract_path); @@ -61,43 +135,6 @@ fn deploy_1_inch_limit_order_contract( outcome.unwrap() } -fn download_and_compile_solidity_sources() -> PathBuf { - let sources_dir = Path::new("target").join("limit-order-protocol"); - if !sources_dir.exists() { - // Contracts not already present, so download them (but only once, even - // if multiple tests running in parallel saw `contracts_dir` does not exist). - DOWNLOAD_ONCE.call_once(|| { - let url = "https://github.com/1inch/limit-order-protocol"; - git2::Repository::clone(url, &sources_dir).unwrap(); - }); - } - - COMPILE_ONCE.call_once(|| { - // install packages - let status = Command::new("/usr/bin/env") - .current_dir(&sources_dir) - .args(["yarn", "install"]) - .status() - .unwrap(); - assert!(status.success()); - - let hardhat = |command: &str| { - let status = Command::new("/usr/bin/env") - .current_dir(&sources_dir) - .args(["node_modules/hardhat/internal/cli/cli.js", command]) - .status() - .unwrap(); - assert!(status.success()); - }; - - // clean and compile - hardhat("clean"); - hardhat("compile"); - }); - - sources_dir.join("artifacts/contracts/LimitOrderProtocol.sol/LimitOrderProtocol.json") -} - fn initialize() -> (test_utils::AuroraRunner, test_utils::Signer) { // set up Aurora runner and accounts let mut runner = test_utils::deploy_evm(); From b25fc8b21791deb0356cb860a31f1d10327e7bef Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Fri, 17 Sep 2021 02:14:14 -0400 Subject: [PATCH 2/9] Fix deploy benchmark to use a realistic transaction (that actually writes data to the created account code) (#277) --- src/benches/eth_deploy_code.rs | 19 +++++------- src/test_utils/mod.rs | 53 ++++++++++++++++++++++++++++++---- src/tests/sanity.rs | 27 +++++++++++++++++ 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/benches/eth_deploy_code.rs b/src/benches/eth_deploy_code.rs index a489057b3..9b21aea8a 100644 --- a/src/benches/eth_deploy_code.rs +++ b/src/benches/eth_deploy_code.rs @@ -1,12 +1,13 @@ use criterion::{BatchSize, BenchmarkId, Criterion, Throughput}; use secp256k1::SecretKey; -use crate::test_utils::{address_from_secret_key, create_eth_transaction, deploy_evm, SUBMIT}; +use crate::test_utils::{ + address_from_secret_key, create_deploy_transaction, deploy_evm, sign_transaction, SUBMIT, +}; use crate::types::Wei; const INITIAL_BALANCE: Wei = Wei::new_u64(1000); const INITIAL_NONCE: u64 = 0; -const TRANSFER_AMOUNT: Wei = Wei::zero(); pub(crate) fn eth_deploy_code_benchmark(c: &mut Criterion) { let mut runner = deploy_evm(); @@ -17,20 +18,16 @@ pub(crate) fn eth_deploy_code_benchmark(c: &mut Criterion) { INITIAL_BALANCE, INITIAL_NONCE.into(), ); - let inputs: Vec<_> = [1, 4, 8, 12, 16] + let inputs: Vec<_> = [1, 4, 8, 10, 13, 14] .iter() .copied() .map(|n| { let code_size = 2usize.pow(n); let code: Vec = vec![0; code_size]; - let transaction = create_eth_transaction( - None, - TRANSFER_AMOUNT.into(), - code, - Some(runner.chain_id), - &source_account, - ); - rlp::encode(&transaction).to_vec() + let transaction = create_deploy_transaction(code, INITIAL_NONCE.into()); + let signed_transaction = + sign_transaction(transaction, Some(runner.chain_id), &source_account); + rlp::encode(&signed_transaction).to_vec() }) .collect(); let calling_account_id = "some-account.near"; diff --git a/src/test_utils/mod.rs b/src/test_utils/mod.rs index e8b807335..f6e43bfad 100644 --- a/src/test_utils/mod.rs +++ b/src/test_utils/mod.rs @@ -22,7 +22,7 @@ use crate::transaction::{ LegacyEthSignedTransaction, LegacyEthTransaction, }; use crate::types; -use crate::types::AccountId; +use crate::types::{AccountId, Wei}; // TODO(Copied from #84): Make sure that there is only one Signer after both PR are merged. @@ -314,22 +314,30 @@ impl AuroraRunner { } pub fn get_balance(&self, address: Address) -> types::Wei { - types::Wei::new(self.getter_method_call("get_balance", address)) + types::Wei::new(self.u256_getter_method_call("get_balance", address)) } pub fn get_nonce(&self, address: Address) -> U256 { - self.getter_method_call("get_nonce", address) + self.u256_getter_method_call("get_nonce", address) + } + + pub fn get_code(&self, address: Address) -> Vec { + self.getter_method_call("get_code", address) + } + + fn u256_getter_method_call(&self, method_name: &str, address: Address) -> U256 { + let bytes = self.getter_method_call(method_name, address); + U256::from_big_endian(&bytes) } // Used in `get_balance` and `get_nonce`. This function exists to avoid code duplication // since the contract's `get_nonce` and `get_balance` have the same type signature. - fn getter_method_call(&self, method_name: &str, address: Address) -> U256 { + fn getter_method_call(&self, method_name: &str, address: Address) -> Vec { let (outcome, maybe_error) = self.one_shot() .call(method_name, "getter", address.as_bytes().to_vec()); assert!(maybe_error.is_none()); - let bytes = outcome.unwrap().return_data.as_value().unwrap(); - U256::from_big_endian(&bytes) + outcome.unwrap().return_data.as_value().unwrap() } fn bytes_from_outcome( @@ -453,6 +461,39 @@ pub(crate) fn transfer(to: Address, amount: types::Wei, nonce: U256) -> LegacyEt } } +pub(crate) fn create_deploy_transaction( + contract_bytes: Vec, + nonce: U256, +) -> LegacyEthTransaction { + let len = contract_bytes.len(); + if len > u16::MAX as usize { + panic!("Cannot deploy a contract with that many bytes!"); + } + let len = len as u16; + // This bit of EVM byte code essentially says: + // "If msg.value > 0 revert; otherwise return `len` amount of bytes that come after me + // in the code." By prepending this to `contract_bytes` we create a valid EVM program which + // returns `contract_bytes`, which is exactly what we want. + let init_code = format!( + "608060405234801561001057600080fd5b5061{}806100206000396000f300", + hex::encode(len.to_be_bytes()) + ); + let data = hex::decode(init_code) + .unwrap() + .into_iter() + .chain(contract_bytes.into_iter()) + .collect(); + + LegacyEthTransaction { + nonce, + gas_price: Default::default(), + gas: u64::MAX.into(), + to: None, + value: Wei::zero(), + data, + } +} + pub(crate) fn create_eth_transaction( to: Option
, value: types::Wei, diff --git a/src/tests/sanity.rs b/src/tests/sanity.rs index 0ac19c2bb..ff064f826 100644 --- a/src/tests/sanity.rs +++ b/src/tests/sanity.rs @@ -5,6 +5,7 @@ use crate::test_utils; use crate::tests::state_migration; use crate::types::{self, Wei, ERC20_MINT_SELECTOR}; use borsh::{BorshDeserialize, BorshSerialize}; +use rand::RngCore; use secp256k1::SecretKey; use std::path::{Path, PathBuf}; @@ -13,6 +14,32 @@ const INITIAL_NONCE: u64 = 0; const TRANSFER_AMOUNT: Wei = Wei::new_u64(123); const GAS_PRICE: u64 = 10; +#[test] +fn test_deploy_contract() { + let (mut runner, mut signer, _) = initialize_transfer(); + + // Randomly generate some "contract code" + const LEN: usize = 567; + let code: Vec = { + let mut rng = rand::thread_rng(); + let mut buf = vec![0u8; LEN]; + rng.fill_bytes(&mut buf); + buf + }; + + // Deploy that code + let result = runner + .submit_with_signer(&mut signer, |nonce| { + test_utils::create_deploy_transaction(code.clone(), nonce) + }) + .unwrap(); + let address = Address::from_slice(test_utils::unwrap_success_slice(&result)); + + // Confirm the code stored at that address is equal to the input code. + let stored_code = runner.get_code(address); + assert_eq!(code, stored_code); +} + #[test] fn test_override_state() { let (mut runner, mut account1, viewer_address) = initialize_transfer(); From cf9f9d065c2425c00a82254499e9c43b95487d01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Sep 2021 13:19:05 +0700 Subject: [PATCH 3/9] Bump @openzeppelin/contracts from 4.3.1 to 4.3.2 in /etc/eth-contracts (#275) Bumps [@openzeppelin/contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) from 4.3.1 to 4.3.2. - [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts/releases) - [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md) - [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts/compare/v4.3.1...v4.3.2) --- updated-dependencies: - dependency-name: "@openzeppelin/contracts" dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- etc/eth-contracts/package.json | 2 +- etc/eth-contracts/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/etc/eth-contracts/package.json b/etc/eth-contracts/package.json index e9a62b4ed..4d57b57c3 100644 --- a/etc/eth-contracts/package.json +++ b/etc/eth-contracts/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "description": "ERC20 token implementation on EVM mapped from Native NEP-141", "dependencies": { - "@openzeppelin/contracts": "^4.3.1" + "@openzeppelin/contracts": "^4.3.2" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.1", diff --git a/etc/eth-contracts/yarn.lock b/etc/eth-contracts/yarn.lock index ca241908a..ca51c0049 100644 --- a/etc/eth-contracts/yarn.lock +++ b/etc/eth-contracts/yarn.lock @@ -903,10 +903,10 @@ "@types/sinon-chai" "^3.2.3" "@types/web3" "1.0.19" -"@openzeppelin/contracts@^4.3.1": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.1.tgz#c01f791ce6c9d3989ac1a643267501dbe336b9e3" - integrity sha512-QjgbPPlmDK2clK1hzjw2ROfY8KA5q+PfhDUUxZFEBCZP9fi6d5FuNoh/Uq0oCTMEKPmue69vhX2jcl0N/tFKGw== +"@openzeppelin/contracts@^4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.2.tgz#ff80affd6d352dbe1bbc5b4e1833c41afd6283b6" + integrity sha512-AybF1cesONZStg5kWf6ao9OlqTZuPqddvprc0ky7lrUVOjXeKpmQ2Y9FK+6ygxasb+4aic4O5pneFBfwVsRRRg== "@resolver-engine/core@^0.3.3": version "0.3.3" From d34ea646ca8772287ab510c6aa406a1fb35eb8b9 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Thu, 23 Sep 2021 08:06:47 +0300 Subject: [PATCH 4/9] Split to crates: engine, prelude, sdk (#243) * Introduce workspace * Split to crate: * engine * prelude * sdk * Fixed tests * Refactored dependencies to new crates Co-authored-by: Michael Birch --- .github/workflows/lints.yml | 2 - .github/workflows/tests.yml | 2 - .gitignore | 5 +- Cargo.lock | 175 ++++++++++--- Cargo.toml | 81 +----- Makefile | 5 +- README.md | 5 + VERSION | 2 +- engine-precompiles/Cargo.toml | 45 ++++ .../src}/blake2.rs | 6 +- .../src}/bn128.rs | 8 +- .../src}/hash.rs | 10 +- .../src}/identity.rs | 7 +- .../mod.rs => engine-precompiles/src/lib.rs | 94 +++---- .../src}/modexp.rs | 24 +- .../src}/native.rs | 52 ++-- engine-precompiles/src/prelude.rs | 7 + .../src}/secp256k1.rs | 16 +- engine-precompiles/src/utils.rs | 9 + engine-sdk/Cargo.toml | 22 ++ src/sdk.rs => engine-sdk/src/lib.rs | 53 ++-- engine-sdk/src/prelude.rs | 3 + engine-sdk/src/types.rs | 106 ++++++++ engine-tests/Cargo.toml | 48 ++++ .../src}/benches/eth_deploy_code.rs | 2 +- .../src}/benches/eth_erc20.rs | 2 +- .../src}/benches/eth_standard_precompiles.rs | 2 +- .../src}/benches/eth_transfer.rs | 2 +- {src => engine-tests/src}/benches/mod.rs | 0 .../src}/benches/nft_pagination.rs | 4 +- .../src}/benches/res/StandardPrecompiles.sol | 0 engine-tests/src/lib.rs | 8 + engine-tests/src/prelude.rs | 9 + {src => engine-tests/src}/test_utils/erc20.rs | 3 +- .../src}/test_utils/exit_precompile.rs | 6 +- {src => engine-tests/src}/test_utils/mod.rs | 78 +++--- .../test_utils/one_inch/liquidity_protocol.rs | 6 +- .../src}/test_utils/one_inch/mod.rs | 0 .../src}/test_utils/self_destruct.rs | 12 +- .../src}/test_utils/solidity.rs | 4 +- .../src}/test_utils/standard_precompiles.rs | 3 +- .../src}/tests/access_lists.rs | 6 +- .../src}/tests/contract_call.rs | 0 {src => engine-tests/src}/tests/erc20.rs | 9 +- .../src}/tests/erc20_connector.rs | 7 +- .../src}/tests/eth_connector.rs | 27 +- .../src}/tests/meta_parsing.rs | 5 +- {src => engine-tests/src}/tests/mod.rs | 0 {src => engine-tests/src}/tests/one_inch.rs | 18 +- .../src}/tests/res/blockhash.sol | 0 .../src}/tests/res/poster.sol | 0 {src => engine-tests/src}/tests/sanity.rs | 32 ++- .../src}/tests/self_destruct_state.rs | 0 .../src}/tests/standard_precompiles.rs | 2 +- .../src}/tests/state_migration.rs | 7 +- engine-types/Cargo.toml | 30 +++ src/prelude.rs => engine-types/src/lib.rs | 107 ++++---- engine-types/src/parameters.rs | 19 ++ {src => engine-types/src}/storage.rs | 5 +- {src => engine-types/src}/types.rs | 231 +----------------- engine/Cargo.toml | 60 +++++ LICENSE => engine/LICENSE | 0 {src => engine/src}/admin_controlled.rs | 4 +- {src => engine/src}/connector.rs | 79 +++--- {src => engine/src}/deposit_event.rs | 60 +++-- {src => engine/src}/engine.rs | 38 +-- {src => engine/src}/fungible_token.rs | 69 +++--- {src => engine/src}/json.rs | 4 +- {src => engine/src}/lib.rs | 71 +++--- {src => engine/src}/log_entry.rs | 3 +- {src => engine/src}/map.rs | 14 +- {src => engine/src}/meta_parsing.rs | 14 +- {src => engine/src}/parameters.rs | 95 ++----- engine/src/prelude.rs | 11 + engine/src/proof.rs | 25 ++ .../src}/transaction/access_list.rs | 8 +- {src => engine/src}/transaction/legacy.rs | 10 +- {src => engine/src}/transaction/mod.rs | 4 +- etc/state-migration-test/Cargo.lock | 54 +++- etc/state-migration-test/Cargo.toml | 4 +- etc/state-migration-test/src/lib.rs | 3 +- 81 files changed, 1167 insertions(+), 896 deletions(-) create mode 100644 engine-precompiles/Cargo.toml rename {src/precompiles => engine-precompiles/src}/blake2.rs (98%) rename {src/precompiles => engine-precompiles/src}/bn128.rs (99%) rename {src/precompiles => engine-precompiles/src}/hash.rs (96%) rename {src/precompiles => engine-precompiles/src}/identity.rs (95%) rename src/precompiles/mod.rs => engine-precompiles/src/lib.rs (78%) rename {src/precompiles => engine-precompiles/src}/modexp.rs (98%) rename {src/precompiles => engine-precompiles/src}/native.rs (91%) create mode 100644 engine-precompiles/src/prelude.rs rename {src/precompiles => engine-precompiles/src}/secp256k1.rs (95%) create mode 100644 engine-precompiles/src/utils.rs create mode 100644 engine-sdk/Cargo.toml rename src/sdk.rs => engine-sdk/src/lib.rs (94%) create mode 100644 engine-sdk/src/prelude.rs create mode 100644 engine-sdk/src/types.rs create mode 100644 engine-tests/Cargo.toml rename {src => engine-tests/src}/benches/eth_deploy_code.rs (98%) rename {src => engine-tests/src}/benches/eth_erc20.rs (98%) rename {src => engine-tests/src}/benches/eth_standard_precompiles.rs (98%) rename {src => engine-tests/src}/benches/eth_transfer.rs (98%) rename {src => engine-tests/src}/benches/mod.rs (100%) rename {src => engine-tests/src}/benches/nft_pagination.rs (98%) rename {src => engine-tests/src}/benches/res/StandardPrecompiles.sol (100%) create mode 100644 engine-tests/src/lib.rs create mode 100644 engine-tests/src/prelude.rs rename {src => engine-tests/src}/test_utils/erc20.rs (98%) rename {src => engine-tests/src}/test_utils/exit_precompile.rs (95%) rename {src => engine-tests/src}/test_utils/mod.rs (91%) rename {src => engine-tests/src}/test_utils/one_inch/liquidity_protocol.rs (98%) rename {src => engine-tests/src}/test_utils/one_inch/mod.rs (100%) rename {src => engine-tests/src}/test_utils/self_destruct.rs (93%) rename {src => engine-tests/src}/test_utils/solidity.rs (98%) rename {src => engine-tests/src}/test_utils/standard_precompiles.rs (95%) rename {src => engine-tests/src}/tests/access_lists.rs (94%) rename {src => engine-tests/src}/tests/contract_call.rs (100%) rename {src => engine-tests/src}/tests/erc20.rs (97%) rename {src => engine-tests/src}/tests/erc20_connector.rs (98%) rename {src => engine-tests/src}/tests/eth_connector.rs (99%) rename {src => engine-tests/src}/tests/meta_parsing.rs (96%) rename {src => engine-tests/src}/tests/mod.rs (100%) rename {src => engine-tests/src}/tests/one_inch.rs (92%) rename {src => engine-tests/src}/tests/res/blockhash.sol (100%) rename {src => engine-tests/src}/tests/res/poster.sol (100%) rename {src => engine-tests/src}/tests/sanity.rs (95%) rename {src => engine-tests/src}/tests/self_destruct_state.rs (100%) rename {src => engine-tests/src}/tests/standard_precompiles.rs (97%) rename {src => engine-tests/src}/tests/state_migration.rs (93%) create mode 100644 engine-types/Cargo.toml rename src/prelude.rs => engine-types/src/lib.rs (54%) create mode 100644 engine-types/src/parameters.rs rename {src => engine-types/src}/storage.rs (97%) rename {src => engine-types/src}/types.rs (59%) create mode 100644 engine/Cargo.toml rename LICENSE => engine/LICENSE (100%) rename {src => engine/src}/admin_controlled.rs (93%) rename {src => engine/src}/connector.rs (91%) rename {src => engine/src}/deposit_event.rs (61%) rename {src => engine/src}/engine.rs (97%) rename {src => engine/src}/fungible_token.rs (93%) rename {src => engine/src}/json.rs (99%) rename {src => engine/src}/lib.rs (93%) rename {src => engine/src}/log_entry.rs (92%) rename {src => engine/src}/map.rs (88%) rename {src => engine/src}/meta_parsing.rs (98%) rename {src => engine/src}/parameters.rs (83%) create mode 100644 engine/src/prelude.rs create mode 100644 engine/src/proof.rs rename {src => engine/src}/transaction/access_list.rs (95%) rename {src => engine/src}/transaction/legacy.rs (96%) rename {src => engine/src}/transaction/mod.rs (99%) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index ce50f5641..a71d69047 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -6,8 +6,6 @@ on: - master - develop pull_request: - branches: - - "*" name: Lints jobs: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8303806a9..1d2eab0b2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,8 +5,6 @@ on: - master - develop pull_request: - branches: - - "*" name: Tests jobs: diff --git a/.gitignore b/.gitignore index f0b0d9eb7..e9107811e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,16 +3,17 @@ # Visual Studio Code .vscode/ +.run/ # IDEA .idea - +.run/ # Editor backup files *~ # Rust artifacts /*.wasm -/target/ +target/ # Solidity artifacts artifacts/ diff --git a/Cargo.lock b/Cargo.lock index a99cc29e9..5cc94c990 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,22 +115,90 @@ dependencies = [ [[package]] name = "aurora-engine" -version = "1.6.3" +version = "1.7.0" dependencies = [ "aurora-bn", + "aurora-engine-precompiles", + "aurora-engine-sdk", + "aurora-engine-types", "base64 0.13.0", "blake2 0.9.1 (git+https://github.com/near/near-blake2.git)", "borsh 0.8.2", + "byte-slice-cast", + "ethabi", + "evm", + "evm-core", + "hex", + "libsecp256k1", + "logos", + "num", + "primitive-types 0.9.0", + "rand 0.7.3", + "ripemd160", + "rjson", + "rlp", + "serde", + "serde_json", + "sha2 0.9.5", + "sha3 0.9.1", + "wee_alloc", +] + +[[package]] +name = "aurora-engine-precompiles" +version = "1.0.0" +dependencies = [ + "aurora-bn", + "aurora-engine-sdk", + "aurora-engine-types", + "base64 0.13.0", + "blake2 0.9.1 (git+https://github.com/near/near-blake2.git)", + "borsh 0.8.2", + "byte-slice-cast", + "ethabi", + "evm", + "evm-core", + "hex", + "libsecp256k1", + "logos", + "num", + "primitive-types 0.9.0", + "rand 0.7.3", + "ripemd160", + "rjson", + "rlp", + "serde", + "serde_json", + "sha2 0.9.5", + "sha3 0.9.1", + "wee_alloc", +] + +[[package]] +name = "aurora-engine-sdk" +version = "1.0.0" +dependencies = [ + "aurora-engine-types", + "borsh 0.8.2", + "sha3 0.9.1", +] + +[[package]] +name = "aurora-engine-tests" +version = "1.0.0" +dependencies = [ + "aurora-engine", + "aurora-engine-sdk", + "aurora-engine-types", + "borsh 0.8.2", "bstr", "byte-slice-cast", "criterion", "ethabi", "evm", - "evm-core", "git2", "hex", "libsecp256k1", - "logos", "near-crypto 0.1.0 (git+https://github.com/near/nearcore.git?rev=8a377fda0b4ce319385c463f1ae46e4b0b29dcd9)", "near-primitives 0.1.0 (git+https://github.com/near/nearcore.git?rev=8a377fda0b4ce319385c463f1ae46e4b0b29dcd9)", "near-primitives-core 0.1.0 (git+https://github.com/near/nearcore.git?rev=8a377fda0b4ce319385c463f1ae46e4b0b29dcd9)", @@ -138,18 +206,27 @@ dependencies = [ "near-sdk-sim", "near-vm-logic 3.0.0 (git+https://github.com/near/nearcore.git?rev=8a377fda0b4ce319385c463f1ae46e4b0b29dcd9)", "near-vm-runner", - "num", - "primitive-types 0.9.0", "rand 0.7.3", - "ripemd160", - "rjson", "rlp", "serde", "serde_json", - "sha2 0.9.5", "sha3 0.9.1", "wasmer-runtime-core-near", - "wee_alloc", +] + +[[package]] +name = "aurora-engine-types" +version = "1.0.0" +dependencies = [ + "borsh 0.8.2", + "bstr", + "ethabi", + "hex", + "primitive-types 0.9.0", + "rand 0.7.3", + "serde", + "serde_json", + "sha3 0.9.1", ] [[package]] @@ -338,7 +415,7 @@ checksum = "307f3740906bac2c118a8122fe22681232b244f1369273e45f1156b45c43d2dd" dependencies = [ "borsh-derive-internal 0.8.2", "borsh-schema-derive-internal 0.8.2", - "proc-macro-crate", + "proc-macro-crate 0.1.5", "proc-macro2", "syn", ] @@ -351,7 +428,7 @@ checksum = "684155372435f578c0fa1acd13ebbb182cc19d6b38b64ae7901da4393217d264" dependencies = [ "borsh-derive-internal 0.9.1", "borsh-schema-derive-internal 0.9.1", - "proc-macro-crate", + "proc-macro-crate 0.1.5", "proc-macro2", "syn", ] @@ -1629,9 +1706,9 @@ dependencies = [ [[package]] name = "impl-codec" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df170efa359aebdd5cb7fe78edcc67107748e4737bdca8a8fb40d15ea7a877ed" +checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" dependencies = [ "parity-scale-codec", ] @@ -1654,6 +1731,17 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "indexmap" version = "1.6.2" @@ -1730,9 +1818,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.53" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4bf49d50e2961077d9c99f4b7997d770a1114f087c3c2e0069b36c13fc2979d" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" dependencies = [ "wasm-bindgen", ] @@ -2042,7 +2130,7 @@ dependencies = [ "libc", "near-account-id", "parity-secp256k1", - "primitive-types 0.10.0", + "primitive-types 0.10.1", "rand 0.7.3", "rand_core 0.5.1", "serde", @@ -2116,7 +2204,7 @@ dependencies = [ "near-rpc-error-macro 0.1.0 (git+https://github.com/near/nearcore.git?rev=8a377fda0b4ce319385c463f1ae46e4b0b29dcd9)", "near-vm-errors 3.0.0 (git+https://github.com/near/nearcore.git?rev=8a377fda0b4ce319385c463f1ae46e4b0b29dcd9)", "num-rational 0.3.2", - "primitive-types 0.10.0", + "primitive-types 0.10.1", "rand 0.7.3", "reed-solomon-erasure", "regex", @@ -2370,8 +2458,8 @@ dependencies = [ "near-vm-errors 3.0.0 (git+https://github.com/near/nearcore.git?rev=8a377fda0b4ce319385c463f1ae46e4b0b29dcd9)", "ripemd160", "serde", - "sha2 0.8.2", - "sha3 0.8.2", + "sha2 0.9.5", + "sha3 0.9.1", ] [[package]] @@ -2665,24 +2753,25 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f518afaa5a47d0d6386229b0a6e01e86427291d643aa4cabb4992219f504f8" +checksum = "e11263a97373b43da4b426edbb52ef99a7b51e2d9752ef56a7f8b356f48495a5" dependencies = [ "arrayvec 0.7.0", "bitvec", "byte-slice-cast", + "impl-trait-for-tuples", "parity-scale-codec-derive", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44c5f94427bd0b5076e8f7e15ca3f60a4d8ac0077e4793884e6fdfd8915344e" +checksum = "b157dc92b3db2bae522afb31b3843e91ae097eb01d66c72dda66a2e86bc3ca14" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.1.0", "proc-macro2", "quote", "syn", @@ -2840,9 +2929,9 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90f6931e6b3051e208a449c342246cb7c786ef300789b95619f46f1dd75d9b0" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", "impl-codec", @@ -2858,6 +2947,16 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-crate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +dependencies = [ + "thiserror", + "toml", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3463,9 +3562,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" -version = "1.0.75" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" +checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" dependencies = [ "proc-macro2", "quote", @@ -3786,9 +3885,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3796,9 +3895,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe8dc78e2326ba5f845f4b5bf548401604fa20b1dd1d365fb73b6c1d6364041" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" dependencies = [ "bumpalo", "lazy_static", @@ -3811,9 +3910,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44468aa53335841d9d6b6c023eaab07c0cd4bddbcfdee3e2bb1e8d2cb8069fef" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3821,9 +3920,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0195807922713af1e67dc66132c7328206ed9766af3858164fb583eedc25fbad" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ "proc-macro2", "quote", @@ -3834,9 +3933,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "wasmer" diff --git a/Cargo.toml b/Cargo.toml index d5e1cf970..2db400880 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,3 @@ -[package] -name = "aurora-engine" -version = "1.6.3" -authors = ["NEAR "] -edition = "2018" -description = "" -documentation = "" -readme = true -homepage = "https://github.com/aurora-is-near/aurora-engine" -repository = "https://github.com/aurora-is-near/aurora-engine" -license = "CC0-1.0" -publish = false -autobenches = false - -[lib] -crate-type = ["cdylib", "rlib"] - [profile.release] opt-level = 3 debug = false @@ -44,56 +27,14 @@ rpath = false lto = true opt-level = 3 -[dependencies] -base64 = { version = "0.13.0", default-features = false, features = ["alloc"] } -blake2 = { git = "https://github.com/near/near-blake2.git", version = "0.9.1", default-features = false } -borsh = { version = "0.8.2", default-features = false } -bn = { package = "aurora-bn", git = "https://github.com/aurora-is-near/aurora-bn.git", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } -libsecp256k1 = { version = "0.3.5", default-features = false } -num = { version = "0.4.0", default-features = false, features = ["alloc"] } -primitive-types = { version = "0.9.0", default-features = false, features = ["rlp"] } -ripemd160 = { version = "0.9.1", default-features = false } -rlp = { version = "0.5.0", default-features = false } -sha2 = { version = "0.9.3", default-features = false, optional = true } -sha3 = { version = "0.9.1", default-features = false } -wee_alloc = { version = "0.4.5", default-features = false } -logos = { version = "0.12", default-features = false, features = ["export_derive"] } -ethabi = { git = "https://github.com/darwinia-network/ethabi", branch = "xavier-no-std", default-features = false } -hex = { version = "0.4", default-features = false, features = ["alloc"] } -byte-slice-cast = { version = "1.0", default-features = false } -rjson = { git = "https://github.com/aurora-is-near/rjson", rev = "cc3da949", default-features = false, features = ["integer"] } - -[dev-dependencies] -bstr = "0.2" -serde = { version = "1", features = ["derive"] } -serde_json = "1" -hex = { version = "0.4.3", default-features = false } -near-sdk = { git = "https://github.com/aurora-is-near/near-sdk-rs.git", rev = "5e58722bd61d9d24ae6293326146c751f0a814fb" } -near-sdk-sim = { git = "https://github.com/aurora-is-near/near-sdk-rs.git", rev = "5e58722bd61d9d24ae6293326146c751f0a814fb" } -near-crypto = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9"} -near-vm-runner = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9"} -near-vm-logic = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9"} -near-primitives-core = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9"} -near-primitives = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9"} -wasmer-runtime-core = { version = "0.18.2", package = "wasmer-runtime-core-near"} -libsecp256k1 = "0.3.5" -rand = "0.7.3" -criterion = "0.3.4" -git2 = "0.13" - -[features] -default = ["sha2", "std"] -std = ["borsh/std", "evm/std", "primitive-types/std", "rlp/std", "sha3/std", "ethabi/std", "logos/std", "bn/std"] -contract = [] -evm_bully = [] -log = [] -meta-call = [] -integration-test = ["log"] -mainnet = ["contract", "log"] -testnet = ["contract", "log"] -betanet = ["contract", "log", "meta-call"] -mainnet-test = ["meta-call"] -testnet-test = ["meta-call"] -betanet-test = ["meta-call"] +[workspace] +members = [ + "engine", + "engine-types", + "engine-sdk", + "engine-precompiles", + "engine-tests" +] +exclude = [ + "etc/state-migration-test" +] diff --git a/Makefile b/Makefile index f786c2cc7..64eddce77 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ CARGO = cargo NEAR = near FEATURES = mainnet +# More strict clippy rules +FEATURES_CLIPPY = contract ADDITIONAL_FEATURES = ifeq ($(evm-bully),yes) @@ -76,6 +78,7 @@ target/wasm32-unknown-unknown/release/aurora_engine.wasm: Cargo.toml Cargo.lock RUSTFLAGS='-C link-arg=-s' $(CARGO) build \ --target wasm32-unknown-unknown \ --release \ + --verbose \ --no-default-features \ --features=$(FEATURES)$(ADDITIONAL_FEATURES) \ -Z avoid-dev-deps @@ -97,7 +100,7 @@ check-format: $(CARGO) fmt -- --check check-clippy: - $(CARGO) clippy --no-default-features --features=$(FEATURES)$(ADDITIONAL_FEATURES) -- -D warnings + $(CARGO) clippy --no-default-features --features=$(FEATURES_CLIPPY)$(ADDITIONAL_FEATURES) -- -D warnings test-sol: cd etc/eth-contracts && yarn && yarn test diff --git a/README.md b/README.md index 9b9faa843..f33983898 100644 --- a/README.md +++ b/README.md @@ -168,3 +168,8 @@ aurora dump-storage [`master`]: https://github.com/aurora-is-near/aurora-engine/commits/master [`develop`]: https://github.com/aurora-is-near/aurora-engine/commits/develop + +## License +**aurora-engine** has multiple licenses: +* all crates except `engine-test` has **CCO-1.0** license +* `engine-test` has **GPL-v3** license diff --git a/VERSION b/VERSION index 266146b87..bd8bf882d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6.3 +1.7.0 diff --git a/engine-precompiles/Cargo.toml b/engine-precompiles/Cargo.toml new file mode 100644 index 000000000..a83ebfac7 --- /dev/null +++ b/engine-precompiles/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "aurora-engine-precompiles" +version = "1.0.0" +authors = ["NEAR "] +edition = "2018" +description = "" +documentation = "" +readme = true +homepage = "https://github.com/aurora-is-near/aurora-engine" +repository = "https://github.com/aurora-is-near/aurora-engine" +license = "CC0-1.0" +publish = false +autobenches = false + +[dependencies] +aurora-engine-types = { path = "../engine-types", default-features = false } +aurora-engine-sdk = { path = "../engine-sdk", default-features = false } +base64 = { version = "0.13.0", default-features = false, features = ["alloc"] } +blake2 = { git = "https://github.com/near/near-blake2.git", version = "0.9.1", default-features = false } +borsh = { version = "0.8.2", default-features = false } +bn = { package = "aurora-bn", git = "https://github.com/aurora-is-near/aurora-bn.git", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } +libsecp256k1 = { version = "0.3.5", default-features = false } +num = { version = "0.4.0", default-features = false, features = ["alloc"] } +primitive-types = { version = "0.9.0", default-features = false, features = ["rlp"] } +ripemd160 = { version = "0.9.1", default-features = false } +rlp = { version = "0.5.0", default-features = false } +sha2 = { version = "0.9.3", default-features = false } +sha3 = { version = "0.9.1", default-features = false } +wee_alloc = { version = "0.4.5", default-features = false } +logos = { version = "0.12", default-features = false, features = ["export_derive"] } +ethabi = { git = "https://github.com/darwinia-network/ethabi", branch = "xavier-no-std", default-features = false } +hex = { version = "0.4", default-features = false, features = ["alloc"] } +byte-slice-cast = { version = "1.0", default-features = false } +rjson = { git = "https://github.com/aurora-is-near/rjson", rev = "cc3da949", default-features = false, features = ["integer"] } + +[dev-dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = "1" +rand = "0.7.3" + +[features] +contract = [] +log = [] diff --git a/src/precompiles/blake2.rs b/engine-precompiles/src/blake2.rs similarity index 98% rename from src/precompiles/blake2.rs rename to engine-precompiles/src/blake2.rs index 66864e9f5..25121e85e 100644 --- a/src/precompiles/blake2.rs +++ b/engine-precompiles/src/blake2.rs @@ -1,7 +1,7 @@ use evm::{Context, ExitError}; -use crate::precompiles::{EvmPrecompileResult, Precompile, PrecompileOutput}; use crate::prelude::{mem, Address, Borrowed, TryInto}; +use crate::{EvmPrecompileResult, Precompile, PrecompileOutput}; /// Blake2 costs. mod costs { @@ -17,7 +17,7 @@ mod consts { pub(super) struct Blake2F; impl Blake2F { - pub(super) const ADDRESS: Address = super::make_address(0, 9); + pub(super) const ADDRESS: Address = crate::make_address(0, 9); } impl Precompile for Blake2F { @@ -95,8 +95,8 @@ impl Precompile for Blake2F { #[cfg(test)] mod tests { + use super::super::utils::new_context; use crate::prelude::Vec; - use crate::test_utils::new_context; use super::*; diff --git a/src/precompiles/bn128.rs b/engine-precompiles/src/bn128.rs similarity index 99% rename from src/precompiles/bn128.rs rename to engine-precompiles/src/bn128.rs index 144d44e06..f6fce193e 100644 --- a/src/precompiles/bn128.rs +++ b/engine-precompiles/src/bn128.rs @@ -1,7 +1,5 @@ -use crate::precompiles::{ - Byzantium, EvmPrecompileResult, HardFork, Istanbul, Precompile, PrecompileOutput, -}; -use crate::prelude::*; +use crate::prelude::{Address, Borrowed, PhantomData, Vec}; +use crate::{Byzantium, EvmPrecompileResult, HardFork, Istanbul, Precompile, PrecompileOutput}; use evm::{Context, ExitError}; /// bn128 costs. @@ -396,7 +394,7 @@ impl Precompile for Bn128Pair { #[cfg(test)] mod tests { - use crate::test_utils::new_context; + use crate::utils::new_context; use super::*; diff --git a/src/precompiles/hash.rs b/engine-precompiles/src/hash.rs similarity index 96% rename from src/precompiles/hash.rs rename to engine-precompiles/src/hash.rs index 9a976e971..8c2834ccb 100644 --- a/src/precompiles/hash.rs +++ b/engine-precompiles/src/hash.rs @@ -1,5 +1,7 @@ -use crate::precompiles::{EvmPrecompileResult, Precompile, PrecompileOutput}; +#[cfg(feature = "contract")] +use crate::prelude::sdk; use crate::prelude::{vec, Address}; +use crate::{EvmPrecompileResult, Precompile, PrecompileOutput}; use evm::{Context, ExitError}; mod costs { @@ -67,8 +69,6 @@ impl Precompile for SHA256 { _context: &Context, _is_static: bool, ) -> EvmPrecompileResult { - use crate::sdk; - let cost = Self::required_gas(input)?; if let Some(target_gas) = target_gas { if cost > target_gas { @@ -125,7 +125,7 @@ impl Precompile for RIPEMD160 { #[cfg(not(feature = "contract"))] let hash = Self::internal_impl(input); #[cfg(feature = "contract")] - let hash = crate::sdk::ripemd160(input); + let hash = sdk::ripemd160(input); // The result needs to be padded with leading zeros because it is only 20 bytes, but // the evm works with 32-byte words. let mut output = vec![0u8; 32]; @@ -136,7 +136,7 @@ impl Precompile for RIPEMD160 { #[cfg(test)] mod tests { - use crate::test_utils::new_context; + use crate::utils::new_context; use super::*; diff --git a/src/precompiles/identity.rs b/engine-precompiles/src/identity.rs similarity index 95% rename from src/precompiles/identity.rs rename to engine-precompiles/src/identity.rs index f94ce4056..a7b37305f 100644 --- a/src/precompiles/identity.rs +++ b/engine-precompiles/src/identity.rs @@ -1,7 +1,6 @@ -use crate::precompiles::{EvmPrecompileResult, Precompile, PrecompileOutput}; -use evm::{Context, ExitError}; - use crate::prelude::Address; +use crate::{EvmPrecompileResult, Precompile, PrecompileOutput}; +use evm::{Context, ExitError}; /// Identity precompile costs. mod costs { @@ -57,7 +56,7 @@ impl Precompile for Identity { mod tests { use evm::ExitError; - use crate::test_utils::new_context; + use crate::utils::new_context; use super::*; diff --git a/src/precompiles/mod.rs b/engine-precompiles/src/lib.rs similarity index 78% rename from src/precompiles/mod.rs rename to engine-precompiles/src/lib.rs index 03c15e29f..b33ef00b8 100644 --- a/src/precompiles/mod.rs +++ b/engine-precompiles/src/lib.rs @@ -1,42 +1,43 @@ -pub(crate) use crate::precompiles::secp256k1::ecrecover; -use crate::prelude::{vec, BTreeMap, Vec}; -use crate::{ - precompiles::blake2::Blake2F, - precompiles::bn128::{Bn128Add, Bn128Mul, Bn128Pair}, - precompiles::hash::{RIPEMD160, SHA256}, - precompiles::identity::Identity, - precompiles::modexp::ModExp, - precompiles::native::{ExitToEthereum, ExitToNear}, - precompiles::secp256k1::ECRecover, - prelude::Address, -}; +#![allow(dead_code)] +#![feature(array_methods)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] +#![cfg_attr(feature = "log", feature(panic_info_message))] + +pub mod blake2; +pub mod bn128; +pub mod hash; +pub mod identity; +pub mod modexp; +pub mod native; +mod prelude; +pub mod secp256k1; +#[cfg(test)] +mod utils; + +use crate::blake2::Blake2F; +use crate::bn128::{Bn128Add, Bn128Mul, Bn128Pair}; +use crate::hash::{RIPEMD160, SHA256}; +use crate::identity::Identity; +use crate::modexp::ModExp; +use crate::native::{ExitToEthereum, ExitToNear}; +use crate::secp256k1::ECRecover; use evm::backend::Log; -use evm::ExitSucceed; -use evm::{Context, ExitError}; - -mod blake2; -mod bn128; -mod hash; -mod identity; -mod modexp; -#[cfg_attr(not(feature = "contract"), allow(dead_code))] -// TODO: Refactor where the addresses are. -pub(crate) mod native; -mod secp256k1; +use evm::{Context, ExitError, ExitSucceed}; #[derive(Debug)] pub struct PrecompileOutput { pub cost: u64, - pub output: Vec, - pub logs: Vec, + pub output: prelude::Vec, + pub logs: prelude::Vec, } impl PrecompileOutput { - pub fn without_logs(cost: u64, output: Vec) -> Self { + pub fn without_logs(cost: u64, output: prelude::Vec) -> Self { Self { cost, output, - logs: Vec::new(), + logs: prelude::Vec::new(), } } } @@ -45,8 +46,8 @@ impl Default for PrecompileOutput { fn default() -> Self { PrecompileOutput { cost: 0, - output: Vec::new(), - logs: Vec::new(), + output: prelude::Vec::new(), + logs: prelude::Vec::new(), } } } @@ -103,19 +104,19 @@ impl HardFork for Berlin {} type PrecompileFn = fn(&[u8], Option, &Context, bool) -> EvmPrecompileResult; -pub struct Precompiles(pub BTreeMap); +pub struct Precompiles(pub prelude::BTreeMap); impl Precompiles { #[allow(dead_code)] pub fn new_homestead() -> Self { - let addresses = vec![ + let addresses = prelude::vec![ ECRecover::ADDRESS, SHA256::ADDRESS, RIPEMD160::ADDRESS, ExitToNear::ADDRESS, ExitToEthereum::ADDRESS, ]; - let fun: Vec = vec![ + let fun: prelude::Vec = prelude::vec![ ECRecover::run, SHA256::run, RIPEMD160::run, @@ -129,7 +130,7 @@ impl Precompiles { #[allow(dead_code)] pub fn new_byzantium() -> Self { - let addresses = vec![ + let addresses = prelude::vec![ ECRecover::ADDRESS, SHA256::ADDRESS, RIPEMD160::ADDRESS, @@ -141,7 +142,7 @@ impl Precompiles { ExitToNear::ADDRESS, ExitToEthereum::ADDRESS, ]; - let fun: Vec = vec![ + let fun: prelude::Vec = prelude::vec![ ECRecover::run, SHA256::run, RIPEMD160::run, @@ -153,7 +154,7 @@ impl Precompiles { ExitToNear::run, ExitToEthereum::run, ]; - let mut map = BTreeMap::new(); + let mut map = prelude::BTreeMap::new(); for (address, fun) in addresses.into_iter().zip(fun) { map.insert(address, fun); } @@ -162,7 +163,7 @@ impl Precompiles { } pub fn new_istanbul() -> Self { - let addresses = vec![ + let addresses = prelude::vec![ ECRecover::ADDRESS, SHA256::ADDRESS, RIPEMD160::ADDRESS, @@ -175,7 +176,7 @@ impl Precompiles { ExitToNear::ADDRESS, ExitToEthereum::ADDRESS, ]; - let fun: Vec = vec![ + let fun: prelude::Vec = prelude::vec![ ECRecover::run, SHA256::run, RIPEMD160::run, @@ -188,7 +189,7 @@ impl Precompiles { ExitToNear::run, ExitToEthereum::run, ]; - let mut map = BTreeMap::new(); + let mut map = prelude::BTreeMap::new(); for (address, fun) in addresses.into_iter().zip(fun) { map.insert(address, fun); } @@ -205,10 +206,10 @@ impl Precompiles { /// const fn for making an address by concatenating the bytes from two given numbers, /// Note that 32 + 128 = 160 = 20 bytes (the length of an address). This function is used /// as a convenience for specifying the addresses of the various precompiles. -const fn make_address(x: u32, y: u128) -> Address { +const fn make_address(x: u32, y: u128) -> prelude::Address { let x_bytes = x.to_be_bytes(); let y_bytes = y.to_be_bytes(); - Address([ + prelude::Address([ x_bytes[0], x_bytes[1], x_bytes[2], @@ -234,8 +235,7 @@ const fn make_address(x: u32, y: u128) -> Address { #[cfg(test)] mod tests { - use crate::precompiles::{Byzantium, Istanbul}; - use crate::prelude::Address; + use crate::{prelude, Byzantium, Istanbul}; use rand::Rng; #[test] @@ -259,20 +259,20 @@ mod tests { let mut rng = rand::thread_rng(); for _ in 0..u8::MAX { - let address: Address = Address(rng.gen()); + let address: prelude::Address = prelude::Address(rng.gen()); let (x, y) = split_address(address); assert_eq!(address, super::make_address(x, y)) } } - fn u8_to_address(x: u8) -> Address { + fn u8_to_address(x: u8) -> prelude::Address { let mut bytes = [0u8; 20]; bytes[19] = x; - Address(bytes) + prelude::Address(bytes) } // Inverse function of `super::make_address`. - fn split_address(a: Address) -> (u32, u128) { + fn split_address(a: prelude::Address) -> (u32, u128) { let mut x_bytes = [0u8; 4]; let mut y_bytes = [0u8; 16]; diff --git a/src/precompiles/modexp.rs b/engine-precompiles/src/modexp.rs similarity index 98% rename from src/precompiles/modexp.rs rename to engine-precompiles/src/modexp.rs index a3e667ae8..649e745f7 100644 --- a/src/precompiles/modexp.rs +++ b/engine-precompiles/src/modexp.rs @@ -1,7 +1,6 @@ -use crate::precompiles::{ - Berlin, Byzantium, EvmPrecompileResult, HardFork, Precompile, PrecompileOutput, -}; use crate::prelude::{Address, PhantomData, Vec, U256}; +use crate::{Berlin, Byzantium, EvmPrecompileResult, HardFork, Precompile, PrecompileOutput}; + use evm::{Context, ExitError}; use num::{BigUint, Integer}; @@ -197,9 +196,10 @@ fn parse_lengths(input: &[u8]) -> (u64, u64, u64) { #[cfg(test)] mod tests { - use crate::test_utils::new_context; + use crate::utils::new_context; use super::*; + use crate::prelude::types::u256_to_arr; // Byzantium tests: https://github.com/holiman/go-ethereum/blob/master/core/vm/testdata/precompiles/modexp.json // Berlin tests:https://github.com/holiman/go-ethereum/blob/master/core/vm/testdata/precompiles/modexp_eip2565.json @@ -397,11 +397,11 @@ mod tests { let exp = U256::MAX; let mut input: Vec = Vec::new(); - input.extend_from_slice(&crate::types::u256_to_arr(&base_len)); - input.extend_from_slice(&crate::types::u256_to_arr(&exp_len)); - input.extend_from_slice(&crate::types::u256_to_arr(&mod_len)); + input.extend_from_slice(&u256_to_arr(&base_len)); + input.extend_from_slice(&u256_to_arr(&exp_len)); + input.extend_from_slice(&u256_to_arr(&mod_len)); input.extend_from_slice(&base.to_be_bytes()); - input.extend_from_slice(&crate::types::u256_to_arr(&exp)); + input.extend_from_slice(&u256_to_arr(&exp)); // completes without any overflow ModExp::::required_gas(&input).unwrap(); @@ -416,11 +416,11 @@ mod tests { let exp = U256::MAX; let mut input: Vec = Vec::new(); - input.extend_from_slice(&crate::types::u256_to_arr(&base_len)); - input.extend_from_slice(&crate::types::u256_to_arr(&exp_len)); - input.extend_from_slice(&crate::types::u256_to_arr(&mod_len)); + input.extend_from_slice(&u256_to_arr(&base_len)); + input.extend_from_slice(&u256_to_arr(&exp_len)); + input.extend_from_slice(&u256_to_arr(&mod_len)); input.extend_from_slice(&base.to_be_bytes()); - input.extend_from_slice(&crate::types::u256_to_arr(&exp)); + input.extend_from_slice(&u256_to_arr(&exp)); // completes without any overflow ModExp::::required_gas(&input).unwrap(); diff --git a/src/precompiles/native.rs b/engine-precompiles/src/native.rs similarity index 91% rename from src/precompiles/native.rs rename to engine-precompiles/src/native.rs index 41e0af2ad..20cf3ceb7 100644 --- a/src/precompiles/native.rs +++ b/engine-precompiles/src/native.rs @@ -1,24 +1,24 @@ -use crate::prelude::Address; -use evm::{Context, ExitError}; +use super::{EvmPrecompileResult, Precompile}; #[cfg(feature = "contract")] -use { - crate::parameters::WithdrawCallArgs, - crate::prelude::{is_valid_account_id, vec, Cow, String, ToString, TryInto, Vec, U256}, - crate::storage::{bytes_to_key, KeyPrefix}, - crate::types::AccountId, - crate::PromiseCreateArgs, - borsh::BorshSerialize, - evm::backend::Log, +use crate::prelude::{ + format, is_valid_account_id, + parameters::{PromiseCreateArgs, WithdrawCallArgs}, + sdk, + storage::{bytes_to_key, KeyPrefix}, + types::AccountId, + vec, BorshSerialize, Cow, String, ToString, TryInto, Vec, U256, }; -use super::{EvmPrecompileResult, Precompile}; +use crate::prelude::Address; +use crate::PrecompileOutput; +#[cfg(feature = "contract")] +use evm::backend::Log; +use evm::{Context, ExitError}; const ERR_TARGET_TOKEN_NOT_FOUND: &str = "Target token not found"; -use crate::precompiles::PrecompileOutput; - mod costs { - use crate::types::Gas; + use crate::prelude::types::Gas; // TODO(#51): Determine the correct amount of gas pub(super) const EXIT_TO_NEAR_GAS: Gas = 0; @@ -40,14 +40,14 @@ impl ExitToNear { /// /// Address: `0xe9217bc70b7ed1f598ddd3199e80b093fa71124f` /// This address is computed as: `&keccak("exitToNear")[12..]` - pub(crate) const ADDRESS: Address = + pub const ADDRESS: Address = super::make_address(0xe9217bc7, 0x0b7ed1f598ddd3199e80b093fa71124f); } #[cfg(feature = "contract")] fn get_nep141_from_erc20(erc20_token: &[u8]) -> AccountId { AccountId::from_utf8( - crate::sdk::read_storage(bytes_to_key(KeyPrefix::Erc20Nep141Map, erc20_token).as_slice()) + sdk::read_storage(bytes_to_key(KeyPrefix::Erc20Nep141Map, erc20_token).as_slice()) .expect(ERR_TARGET_TOKEN_NOT_FOUND), ) .unwrap() @@ -108,10 +108,10 @@ impl Precompile for ExitToNear { if is_valid_account_id(input) { ( - String::from_utf8(crate::sdk::current_account_id()).unwrap(), + String::from_utf8(sdk::current_account_id()).unwrap(), // There is no way to inject json, given the encoding of both arguments // as decimal and valid account id respectively. - crate::prelude::format!( + format!( r#"{{"receiver_id": "{}", "amount": "{}", "memo": null}}"#, String::from_utf8(input.to_vec()).unwrap(), context.apparent_value.as_u128() @@ -149,10 +149,9 @@ impl Precompile for ExitToNear { nep141_address, // There is no way to inject json, given the encoding of both arguments // as decimal and valid account id respectively. - crate::prelude::format!( + format!( r#"{{"receiver_id": "{}", "amount": "{}", "memo": null}}"#, - receiver_account_id, - amount + receiver_account_id, amount ), ) } else { @@ -194,7 +193,7 @@ impl ExitToEthereum { /// /// Address: `0xb0bd02f6a392af548bdf1cfaee5dfa0eefcc8eab` /// This address is computed as: `&keccak("exitToEthereum")[12..]` - pub(crate) const ADDRESS: Address = + pub const ADDRESS: Address = super::make_address(0xb0bd02f6, 0xa392af548bdf1cfaee5dfa0eefcc8eab); } @@ -251,7 +250,7 @@ impl Precompile for ExitToEthereum { // Input slice format: // eth_recipient (20 bytes) - the address of recipient which will receive ETH on Ethereum ( - String::from_utf8(crate::sdk::current_account_id()).unwrap(), + String::from_utf8(sdk::current_account_id()).unwrap(), // There is no way to inject json, given the encoding of both arguments // as decimal and hexadecimal respectively. WithdrawCallArgs { @@ -293,10 +292,9 @@ impl Precompile for ExitToEthereum { nep141_address, // There is no way to inject json, given the encoding of both arguments // as decimal and hexadecimal respectively. - crate::prelude::format!( + format!( r#"{{"amount": "{}", "recipient": "{}"}}"#, - amount, - eth_recipient + amount, eth_recipient ) .as_bytes() .to_vec(), @@ -338,7 +336,7 @@ impl Precompile for ExitToEthereum { #[cfg(test)] mod tests { use super::{ExitToEthereum, ExitToNear}; - use crate::types::near_account_to_evm_address; + use crate::prelude::sdk::types::near_account_to_evm_address; #[test] fn test_precompile_id() { diff --git a/engine-precompiles/src/prelude.rs b/engine-precompiles/src/prelude.rs new file mode 100644 index 000000000..c5f474d20 --- /dev/null +++ b/engine-precompiles/src/prelude.rs @@ -0,0 +1,7 @@ +pub use aurora_engine_sdk as sdk; +pub use aurora_engine_types::parameters; +pub use aurora_engine_types::storage; +pub use aurora_engine_types::types; +pub use aurora_engine_types::*; + +pub use borsh::{BorshDeserialize, BorshSerialize}; diff --git a/src/precompiles/secp256k1.rs b/engine-precompiles/src/secp256k1.rs similarity index 95% rename from src/precompiles/secp256k1.rs rename to engine-precompiles/src/secp256k1.rs index 5ddba52aa..0d0413957 100644 --- a/src/precompiles/secp256k1.rs +++ b/engine-precompiles/src/secp256k1.rs @@ -1,5 +1,6 @@ -use crate::precompiles::{EvmPrecompileResult, Precompile, PrecompileOutput}; -use crate::prelude::*; +use crate::prelude::{sdk, vec, Borrowed, H256}; +use crate::{EvmPrecompileResult, Precompile, PrecompileOutput}; +use ethabi::Address; use evm::{Context, ExitError}; mod costs { @@ -15,12 +16,11 @@ mod consts { /// See: https://etherscan.io/address/0000000000000000000000000000000000000001 // Quite a few library methods rely on this and that should be changed. This // should only be for precompiles. -pub(crate) fn ecrecover(hash: H256, signature: &[u8]) -> Result { +pub fn ecrecover(hash: H256, signature: &[u8]) -> Result { assert_eq!(signature.len(), 65); #[cfg(feature = "contract")] - return crate::sdk::ecrecover(hash, signature) - .map_err(|e| ExitError::Other(Borrowed(e.as_str()))); + return sdk::ecrecover(hash, signature).map_err(|e| ExitError::Other(Borrowed(e.as_str()))); #[cfg(not(feature = "contract"))] internal_impl(hash, signature) @@ -46,9 +46,7 @@ fn internal_impl(hash: H256, signature: &[u8]) -> Result { } } - Err(ExitError::Other(Borrowed( - crate::sdk::ECRecoverErr.as_str(), - ))) + Err(ExitError::Other(Borrowed(sdk::ECRecoverErr.as_str()))) } pub(super) struct ECRecover; @@ -115,7 +113,7 @@ impl Precompile for ECRecover { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::new_context; + use crate::utils::new_context; fn ecverify(hash: H256, signature: &[u8], signer: Address) -> bool { matches!(ecrecover(hash, signature), Ok(s) if s == signer) diff --git a/engine-precompiles/src/utils.rs b/engine-precompiles/src/utils.rs new file mode 100644 index 000000000..7a62515f8 --- /dev/null +++ b/engine-precompiles/src/utils.rs @@ -0,0 +1,9 @@ +use evm::Context; + +pub fn new_context() -> Context { + Context { + address: Default::default(), + caller: Default::default(), + apparent_value: Default::default(), + } +} diff --git a/engine-sdk/Cargo.toml b/engine-sdk/Cargo.toml new file mode 100644 index 000000000..a3a72e3fb --- /dev/null +++ b/engine-sdk/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "aurora-engine-sdk" +version = "1.0.0" +authors = ["NEAR "] +edition = "2018" +description = "" +documentation = "" +readme = true +homepage = "https://github.com/aurora-is-near/aurora-engine" +repository = "https://github.com/aurora-is-near/aurora-engine" +license = "CC0-1.0" +publish = false +autobenches = false + +[dependencies] +aurora-engine-types = { path = "../engine-types", default-features = false } +borsh = { version = "0.8.2", default-features = false } +sha3 = { version = "0.9.1", default-features = false } + +[features] +contract = [] +log = [] diff --git a/src/sdk.rs b/engine-sdk/src/lib.rs similarity index 94% rename from src/sdk.rs rename to engine-sdk/src/lib.rs index c7b484ce1..df408608e 100644 --- a/src/sdk.rs +++ b/engine-sdk/src/lib.rs @@ -1,7 +1,16 @@ -use crate::prelude::{vec, Vec, H256}; -use crate::types::PromiseResult; -use crate::types::STORAGE_PRICE_PER_BYTE; -use borsh::{BorshDeserialize, BorshSerialize}; +#![feature(array_methods)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] +#![cfg_attr(feature = "log", feature(panic_info_message))] + +use crate::prelude::{ + vec, Address, BorshDeserialize, BorshSerialize, PromiseResult, Vec, H256, + STORAGE_PRICE_PER_BYTE, +}; +pub use types::keccak; + +mod prelude; +pub mod types; const READ_STORAGE_REGISTER_ID: u64 = 0; const INPUT_REGISTER_ID: u64 = 0; @@ -187,13 +196,13 @@ pub fn read_input() -> Vec { } #[cfg_attr(not(feature = "contract"), allow(dead_code))] -pub(crate) fn read_input_borsh() -> Result { +pub fn read_input_borsh() -> Result { let bytes = read_input(); T::try_from_slice(&bytes).map_err(|_| ArgParseErr) } #[cfg_attr(not(feature = "contract"), allow(dead_code))] -pub(crate) fn read_input_arr20() -> Result<[u8; 20], IncorrectInputLength> { +pub fn read_input_arr20() -> Result<[u8; 20], IncorrectInputLength> { unsafe { exports::input(INPUT_REGISTER_ID); if exports::register_len(INPUT_REGISTER_ID) == 20 { @@ -249,7 +258,7 @@ pub fn read_storage_len(key: &[u8]) -> Option { } /// Read u64 from storage at given key. -pub(crate) fn read_u64(key: &[u8]) -> Result { +pub fn read_u64(key: &[u8]) -> Result { read_storage_len(key) .ok_or(ReadU64Error::MissingValue) .and_then(|value_size| unsafe { @@ -280,6 +289,7 @@ pub fn remove_storage(key: &[u8]) { exports::storage_remove(key.len() as u64, key.as_ptr() as u64, EVICTED_REGISTER); } } + /// Returns the size of the blob stored in the given register. /// * If register is used, then returns the size, which can potentially be zero; /// * If register is not used, returns `u64::MAX` @@ -377,16 +387,6 @@ pub fn sha256(input: &[u8]) -> H256 { } } -/// Calls environment keccak256 on given input. -pub fn keccak(input: &[u8]) -> H256 { - unsafe { - exports::keccak256(input.len() as u64, input.as_ptr() as u64, 1); - let bytes = H256::zero(); - exports::read_register(1, bytes.0.as_ptr() as *const u64 as u64); - bytes - } -} - /// Calls environment ripemd160 on given input. pub fn ripemd160(input: &[u8]) -> [u8; 20] { unsafe { @@ -399,7 +399,7 @@ pub fn ripemd160(input: &[u8]) -> [u8; 20] { } /// Recover address from message hash and signature. -pub fn ecrecover(hash: H256, signature: &[u8]) -> Result { +pub fn ecrecover(hash: H256, signature: &[u8]) -> Result { unsafe { let hash_ptr = hash.as_ptr() as u64; let sig_ptr = signature.as_ptr() as u64; @@ -421,9 +421,7 @@ pub fn ecrecover(hash: H256, signature: &[u8]) -> Result { #[cfg(feature = "log")] - $crate::sdk::log($e) + $crate::log($e) }; } @@ -610,24 +608,27 @@ pub fn storage_has_key(key: &[u8]) -> bool { unsafe { exports::storage_has_key(key.len() as _, key.as_ptr() as _) == 1 } } -pub(crate) struct IncorrectInputLength; +pub struct IncorrectInputLength; + impl AsRef<[u8]> for IncorrectInputLength { fn as_ref(&self) -> &[u8] { b"ERR_INCORRECT_INPUT_LENGTH" } } -pub(crate) struct ArgParseErr; +pub struct ArgParseErr; + impl AsRef<[u8]> for ArgParseErr { fn as_ref(&self) -> &[u8] { b"ERR_ARG_PARSE" } } -pub(crate) enum ReadU64Error { +pub enum ReadU64Error { InvalidU64, MissingValue, } + impl AsRef<[u8]> for ReadU64Error { fn as_ref(&self) -> &[u8] { match self { @@ -638,11 +639,13 @@ impl AsRef<[u8]> for ReadU64Error { } pub struct ECRecoverErr; + impl ECRecoverErr { pub fn as_str(&self) -> &'static str { "ERR_ECRECOVER" } } + impl AsRef<[u8]> for ECRecoverErr { fn as_ref(&self) -> &[u8] { self.as_str().as_bytes() diff --git a/engine-sdk/src/prelude.rs b/engine-sdk/src/prelude.rs new file mode 100644 index 000000000..ddfddb007 --- /dev/null +++ b/engine-sdk/src/prelude.rs @@ -0,0 +1,3 @@ +pub use aurora_engine_types::types::{PromiseResult, STORAGE_PRICE_PER_BYTE}; +pub use aurora_engine_types::{vec, Address, Vec, H256}; +pub use borsh::{BorshDeserialize, BorshSerialize}; diff --git a/engine-sdk/src/types.rs b/engine-sdk/src/types.rs new file mode 100644 index 000000000..a6292789f --- /dev/null +++ b/engine-sdk/src/types.rs @@ -0,0 +1,106 @@ +use crate::prelude::{Address, H256}; +use crate::{panic_utf8, return_output}; + +#[cfg(not(feature = "contract"))] +use sha3::{Digest, Keccak256}; + +#[cfg(feature = "contract")] +#[inline] +pub fn keccak(input: &[u8]) -> H256 { + unsafe { + super::exports::keccak256(input.len() as u64, input.as_ptr() as u64, 1); + let bytes = H256::zero(); + super::exports::read_register(1, bytes.0.as_ptr() as *const u64 as u64); + bytes + } +} + +#[cfg(not(feature = "contract"))] +#[inline] +pub fn keccak(data: &[u8]) -> H256 { + H256::from_slice(Keccak256::digest(data).as_slice()) +} + +#[allow(dead_code)] +pub fn near_account_to_evm_address(addr: &[u8]) -> Address { + Address::from_slice(&keccak(addr)[12..]) +} + +pub trait ExpectUtf8 { + fn expect_utf8(self, message: &[u8]) -> T; +} + +impl ExpectUtf8 for Option { + fn expect_utf8(self, message: &[u8]) -> T { + match self { + Some(t) => t, + None => panic_utf8(message), + } + } +} + +impl ExpectUtf8 for core::result::Result { + fn expect_utf8(self, message: &[u8]) -> T { + match self { + Ok(t) => t, + Err(_) => panic_utf8(message), + } + } +} + +pub trait SdkExpect { + fn sdk_expect(self, msg: &str) -> T; +} + +impl SdkExpect for Option { + fn sdk_expect(self, msg: &str) -> T { + match self { + Some(t) => t, + None => panic_utf8(msg.as_ref()), + } + } +} + +impl SdkExpect for core::result::Result { + fn sdk_expect(self, msg: &str) -> T { + match self { + Ok(t) => t, + Err(_) => panic_utf8(msg.as_ref()), + } + } +} + +pub trait SdkUnwrap { + fn sdk_unwrap(self) -> T; +} + +impl SdkUnwrap for Option { + fn sdk_unwrap(self) -> T { + match self { + Some(t) => t, + None => panic_utf8("ERR_UNWRAP".as_bytes()), + } + } +} + +impl> SdkUnwrap for core::result::Result { + fn sdk_unwrap(self) -> T { + match self { + Ok(t) => t, + Err(e) => panic_utf8(e.as_ref()), + } + } +} + +pub trait SdkProcess { + fn sdk_process(self); +} + +impl, E: AsRef<[u8]>> SdkProcess for Result { + fn sdk_process(self) { + match self { + Ok(r) => return_output(r.as_ref()), + Err(e) => panic_utf8(e.as_ref()), + } + } +} diff --git a/engine-tests/Cargo.toml b/engine-tests/Cargo.toml new file mode 100644 index 000000000..4738f2005 --- /dev/null +++ b/engine-tests/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "aurora-engine-tests" +version = "1.0.0" +authors = ["NEAR "] +edition = "2018" +description = "" +documentation = "" +readme = true +homepage = "https://github.com/aurora-is-near/aurora-engine" +repository = "https://github.com/aurora-is-near/aurora-engine" +license = "GPL-3.0" +publish = false +autobenches = false + +[dependencies] +aurora-engine = { path = "../engine", default-features = false, features=["sha2"] } +aurora-engine-types = { path = "../engine-types", default-features = false } +aurora-engine-sdk = { path = "../engine-sdk", default-features = false } +borsh = { version = "0.8.2", default-features = false } +byte-slice-cast = { version = "1.0", default-features = false } +sha3 = { version = "0.9.1", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } +rlp = { version = "0.5.0", default-features = false } + +[dev-dependencies] +bstr = "0.2" +ethabi = { git = "https://github.com/darwinia-network/ethabi", branch = "xavier-no-std" } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +hex = { version = "0.4.3", default-features = false } +near-sdk = { git = "https://github.com/aurora-is-near/near-sdk-rs.git", rev = "5e58722bd61d9d24ae6293326146c751f0a814fb" } +near-sdk-sim = { git = "https://github.com/aurora-is-near/near-sdk-rs.git", rev = "5e58722bd61d9d24ae6293326146c751f0a814fb" } +near-crypto = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9" } +near-vm-runner = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9" } +near-vm-logic = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9" } +near-primitives-core = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9" } +near-primitives = { git = "https://github.com/near/nearcore.git", rev = "8a377fda0b4ce319385c463f1ae46e4b0b29dcd9" } +wasmer-runtime-core = { version = "0.18.2", package = "wasmer-runtime-core-near" } +libsecp256k1 = "0.3.5" +rand = "0.7.3" +criterion = "0.3.4" +git2 = "0.13" + +[features] +meta-call = ["aurora-engine/meta-call"] +mainnet-test = ["aurora-engine/mainnet-test"] +testnet-test = ["aurora-engine/testnet-test"] +betanet-test = ["aurora-engine/betanet-test"] diff --git a/src/benches/eth_deploy_code.rs b/engine-tests/src/benches/eth_deploy_code.rs similarity index 98% rename from src/benches/eth_deploy_code.rs rename to engine-tests/src/benches/eth_deploy_code.rs index 9b21aea8a..6a7311a56 100644 --- a/src/benches/eth_deploy_code.rs +++ b/engine-tests/src/benches/eth_deploy_code.rs @@ -1,10 +1,10 @@ use criterion::{BatchSize, BenchmarkId, Criterion, Throughput}; use secp256k1::SecretKey; +use crate::prelude::types::Wei; use crate::test_utils::{ address_from_secret_key, create_deploy_transaction, deploy_evm, sign_transaction, SUBMIT, }; -use crate::types::Wei; const INITIAL_BALANCE: Wei = Wei::new_u64(1000); const INITIAL_NONCE: u64 = 0; diff --git a/src/benches/eth_erc20.rs b/engine-tests/src/benches/eth_erc20.rs similarity index 98% rename from src/benches/eth_erc20.rs rename to engine-tests/src/benches/eth_erc20.rs index 31124abe8..369307298 100644 --- a/src/benches/eth_erc20.rs +++ b/engine-tests/src/benches/eth_erc20.rs @@ -15,7 +15,7 @@ pub(crate) fn eth_erc20_benchmark(c: &mut Criterion) { let source_account = SecretKey::random(&mut rng); runner.create_address( address_from_secret_key(&source_account), - crate::types::Wei::new_u64(INITIAL_BALANCE), + crate::prelude::types::Wei::new_u64(INITIAL_BALANCE), INITIAL_NONCE.into(), ); let calling_account_id = "some-account.near"; diff --git a/src/benches/eth_standard_precompiles.rs b/engine-tests/src/benches/eth_standard_precompiles.rs similarity index 98% rename from src/benches/eth_standard_precompiles.rs rename to engine-tests/src/benches/eth_standard_precompiles.rs index 75d8ed2f5..2aeea79f1 100644 --- a/src/benches/eth_standard_precompiles.rs +++ b/engine-tests/src/benches/eth_standard_precompiles.rs @@ -2,9 +2,9 @@ use crate::prelude::U256; use criterion::{BatchSize, BenchmarkId, Criterion}; use secp256k1::SecretKey; +use crate::prelude::types::Wei; use crate::test_utils::standard_precompiles::{PrecompilesConstructor, PrecompilesContract}; use crate::test_utils::{address_from_secret_key, deploy_evm, sign_transaction, SUBMIT}; -use crate::types::Wei; const INITIAL_BALANCE: Wei = Wei::new_u64(1000); const INITIAL_NONCE: u64 = 0; diff --git a/src/benches/eth_transfer.rs b/engine-tests/src/benches/eth_transfer.rs similarity index 98% rename from src/benches/eth_transfer.rs rename to engine-tests/src/benches/eth_transfer.rs index 2af89cfe1..8aa443a24 100644 --- a/src/benches/eth_transfer.rs +++ b/engine-tests/src/benches/eth_transfer.rs @@ -1,8 +1,8 @@ use criterion::{BatchSize, Criterion}; use secp256k1::SecretKey; +use crate::prelude::types::Wei; use crate::test_utils::{address_from_secret_key, create_eth_transaction, deploy_evm, SUBMIT}; -use crate::types::Wei; const INITIAL_BALANCE: Wei = Wei::new_u64(1000); const INITIAL_NONCE: u64 = 0; diff --git a/src/benches/mod.rs b/engine-tests/src/benches/mod.rs similarity index 100% rename from src/benches/mod.rs rename to engine-tests/src/benches/mod.rs diff --git a/src/benches/nft_pagination.rs b/engine-tests/src/benches/nft_pagination.rs similarity index 98% rename from src/benches/nft_pagination.rs rename to engine-tests/src/benches/nft_pagination.rs index 49448191c..166b7ec1e 100644 --- a/src/benches/nft_pagination.rs +++ b/engine-tests/src/benches/nft_pagination.rs @@ -1,7 +1,7 @@ +use crate::prelude::types::Wei; use crate::prelude::{Address, U256}; use crate::test_utils::{self, solidity}; -use crate::transaction::LegacyEthTransaction; -use crate::types::Wei; +use aurora_engine::transaction::LegacyEthTransaction; use secp256k1::SecretKey; use std::path::{Path, PathBuf}; use std::process::Command; diff --git a/src/benches/res/StandardPrecompiles.sol b/engine-tests/src/benches/res/StandardPrecompiles.sol similarity index 100% rename from src/benches/res/StandardPrecompiles.sol rename to engine-tests/src/benches/res/StandardPrecompiles.sol diff --git a/engine-tests/src/lib.rs b/engine-tests/src/lib.rs new file mode 100644 index 000000000..19f99d38f --- /dev/null +++ b/engine-tests/src/lib.rs @@ -0,0 +1,8 @@ +#[cfg(test)] +mod benches; +#[cfg(test)] +mod prelude; +#[cfg(test)] +mod test_utils; +#[cfg(test)] +mod tests; diff --git a/engine-tests/src/prelude.rs b/engine-tests/src/prelude.rs new file mode 100644 index 000000000..30bafb53e --- /dev/null +++ b/engine-tests/src/prelude.rs @@ -0,0 +1,9 @@ +pub use aurora_engine::connector; +pub use aurora_engine::fungible_token; +pub use aurora_engine::parameters; +pub use aurora_engine::transaction; +pub use aurora_engine_sdk as sdk; +pub use aurora_engine_types::parameters::*; +pub use aurora_engine_types::storage; +pub use aurora_engine_types::types::*; +pub use aurora_engine_types::*; diff --git a/src/test_utils/erc20.rs b/engine-tests/src/test_utils/erc20.rs similarity index 98% rename from src/test_utils/erc20.rs rename to engine-tests/src/test_utils/erc20.rs index b48dff9ab..7094a440a 100644 --- a/src/test_utils/erc20.rs +++ b/engine-tests/src/test_utils/erc20.rs @@ -1,6 +1,5 @@ -use crate::prelude::{Address, U256}; +use crate::prelude::{transaction::LegacyEthTransaction, Address, U256}; use crate::test_utils::solidity; -use crate::transaction::LegacyEthTransaction; use std::path::{Path, PathBuf}; use std::sync::Once; diff --git a/src/test_utils/exit_precompile.rs b/engine-tests/src/test_utils/exit_precompile.rs similarity index 95% rename from src/test_utils/exit_precompile.rs rename to engine-tests/src/test_utils/exit_precompile.rs index 11ea55bc5..908d871fd 100644 --- a/src/test_utils/exit_precompile.rs +++ b/engine-tests/src/test_utils/exit_precompile.rs @@ -1,7 +1,5 @@ -use crate::parameters::SubmitResult; -use crate::prelude::{Address, U256}; +use crate::prelude::{parameters::SubmitResult, transaction::LegacyEthTransaction, Address, U256}; use crate::test_utils::{self, solidity, AuroraRunner, Signer}; -use crate::transaction::LegacyEthTransaction; pub(crate) struct TesterConstructor(pub solidity::ContractConstructor); @@ -10,7 +8,7 @@ const DEPLOY_CONTRACT_GAS: u64 = 1_000_000_000; impl TesterConstructor { pub fn load() -> Self { Self(solidity::ContractConstructor::compile_from_extended_json( - "etc/eth-contracts/artifacts/contracts/test/Tester.sol/Tester.json", + "../etc/eth-contracts/artifacts/contracts/test/Tester.sol/Tester.json", )) } diff --git a/src/test_utils/mod.rs b/engine-tests/src/test_utils/mod.rs similarity index 91% rename from src/test_utils/mod.rs rename to engine-tests/src/test_utils/mod.rs index f6e43bfad..26fd2ef52 100644 --- a/src/test_utils/mod.rs +++ b/engine-tests/src/test_utils/mod.rs @@ -1,5 +1,4 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use evm::Context; use near_primitives_core::config::VMConfig; use near_primitives_core::contract::ContractCode; use near_primitives_core::profile::ProfileData; @@ -8,21 +7,19 @@ use near_vm_logic::mocks::mock_external::MockedExternal; use near_vm_logic::types::ReturnData; use near_vm_logic::{VMContext, VMOutcome}; use near_vm_runner::{MockCompiledContractCache, VMError}; -use primitive_types::U256; use rlp::RlpStream; use secp256k1::{self, Message, PublicKey, SecretKey}; -use crate::fungible_token::{FungibleToken, FungibleTokenMetadata}; -use crate::parameters::{InitCallArgs, NewCallArgs, SubmitResult, TransactionStatus, ViewCallArgs}; -use crate::prelude::Address; -use crate::storage; -use crate::test_utils::solidity::{ContractConstructor, DeployedContract}; -use crate::transaction::{ +use crate::prelude::fungible_token::{FungibleToken, FungibleTokenMetadata}; +use crate::prelude::parameters::{ + InitCallArgs, NewCallArgs, SubmitResult, TransactionStatus, ViewCallArgs, +}; +use crate::prelude::transaction::{ access_list::{self, AccessListEthSignedTransaction, AccessListEthTransaction}, LegacyEthSignedTransaction, LegacyEthTransaction, }; -use crate::types; -use crate::types::{AccountId, Wei}; +use crate::prelude::{sdk, AccountId, Address, Wei, U256}; +use crate::test_utils::solidity::{ContractConstructor, DeployedContract}; // TODO(Copied from #84): Make sure that there is only one Signer after both PR are merged. @@ -192,18 +189,29 @@ impl AuroraRunner { (maybe_outcome, maybe_error) } - pub fn create_address(&mut self, address: Address, init_balance: types::Wei, init_nonce: U256) { + pub fn create_address( + &mut self, + address: Address, + init_balance: crate::prelude::Wei, + init_nonce: U256, + ) { let trie = &mut self.ext.fake_trie; - let balance_key = storage::address_to_key(storage::KeyPrefix::Balance, &address); + let balance_key = crate::prelude::storage::address_to_key( + crate::prelude::storage::KeyPrefix::Balance, + &address, + ); let balance_value = init_balance.to_bytes(); - let nonce_key = storage::address_to_key(storage::KeyPrefix::Nonce, &address); - let nonce_value = types::u256_to_arr(&init_nonce); + let nonce_key = crate::prelude::storage::address_to_key( + crate::prelude::storage::KeyPrefix::Nonce, + &address, + ); + let nonce_value = crate::prelude::u256_to_arr(&init_nonce); - let ft_key = storage::bytes_to_key( - storage::KeyPrefix::EthConnector, - &[storage::EthConnectorStorageId::FungibleToken as u8], + let ft_key = crate::prelude::storage::bytes_to_key( + crate::prelude::storage::KeyPrefix::EthConnector, + &[crate::prelude::storage::EthConnectorStorageId::FungibleToken as u8], ); let ft_value = { let mut current_ft: FungibleToken = trie @@ -313,8 +321,8 @@ impl AuroraRunner { (status, profile) } - pub fn get_balance(&self, address: Address) -> types::Wei { - types::Wei::new(self.u256_getter_method_call("get_balance", address)) + pub fn get_balance(&self, address: Address) -> Wei { + Wei::new(self.u256_getter_method_call("get_balance", address)) } pub fn get_nonce(&self, address: Address) -> U256 { @@ -357,11 +365,11 @@ impl Default for AuroraRunner { fn default() -> Self { let aurora_account_id = "aurora".to_string(); let evm_wasm_bytes = if cfg!(feature = "mainnet-test") { - std::fs::read("mainnet-test.wasm").unwrap() + std::fs::read("../mainnet-test.wasm").unwrap() } else if cfg!(feature = "testnet-test") { - std::fs::read("testnet-test.wasm").unwrap() + std::fs::read("../testnet-test.wasm").unwrap() } else { - std::fs::read("betanet-test.wasm").unwrap() + std::fs::read("../betanet-test.wasm").unwrap() }; Self { @@ -426,7 +434,7 @@ impl ExecutionProfile { pub(crate) fn deploy_evm() -> AuroraRunner { let mut runner = AuroraRunner::default(); let args = NewCallArgs { - chain_id: types::u256_to_arr(&U256::from(runner.chain_id)), + chain_id: crate::prelude::u256_to_arr(&U256::from(runner.chain_id)), owner_id: runner.aurora_account_id.clone(), bridge_prover_id: "bridge_prover.near".to_string(), upgrade_delay_blocks: 1, @@ -450,7 +458,11 @@ pub(crate) fn deploy_evm() -> AuroraRunner { runner } -pub(crate) fn transfer(to: Address, amount: types::Wei, nonce: U256) -> LegacyEthTransaction { +pub(crate) fn transfer( + to: Address, + amount: crate::prelude::Wei, + nonce: U256, +) -> LegacyEthTransaction { LegacyEthTransaction { nonce, gas_price: Default::default(), @@ -496,7 +508,7 @@ pub(crate) fn create_deploy_transaction( pub(crate) fn create_eth_transaction( to: Option
, - value: types::Wei, + value: crate::prelude::Wei, data: Vec, chain_id: Option, secret_key: &SecretKey, @@ -529,7 +541,7 @@ pub(crate) fn sign_transaction( ) -> LegacyEthSignedTransaction { let mut rlp_stream = RlpStream::new(); tx.rlp_append_unsigned(&mut rlp_stream, chain_id); - let message_hash = types::keccak(rlp_stream.as_raw()); + let message_hash = sdk::keccak(rlp_stream.as_raw()); let message = Message::parse_slice(message_hash.as_bytes()).unwrap(); let (signature, recovery_id) = secp256k1::sign(&message, secret_key); @@ -554,7 +566,7 @@ pub(crate) fn sign_access_list_transaction( let mut rlp_stream = RlpStream::new(); rlp_stream.append(&access_list::TYPE_BYTE); tx.rlp_append_unsigned(&mut rlp_stream); - let message_hash = types::keccak(rlp_stream.as_raw()); + let message_hash = sdk::keccak(rlp_stream.as_raw()); let message = Message::parse_slice(message_hash.as_bytes()).unwrap(); let (signature, recovery_id) = secp256k1::sign(&message, secret_key); @@ -571,7 +583,7 @@ pub(crate) fn sign_access_list_transaction( pub(crate) fn address_from_secret_key(sk: &SecretKey) -> Address { let pk = PublicKey::from_secret_key(sk); - let hash = types::keccak(&pk.serialize()[1..]); + let hash = sdk::keccak(&pk.serialize()[1..]); Address::from_slice(&hash[12..]) } @@ -587,21 +599,13 @@ pub(crate) fn parse_eth_gas(output: &VMOutcome) -> u64 { pub(crate) fn validate_address_balance_and_nonce( runner: &AuroraRunner, address: Address, - expected_balance: types::Wei, + expected_balance: crate::prelude::Wei, expected_nonce: U256, ) { assert_eq!(runner.get_balance(address), expected_balance, "balance"); assert_eq!(runner.get_nonce(address), expected_nonce, "nonce"); } -pub fn new_context() -> Context { - Context { - address: Default::default(), - caller: Default::default(), - apparent_value: Default::default(), - } -} - pub(crate) fn address_from_hex(address: &str) -> Address { let bytes = if address.starts_with("0x") { hex::decode(&address[2..]).unwrap() diff --git a/src/test_utils/one_inch/liquidity_protocol.rs b/engine-tests/src/test_utils/one_inch/liquidity_protocol.rs similarity index 98% rename from src/test_utils/one_inch/liquidity_protocol.rs rename to engine-tests/src/test_utils/one_inch/liquidity_protocol.rs index e9ce72a89..dd30b9215 100644 --- a/src/test_utils/one_inch/liquidity_protocol.rs +++ b/engine-tests/src/test_utils/one_inch/liquidity_protocol.rs @@ -1,4 +1,4 @@ -use crate::parameters::SubmitResult; +use crate::prelude::parameters::SubmitResult; use crate::prelude::{Address, U256}; use crate::test_utils::{self, solidity, ExecutionProfile}; use std::path::PathBuf; @@ -27,7 +27,7 @@ impl<'a> Helper<'a> { let (result, profile) = self .runner .submit_with_signer_profiled(self.signer, |nonce| { - crate::transaction::LegacyEthTransaction { + crate::prelude::transaction::LegacyEthTransaction { nonce, gas_price: Default::default(), gas: u64::MAX.into(), @@ -223,7 +223,9 @@ impl<'a> Helper<'a> { } pub(crate) struct PoolDeployer(solidity::DeployedContract); + pub(crate) struct PoolFactory(solidity::DeployedContract); + pub(crate) struct Pool(solidity::DeployedContract); pub(crate) struct DepositArgs { diff --git a/src/test_utils/one_inch/mod.rs b/engine-tests/src/test_utils/one_inch/mod.rs similarity index 100% rename from src/test_utils/one_inch/mod.rs rename to engine-tests/src/test_utils/one_inch/mod.rs diff --git a/src/test_utils/self_destruct.rs b/engine-tests/src/test_utils/self_destruct.rs similarity index 93% rename from src/test_utils/self_destruct.rs rename to engine-tests/src/test_utils/self_destruct.rs index 861887906..93afc4aac 100644 --- a/src/test_utils/self_destruct.rs +++ b/engine-tests/src/test_utils/self_destruct.rs @@ -1,9 +1,8 @@ -use crate::parameters::FunctionCallArgs; -use crate::prelude::Address; +use crate::prelude::{ + parameters::FunctionCallArgs, transaction::LegacyEthTransaction, Address, U256, +}; use crate::test_utils::{self, solidity, AuroraRunner, Signer}; -use crate::transaction::LegacyEthTransaction; use borsh::BorshSerialize; -use primitive_types::U256; use std::convert::TryInto; pub(crate) struct SelfDestructFactoryConstructor(pub solidity::ContractConstructor); @@ -13,7 +12,7 @@ const DEFAULT_GAS: u64 = 1_000_000_000; impl SelfDestructFactoryConstructor { pub fn load() -> Self { Self(solidity::ContractConstructor::compile_from_extended_json( - "etc/eth-contracts/artifacts/contracts/test/StateTest.sol/SelfDestructFactory.json", + "../etc/eth-contracts/artifacts/contracts/test/StateTest.sol/SelfDestructFactory.json", )) } @@ -84,10 +83,11 @@ pub(crate) struct SelfDestructConstructor(pub solidity::ContractConstructor); impl SelfDestructConstructor { pub fn load() -> Self { Self(solidity::ContractConstructor::compile_from_extended_json( - "etc/eth-contracts/artifacts/contracts/test/StateTest.sol/SelfDestruct.json", + "../etc/eth-contracts/artifacts/contracts/test/StateTest.sol/SelfDestruct.json", )) } } + pub(crate) struct SelfDestruct { contract: solidity::DeployedContract, } diff --git a/src/test_utils/solidity.rs b/engine-tests/src/test_utils/solidity.rs similarity index 98% rename from src/test_utils/solidity.rs rename to engine-tests/src/test_utils/solidity.rs index 6e68c17a6..23c4dc6c4 100644 --- a/src/test_utils/solidity.rs +++ b/engine-tests/src/test_utils/solidity.rs @@ -1,5 +1,5 @@ -use crate::prelude::{Address, U256}; -use crate::transaction::LegacyEthTransaction; +use crate::prelude::{transaction::LegacyEthTransaction, Address, U256}; +use near_sdk::serde_json; use serde::Deserialize; use std::fs; use std::path::Path; diff --git a/src/test_utils/standard_precompiles.rs b/engine-tests/src/test_utils/standard_precompiles.rs similarity index 95% rename from src/test_utils/standard_precompiles.rs rename to engine-tests/src/test_utils/standard_precompiles.rs index 56db06814..169596f7c 100644 --- a/src/test_utils/standard_precompiles.rs +++ b/engine-tests/src/test_utils/standard_precompiles.rs @@ -1,6 +1,5 @@ -use crate::prelude::U256; +use crate::prelude::{transaction::LegacyEthTransaction, U256}; use crate::test_utils::solidity; -use crate::transaction::LegacyEthTransaction; use std::path::{Path, PathBuf}; pub(crate) struct PrecompilesConstructor(pub solidity::ContractConstructor); diff --git a/src/tests/access_lists.rs b/engine-tests/src/tests/access_lists.rs similarity index 94% rename from src/tests/access_lists.rs rename to engine-tests/src/tests/access_lists.rs index 5676e39a3..2b556f619 100644 --- a/src/tests/access_lists.rs +++ b/engine-tests/src/tests/access_lists.rs @@ -1,8 +1,8 @@ +use crate::prelude::Wei; use crate::prelude::{H256, U256}; use crate::test_utils; -use crate::transaction::access_list::{self, AccessListEthTransaction, AccessTuple}; -use crate::transaction::EthTransaction; -use crate::types::Wei; +use aurora_engine::transaction::access_list::{self, AccessListEthTransaction, AccessTuple}; +use aurora_engine::transaction::EthTransaction; use std::convert::TryFrom; use std::iter; diff --git a/src/tests/contract_call.rs b/engine-tests/src/tests/contract_call.rs similarity index 100% rename from src/tests/contract_call.rs rename to engine-tests/src/tests/contract_call.rs diff --git a/src/tests/erc20.rs b/engine-tests/src/tests/erc20.rs similarity index 97% rename from src/tests/erc20.rs rename to engine-tests/src/tests/erc20.rs index fa8c92cb6..0262208a0 100644 --- a/src/tests/erc20.rs +++ b/engine-tests/src/tests/erc20.rs @@ -1,11 +1,12 @@ -use crate::parameters::TransactionStatus; +use crate::prelude::Wei; use crate::prelude::{Address, U256}; use crate::test_utils::{ self, erc20::{ERC20Constructor, ERC20}, Signer, }; -use crate::types::{self, Wei}; +use aurora_engine::parameters::TransactionStatus; +use aurora_engine_sdk as sdk; use bstr::ByteSlice; use secp256k1::SecretKey; @@ -78,7 +79,7 @@ fn erc20_mint_out_of_gas() { ); test_utils::validate_address_balance_and_nonce( &runner, - types::near_account_to_evm_address( + sdk::types::near_account_to_evm_address( runner.context.predecessor_account_id.as_ref().as_bytes(), ), Wei::new_u64(GAS_LIMIT * GAS_PRICE), @@ -241,7 +242,7 @@ fn get_address_erc20_balance( )) .unwrap(); let bytes = match result { - crate::parameters::TransactionStatus::Succeed(bytes) => bytes, + aurora_engine::parameters::TransactionStatus::Succeed(bytes) => bytes, err => panic!("Unexpected view call status {:?}", err), }; U256::from_big_endian(&bytes) diff --git a/src/tests/erc20_connector.rs b/engine-tests/src/tests/erc20_connector.rs similarity index 98% rename from src/tests/erc20_connector.rs rename to engine-tests/src/tests/erc20_connector.rs index c43f85a89..76569cfdf 100644 --- a/src/tests/erc20_connector.rs +++ b/engine-tests/src/tests/erc20_connector.rs @@ -1,9 +1,8 @@ -use crate::parameters::{FunctionCallArgs, SubmitResult}; -use crate::prelude::*; +use crate::prelude::{AccountId, Address, Balance, RawAddress, TryInto, Wei, U256}; use crate::test_utils; use crate::test_utils::{create_eth_transaction, origin, AuroraRunner}; -use crate::transaction::LegacyEthSignedTransaction; -use crate::types::{AccountId, Balance, RawAddress, Wei}; +use aurora_engine::parameters::{FunctionCallArgs, SubmitResult}; +use aurora_engine::transaction::LegacyEthSignedTransaction; use borsh::{BorshDeserialize, BorshSerialize}; use ethabi::Token; use near_vm_logic::VMOutcome; diff --git a/src/tests/eth_connector.rs b/engine-tests/src/tests/eth_connector.rs similarity index 99% rename from src/tests/eth_connector.rs rename to engine-tests/src/tests/eth_connector.rs index 2811fb17d..d41b6435b 100644 --- a/src/tests/eth_connector.rs +++ b/engine-tests/src/tests/eth_connector.rs @@ -1,18 +1,19 @@ -use crate::admin_controlled::{PausedMask, ERR_PAUSED}; -use crate::connector::{ +use crate::prelude::EthAddress; +use crate::prelude::WithdrawCallArgs; +use crate::prelude::U256; +use aurora_engine::admin_controlled::{PausedMask, ERR_PAUSED}; +use aurora_engine::connector::{ ERR_NOT_ENOUGH_BALANCE_FOR_FEE, PAUSE_DEPOSIT, PAUSE_WITHDRAW, UNPAUSE_ALL, }; -use crate::fungible_token::FungibleTokenMetadata; -use crate::parameters::{ - InitCallArgs, NewCallArgs, RegisterRelayerCallArgs, WithdrawCallArgs, WithdrawResult, +use aurora_engine::fungible_token::FungibleTokenMetadata; +use aurora_engine::parameters::{ + InitCallArgs, NewCallArgs, RegisterRelayerCallArgs, WithdrawResult, }; -use crate::types::{EthAddress, Proof}; use borsh::{BorshDeserialize, BorshSerialize}; use byte_slice_cast::AsByteSlice; use near_sdk::test_utils::accounts; use near_sdk_sim::transaction::ExecutionStatus; use near_sdk_sim::{to_yocto, ExecutionResult, UserAccount, DEFAULT_GAS, STORAGE_AMOUNT}; -use primitive_types::U256; use serde_json::json; const CONTRACT_ACC: &'static str = "eth_connector.root"; @@ -28,6 +29,18 @@ const EVM_CUSTODIAN_ADDRESS: &'static str = "096DE9C2B8A5B8c22cEe3289B101f6960d6 const DEPOSITED_EVM_AMOUNT: u128 = 10200; const DEPOSITED_EVM_FEE: u128 = 200; +#[derive( + Default, BorshDeserialize, BorshSerialize, Clone, serde::Deserialize, serde::Serialize, +)] +pub struct Proof { + pub log_index: u64, + pub log_entry_data: Vec, + pub receipt_index: u64, + pub receipt_data: Vec, + pub header_data: Vec, + pub proof: Vec>, +} + #[derive(BorshDeserialize, Debug)] pub struct IsUsedProofResult { pub is_used_proof: bool, diff --git a/src/tests/meta_parsing.rs b/engine-tests/src/tests/meta_parsing.rs similarity index 96% rename from src/tests/meta_parsing.rs rename to engine-tests/src/tests/meta_parsing.rs index c25f12af4..1dbe2efb1 100644 --- a/src/tests/meta_parsing.rs +++ b/engine-tests/src/tests/meta_parsing.rs @@ -1,8 +1,9 @@ use { crate::meta_parsing::{near_erc712_domain, parse_meta_call, prepare_meta_call_args}, - crate::parameters::MetaCallArgs, + crate::prelude::keccak, + crate::prelude::{u256_to_arr, InternalMetaCallArgs, Wei}, crate::prelude::{Address, U256}, - crate::types::{keccak, u256_to_arr, InternalMetaCallArgs, Wei}, + aurora_engine::parameters::MetaCallArgs, borsh::BorshSerialize, near_crypto::{InMemorySigner, KeyType, PublicKey, Signature, Signer}, }; diff --git a/src/tests/mod.rs b/engine-tests/src/tests/mod.rs similarity index 100% rename from src/tests/mod.rs rename to engine-tests/src/tests/mod.rs diff --git a/src/tests/one_inch.rs b/engine-tests/src/tests/one_inch.rs similarity index 92% rename from src/tests/one_inch.rs rename to engine-tests/src/tests/one_inch.rs index bf454793a..bfd83720a 100644 --- a/src/tests/one_inch.rs +++ b/engine-tests/src/tests/one_inch.rs @@ -1,8 +1,7 @@ -use crate::parameters::SubmitResult; -use crate::prelude::U256; +use crate::prelude::parameters::SubmitResult; +use crate::prelude::{Wei, U256}; use crate::test_utils; use crate::test_utils::one_inch::liquidity_protocol; -use crate::types::Wei; use borsh::BorshDeserialize; use near_vm_logic::VMOutcome; use secp256k1::SecretKey; @@ -40,7 +39,12 @@ fn test_1inch_liquidity_protocol() { let (result, profile, pool) = helper.create_pool(&pool_factory, token_a.0.address, token_b.0.address); assert!(result.gas_used >= 4_500_000); // more than 4.5M EVM gas used - assert!(profile.all_gas() <= 103_000_000_000_000); // less than 103 NEAR Tgas used + let total_gas = profile.all_gas(); + assert!( + total_gas <= 104_000_000_000_000, + "{} is not less than 104 Tgas", + total_gas + ); // less than 104 NEAR Tgas used // Approve giving ERC-20 tokens to the pool helper.approve_erc20_tokens(&token_a, pool.address()); @@ -96,8 +100,8 @@ fn test_1_inch_limit_order_deploy() { // more than 4 million Ethereum gas used assert!(result.gas_used > 4_000_000); - // less than 42 NEAR Tgas used - assert!(profile.all_gas() < 42_000_000_000_000); + // less than 43 NEAR Tgas used + assert!(profile.all_gas() < 43_000_000_000_000); // at least 70% of which is from wasm execution assert!(100 * profile.wasm_gas() / profile.all_gas() > 70); } @@ -116,7 +120,7 @@ fn deploy_1_inch_limit_order_contract( test_utils::solidity::ContractConstructor::compile_from_extended_json(contract_path); let nonce = signer.use_nonce(); - let deploy_tx = crate::transaction::LegacyEthTransaction { + let deploy_tx = crate::prelude::transaction::LegacyEthTransaction { nonce: nonce.into(), gas_price: Default::default(), gas: u64::MAX.into(), diff --git a/src/tests/res/blockhash.sol b/engine-tests/src/tests/res/blockhash.sol similarity index 100% rename from src/tests/res/blockhash.sol rename to engine-tests/src/tests/res/blockhash.sol diff --git a/src/tests/res/poster.sol b/engine-tests/src/tests/res/poster.sol similarity index 100% rename from src/tests/res/poster.sol rename to engine-tests/src/tests/res/poster.sol diff --git a/src/tests/sanity.rs b/engine-tests/src/tests/sanity.rs similarity index 95% rename from src/tests/sanity.rs rename to engine-tests/src/tests/sanity.rs index ff064f826..0c08335d3 100644 --- a/src/tests/sanity.rs +++ b/engine-tests/src/tests/sanity.rs @@ -1,9 +1,10 @@ -use crate::fungible_token::FungibleTokenMetadata; -use crate::parameters::{SubmitResult, TransactionStatus}; use crate::prelude::{Address, U256}; +use crate::prelude::{Wei, ERC20_MINT_SELECTOR}; use crate::test_utils; use crate::tests::state_migration; -use crate::types::{self, Wei, ERC20_MINT_SELECTOR}; +use aurora_engine::fungible_token::FungibleTokenMetadata; +use aurora_engine::parameters::{SubmitResult, TransactionStatus}; +use aurora_engine_sdk as sdk; use borsh::{BorshDeserialize, BorshSerialize}; use rand::RngCore; use secp256k1::SecretKey; @@ -58,7 +59,7 @@ fn test_override_state() { // deploy contract let result = runner .submit_with_signer(&mut account1, |nonce| { - crate::transaction::LegacyEthTransaction { + crate::prelude::transaction::LegacyEthTransaction { nonce, gas_price: Default::default(), gas: u64::MAX.into(), @@ -80,7 +81,7 @@ fn test_override_state() { )) .unwrap(); match result { - crate::parameters::TransactionStatus::Succeed(bytes) => { + crate::prelude::parameters::TransactionStatus::Succeed(bytes) => { Address::from_slice(&bytes[12..32]) } _ => panic!("tx failed"), @@ -118,7 +119,11 @@ fn test_num_wasm_functions() { let artifact = get_compiled_artifact(&runner); let module_info = artifact.info(); let num_functions = module_info.func_assoc.len(); - assert!(num_functions <= 1281); + assert!( + num_functions <= 1400, + "{} is not less than 1400", + num_functions + ); } /// Tests we can transfer Eth from one account to another and that the balances are correctly @@ -294,7 +299,7 @@ fn test_transfer_charging_gas_success() { let expected_source_balance = INITIAL_BALANCE - TRANSFER_AMOUNT - spent_amount; let expected_dest_balance = TRANSFER_AMOUNT; let expected_relayer_balance = spent_amount; - let relayer_address = types::near_account_to_evm_address( + let relayer_address = sdk::types::near_account_to_evm_address( runner.context.predecessor_account_id.as_ref().as_bytes(), ); @@ -348,9 +353,10 @@ fn test_eth_transfer_charging_gas_not_enough_balance() { assert_eq!(result.status, TransactionStatus::OutOfFund); // validate post-state - let relayer = types::near_account_to_evm_address( + let relayer = sdk::types::near_account_to_evm_address( runner.context.predecessor_account_id.as_ref().as_bytes(), ); + test_utils::validate_address_balance_and_nonce( &runner, source_address, @@ -393,10 +399,11 @@ fn test_block_hash() { let runner = test_utils::AuroraRunner::default(); let chain_id = { let number = crate::prelude::U256::from(runner.chain_id); - crate::types::u256_to_arr(&number) + crate::prelude::u256_to_arr(&number) }; let account_id = runner.aurora_account_id; - let block_hash = crate::engine::Engine::compute_block_hash(chain_id, 10, account_id.as_bytes()); + let block_hash = + aurora_engine::engine::Engine::compute_block_hash(chain_id, 10, account_id.as_bytes()); assert_eq!( hex::encode(block_hash.0).as_str(), @@ -437,11 +444,12 @@ fn test_ft_metadata() { let (maybe_outcome, maybe_error) = runner.call("ft_metadata", &account_id, Vec::new()); assert!(maybe_error.is_none()); let outcome = maybe_outcome.unwrap(); - let json_value = crate::json::parse_json(&outcome.return_data.as_value().unwrap()).unwrap(); + let json_value = + aurora_engine::json::parse_json(&outcome.return_data.as_value().unwrap()).unwrap(); assert_eq!( json_value, - crate::json::JsonValue::from(FungibleTokenMetadata::default()) + aurora_engine::json::JsonValue::from(FungibleTokenMetadata::default()) ); } diff --git a/src/tests/self_destruct_state.rs b/engine-tests/src/tests/self_destruct_state.rs similarity index 100% rename from src/tests/self_destruct_state.rs rename to engine-tests/src/tests/self_destruct_state.rs diff --git a/src/tests/standard_precompiles.rs b/engine-tests/src/tests/standard_precompiles.rs similarity index 97% rename from src/tests/standard_precompiles.rs rename to engine-tests/src/tests/standard_precompiles.rs index c6dd25f9f..e16405db5 100644 --- a/src/tests/standard_precompiles.rs +++ b/engine-tests/src/tests/standard_precompiles.rs @@ -1,8 +1,8 @@ +use crate::prelude::Wei; use crate::test_utils::{ self, standard_precompiles::{PrecompilesConstructor, PrecompilesContract}, }; -use crate::types::Wei; use secp256k1::SecretKey; const INITIAL_BALANCE: Wei = Wei::new_u64(1000); diff --git a/src/tests/state_migration.rs b/engine-tests/src/tests/state_migration.rs similarity index 93% rename from src/tests/state_migration.rs rename to engine-tests/src/tests/state_migration.rs index a00cf5d7e..e1e31b473 100644 --- a/src/tests/state_migration.rs +++ b/engine-tests/src/tests/state_migration.rs @@ -1,7 +1,6 @@ -use crate::parameters::{InitCallArgs, NewCallArgs}; use crate::prelude::U256; use crate::test_utils::AuroraRunner; -use crate::types; +use aurora_engine::parameters::{InitCallArgs, NewCallArgs}; use borsh::BorshSerialize; use near_sdk_sim::{ExecutionResult, UserAccount}; use std::fs; @@ -36,7 +35,7 @@ pub fn deploy_evm() -> AuroraAccount { ); let prover_account = "prover.near".to_string(); let new_args = NewCallArgs { - chain_id: types::u256_to_arr(&U256::from(aurora_runner.chain_id)), + chain_id: crate::prelude::u256_to_arr(&U256::from(aurora_runner.chain_id)), owner_id: main_account.account_id.clone().into(), bridge_prover_id: prover_account.clone(), upgrade_delay_blocks: 1, @@ -88,7 +87,7 @@ impl AuroraAccount { } fn contract_bytes() -> Vec { - let base_path = Path::new("etc").join("state-migration-test"); + let base_path = Path::new("../etc").join("state-migration-test"); let output_path = base_path .join("target/wasm32-unknown-unknown/release/aurora_engine_state_migration_test.wasm"); compile(base_path); diff --git a/engine-types/Cargo.toml b/engine-types/Cargo.toml new file mode 100644 index 000000000..8ee5ec236 --- /dev/null +++ b/engine-types/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "aurora-engine-types" +version = "1.0.0" +authors = ["NEAR "] +edition = "2018" +description = "" +documentation = "" +readme = true +homepage = "https://github.com/aurora-is-near/aurora-engine" +repository = "https://github.com/aurora-is-near/aurora-engine" +license = "CC0-1.0" +publish = false +autobenches = false + +[dependencies] +borsh = { version = "0.8.2", default-features = false } +ethabi = { git = "https://github.com/darwinia-network/ethabi", branch = "xavier-no-std", default-features = false } +hex = { version = "0.4", default-features = false, features = ["alloc"] } +primitive-types = { version = "0.9.0", default-features = false, features = ["rlp"] } +sha3 = { version = "0.9.1", default-features = false } + +[dev-dependencies] +bstr = "0.2" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +rand = "0.7.3" + +[features] +default = ["std"] +std = ["primitive-types/std"] diff --git a/src/prelude.rs b/engine-types/src/lib.rs similarity index 54% rename from src/prelude.rs rename to engine-types/src/lib.rs index 6c6fa89bf..82bd44720 100644 --- a/src/prelude.rs +++ b/engine-types/src/lib.rs @@ -1,49 +1,66 @@ -#[cfg(not(feature = "std"))] -pub use alloc::{ - borrow::ToOwned, - borrow::{Cow, Cow::*}, - boxed::Box, - collections::BTreeMap as HashMap, - collections::BTreeMap, - fmt, format, str, - string::String, - string::ToString, - vec, - vec::Vec, -}; -#[cfg(not(feature = "std"))] -pub use core::{ - cmp::Ordering, - convert::TryFrom, - convert::TryInto, - marker::PhantomData, - mem, - ops::{Add, Sub}, -}; -#[cfg(feature = "std")] -pub use std::{ - borrow::Cow, - borrow::Cow::Borrowed, - borrow::ToOwned, - boxed::Box, - cmp::Ordering, - collections::BTreeMap, - collections::HashMap, - convert::TryFrom, - convert::TryInto, - error::Error, - fmt, format, - marker::PhantomData, - mem, - ops::{Add, Sub}, - str, - string::String, - string::ToString, - vec, - vec::Vec, -}; +#![feature(array_methods)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] +#![cfg_attr(feature = "log", feature(panic_info_message))] -pub use primitive_types::{H160, H256, U256}; +pub mod parameters; +pub mod storage; +pub mod types; + +mod v0 { + #[cfg(not(feature = "std"))] + extern crate alloc; + #[cfg(not(feature = "std"))] + extern crate core; + + #[cfg(not(feature = "std"))] + pub use alloc::{ + borrow::ToOwned, + borrow::{Cow, Cow::*}, + boxed::Box, + collections::BTreeMap as HashMap, + collections::BTreeMap, + fmt, format, str, + string::String, + string::ToString, + vec, + vec::Vec, + }; + #[cfg(not(feature = "std"))] + pub use core::{ + cmp::Ordering, + convert::TryFrom, + convert::TryInto, + marker::PhantomData, + mem, + ops::{Add, Sub}, + }; + pub use primitive_types::{H160, H256, U256}; + #[cfg(feature = "std")] + pub use std::{ + borrow::Cow, + borrow::Cow::Borrowed, + borrow::ToOwned, + boxed::Box, + cmp::Ordering, + collections::BTreeMap, + collections::HashMap, + convert::TryFrom, + convert::TryInto, + error::Error, + fmt, format, + marker::PhantomData, + mem, + ops::{Add, Sub}, + str, + string::String, + string::ToString, + vec, + vec::Vec, + }; +} + +pub use v0::*; /// See: https://ethereum-magicians.org/t/increasing-address-size-from-20-to-32-bytes/5485 pub type Address = H160; diff --git a/engine-types/src/parameters.rs b/engine-types/src/parameters.rs new file mode 100644 index 000000000..beb8085bd --- /dev/null +++ b/engine-types/src/parameters.rs @@ -0,0 +1,19 @@ +use crate::types::*; +use crate::*; +use borsh::{BorshDeserialize, BorshSerialize}; + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct PromiseCreateArgs { + pub target_account_id: AccountId, + pub method: String, + pub args: Vec, + pub attached_balance: u128, + pub attached_gas: u64, +} + +/// withdraw NEAR eth-connector call args +#[derive(BorshSerialize, BorshDeserialize)] +pub struct WithdrawCallArgs { + pub recipient_address: EthAddress, + pub amount: Balance, +} diff --git a/src/storage.rs b/engine-types/src/storage.rs similarity index 97% rename from src/storage.rs rename to engine-types/src/storage.rs index 6d8132fbf..9a6827a96 100644 --- a/src/storage.rs +++ b/engine-types/src/storage.rs @@ -1,4 +1,4 @@ -use crate::prelude::{Address, Vec, H256}; +use crate::*; use borsh::{BorshDeserialize, BorshSerialize}; // NOTE: We start at 0x7 as our initial value as our original storage was not @@ -112,6 +112,3 @@ fn generation_storage_key(address: &Address, key: &H256, generation: u32) -> [u8 result[26..58].copy_from_slice(&key.0); result } - -#[cfg(test)] -mod tests {} diff --git a/src/types.rs b/engine-types/src/types.rs similarity index 59% rename from src/types.rs rename to engine-types/src/types.rs index 008e59dbb..8bef46d8d 100644 --- a/src/types.rs +++ b/engine-types/src/types.rs @@ -1,20 +1,5 @@ -use crate::prelude::{self, str, Address, String, ToString, Vec, H256, U256}; -#[cfg(not(feature = "contract"))] -use crate::prelude::{format, vec}; +use super::{str, vec, Add, Address, String, Sub, Vec, U256}; use borsh::{BorshDeserialize, BorshSerialize}; -use ethabi::{Event, EventParam, Hash, Log, RawLog}; - -#[cfg(not(feature = "contract"))] -use ethabi::{ParamType, Token}; - -#[cfg(not(feature = "contract"))] -use sha3::{Digest, Keccak256}; - -use crate::log_entry::LogEntry; -use crate::sdk; - -#[cfg(not(feature = "contract"))] -use ethabi::param_type::Writer; pub type AccountId = String; pub type Balance = u128; @@ -29,90 +14,7 @@ pub type StorageUsage = u64; /// /// keccak("mint(address,uint256)".as_bytes())[..4]; #[allow(dead_code)] -pub(crate) const ERC20_MINT_SELECTOR: &[u8] = &[64, 193, 15, 25]; - -pub type EventParams = Vec; - -/// Ethereum event -pub struct EthEvent { - pub eth_custodian_address: EthAddress, - pub log: Log, -} - -#[allow(dead_code)] -impl EthEvent { - /// Get Ethereum event from `log_entry_data` - pub fn fetch_log_entry_data(name: &str, params: EventParams, data: &[u8]) -> Self { - let event = Event { - name: name.to_string(), - inputs: params, - anonymous: false, - }; - let log_entry: LogEntry = rlp::decode(data).expect("INVALID_RLP"); - let eth_custodian_address = log_entry.address.0; - let topics = log_entry.topics.iter().map(|h| Hash::from(h.0)).collect(); - - let raw_log = RawLog { - topics, - data: log_entry.data, - }; - let log = event.parse_log(raw_log).expect("Failed to parse event log"); - - Self { - eth_custodian_address, - log, - } - } - - /// Build log_entry_data from ethereum event - #[cfg(not(feature = "contract"))] - #[allow(dead_code)] - pub fn params_to_log_entry_data( - name: &str, - params: EventParams, - locker_address: EthAddress, - indexes: Vec>, - values: Vec, - ) -> Vec { - let event = Event { - name: name.to_string(), - inputs: params.into_iter().collect(), - anonymous: false, - }; - let params: Vec = event.inputs.iter().map(|p| p.kind.clone()).collect(); - let topics = indexes - .into_iter() - .map(|value| { - let mut result: [u8; 32] = Default::default(); - result[12..].copy_from_slice(value.as_slice()); - H256::from(result) - }) - .collect(); - let log_entry = LogEntry { - address: locker_address.into(), - topics: vec![vec![long_signature(&event.name, ¶ms).0.into()], topics].concat(), - data: ethabi::encode(&values), - }; - rlp::encode(&log_entry).to_vec() - } -} - -#[cfg(not(feature = "contract"))] -fn long_signature(name: &str, params: &[ParamType]) -> Hash { - let types = params - .iter() - .map(Writer::write) - .collect::>() - .join(","); - - let data: Vec = From::from(format!("{}({})", name, types).as_str()); - - let mut sponge = sha3::Keccak256::default(); - sponge.update(&data); - let mut result: [u8; 32] = Default::default(); - result.copy_from_slice(sponge.finalize().as_slice()); - H256::from(result) -} +pub const ERC20_MINT_SELECTOR: &[u8] = &[64, 193, 15, 25]; #[derive(Debug)] pub enum ValidationError { @@ -141,30 +43,6 @@ pub fn validate_eth_address(address: String) -> Result, - pub receipt_index: u64, - pub receipt_data: Vec, - pub header_data: Vec, - pub proof: Vec>, -} - -impl Proof { - pub fn get_key(&self) -> String { - let mut data = self.log_index.try_to_vec().unwrap(); - data.extend(self.receipt_index.try_to_vec().unwrap()); - data.extend(self.header_data.clone()); - sdk::sha256(&data[..]) - .0 - .iter() - .map(|n| n.to_string()) - .collect() - } -} - /// Newtype to distinguish balances (denominated in Wei) from other U256 types. #[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Copy, Clone, Default)] pub struct Wei(U256); @@ -212,14 +90,14 @@ impl Wei { self.0.checked_add(other.0).map(Self) } } -impl prelude::Sub for Wei { +impl Sub for Wei { type Output = Self; fn sub(self, other: Self) -> Self::Output { Self(self.0 - other.0) } } -impl prelude::Add for Wei { +impl Add for Wei { type Output = Self; fn add(self, other: Self) -> Self::Output { @@ -290,23 +168,6 @@ pub fn bytes_to_hex(v: &[u8]) -> String { result } -#[cfg(feature = "contract")] -#[inline] -pub fn keccak(data: &[u8]) -> H256 { - sdk::keccak(data) -} - -#[cfg(not(feature = "contract"))] -#[inline] -pub fn keccak(data: &[u8]) -> H256 { - H256::from_slice(Keccak256::digest(data).as_slice()) -} - -#[allow(dead_code)] -pub fn near_account_to_evm_address(addr: &[u8]) -> Address { - Address::from_slice(&keccak(addr)[12..]) -} - #[derive(Default)] pub struct Stack { stack: Vec, @@ -317,7 +178,7 @@ impl Stack { pub fn new() -> Self { Self { stack: Vec::new(), - boundaries: crate::prelude::vec![0], + boundaries: vec![0], } } @@ -346,88 +207,6 @@ pub fn str_from_slice(inp: &[u8]) -> &str { str::from_utf8(inp).unwrap() } -#[cfg(feature = "contract")] -pub trait ExpectUtf8 { - fn expect_utf8(self, message: &[u8]) -> T; -} - -#[cfg(feature = "contract")] -impl ExpectUtf8 for Option { - fn expect_utf8(self, message: &[u8]) -> T { - match self { - Some(t) => t, - None => sdk::panic_utf8(message), - } - } -} - -#[cfg(feature = "contract")] -impl ExpectUtf8 for core::result::Result { - fn expect_utf8(self, message: &[u8]) -> T { - match self { - Ok(t) => t, - Err(_) => sdk::panic_utf8(message), - } - } -} - -pub trait SdkExpect { - fn sdk_expect(self, msg: &str) -> T; -} - -impl SdkExpect for Option { - fn sdk_expect(self, msg: &str) -> T { - match self { - Some(t) => t, - None => sdk::panic_utf8(msg.as_ref()), - } - } -} - -impl SdkExpect for core::result::Result { - fn sdk_expect(self, msg: &str) -> T { - match self { - Ok(t) => t, - Err(_) => sdk::panic_utf8(msg.as_ref()), - } - } -} - -pub trait SdkUnwrap { - fn sdk_unwrap(self) -> T; -} - -impl SdkUnwrap for Option { - fn sdk_unwrap(self) -> T { - match self { - Some(t) => t, - None => sdk::panic_utf8("ERR_UNWRAP".as_bytes()), - } - } -} - -impl> SdkUnwrap for core::result::Result { - fn sdk_unwrap(self) -> T { - match self { - Ok(t) => t, - Err(e) => sdk::panic_utf8(e.as_ref()), - } - } -} - -pub(crate) trait SdkProcess { - fn sdk_process(self); -} - -impl, E: AsRef<[u8]>> SdkProcess for Result { - fn sdk_process(self) { - match self { - Ok(r) => sdk::return_output(r.as_ref()), - Err(e) => sdk::panic_utf8(e.as_ref()), - } - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/engine/Cargo.toml b/engine/Cargo.toml new file mode 100644 index 000000000..5b2ce5365 --- /dev/null +++ b/engine/Cargo.toml @@ -0,0 +1,60 @@ +[package] +name = "aurora-engine" +version = "1.7.0" +authors = ["NEAR "] +edition = "2018" +description = "" +documentation = "" +readme = true +homepage = "https://github.com/aurora-is-near/aurora-engine" +repository = "https://github.com/aurora-is-near/aurora-engine" +license = "CC0-1.0" +publish = false +autobenches = false + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +aurora-engine-types = { path = "../engine-types", default-features = false } +aurora-engine-sdk = { path = "../engine-sdk", default-features = false } +aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false } +base64 = { version = "0.13.0", default-features = false, features = ["alloc"] } +blake2 = { git = "https://github.com/near/near-blake2.git", version = "0.9.1", default-features = false } +borsh = { version = "0.8.2", default-features = false } +bn = { package = "aurora-bn", git = "https://github.com/aurora-is-near/aurora-bn.git", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } +libsecp256k1 = { version = "0.3.5", default-features = false } +num = { version = "0.4.0", default-features = false, features = ["alloc"] } +primitive-types = { version = "0.9.0", default-features = false, features = ["rlp"] } +ripemd160 = { version = "0.9.1", default-features = false } +rlp = { version = "0.5.0", default-features = false } +sha2 = { version = "0.9.3", default-features = false, optional = true } +sha3 = { version = "0.9.1", default-features = false } +wee_alloc = { version = "0.4.5", default-features = false } +logos = { version = "0.12", default-features = false, features = ["export_derive"] } +ethabi = { git = "https://github.com/darwinia-network/ethabi", branch = "xavier-no-std", default-features = false } +hex = { version = "0.4", default-features = false, features = ["alloc"] } +byte-slice-cast = { version = "1.0", default-features = false } +rjson = { git = "https://github.com/aurora-is-near/rjson", rev = "cc3da949", default-features = false, features = ["integer"] } + +[dev-dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = "1" +rand = "0.7.3" + +[features] +default = ["sha2", "std"] +std = ["borsh/std", "evm/std", "primitive-types/std", "rlp/std", "sha3/std", "ethabi/std", "logos/std", "bn/std", "aurora-engine-types/std"] +contract = ["aurora-engine-sdk/contract", "aurora-engine-precompiles/contract"] +evm_bully = [] +log = ["aurora-engine-sdk/log", "aurora-engine-precompiles/log"] +meta-call = [] +integration-test = ["log"] +mainnet = ["contract", "log"] +testnet = ["contract", "log"] +betanet = ["contract", "log", "meta-call"] +mainnet-test = ["meta-call"] +testnet-test = ["meta-call"] +betanet-test = ["meta-call"] diff --git a/LICENSE b/engine/LICENSE similarity index 100% rename from LICENSE rename to engine/LICENSE diff --git a/src/admin_controlled.rs b/engine/src/admin_controlled.rs similarity index 93% rename from src/admin_controlled.rs rename to engine/src/admin_controlled.rs index 12046f24c..e68dd4d8d 100644 --- a/src/admin_controlled.rs +++ b/engine/src/admin_controlled.rs @@ -1,8 +1,8 @@ -use crate::sdk; +use crate::prelude::sdk; pub type PausedMask = u8; -pub(crate) const ERR_PAUSED: &str = "ERR_PAUSED"; +pub const ERR_PAUSED: &str = "ERR_PAUSED"; pub trait AdminControlled { /// Returns true if the current account is owner diff --git a/src/connector.rs b/engine/src/connector.rs similarity index 91% rename from src/connector.rs rename to engine/src/connector.rs index b50328780..f0ce72dee 100644 --- a/src/connector.rs +++ b/engine/src/connector.rs @@ -1,27 +1,31 @@ -use crate::fungible_token::*; -use crate::parameters::*; -use crate::sdk; -use crate::types::{ - AccountId, Balance, EthAddress, Gas, PromiseResult, Proof, SdkUnwrap, ERR_FAILED_PARSE, -}; - use crate::admin_controlled::{AdminControlled, PausedMask}; -use crate::deposit_event::*; +use crate::deposit_event::DepositedEvent; use crate::engine::Engine; +use crate::fungible_token::{FungibleToken, FungibleTokenMetadata}; use crate::json::parse_json; -use crate::prelude::*; -use crate::storage::{self, EthConnectorStorageId, KeyPrefix}; -use borsh::{BorshDeserialize, BorshSerialize}; +use crate::parameters::{ + BalanceOfCallArgs, BalanceOfEthCallArgs, FinishDepositCallArgs, InitCallArgs, + NEP141FtOnTransferArgs, PauseEthConnectorCallArgs, ResolveTransferCallArgs, + SetContractDataCallArgs, StorageBalanceOfCallArgs, StorageDepositCallArgs, + StorageWithdrawCallArgs, TransferCallArgs, TransferCallCallArgs, WithdrawResult, +}; +use crate::prelude::sdk::types::{ExpectUtf8, SdkUnwrap}; +use crate::prelude::{ + format, is_valid_account_id, sdk, str, validate_eth_address, AccountId, Address, Balance, + BorshDeserialize, BorshSerialize, EthAddress, EthConnectorStorageId, Gas, KeyPrefix, + PromiseResult, String, ToString, Vec, WithdrawCallArgs, ERR_FAILED_PARSE, H160, U256, +}; +use crate::proof::Proof; -pub(crate) const ERR_NOT_ENOUGH_BALANCE_FOR_FEE: &str = "ERR_NOT_ENOUGH_BALANCE_FOR_FEE"; +pub const ERR_NOT_ENOUGH_BALANCE_FOR_FEE: &str = "ERR_NOT_ENOUGH_BALANCE_FOR_FEE"; pub const NO_DEPOSIT: Balance = 0; const GAS_FOR_FINISH_DEPOSIT: Gas = 50_000_000_000_000; // Note: Is 40Tgas always enough? const GAS_FOR_VERIFY_LOG_ENTRY: Gas = 40_000_000_000_000; -pub(crate) const UNPAUSE_ALL: PausedMask = 0; -pub(crate) const PAUSE_DEPOSIT: PausedMask = 1 << 0; -pub(crate) const PAUSE_WITHDRAW: PausedMask = 1 << 1; +pub const UNPAUSE_ALL: PausedMask = 0; +pub const PAUSE_DEPOSIT: PausedMask = 1 << 0; +pub const PAUSE_WITHDRAW: PausedMask = 1 << 1; #[derive(BorshSerialize, BorshDeserialize)] pub struct EthConnectorContract { @@ -62,7 +66,7 @@ impl EthConnectorContract { } fn get_contract_key(suffix: &EthConnectorStorageId) -> Vec { - storage::bytes_to_key(KeyPrefix::EthConnector, &[*suffix as u8]) + crate::prelude::bytes_to_key(KeyPrefix::EthConnector, &[*suffix as u8]) } fn get_contract_data(suffix: &EthConnectorStorageId) -> T { @@ -77,7 +81,7 @@ impl EthConnectorContract { !sdk::storage_has_key(&Self::get_contract_key(&EthConnectorStorageId::Contract)), "ERR_CONTRACT_INITIALIZED" ); - crate::log!("[init contract]"); + sdk::log!("[init contract]"); let contract_data = Self::set_contract_data(SetContractDataCallArgs { prover_account: args.prover_account, @@ -110,8 +114,7 @@ impl EthConnectorContract { // Get initial contract arguments let contract_data = EthConnector { prover_account: args.prover_account, - eth_custodian_address: crate::types::validate_eth_address(args.eth_custodian_address) - .sdk_unwrap(), + eth_custodian_address: validate_eth_address(args.eth_custodian_address).sdk_unwrap(), }; // Save eth-connector specific data sdk::save_contract( @@ -186,7 +189,7 @@ impl EthConnectorContract { pub fn deposit(&self) { self.assert_not_paused(PAUSE_DEPOSIT); - crate::log!("[Deposit tokens]"); + sdk::log!("[Deposit tokens]"); // Get incoming deposit arguments let raw_proof = sdk::read_input(); @@ -194,7 +197,7 @@ impl EthConnectorContract { // Fetch event data from Proof let event = DepositedEvent::from_log_entry_data(&proof.log_entry_data); - crate::log!(&format!( + sdk::log!(&format!( "Deposit started: from {} to recipient {:?} with amount: {:?} and fee {:?}", hex::encode(event.sender), event.recipient, @@ -202,7 +205,7 @@ impl EthConnectorContract { event.fee.as_u128() )); - crate::log!(&format!( + sdk::log!(&format!( "Event's address {}, custodian address {}", hex::encode(&event.eth_custodian_address), hex::encode(&self.contract.eth_custodian_address), @@ -220,7 +223,7 @@ impl EthConnectorContract { ); // Verify proof data with cross-contract call to prover account - crate::log!(&format!( + sdk::log!(&format!( "Deposit verify_log_entry for prover: {}", self.contract.prover_account, )); @@ -300,7 +303,7 @@ impl EthConnectorContract { sdk::assert_private_call(); let data: FinishDepositCallArgs = FinishDepositCallArgs::try_from_slice(&sdk::read_input()).unwrap(); - crate::log!(&format!("Finish deposit with the amount: {}", data.amount)); + sdk::log!(&format!("Finish deposit with the amount: {}", data.amount)); assert_eq!(sdk::promise_results_count(), 1); // Check promise results @@ -310,7 +313,7 @@ impl EthConnectorContract { // This shouldn't be reachable PromiseResult::NotReady => sdk::panic_utf8(b"ERR_PROMISE_NOT_READY"), }; - crate::log!("Check verification_success"); + sdk::log!("Check verification_success"); let verification_success = bool::try_from_slice(&data0).unwrap(); assert!(verification_success, "ERR_VERIFY_PROOF"); @@ -353,7 +356,7 @@ impl EthConnectorContract { /// Record used proof as hash key fn record_proof(&mut self, key: &str) { - crate::log!(&format!("Record proof: {}", key)); + sdk::log!(&format!("Record proof: {}", key)); assert!(!self.check_used_event(key), "ERR_PROOF_EXIST"); self.save_used_event(key); @@ -361,7 +364,7 @@ impl EthConnectorContract { /// Mint nETH tokens fn mint_eth_on_near(&mut self, owner_id: AccountId, amount: Balance) { - crate::log!(&format!("Mint {} nETH tokens for: {}", amount, owner_id)); + sdk::log!(&format!("Mint {} nETH tokens for: {}", amount, owner_id)); if self.ft.accounts_get(&owner_id).is_none() { self.ft.accounts_insert(&owner_id, 0); @@ -371,7 +374,7 @@ impl EthConnectorContract { /// Mint ETH tokens fn mint_eth_on_aurora(&mut self, owner_id: EthAddress, amount: Balance) { - crate::log!(&format!( + sdk::log!(&format!( "Mint {} ETH tokens for: {}", amount, hex::encode(owner_id) @@ -381,7 +384,7 @@ impl EthConnectorContract { /// Burn ETH tokens fn burn_eth_on_aurora(&mut self, address: EthAddress, amount: Balance) { - crate::log!(&format!( + sdk::log!(&format!( "Burn {} ETH tokens for: {}", amount, hex::encode(address) @@ -415,14 +418,14 @@ impl EthConnectorContract { /// Returns total ETH supply on NEAR (nETH as NEP-141 token) pub fn ft_total_eth_supply_on_near(&self) { let total_supply = self.ft.ft_total_eth_supply_on_near(); - crate::log!(&format!("Total ETH supply on NEAR: {}", total_supply)); + sdk::log!(&format!("Total ETH supply on NEAR: {}", total_supply)); sdk::return_output(format!("\"{}\"", total_supply.to_string()).as_bytes()); } /// Returns total ETH supply on Aurora (ETH in Aurora EVM) pub fn ft_total_eth_supply_on_aurora(&self) { let total_supply = self.ft.ft_total_eth_supply_on_aurora(); - crate::log!(&format!("Total ETH supply on Aurora: {}", total_supply)); + sdk::log!(&format!("Total ETH supply on Aurora: {}", total_supply)); sdk::return_output(format!("\"{}\"", total_supply.to_string()).as_bytes()); } @@ -433,7 +436,7 @@ impl EthConnectorContract { ); let balance = self.ft.ft_balance_of(&args.account_id); - crate::log!(&format!( + sdk::log!(&format!( "Balance of nETH [{}]: {}", args.account_id, balance )); @@ -448,7 +451,7 @@ impl EthConnectorContract { let balance = self .ft .internal_unwrap_balance_of_eth_on_aurora(args.address); - crate::log!(&format!( + sdk::log!(&format!( "Balance of ETH [{}]: {}", hex::encode(args.address), balance @@ -465,7 +468,7 @@ impl EthConnectorContract { self.ft .ft_transfer(&args.receiver_id, args.amount, &args.memo); self.save_ft_contract(); - crate::log!(&format!( + sdk::log!(&format!( "Transfer amount {} to {} success with memo: {:?}", args.amount, args.receiver_id, args.memo )); @@ -481,7 +484,7 @@ impl EthConnectorContract { let amount = self .ft .ft_resolve_transfer(&args.sender_id, &args.receiver_id, args.amount); - crate::log!(&format!( + sdk::log!(&format!( "Resolve transfer from {} to {} success", args.sender_id, args.receiver_id )); @@ -494,7 +497,7 @@ impl EthConnectorContract { /// We starting early checking for message data to avoid `ft_on_transfer` call panics /// But we don't check relayer exists. If relayer doesn't exist we simply not mint/burn the amount of the fee pub fn ft_transfer_call(&mut self, args: TransferCallCallArgs) { - crate::log!(&format!( + sdk::log!(&format!( "Transfer call to {} amount {}", args.receiver_id, args.amount, )); @@ -558,7 +561,7 @@ impl EthConnectorContract { /// ft_on_transfer callback function pub fn ft_on_transfer(&mut self, engine: &Engine, args: &NEP141FtOnTransferArgs) { - crate::log!("Call ft_on_transfer"); + sdk::log!("Call ft_on_transfer"); // Parse message with specific rules let message_data = self.parse_on_transfer_message(&args.msg); @@ -567,7 +570,7 @@ impl EthConnectorContract { // Mint fee to relayer let relayer = engine.get_relayer(message_data.relayer.as_bytes()); match (fee, relayer) { - (fee, Some(crate::prelude::H160(evm_relayer_address))) if fee > 0 => { + (fee, Some(H160(evm_relayer_address))) if fee > 0 => { self.mint_eth_on_aurora(message_data.recipient, args.amount - fee); self.mint_eth_on_aurora(evm_relayer_address, fee); } diff --git a/src/deposit_event.rs b/engine/src/deposit_event.rs similarity index 61% rename from src/deposit_event.rs rename to engine/src/deposit_event.rs index 39c80ecf6..a7af47587 100644 --- a/src/deposit_event.rs +++ b/engine/src/deposit_event.rs @@ -1,13 +1,43 @@ -#[cfg(not(feature = "contract"))] -use crate::prelude::Vec; -use crate::prelude::{vec, String, ToString}; - -use crate::types::*; -use ethabi::{EventParam, ParamType}; -use primitive_types::U256; +use crate::log_entry::LogEntry; +use crate::prelude::{vec, EthAddress, String, ToString, Vec, U256}; +use ethabi::{Event, EventParam, Hash, Log, ParamType, RawLog}; const DEPOSITED_EVENT: &str = "Deposited"; +pub type EventParams = Vec; + +/// Ethereum event +pub struct EthEvent { + pub eth_custodian_address: EthAddress, + pub log: Log, +} + +#[allow(dead_code)] +impl EthEvent { + /// Get Ethereum event from `log_entry_data` + pub fn fetch_log_entry_data(name: &str, params: EventParams, data: &[u8]) -> Self { + let event = Event { + name: name.to_string(), + inputs: params, + anonymous: false, + }; + let log_entry: LogEntry = rlp::decode(data).expect("INVALID_RLP"); + let eth_custodian_address = log_entry.address.0; + let topics = log_entry.topics.iter().map(|h| Hash::from(h.0)).collect(); + + let raw_log = RawLog { + topics, + data: log_entry.data, + }; + let log = event.parse_log(raw_log).expect("Failed to parse event log"); + + Self { + eth_custodian_address, + log, + } + } +} + /// Data that was emitted by Deposited event. #[derive(Debug, PartialEq)] pub struct DepositedEvent { @@ -61,20 +91,4 @@ impl DepositedEvent { fee, } } - - #[cfg(not(feature = "contract"))] - #[allow(dead_code)] - pub fn to_log_entry_data(&self) -> Vec { - EthEvent::params_to_log_entry_data( - DEPOSITED_EVENT, - DepositedEvent::event_params(), - self.eth_custodian_address, - vec![self.sender.to_vec()], - vec![ - ethabi::Token::String(self.recipient.clone()), - ethabi::Token::Uint(self.amount), - ethabi::Token::Uint(self.fee), - ], - ) - } } diff --git a/src/engine.rs b/engine/src/engine.rs similarity index 97% rename from src/engine.rs rename to engine/src/engine.rs index 672411f8d..e336c2f75 100644 --- a/src/engine.rs +++ b/engine/src/engine.rs @@ -1,25 +1,24 @@ -use borsh::{BorshDeserialize, BorshSerialize}; +use crate::parameters::{ + FunctionCallArgs, NEP141FtOnTransferArgs, ResultLog, SubmitResult, ViewCallArgs, +}; use core::mem; use evm::backend::{Apply, ApplyBackend, Backend, Basic, Log}; use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; -use evm::ExitFatal; -use evm::{Config, CreateScheme, ExitError, ExitReason}; +use evm::{Config, CreateScheme, ExitError, ExitFatal, ExitReason}; use crate::connector::EthConnectorContract; #[cfg(feature = "contract")] use crate::contract::current_address; use crate::map::{BijectionMap, LookupMap}; -use crate::parameters::{ - FunctionCallArgs, NEP141FtOnTransferArgs, NewCallArgs, PromiseCreateArgs, ResultLog, - SubmitResult, TransactionStatus, ViewCallArgs, +use crate::prelude::{ + address_to_key, bytes_to_key, is_valid_account_id, sdk, storage_to_key, u256_to_arr, AccountId, + Address, BorshDeserialize, BorshSerialize, KeyPrefix, KeyPrefixU8, PromiseCreateArgs, TryInto, + Vec, Wei, ERC20_MINT_SELECTOR, H256, U256, }; -use crate::precompiles::native::{ExitToEthereum, ExitToNear}; -use crate::precompiles::Precompiles; -use crate::prelude::{is_valid_account_id, Address, Cow, String, TryInto, Vec, H256, U256}; -use crate::sdk; -use crate::storage::{address_to_key, bytes_to_key, storage_to_key, KeyPrefix, KeyPrefixU8}; -use crate::types::{u256_to_arr, AccountId, Wei, ERC20_MINT_SELECTOR}; +use crate::parameters::{NewCallArgs, TransactionStatus}; +use crate::prelude::precompiles::native::{ExitToEthereum, ExitToNear}; +use crate::prelude::precompiles::Precompiles; /// Used as the first byte in the concatenation of data used to compute the blockhash. /// Could be useful in the future as a version byte, or to distinguish different types of blocks. @@ -30,7 +29,7 @@ const CHAIN_ID_SIZE: usize = 32; #[cfg(not(feature = "contract"))] pub fn current_address() -> Address { - crate::types::near_account_to_evm_address("engine".as_bytes()) + sdk::types::near_account_to_evm_address("engine".as_bytes()) } macro_rules! unwrap_res_or_finish { @@ -166,6 +165,7 @@ impl ExitIntoResult for ExitReason { } pub struct BalanceOverflow; + impl AsRef<[u8]> for BalanceOverflow { fn as_ref(&self) -> &[u8] { b"ERR_BALANCE_OVERFLOW" @@ -181,6 +181,7 @@ pub enum GasPaymentError { /// Not enough balance for account to cover the gas cost OutOfFund, } + impl AsRef<[u8]> for GasPaymentError { fn as_ref(&self) -> &[u8] { match self { @@ -190,6 +191,7 @@ impl AsRef<[u8]> for GasPaymentError { } } } + impl From for GasPaymentError { fn from(overflow: BalanceOverflow) -> Self { Self::BalanceOverflow(overflow) @@ -683,7 +685,7 @@ impl Engine { match Self::get_erc20_from_nep141(nep141_token) { Err(GetErc20FromNep141Error::Nep141NotFound) => (), Err(GetErc20FromNep141Error::InvalidNep141AccountId) => { - return Err(RegisterTokenError::InvalidNep141AccountId) + return Err(RegisterTokenError::InvalidNep141AccountId); } Ok(_) => return Err(RegisterTokenError::TokenAlreadyRegistered), } @@ -807,12 +809,12 @@ impl Engine { TransactionStatus::Revert(bytes) => { let error_message = crate::prelude::format!( "Reverted with message: {}", - String::from_utf8_lossy(&bytes) + crate::prelude::String::from_utf8_lossy(&bytes) ); Err(EngineError { - kind: EngineErrorKind::EvmError(ExitError::Other(Cow::from( - error_message, - ))), + kind: EngineErrorKind::EvmError(ExitError::Other( + crate::prelude::Cow::from(error_message), + )), gas_used: submit_result.gas_used, }) } diff --git a/src/fungible_token.rs b/engine/src/fungible_token.rs similarity index 93% rename from src/fungible_token.rs rename to engine/src/fungible_token.rs index de57c10cb..55d8abc99 100644 --- a/src/fungible_token.rs +++ b/engine/src/fungible_token.rs @@ -1,17 +1,11 @@ -use crate::json::JsonValue; -#[cfg(feature = "log")] -use crate::prelude::format; -use crate::prelude::BTreeMap; -use crate::types::*; -use borsh::{BorshDeserialize, BorshSerialize}; -use { - crate::connector, - crate::engine, - crate::json::parse_json, - crate::parameters::*, - crate::prelude::{self, Ordering, String, ToString, TryInto, Vec, U256}, - crate::sdk, - crate::storage, +use crate::connector::NO_DEPOSIT; +use crate::engine::Engine; +use crate::json::{parse_json, JsonValue}; +use crate::parameters::{FtResolveTransfer, NEP141FtOnTransferArgs, StorageBalance}; +use crate::prelude::{ + sdk, storage, str_from_slice, AccountId, Address, BTreeMap, Balance, BorshDeserialize, + BorshSerialize, EthAddress, Gas, Ordering, PromiseResult, StorageBalanceBounds, StorageUsage, + String, ToString, TryInto, Vec, Wei, U256, }; const GAS_FOR_RESOLVE_TRANSFER: Gas = 5_000_000_000_000; @@ -105,9 +99,7 @@ impl FungibleToken { /// Balance of ETH (ETH on Aurora) pub fn internal_unwrap_balance_of_eth_on_aurora(&self, address: EthAddress) -> Balance { - engine::Engine::get_balance(&prelude::Address(address)) - .raw() - .as_u128() + Engine::get_balance(&Address(address)).raw().as_u128() } /// Internal ETH deposit to NEAR - nETH (NEP-141) @@ -128,10 +120,7 @@ impl FungibleToken { pub fn internal_deposit_eth_to_aurora(&mut self, address: EthAddress, amount: Balance) { let balance = self.internal_unwrap_balance_of_eth_on_aurora(address); if let Some(new_balance) = balance.checked_add(amount) { - engine::Engine::set_balance( - &prelude::Address(address), - &Wei::new(U256::from(new_balance)), - ); + Engine::set_balance(&Address(address), &Wei::new(U256::from(new_balance))); self.total_eth_supply_on_aurora = self .total_eth_supply_on_aurora .checked_add(amount) @@ -178,10 +167,7 @@ impl FungibleToken { pub fn internal_withdraw_eth_from_aurora(&mut self, address: EthAddress, amount: Balance) { let balance = self.internal_unwrap_balance_of_eth_on_aurora(address); if let Some(new_balance) = balance.checked_sub(amount) { - engine::Engine::set_balance( - &prelude::Address(address), - &Wei::new(U256::from(new_balance)), - ); + Engine::set_balance(&Address(address), &Wei::new(U256::from(new_balance))); self.total_eth_supply_on_aurora = self .total_eth_supply_on_aurora .checked_sub(amount) @@ -210,13 +196,15 @@ impl FungibleToken { } self.internal_withdraw_eth_from_near(sender_id, amount); self.internal_deposit_eth_to_near(receiver_id, amount); - crate::log!(&format!( + sdk::log!(&crate::prelude::format!( "Transfer {} from {} to {}", - amount, sender_id, receiver_id + amount, + sender_id, + receiver_id )); #[cfg(feature = "log")] if let Some(memo) = memo { - sdk::log(&format!("Memo: {}", memo)); + sdk::log(&crate::prelude::format!("Memo: {}", memo)); } } @@ -281,7 +269,7 @@ impl FungibleToken { receiver_id.as_bytes(), b"ft_on_transfer", data1.as_bytes(), - connector::NO_DEPOSIT, + NO_DEPOSIT, GAS_FOR_FT_ON_TRANSFER, ); let promise1 = sdk::promise_then( @@ -289,7 +277,7 @@ impl FungibleToken { &sdk::current_account_id(), b"ft_resolve_transfer", &data2[..], - connector::NO_DEPOSIT, + NO_DEPOSIT, GAS_FOR_RESOLVE_TRANSFER, ); sdk::promise_return(promise1); @@ -334,7 +322,7 @@ impl FungibleToken { receiver_balance }; self.accounts_insert(receiver_id, receiver_balance - refund_amount); - crate::log!(&format!( + sdk::log!(&crate::prelude::format!( "Decrease receiver {} balance to: {}", receiver_id, receiver_balance - refund_amount @@ -343,15 +331,17 @@ impl FungibleToken { return if let Some(sender_balance) = self.accounts_get(sender_id) { let sender_balance = u128::try_from_slice(&sender_balance[..]).unwrap(); self.accounts_insert(sender_id, sender_balance + refund_amount); - crate::log!(&format!( + sdk::log!(&crate::prelude::format!( "Refund amount {} from {} to {}", - refund_amount, receiver_id, sender_id + refund_amount, + receiver_id, + sender_id )); (amount - refund_amount, 0) } else { // Sender's account was deleted, so we need to burn tokens. self.total_eth_supply_on_near -= refund_amount; - crate::log!("The account of the sender was deleted"); + sdk::log!("The account of the sender was deleted"); (amount, refund_amount) }; } @@ -390,7 +380,10 @@ impl FungibleToken { sdk::panic_utf8(b"ERR_FAILED_UNREGISTER_ACCOUNT_POSITIVE_BALANCE") } } else { - crate::log!(&format!("The account {} is not registered", &account_id)); + sdk::log!(&crate::prelude::format!( + "The account {} is not registered", + &account_id + )); None } } @@ -431,7 +424,7 @@ impl FungibleToken { let predecessor_account_id = String::from_utf8(sdk::predecessor_account_id()).unwrap(); let account_id = account_id.unwrap_or(&predecessor_account_id); if self.accounts_contains_key(account_id) { - crate::log!("The account is already registered, refunding the deposit"); + sdk::log!("The account is already registered, refunding the deposit"); if amount > 0 { let promise0 = sdk::promise_batch_create(&sdk::predecessor_account_id()); sdk::promise_batch_action_transfer(promise0, amount); @@ -517,8 +510,8 @@ impl FungibleToken { /// Key for store contract statistics data fn get_statistic_key() -> Vec { storage::bytes_to_key( - storage::KeyPrefix::EthConnector, - &[storage::EthConnectorStorageId::StatisticsAuroraAccountsCounter as u8], + crate::prelude::storage::KeyPrefix::EthConnector, + &[crate::prelude::EthConnectorStorageId::StatisticsAuroraAccountsCounter as u8], ) } } diff --git a/src/json.rs b/engine/src/json.rs similarity index 99% rename from src/json.rs rename to engine/src/json.rs index 242699d73..7d5bc5a2c 100644 --- a/src/json.rs +++ b/engine/src/json.rs @@ -1,9 +1,7 @@ -use super::prelude::*; +use crate::prelude::{BTreeMap, String, TryFrom, TryInto, Vec}; use core::convert::From; use rjson::{Array, Null, Object, Value}; -#[cfg(test)] -use std::collections::BTreeMap; #[derive(PartialEq)] pub enum JsonValue { diff --git a/src/lib.rs b/engine/src/lib.rs similarity index 93% rename from src/lib.rs rename to engine/src/lib.rs index bf8ec9a39..cf2bfccc1 100644 --- a/src/lib.rs +++ b/engine/src/lib.rs @@ -3,39 +3,29 @@ #![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] #![cfg_attr(feature = "log", feature(panic_info_message))] +use aurora_engine_types::parameters::PromiseCreateArgs; + #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(not(feature = "std"))] extern crate core; -use crate::parameters::PromiseCreateArgs; - mod map; #[cfg(feature = "meta-call")] pub mod meta_parsing; pub mod parameters; -pub mod prelude; -pub mod storage; +pub mod proof; pub mod transaction; -pub mod types; -mod admin_controlled; -#[cfg_attr(not(feature = "contract"), allow(dead_code))] -mod connector; +pub mod admin_controlled; +#[cfg_attr(feature = "contract", allow(dead_code))] +pub mod connector; mod deposit_event; pub mod engine; -mod fungible_token; -mod json; +pub mod fungible_token; +pub mod json; mod log_entry; -mod precompiles; -pub mod sdk; - -#[cfg(test)] -mod benches; -#[cfg(test)] -mod test_utils; -#[cfg(test)] -mod tests; +mod prelude; #[cfg(target_arch = "wasm32")] #[global_allocator] @@ -48,16 +38,17 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; pub unsafe fn on_panic(info: &::core::panic::PanicInfo) -> ! { #[cfg(feature = "log")] { - use alloc::{format, string::ToString}; + use prelude::ToString; + if let Some(msg) = info.message() { let msg = if let Some(log) = info.location() { - format!("{} [{}]", msg, log) + prelude::format!("{} [{}]", msg, log) } else { msg.to_string() }; - sdk::panic_utf8(msg.as_bytes()); + prelude::sdk::panic_utf8(msg.as_bytes()); } else if let Some(log) = info.location() { - sdk::panic_utf8(log.to_string().as_bytes()); + prelude::sdk::panic_utf8(log.to_string().as_bytes()); } } @@ -81,20 +72,19 @@ mod contract { #[cfg(feature = "evm_bully")] use crate::parameters::{BeginBlockArgs, BeginChainArgs}; use crate::parameters::{ - DeployErc20TokenArgs, ExpectUtf8, FunctionCallArgs, GetErc20FromNep141CallArgs, - GetStorageAtArgs, InitCallArgs, IsUsedProofCallArgs, NEP141FtOnTransferArgs, NewCallArgs, + DeployErc20TokenArgs, FunctionCallArgs, GetErc20FromNep141CallArgs, GetStorageAtArgs, + InitCallArgs, IsUsedProofCallArgs, NEP141FtOnTransferArgs, NewCallArgs, PauseEthConnectorCallArgs, SetContractDataCallArgs, SubmitResult, TransactionStatus, TransferCallCallArgs, ViewCallArgs, }; use crate::json::parse_json; - use crate::prelude::{Address, ToString, TryInto, H160, H256, U256}; - use crate::sdk; - use crate::storage::{bytes_to_key, KeyPrefix}; - use crate::types::{ - near_account_to_evm_address, u256_to_arr, SdkExpect, SdkProcess, SdkUnwrap, - ERR_FAILED_PARSE, + use crate::prelude::sdk::types::{ + near_account_to_evm_address, SdkExpect, SdkProcess, SdkUnwrap, }; + use crate::prelude::storage::{bytes_to_key, KeyPrefix}; + use crate::prelude::types::{u256_to_arr, ERR_FAILED_PARSE}; + use crate::prelude::{sdk, Address, ToString, TryFrom, TryInto, H160, H256, U256}; const CODE_KEY: &[u8; 4] = b"CODE"; const CODE_STAGE_KEY: &[u8; 10] = b"CODE_STAGE"; @@ -121,7 +111,7 @@ mod contract { pub extern "C" fn get_version() { let version = match option_env!("NEAR_EVM_VERSION") { Some(v) => v.as_bytes(), - None => include_bytes!("../VERSION"), + None => include_bytes!("../../VERSION"), }; sdk::return_output(version) } @@ -176,7 +166,7 @@ mod contract { sdk::self_deploy(&bytes_to_key(KeyPrefix::Config, CODE_KEY)); } - /// Called as part of the upgrade process (see `sdk::self_deploy`). This function is meant + /// Called as part of the upgrade process (see `engine-sdk::self_deploy`). This function is meant /// to make any necessary changes to the state such that it aligns with the newly deployed /// code. #[no_mangle] @@ -214,7 +204,6 @@ mod contract { /// Must match CHAIN_ID to make sure it's signed for given chain vs replayed from another chain. #[no_mangle] pub extern "C" fn submit() { - use crate::prelude::TryFrom; use crate::transaction::EthTransaction; let input = sdk::read_input(); @@ -383,7 +372,8 @@ mod contract { let mut engine = Engine::new(predecessor_address()).sdk_unwrap(); let erc20_admin_address = current_address(); - let erc20_contract = include_bytes!("../etc/eth-contracts/res/EvmErc20.bin"); + let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20.bin"); + let deploy_args = ethabi::encode(&[ ethabi::Token::String("Empty".to_string()), ethabi::Token::String("EMPTY".to_string()), @@ -402,9 +392,7 @@ mod contract { Err(e) => sdk::panic_utf8(e.as_ref()), }; - crate::log!( - crate::prelude::format!("Deployed ERC-20 in Aurora at: {:#?}", address).as_str() - ); + sdk::log!(crate::prelude::format!("Deployed ERC-20 in Aurora at: {:#?}", address).as_str()); engine .register_token(address.as_bytes(), args.nep141.as_bytes()) .sdk_unwrap(); @@ -416,7 +404,6 @@ mod contract { /// /// NONMUTATIVE METHODS /// - #[no_mangle] pub extern "C" fn view() { let args: ViewCallArgs = sdk::read_input_borsh().sdk_unwrap(); @@ -458,7 +445,6 @@ mod contract { /// /// BENCHMARKING METHODS /// - #[cfg(feature = "evm_bully")] #[no_mangle] pub extern "C" fn begin_chain() { @@ -471,7 +457,7 @@ mod contract { for account_balance in args.genesis_alloc { Engine::set_balance( &Address(account_balance.address), - &crate::types::Wei::new(U256::from(account_balance.balance)), + &crate::prelude::types::Wei::new(U256::from(account_balance.balance)), ) } // return new chain ID @@ -569,6 +555,7 @@ mod contract { #[no_mangle] pub extern "C" fn ft_transfer_call() { + use sdk::types::ExpectUtf8; // Check is payable sdk::assert_one_yocto(); @@ -648,7 +635,7 @@ mod contract { #[cfg(feature = "integration-test")] #[no_mangle] pub extern "C" fn verify_log_entry() { - crate::log!("Call from verify_log_entry"); + sdk::log!("Call from verify_log_entry"); let data = true.try_to_vec().unwrap(); sdk::return_output(&data[..]); } diff --git a/src/log_entry.rs b/engine/src/log_entry.rs similarity index 92% rename from src/log_entry.rs rename to engine/src/log_entry.rs index bf93a4bba..da6db7a43 100644 --- a/src/log_entry.rs +++ b/engine/src/log_entry.rs @@ -1,5 +1,4 @@ -use crate::prelude::Vec; -use primitive_types::{H160, H256}; +use crate::prelude::{Vec, H160, H256}; #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct LogEntry { diff --git a/src/map.rs b/engine/src/map.rs similarity index 88% rename from src/map.rs rename to engine/src/map.rs index 5f2d0066c..c08ce18be 100644 --- a/src/map.rs +++ b/engine/src/map.rs @@ -1,8 +1,4 @@ -use crate::prelude::Vec; -use borsh::{BorshDeserialize, BorshSerialize}; - -use crate::sdk; -use crate::storage::{bytes_to_key, KeyPrefixU8}; +pub use crate::prelude::{bytes_to_key, BorshDeserialize, BorshSerialize, KeyPrefixU8, Vec}; /// An non-iterable implementation of a map that stores its content directly on the trie. /// Use `key_prefix` as a unique prefix for keys. @@ -24,20 +20,20 @@ impl LookupMap { #[allow(dead_code)] pub fn contains_key_raw(&self, key_raw: &[u8]) -> bool { let storage_key = self.raw_key_to_storage_key(key_raw); - sdk::storage_has_key(&storage_key) + crate::prelude::sdk::storage_has_key(&storage_key) } /// Returns the serialized value corresponding to the serialized key. #[allow(dead_code)] pub fn get_raw(&self, key_raw: &[u8]) -> Option> { let storage_key = self.raw_key_to_storage_key(key_raw); - sdk::read_storage(&storage_key) + crate::prelude::sdk::read_storage(&storage_key) } /// Inserts a serialized key-value pair into the map. pub fn insert_raw(&mut self, key_raw: &[u8], value_raw: &[u8]) { let storage_key = self.raw_key_to_storage_key(key_raw); - sdk::write_storage(&storage_key, value_raw); + crate::prelude::sdk::write_storage(&storage_key, value_raw); } /// Removes a serialized key from the map, returning the serialized value at the key if the key @@ -45,7 +41,7 @@ impl LookupMap { #[allow(dead_code)] pub fn remove_raw(&mut self, key_raw: &[u8]) -> Option> { let storage_key = self.raw_key_to_storage_key(key_raw); - sdk::remove_storage_with_result(&storage_key) + crate::prelude::sdk::remove_storage_with_result(&storage_key) } } diff --git a/src/meta_parsing.rs b/engine/src/meta_parsing.rs similarity index 98% rename from src/meta_parsing.rs rename to engine/src/meta_parsing.rs index 95d2e7734..269ae454c 100644 --- a/src/meta_parsing.rs +++ b/engine/src/meta_parsing.rs @@ -1,12 +1,13 @@ -use borsh::BorshDeserialize; +use crate::parameters::MetaCallArgs; +use crate::prelude::precompiles::secp256k1::ecrecover; +use crate::prelude::{ + keccak, u256_to_arr, vec, Address, BorshDeserialize, Box, HashMap, InternalMetaCallArgs, + RawU256, String, ToOwned, ToString, Vec, Wei, H256, U256, +}; use ethabi::{encode, Token as ABIToken}; use logos::Logos; use rlp::{Decodable, DecoderError, Rlp}; -use crate::parameters::MetaCallArgs; -use crate::prelude::{vec, Address, Box, HashMap, String, ToOwned, ToString, Vec, H256, U256}; -use crate::types::{keccak, u256_to_arr, InternalMetaCallArgs, RawU256, Wei}; - /// Internal errors to propagate up and format in the single place. pub enum ParsingError { ArgumentParseError, @@ -163,6 +164,7 @@ pub fn encode_address(addr: Address) -> Vec { bytes } +#[allow(dead_code)] pub fn encode_string(s: &str) -> Vec { let mut bytes = vec![]; bytes.extend_from_slice(keccak(s.as_bytes()).as_bytes()); @@ -594,7 +596,7 @@ pub fn parse_meta_call( let mut signature: [u8; 65] = [0; 65]; signature[64] = meta_tx.v; signature[..64].copy_from_slice(&meta_tx.signature); - match crate::precompiles::ecrecover(H256::from_slice(&msg), &signature) { + match ecrecover(H256::from_slice(&msg), &signature) { Ok(sender) => { result.sender = sender; result.input = input; diff --git a/src/parameters.rs b/engine/src/parameters.rs similarity index 83% rename from src/parameters.rs rename to engine/src/parameters.rs index 214d3d541..706533438 100644 --- a/src/parameters.rs +++ b/engine/src/parameters.rs @@ -1,15 +1,11 @@ -use borsh::{BorshDeserialize, BorshSerialize}; - +use crate::admin_controlled::PausedMask; use crate::fungible_token::FungibleTokenMetadata; -use crate::prelude::{String, Vec}; -use crate::types::{AccountId, Balance, RawAddress, RawH256, RawU256}; -use crate::{ - admin_controlled::PausedMask, - json, - prelude::{is_valid_account_id, ToString, TryFrom}, - sdk, - types::{EthAddress, Proof, SdkUnwrap}, +use crate::json::{JsonError, JsonValue, ParseError}; +use crate::prelude::{ + format, is_valid_account_id, AccountId, Balance, BorshDeserialize, BorshSerialize, EthAddress, + RawAddress, RawH256, RawU256, SdkUnwrap, String, ToString, TryFrom, Vec, }; +use crate::proof::Proof; use evm::backend::Log; /// Borsh-encoded parameters for the `new` function. @@ -186,10 +182,10 @@ pub struct NEP141FtOnTransferArgs { pub msg: String, } -impl TryFrom for NEP141FtOnTransferArgs { - type Error = json::JsonError; +impl TryFrom for NEP141FtOnTransferArgs { + type Error = JsonError; - fn try_from(value: json::JsonValue) -> Result { + fn try_from(value: JsonValue) -> Result { Ok(Self { sender_id: value.string("sender_id")?, amount: value.u128("amount")?, @@ -199,14 +195,14 @@ impl TryFrom for NEP141FtOnTransferArgs { } impl TryFrom for String { - type Error = json::ParseError; + type Error = ParseError; fn try_from(value: NEP141FtOnTransferArgs) -> Result { if !is_valid_account_id(value.sender_id.as_bytes()) { - return Err(json::ParseError::InvalidAccountId); + return Err(ParseError::InvalidAccountId); } - Ok(crate::prelude::format!( + Ok(format!( r#"{{"sender_id": "{}", "amount": "{}", "msg": "{}"}}"#, value.sender_id, value.amount, @@ -216,14 +212,6 @@ impl TryFrom for String { } } -#[derive(Debug, BorshSerialize, BorshDeserialize)] -pub struct PromiseCreateArgs { - pub target_account_id: AccountId, - pub method: String, - pub args: Vec, - pub attached_balance: u128, - pub attached_gas: u64, -} /// Eth-connector deposit arguments #[derive(BorshSerialize, BorshDeserialize)] pub struct DepositCallArgs { @@ -266,7 +254,7 @@ pub struct StorageBalance { impl StorageBalance { pub fn to_json_bytes(&self) -> Vec { - crate::prelude::format!( + format!( "{{\"total\": \"{}\", \"available\": \"{}\"}}", self.total.to_string(), self.available.to_string() @@ -332,8 +320,8 @@ pub struct TransferCallCallArgs { pub msg: String, } -impl From for TransferCallCallArgs { - fn from(v: json::JsonValue) -> Self { +impl From for TransferCallCallArgs { + fn from(v: JsonValue) -> Self { Self { receiver_id: v.string("receiver_id").sdk_unwrap(), amount: v.u128("amount").sdk_unwrap(), @@ -349,8 +337,8 @@ pub struct StorageBalanceOfCallArgs { pub account_id: AccountId, } -impl From for StorageBalanceOfCallArgs { - fn from(v: json::JsonValue) -> Self { +impl From for StorageBalanceOfCallArgs { + fn from(v: JsonValue) -> Self { Self { account_id: v.string("account_id").sdk_unwrap(), } @@ -364,8 +352,8 @@ pub struct StorageDepositCallArgs { pub registration_only: Option, } -impl From for StorageDepositCallArgs { - fn from(v: json::JsonValue) -> Self { +impl From for StorageDepositCallArgs { + fn from(v: JsonValue) -> Self { Self { account_id: v.string("account_id").ok(), registration_only: v.bool("registration_only").ok(), @@ -379,8 +367,8 @@ pub struct StorageWithdrawCallArgs { pub amount: Option, } -impl From for StorageWithdrawCallArgs { - fn from(v: json::JsonValue) -> Self { +impl From for StorageWithdrawCallArgs { + fn from(v: JsonValue) -> Self { Self { amount: v.u128("amount").ok(), } @@ -395,8 +383,8 @@ pub struct TransferCallArgs { pub memo: Option, } -impl From for TransferCallArgs { - fn from(v: json::JsonValue) -> Self { +impl From for TransferCallArgs { + fn from(v: JsonValue) -> Self { Self { receiver_id: v.string("receiver_id").sdk_unwrap(), amount: v.u128("amount").sdk_unwrap(), @@ -405,13 +393,6 @@ impl From for TransferCallArgs { } } -/// withdraw NEAR eth-connector call args -#[derive(BorshSerialize, BorshDeserialize)] -pub struct WithdrawCallArgs { - pub recipient_address: EthAddress, - pub amount: Balance, -} - /// balance_of args for json invocation #[derive(BorshSerialize, BorshDeserialize)] pub struct BalanceOfCallArgs { @@ -423,8 +404,8 @@ pub struct BalanceOfEthCallArgs { pub address: EthAddress, } -impl From for BalanceOfCallArgs { - fn from(v: json::JsonValue) -> Self { +impl From for BalanceOfCallArgs { + fn from(v: JsonValue) -> Self { Self { account_id: v.string("account_id").sdk_unwrap(), } @@ -441,30 +422,8 @@ pub struct PauseEthConnectorCallArgs { pub paused_mask: PausedMask, } -pub trait ExpectUtf8 { - fn expect_utf8(self, message: &[u8]) -> T; -} - -impl ExpectUtf8 for Option { - fn expect_utf8(self, message: &[u8]) -> T { - match self { - Some(t) => t, - None => sdk::panic_utf8(message), - } - } -} - -impl ExpectUtf8 for core::result::Result { - fn expect_utf8(self, message: &[u8]) -> T { - match self { - Ok(t) => t, - Err(_) => sdk::panic_utf8(message), - } - } -} - -impl From for ResolveTransferCallArgs { - fn from(v: json::JsonValue) -> Self { +impl From for ResolveTransferCallArgs { + fn from(v: JsonValue) -> Self { Self { sender_id: v.string("sender_id").sdk_unwrap(), receiver_id: v.string("receiver_id").sdk_unwrap(), diff --git a/engine/src/prelude.rs b/engine/src/prelude.rs new file mode 100644 index 000000000..46bfd2bc8 --- /dev/null +++ b/engine/src/prelude.rs @@ -0,0 +1,11 @@ +mod v0 { + pub use aurora_engine_precompiles as precompiles; + pub use aurora_engine_sdk as sdk; + pub use aurora_engine_sdk::types::*; + pub use aurora_engine_types::parameters::*; + pub use aurora_engine_types::storage::*; + pub use aurora_engine_types::types::*; + pub use aurora_engine_types::*; + pub use borsh::{BorshDeserialize, BorshSerialize}; +} +pub use v0::*; diff --git a/engine/src/proof.rs b/engine/src/proof.rs new file mode 100644 index 000000000..4c972e7c6 --- /dev/null +++ b/engine/src/proof.rs @@ -0,0 +1,25 @@ +use crate::prelude::{sdk, BorshDeserialize, BorshSerialize, String, ToString, Vec}; + +#[derive(Default, BorshDeserialize, BorshSerialize, Clone)] +#[cfg_attr(test, derive(serde::Deserialize, serde::Serialize))] +pub struct Proof { + pub log_index: u64, + pub log_entry_data: Vec, + pub receipt_index: u64, + pub receipt_data: Vec, + pub header_data: Vec, + pub proof: Vec>, +} + +impl Proof { + pub fn get_key(&self) -> String { + let mut data = self.log_index.try_to_vec().unwrap(); + data.extend(self.receipt_index.try_to_vec().unwrap()); + data.extend(self.header_data.clone()); + sdk::sha256(&data[..]) + .0 + .iter() + .map(|n| n.to_string()) + .collect() + } +} diff --git a/src/transaction/access_list.rs b/engine/src/transaction/access_list.rs similarity index 95% rename from src/transaction/access_list.rs rename to engine/src/transaction/access_list.rs index 88312cfa6..86ff681d5 100644 --- a/src/transaction/access_list.rs +++ b/engine/src/transaction/access_list.rs @@ -1,5 +1,5 @@ -use crate::prelude::{Address, Vec, H256, U256}; -use crate::types::Wei; +use crate::prelude::precompiles::secp256k1::ecrecover; +use crate::prelude::{sdk, Address, Vec, Wei, H256, U256}; use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; /// Type indicator (per EIP-2718) for access list transactions @@ -90,8 +90,8 @@ impl AccessListEthSignedTransaction { let mut rlp_stream = RlpStream::new(); rlp_stream.append(&TYPE_BYTE); self.transaction_data.rlp_append_unsigned(&mut rlp_stream); - let message_hash = crate::types::keccak(rlp_stream.as_raw()); - crate::precompiles::ecrecover( + let message_hash = sdk::keccak(rlp_stream.as_raw()); + ecrecover( message_hash, &super::vrs_to_arr(self.parity, self.r, self.s), ) diff --git a/src/transaction/legacy.rs b/engine/src/transaction/legacy.rs similarity index 96% rename from src/transaction/legacy.rs rename to engine/src/transaction/legacy.rs index 3dac15317..93bc00a6b 100644 --- a/src/transaction/legacy.rs +++ b/engine/src/transaction/legacy.rs @@ -1,5 +1,5 @@ -use crate::prelude::{Address, Vec, U256}; -use crate::types::Wei; +use crate::prelude::precompiles::secp256k1::ecrecover; +use crate::prelude::{sdk, Address, Vec, Wei, U256}; use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; #[derive(Debug, Eq, PartialEq, Clone)] @@ -43,6 +43,7 @@ impl LegacyEthTransaction { } /// Returns self.gas as a u64, or None if self.gas > u64::MAX + #[allow(unused)] pub fn get_gas_limit(&self) -> Option { use crate::prelude::TryInto; self.gas.try_into().ok() @@ -75,8 +76,8 @@ impl LegacyEthSignedTransaction { }; self.transaction .rlp_append_unsigned(&mut rlp_stream, chain_id); - let message_hash = crate::types::keccak(rlp_stream.as_raw()); - crate::precompiles::ecrecover(message_hash, &super::vrs_to_arr(rec_id, self.r, self.s)).ok() + let message_hash = sdk::keccak(rlp_stream.as_raw()); + ecrecover(message_hash, &super::vrs_to_arr(rec_id, self.r, self.s)).ok() } /// Returns chain id encoded in `v` parameter of the signature if that was done, otherwise None. @@ -140,7 +141,6 @@ impl Decodable for LegacyEthSignedTransaction { #[cfg(test)] mod tests { use super::*; - use crate::prelude::*; #[test] fn test_eth_signed_no_chain_sender() { diff --git a/src/transaction/mod.rs b/engine/src/transaction/mod.rs similarity index 99% rename from src/transaction/mod.rs rename to engine/src/transaction/mod.rs index 18a8e378f..a782f1373 100644 --- a/src/transaction/mod.rs +++ b/engine/src/transaction/mod.rs @@ -1,7 +1,7 @@ use crate::prelude::{Address, TryFrom, Vec, U256}; use rlp::{Decodable, DecoderError, Rlp}; -pub(crate) mod access_list; +pub mod access_list; pub(crate) mod legacy; use access_list::AccessTuple; @@ -60,7 +60,7 @@ impl EthTransaction { pub fn destructure( self, ) -> ( - crate::types::Wei, + crate::prelude::Wei, Option, Vec, Option
, diff --git a/etc/state-migration-test/Cargo.lock b/etc/state-migration-test/Cargo.lock index 029c32bf5..46f67c003 100644 --- a/etc/state-migration-test/Cargo.lock +++ b/etc/state-migration-test/Cargo.lock @@ -31,9 +31,12 @@ dependencies = [ [[package]] name = "aurora-engine" -version = "1.6.3" +version = "1.7.0" dependencies = [ "aurora-bn", + "aurora-engine-precompiles", + "aurora-engine-sdk", + "aurora-engine-types", "base64", "blake2", "borsh", @@ -54,14 +57,63 @@ dependencies = [ "wee_alloc", ] +[[package]] +name = "aurora-engine-precompiles" +version = "1.0.0" +dependencies = [ + "aurora-bn", + "aurora-engine-sdk", + "aurora-engine-types", + "base64", + "blake2", + "borsh", + "byte-slice-cast", + "ethabi", + "evm", + "evm-core", + "hex", + "libsecp256k1", + "logos", + "num", + "primitive-types", + "ripemd160", + "rjson", + "rlp", + "sha2", + "sha3 0.9.1", + "wee_alloc", +] + +[[package]] +name = "aurora-engine-sdk" +version = "1.0.0" +dependencies = [ + "aurora-engine-types", + "borsh", + "sha3 0.9.1", +] + [[package]] name = "aurora-engine-state-migration-test" version = "1.0.0" dependencies = [ "aurora-engine", + "aurora-engine-sdk", + "aurora-engine-types", "borsh", ] +[[package]] +name = "aurora-engine-types" +version = "1.0.0" +dependencies = [ + "borsh", + "ethabi", + "hex", + "primitive-types", + "sha3 0.9.1", +] + [[package]] name = "autocfg" version = "1.0.1" diff --git a/etc/state-migration-test/Cargo.toml b/etc/state-migration-test/Cargo.toml index de0f11f77..b5a5ab5c1 100644 --- a/etc/state-migration-test/Cargo.toml +++ b/etc/state-migration-test/Cargo.toml @@ -38,4 +38,6 @@ rpath = false [dependencies] borsh = { version = "0.8.2", default-features = false } -aurora-engine = { path = "../../", default-features = false, features = ["sha2"] } +aurora-engine = { path = "../../engine", default-features = false, features = ["sha2"] } +aurora-engine-sdk = { path = "../../engine-sdk", default-features = false } +aurora-engine-types = { path = "../../engine-types", default-features = false } diff --git a/etc/state-migration-test/src/lib.rs b/etc/state-migration-test/src/lib.rs index 89782d496..8f949be4b 100644 --- a/etc/state-migration-test/src/lib.rs +++ b/etc/state-migration-test/src/lib.rs @@ -4,7 +4,8 @@ extern crate alloc; use alloc::vec::Vec; use aurora_engine::engine::{Engine, EngineState}; -use aurora_engine::{sdk, storage}; +use aurora_engine_sdk as sdk; +use aurora_engine_types::storage; use borsh::{BorshDeserialize, BorshSerialize}; #[derive(BorshDeserialize, BorshSerialize)] From a0a0bb18dc5427814b45f9b20198cb529a254067 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Thu, 23 Sep 2021 09:12:05 -0400 Subject: [PATCH 5/9] Fix json formatting in JsonValue serialization (#279) --- engine/src/json.rs | 104 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 8 deletions(-) diff --git a/engine/src/json.rs b/engine/src/json.rs index 7d5bc5a2c..81616c2fd 100644 --- a/engine/src/json.rs +++ b/engine/src/json.rs @@ -235,15 +235,35 @@ impl TryFrom<&JsonValue> for u128 { impl core::fmt::Debug for JsonValue { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - match *self { + match self { JsonValue::Null => f.write_str("null"), - JsonValue::String(ref v) => f.write_fmt(format_args!("\"{}\"", v)), - JsonValue::F64(ref v) => f.write_fmt(format_args!("{}", v)), - JsonValue::I64(ref v) => f.write_fmt(format_args!("{}", v)), - JsonValue::U64(ref v) => f.write_fmt(format_args!("{}", v)), - JsonValue::Bool(ref v) => f.write_fmt(format_args!("{}", v)), - JsonValue::Array(ref v) => f.write_fmt(format_args!("{:?}", v)), - JsonValue::Object(ref v) => f.write_fmt(format_args!("{:#?}", v)), + JsonValue::String(v) => f.write_fmt(format_args!("\"{}\"", v)), + JsonValue::F64(v) => f.write_fmt(format_args!("{}", v)), + JsonValue::I64(v) => f.write_fmt(format_args!("{}", v)), + JsonValue::U64(v) => f.write_fmt(format_args!("{}", v)), + JsonValue::Bool(v) => f.write_fmt(format_args!("{}", v)), + JsonValue::Array(arr) => { + f.write_str("[")?; + let mut items = arr.iter(); + if let Some(item) = items.next() { + f.write_fmt(format_args!("{:?}", item))?; + } + for item in items { + f.write_fmt(format_args!(", {:?}", item))?; + } + f.write_str("]") + } + JsonValue::Object(kvs) => { + f.write_str("{")?; + let mut pairs = kvs.iter(); + if let Some((key, value)) = pairs.next() { + f.write_fmt(format_args!("\"{}\": {:?}", key, value))?; + } + for (key, value) in pairs { + f.write_fmt(format_args!(", \"{}\": {:?}", key, value))?; + } + f.write_str("}") + } } } } @@ -467,4 +487,72 @@ mod tests { let err = JsonValue::parse_u8(&json).unwrap_err(); assert_eq!(err, JsonError::InvalidU8); } + + #[test] + fn test_json_serialization() { + // Test showing valid json (without trailing commas) is produced from the + // `Display` impl on `JsonValue`. + + // empty object + let object = JsonValue::Object(BTreeMap::new()); + assert_eq!(&format!("{}", object), "{}"); + + // object with 1 field + let object = JsonValue::Object( + vec![("pi".to_string(), JsonValue::F64(std::f64::consts::PI))] + .into_iter() + .collect(), + ); + assert_eq!(&format!("{}", object), "{\"pi\": 3.141592653589793}"); + + // object with 2 fields + let object = JsonValue::Object( + vec![ + ("pi".to_string(), JsonValue::F64(std::f64::consts::PI)), + ("Pie".to_string(), JsonValue::String("Apple".to_string())), + ] + .into_iter() + .collect(), + ); + assert_eq!( + &format!("{}", object), + "{\"Pie\": \"Apple\", \"pi\": 3.141592653589793}" + ); + + // object with empty array + let object = JsonValue::Object( + vec![("empty".to_string(), JsonValue::Array(vec![]))] + .into_iter() + .collect(), + ); + assert_eq!(&format!("{}", object), "{\"empty\": []}"); + + // object with single element array + let object = JsonValue::Object( + vec![( + "numbers".to_string(), + JsonValue::Array(vec![JsonValue::U64(42)]), + )] + .into_iter() + .collect(), + ); + assert_eq!(&format!("{}", object), "{\"numbers\": [42]}"); + + // object with two-element array + let object = JsonValue::Object( + vec![( + "words".to_string(), + JsonValue::Array(vec![ + JsonValue::String("Hello".to_string()), + JsonValue::String("World".to_string()), + ]), + )] + .into_iter() + .collect(), + ); + assert_eq!( + &format!("{}", object), + "{\"words\": [\"Hello\", \"World\"]}" + ); + } } From 4ddad354dfc7c2f341e6c01d3b0c06279130148d Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Thu, 23 Sep 2021 09:13:02 -0400 Subject: [PATCH 6/9] Update primitive-types dependency to 0.10 (#280) --- Cargo.lock | 80 +++++++++++++++++------------ engine-precompiles/Cargo.toml | 6 +-- engine-tests/Cargo.toml | 2 +- engine-types/Cargo.toml | 2 +- engine/Cargo.toml | 6 +-- etc/state-migration-test/Cargo.lock | 34 ++++++------ 6 files changed, 72 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5cc94c990..d086916f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,9 +49,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" +checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" [[package]] name = "arrayref" @@ -132,7 +132,7 @@ dependencies = [ "libsecp256k1", "logos", "num", - "primitive-types 0.9.0", + "primitive-types 0.10.1", "rand 0.7.3", "ripemd160", "rjson", @@ -162,7 +162,7 @@ dependencies = [ "libsecp256k1", "logos", "num", - "primitive-types 0.9.0", + "primitive-types 0.10.1", "rand 0.7.3", "ripemd160", "rjson", @@ -222,7 +222,7 @@ dependencies = [ "bstr", "ethabi", "hex", - "primitive-types 0.9.0", + "primitive-types 0.10.1", "rand 0.7.3", "serde", "serde_json", @@ -1234,11 +1234,11 @@ dependencies = [ [[package]] name = "ethabi" -version = "13.0.0" -source = "git+https://github.com/darwinia-network/ethabi?branch=xavier-no-std#baacf174d5c2f12122c4ee3fe31506fb52069983" +version = "14.1.0" +source = "git+https://github.com/darwinia-network/ethabi?branch=xavier-no-std#09da0834d95f8b43377ca22d7b1c97a2401f4b0c" dependencies = [ "anyhow", - "ethereum-types", + "ethereum-types 0.12.0", "hex", "serde", "serde_json", @@ -1262,12 +1262,12 @@ dependencies = [ [[package]] name = "ethereum" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567ce064a8232c16e2b2c2173a936b91fbe35c2f2c5278871f5a1a31688b42e9" +checksum = "42ccff962ede8fe7c3ec53d46b8316f3c53377a701a30c0325918b38ce04a497" dependencies = [ - "ethereum-types", - "funty", + "bytes", + "ethereum-types 0.12.0", "hash-db", "hash256-std-hasher", "parity-scale-codec", @@ -1292,6 +1292,19 @@ dependencies = [ "uint", ] +[[package]] +name = "ethereum-types" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd6bde671199089e601e8d47e153368b893ef885f11f365a3261ec58153c211" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "primitive-types 0.10.1", + "uint", +] + [[package]] name = "event-listener" version = "2.5.1" @@ -1301,7 +1314,7 @@ checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" [[package]] name = "evm" version = "0.30.1" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?rev=01e000cbf081dada77ac6b325a6521341044d970#01e000cbf081dada77ac6b325a6521341044d970" +source = "git+https://github.com/aurora-is-near/sputnikvm.git#5ecf36ce393380a89c6f1b09ef79f686fe043624" dependencies = [ "environmental", "ethereum", @@ -1310,7 +1323,7 @@ dependencies = [ "evm-runtime", "log", "parity-scale-codec", - "primitive-types 0.9.0", + "primitive-types 0.10.1", "rlp", "serde", "sha3 0.8.2", @@ -1319,33 +1332,33 @@ dependencies = [ [[package]] name = "evm-core" version = "0.30.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?rev=01e000cbf081dada77ac6b325a6521341044d970#01e000cbf081dada77ac6b325a6521341044d970" +source = "git+https://github.com/aurora-is-near/sputnikvm.git#5ecf36ce393380a89c6f1b09ef79f686fe043624" dependencies = [ "funty", "parity-scale-codec", - "primitive-types 0.9.0", + "primitive-types 0.10.1", "serde", ] [[package]] name = "evm-gasometer" version = "0.30.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?rev=01e000cbf081dada77ac6b325a6521341044d970#01e000cbf081dada77ac6b325a6521341044d970" +source = "git+https://github.com/aurora-is-near/sputnikvm.git#5ecf36ce393380a89c6f1b09ef79f686fe043624" dependencies = [ "environmental", "evm-core", "evm-runtime", - "primitive-types 0.9.0", + "primitive-types 0.10.1", ] [[package]] name = "evm-runtime" version = "0.30.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?rev=01e000cbf081dada77ac6b325a6521341044d970#01e000cbf081dada77ac6b325a6521341044d970" +source = "git+https://github.com/aurora-is-near/sputnikvm.git#5ecf36ce393380a89c6f1b09ef79f686fe043624" dependencies = [ "environmental", "evm-core", - "primitive-types 0.9.0", + "primitive-types 0.10.1", "sha3 0.8.2", ] @@ -2152,7 +2165,7 @@ dependencies = [ "curve25519-dalek", "derive_more", "ed25519-dalek", - "ethereum-types", + "ethereum-types 0.11.0", "lazy_static", "libc", "parity-secp256k1", @@ -2459,7 +2472,7 @@ dependencies = [ "ripemd160", "serde", "sha2 0.9.5", - "sha3 0.9.1", + "sha3 0.8.2", ] [[package]] @@ -2479,7 +2492,7 @@ dependencies = [ "ripemd160", "serde", "sha2 0.9.5", - "sha3 0.9.1", + "sha3 0.8.2", ] [[package]] @@ -2935,6 +2948,7 @@ checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", "impl-codec", + "impl-rlp", "uint", ] @@ -3359,9 +3373,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.118" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" dependencies = [ "serde_derive", ] @@ -3397,9 +3411,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.118" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ "proc-macro2", "quote", @@ -3626,18 +3640,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.24" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.24" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" dependencies = [ "proc-macro2", "quote", @@ -3756,9 +3770,9 @@ checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" [[package]] name = "uint" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11fe9a9348741cf134085ad57c249508345fe16411b3d7fb4ff2da2f1d6382e" +checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" dependencies = [ "byteorder", "crunchy", diff --git a/engine-precompiles/Cargo.toml b/engine-precompiles/Cargo.toml index a83ebfac7..e0acc076e 100644 --- a/engine-precompiles/Cargo.toml +++ b/engine-precompiles/Cargo.toml @@ -19,11 +19,11 @@ base64 = { version = "0.13.0", default-features = false, features = ["alloc"] } blake2 = { git = "https://github.com/near/near-blake2.git", version = "0.9.1", default-features = false } borsh = { version = "0.8.2", default-features = false } bn = { package = "aurora-bn", git = "https://github.com/aurora-is-near/aurora-bn.git", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", default-features = false } libsecp256k1 = { version = "0.3.5", default-features = false } num = { version = "0.4.0", default-features = false, features = ["alloc"] } -primitive-types = { version = "0.9.0", default-features = false, features = ["rlp"] } +primitive-types = { version = "0.10.0", default-features = false, features = ["rlp"] } ripemd160 = { version = "0.9.1", default-features = false } rlp = { version = "0.5.0", default-features = false } sha2 = { version = "0.9.3", default-features = false } diff --git a/engine-tests/Cargo.toml b/engine-tests/Cargo.toml index 4738f2005..04f2ad04c 100644 --- a/engine-tests/Cargo.toml +++ b/engine-tests/Cargo.toml @@ -19,7 +19,7 @@ aurora-engine-sdk = { path = "../engine-sdk", default-features = false } borsh = { version = "0.8.2", default-features = false } byte-slice-cast = { version = "1.0", default-features = false } sha3 = { version = "0.9.1", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", default-features = false } rlp = { version = "0.5.0", default-features = false } [dev-dependencies] diff --git a/engine-types/Cargo.toml b/engine-types/Cargo.toml index 8ee5ec236..3b2a73a0e 100644 --- a/engine-types/Cargo.toml +++ b/engine-types/Cargo.toml @@ -16,7 +16,7 @@ autobenches = false borsh = { version = "0.8.2", default-features = false } ethabi = { git = "https://github.com/darwinia-network/ethabi", branch = "xavier-no-std", default-features = false } hex = { version = "0.4", default-features = false, features = ["alloc"] } -primitive-types = { version = "0.9.0", default-features = false, features = ["rlp"] } +primitive-types = { version = "0.10.0", default-features = false, features = ["rlp"] } sha3 = { version = "0.9.1", default-features = false } [dev-dependencies] diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 5b2ce5365..25225ecea 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -23,11 +23,11 @@ base64 = { version = "0.13.0", default-features = false, features = ["alloc"] } blake2 = { git = "https://github.com/near/near-blake2.git", version = "0.9.1", default-features = false } borsh = { version = "0.8.2", default-features = false } bn = { package = "aurora-bn", git = "https://github.com/aurora-is-near/aurora-bn.git", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "01e000cbf081dada77ac6b325a6521341044d970", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", default-features = false } libsecp256k1 = { version = "0.3.5", default-features = false } num = { version = "0.4.0", default-features = false, features = ["alloc"] } -primitive-types = { version = "0.9.0", default-features = false, features = ["rlp"] } +primitive-types = { version = "0.10.0", default-features = false, features = ["rlp"] } ripemd160 = { version = "0.9.1", default-features = false } rlp = { version = "0.5.0", default-features = false } sha2 = { version = "0.9.3", default-features = false, optional = true } diff --git a/etc/state-migration-test/Cargo.lock b/etc/state-migration-test/Cargo.lock index 46f67c003..d1b35d48d 100644 --- a/etc/state-migration-test/Cargo.lock +++ b/etc/state-migration-test/Cargo.lock @@ -10,9 +10,9 @@ checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" [[package]] name = "anyhow" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" +checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" [[package]] name = "arrayref" @@ -311,8 +311,8 @@ dependencies = [ [[package]] name = "ethabi" -version = "13.0.0" -source = "git+https://github.com/darwinia-network/ethabi?branch=xavier-no-std#baacf174d5c2f12122c4ee3fe31506fb52069983" +version = "14.1.0" +source = "git+https://github.com/darwinia-network/ethabi?branch=xavier-no-std#09da0834d95f8b43377ca22d7b1c97a2401f4b0c" dependencies = [ "anyhow", "ethereum-types", @@ -335,12 +335,12 @@ dependencies = [ [[package]] name = "ethereum" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567ce064a8232c16e2b2c2173a936b91fbe35c2f2c5278871f5a1a31688b42e9" +checksum = "42ccff962ede8fe7c3ec53d46b8316f3c53377a701a30c0325918b38ce04a497" dependencies = [ + "bytes", "ethereum-types", - "funty", "hash-db", "hash256-std-hasher", "rlp", @@ -351,9 +351,9 @@ dependencies = [ [[package]] name = "ethereum-types" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64b5df66a228d85e4b17e5d6c6aa43b0310898ffe8a85988c4c032357aaabfd" +checksum = "0dd6bde671199089e601e8d47e153368b893ef885f11f365a3261ec58153c211" dependencies = [ "ethbloom", "fixed-hash", @@ -365,7 +365,7 @@ dependencies = [ [[package]] name = "evm" version = "0.30.1" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?rev=01e000cbf081dada77ac6b325a6521341044d970#01e000cbf081dada77ac6b325a6521341044d970" +source = "git+https://github.com/aurora-is-near/sputnikvm.git#5ecf36ce393380a89c6f1b09ef79f686fe043624" dependencies = [ "ethereum", "evm-core", @@ -380,7 +380,7 @@ dependencies = [ [[package]] name = "evm-core" version = "0.30.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?rev=01e000cbf081dada77ac6b325a6521341044d970#01e000cbf081dada77ac6b325a6521341044d970" +source = "git+https://github.com/aurora-is-near/sputnikvm.git#5ecf36ce393380a89c6f1b09ef79f686fe043624" dependencies = [ "funty", "primitive-types", @@ -389,7 +389,7 @@ dependencies = [ [[package]] name = "evm-gasometer" version = "0.30.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?rev=01e000cbf081dada77ac6b325a6521341044d970#01e000cbf081dada77ac6b325a6521341044d970" +source = "git+https://github.com/aurora-is-near/sputnikvm.git#5ecf36ce393380a89c6f1b09ef79f686fe043624" dependencies = [ "evm-core", "evm-runtime", @@ -399,7 +399,7 @@ dependencies = [ [[package]] name = "evm-runtime" version = "0.30.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?rev=01e000cbf081dada77ac6b325a6521341044d970#01e000cbf081dada77ac6b325a6521341044d970" +source = "git+https://github.com/aurora-is-near/sputnikvm.git#5ecf36ce393380a89c6f1b09ef79f686fe043624" dependencies = [ "evm-core", "primitive-types", @@ -675,9 +675,9 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "primitive-types" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2415937401cb030a2a0a4d922483f945fa068f52a7dbb22ce0fe5f2b6f6adace" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", "impl-rlp", @@ -899,9 +899,9 @@ checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" [[package]] name = "uint" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11fe9a9348741cf134085ad57c249508345fe16411b3d7fb4ff2da2f1d6382e" +checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" dependencies = [ "byteorder", "crunchy", From 3fd7b9efd2b13307970ab29a5c69564fd4519f59 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Tue, 28 Sep 2021 09:30:59 -0400 Subject: [PATCH 7/9] Fix block.timestamp (#287) --- engine-sdk/src/lib.rs | 2 +- engine-tests/src/tests/one_inch.rs | 11 ++++-- engine-tests/src/tests/res/timestamp.sol | 9 +++++ engine-tests/src/tests/sanity.rs | 48 ++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 engine-tests/src/tests/res/timestamp.sol diff --git a/engine-sdk/src/lib.rs b/engine-sdk/src/lib.rs index df408608e..57857c3a7 100644 --- a/engine-sdk/src/lib.rs +++ b/engine-sdk/src/lib.rs @@ -322,7 +322,7 @@ pub fn remove_storage_with_result(key: &[u8]) -> Option> { pub fn block_timestamp() -> u64 { // NEAR timestamp is in nanoseconds let timestamp_ns = unsafe { exports::block_timestamp() }; - timestamp_ns / 1000 // convert to milliseconds for Ethereum compatibility + timestamp_ns / 1_000_000_000 // convert to seconds for Ethereum compatibility } pub fn block_index() -> u64 { diff --git a/engine-tests/src/tests/one_inch.rs b/engine-tests/src/tests/one_inch.rs index bfd83720a..ea8827e78 100644 --- a/engine-tests/src/tests/one_inch.rs +++ b/engine-tests/src/tests/one_inch.rs @@ -50,6 +50,9 @@ fn test_1inch_liquidity_protocol() { helper.approve_erc20_tokens(&token_a, pool.address()); helper.approve_erc20_tokens(&token_b, pool.address()); + // I don't understand why this is needed but for some reason the 1inch + // contract divides by zero unless I mess with the time. + helper.runner.context.block_timestamp += 10_000_000 * 1_000_000_000; let (result, profile) = helper.pool_deposit( &pool, liquidity_protocol::DepositArgs { @@ -60,8 +63,10 @@ fn test_1inch_liquidity_protocol() { }, ); assert!(result.gas_used >= 302_000); // more than 302k EVM gas used - assert!(profile.all_gas() <= 117_000_000_000_000); // less than 117 NEAR Tgas used + assert!(profile.all_gas() <= 120_000_000_000_000); // less than 120 NEAR Tgas used + // Same here + helper.runner.context.block_timestamp += 10_000_000 * 1_000_000_000; let (result, profile) = helper.pool_swap( &pool, liquidity_protocol::SwapArgs { @@ -98,8 +103,8 @@ fn test_1_inch_limit_order_deploy() { SubmitResult::try_from_slice(&outcome.return_data.as_value().unwrap()).unwrap(); assert!(result.status.is_ok()); - // more than 4 million Ethereum gas used - assert!(result.gas_used > 4_000_000); + // more than 3.5 million Ethereum gas used + assert!(result.gas_used > 3_500_000); // less than 43 NEAR Tgas used assert!(profile.all_gas() < 43_000_000_000_000); // at least 70% of which is from wasm execution diff --git a/engine-tests/src/tests/res/timestamp.sol b/engine-tests/src/tests/res/timestamp.sol new file mode 100644 index 000000000..df54b2e08 --- /dev/null +++ b/engine-tests/src/tests/res/timestamp.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.6; + +contract Timestamp { + function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { + timestamp = block.timestamp; + } +} + diff --git a/engine-tests/src/tests/sanity.rs b/engine-tests/src/tests/sanity.rs index 0c08335d3..406c1b406 100644 --- a/engine-tests/src/tests/sanity.rs +++ b/engine-tests/src/tests/sanity.rs @@ -41,6 +41,54 @@ fn test_deploy_contract() { assert_eq!(code, stored_code); } +#[test] +fn test_timestamp() { + let (mut runner, mut signer, _) = initialize_transfer(); + + let constructor = test_utils::solidity::ContractConstructor::compile_from_source( + "src/tests/res", + "target/solidity_build", + "timestamp.sol", + "Timestamp", + ); + + // deploy contract + let nonce = signer.use_nonce(); + let contract = runner.deploy_contract( + &signer.secret_key, + |c| crate::prelude::transaction::LegacyEthTransaction { + nonce: nonce.into(), + gas_price: Default::default(), + gas: u64::MAX.into(), + to: None, + value: Default::default(), + data: c.code.clone(), + }, + constructor, + ); + + // set timestamp + let t = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap(); + let t_ns = t.as_nanos(); + let t_s = U256::from(t.as_secs()); + runner.context.block_timestamp = t_ns as u64; + + // call contract + let result = runner + .submit_with_signer(&mut signer, |nonce| { + contract.call_method_without_args("getCurrentBlockTimestamp", nonce) + }) + .unwrap(); + let timestamp = U256::from_big_endian(&test_utils::unwrap_success(result)); + + // Check time is correct. + // The `+1` is needed here because the runner increments the context + // timestamp by 1 second automatically before each transaction. + assert_eq!(t_s + 1, timestamp); +} + #[test] fn test_override_state() { let (mut runner, mut account1, viewer_address) = initialize_transfer(); From 791795c4e03c37d1da14480e93f2a6e66c76fbeb Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Fri, 24 Sep 2021 18:25:49 +0200 Subject: [PATCH 8/9] Add changes and update version --- CHANGES.md | 7 +++++++ README.md | 8 ++++---- VERSION | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a614d61a3..55825bc4d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.6.4] - 2021-09-24 + +### Changes + +- Fix JSON formatting in `ft_metadata` method by [@birchmd]. +- Fix bug in `block.timestamp` (units should be seconds) by [@birchmd]. + ## [1.6.3] - 2021-09-14 ### Changes diff --git a/README.md b/README.md index f33983898..66a1d370f 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ documentation. Network | Contract ID | Chain ID | Version ------- | ------------------- | ---------- | ------ -Mainnet | [`aurora`][Mainnet] | 1313161554 | 1.6.3 -Testnet | [`aurora`][Testnet] | 1313161555 | 1.6.3 -Betanet | [`aurora`][Betanet] | 1313161556 | 1.6.3 -Local | `aurora.test.near` | 1313161556 | 1.6.3 +Mainnet | [`aurora`][Mainnet] | 1313161554 | 1.6.4 +Testnet | [`aurora`][Testnet] | 1313161555 | 1.6.4 +Betanet | [`aurora`][Betanet] | 1313161556 | 1.6.4 +Local | `aurora.test.near` | 1313161556 | 1.6.4 [Mainnet]: https://explorer.near.org/accounts/aurora [Testnet]: https://explorer.testnet.near.org/accounts/aurora diff --git a/VERSION b/VERSION index bd8bf882d..9edc58bb1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.7.0 +1.6.4 From 65fcad1ad2f88e35daa7097dee4e2fb1fc91753b Mon Sep 17 00:00:00 2001 From: Arto Bendiken Date: Wed, 29 Sep 2021 18:51:44 +0300 Subject: [PATCH 9/9] Fix the changelog. --- CHANGES.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 55825bc4d..df3c68817 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,47 +7,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [1.6.4] - 2021-09-24 +## [1.6.4] - 2021-09-29 ### Changes - Fix JSON formatting in `ft_metadata` method by [@birchmd]. -- Fix bug in `block.timestamp` (units should be seconds) by [@birchmd]. +- Fix a bug in `block.timestamp` (units should be seconds) by [@birchmd]. ## [1.6.3] - 2021-09-14 ### Changes -- Revert ERC20 admin address changes for the time being by [@joshuajbouw]. +- Revert the ERC-20 admin address changes for the time being by [@joshuajbouw]. ## [1.6.2] - 2021-09-13 ### Changes -- ERC20 admin address has been changed to have a dedicated account by [@sept-en]. -- Precompile promises were fixed that were broken in rust-blockchain/evm by [@joshuajbouw] and [@birchmd]. -- Return format of `ft_balance_of` was fixed by [@joshuajbouw]. +- Change the ERC-20 admin address to have a dedicated account by [@sept-en]. +- Fix precompile promises that were broken in rust-blockchain/evm by + [@joshuajbouw] and [@birchmd]. +- Fix the return format of `ft_balance_of` by [@joshuajbouw]. ### Removed -- Testnet balancing `balance_evm_and_nep141` has been removed by [@birchmd]. +- Remove Testnet balancing `balance_evm_and_nep141` by [@birchmd]. ## [1.6.1] - 2021-08-23 ### Breaking changes -- The `view` call has been correctly updated to return the Borsh - serialization of `TransactionStatus`. Previously, it was returning a - string with the result of the transaction by name. +- Update the `view` call to correctly return the Borsh serialization of + `TransactionStatus`. Previously, it returned a string with the result of + the transaction by name. -- The `ft_balance_of` result was changed as previously it was returning a - non-JSON string value `0`. This has been fixed to return `"0"`. +- Change the `ft_balance_of` result as previously it returned a non-JSON + string value `0`. This has been fixed to return `"0"`. ## [1.6.0] - 2021-08-13 ### Breaking changes -- The transaction status of `submit` was changed as running out of gas, +- Change the transaction status of `submit` as running out of gas, funds, or being out-of-the-offset are not fatal errors but failed executions. @@ -93,7 +94,8 @@ struct SubmitResult { ## [1.0.0] - 2021-05-12 -[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/1.6.3...master +[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/1.6.4...master +[1.6.4]: https://github.com/aurora-is-near/aurora-engine/compare/1.6.3...1.6.4 [1.6.3]: https://github.com/aurora-is-near/aurora-engine/compare/1.6.2...1.6.3 [1.6.2]: https://github.com/aurora-is-near/aurora-engine/compare/1.6.1...1.6.2 [1.6.1]: https://github.com/aurora-is-near/aurora-engine/compare/1.6.0...1.6.1