From 70539201173442cec045ca62b845190b119a876d Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 31 May 2021 16:30:54 +0800 Subject: [PATCH 01/45] New precompile named `transfer` --- Cargo.lock | 11 +- Cargo.toml | 2 +- frame/dvm/Cargo.toml | 2 +- frame/evm/precompile/Cargo.toml | 4 +- .../{withdraw => transfer}/Cargo.toml | 12 +- .../precompile/contracts/transfer/src/kton.rs | 232 ++++++++++++++++++ .../precompile/contracts/transfer/src/lib.rs | 82 +++++++ .../precompile/contracts/transfer/src/util.rs | 51 ++++ .../src/lib.rs => transfer/src/withdraw.rs} | 40 +-- frame/evm/precompile/src/lib.rs | 2 +- 10 files changed, 397 insertions(+), 41 deletions(-) rename frame/evm/precompile/contracts/{withdraw => transfer}/Cargo.toml (81%) create mode 100644 frame/evm/precompile/contracts/transfer/src/kton.rs create mode 100644 frame/evm/precompile/contracts/transfer/src/lib.rs create mode 100644 frame/evm/precompile/contracts/transfer/src/util.rs rename frame/evm/precompile/contracts/{withdraw/src/lib.rs => transfer/src/withdraw.rs} (70%) diff --git a/Cargo.lock b/Cargo.lock index 9929024933..aca64d75c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1681,7 +1681,7 @@ dependencies = [ "darwinia-evm-precompile-issuing", "darwinia-evm-precompile-kton", "darwinia-evm-precompile-simple", - "darwinia-evm-precompile-withdraw", + "darwinia-evm-precompile-transfer", ] [[package]] @@ -1818,18 +1818,23 @@ dependencies = [ ] [[package]] -name = "darwinia-evm-precompile-withdraw" +name = "darwinia-evm-precompile-transfer" version = "2.4.0" dependencies = [ "darwinia-evm", "darwinia-support", "dp-evm", + "dvm-ethereum", + "ethabi", + "ethereum-types", "evm", "frame-support", "frame-system", + "log", "pallet-timestamp", "parity-scale-codec", "ripemd160", + "sha3 0.9.1", "sp-core", "sp-io", "sp-runtime", @@ -2371,7 +2376,7 @@ dependencies = [ "darwinia-balances", "darwinia-evm", "darwinia-evm-precompile-simple", - "darwinia-evm-precompile-withdraw", + "darwinia-evm-precompile-transfer", "darwinia-support", "dp-evm", "dp-storage", diff --git a/Cargo.toml b/Cargo.toml index e3d5a111ba..a32dda13ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ members = [ "frame/evm/precompile/contracts/kton", "frame/evm/precompile/contracts/modexp", "frame/evm/precompile/contracts/simple", - "frame/evm/precompile/contracts/withdraw", + "frame/evm/precompile/contracts/transfer", "frame/evm/precompile/contracts/sha3fips", "frame/header-mmr", "frame/header-mmr/rpc", diff --git a/frame/dvm/Cargo.toml b/frame/dvm/Cargo.toml index 2e32f7617b..5902915fce 100644 --- a/frame/dvm/Cargo.toml +++ b/frame/dvm/Cargo.toml @@ -41,7 +41,7 @@ sp-std = { default-features = false, git = "https://github.com/darwini # darwinia darwinia-balances = { path = "../balances" } darwinia-evm-precompile-simple = { path = "../evm/precompile/contracts/simple" } -darwinia-evm-precompile-withdraw = { path = "../evm/precompile/contracts/withdraw" } +darwinia-evm-precompile-transfer = { path = "../evm/precompile/contracts/transfer" } [features] default = ["std"] diff --git a/frame/evm/precompile/Cargo.toml b/frame/evm/precompile/Cargo.toml index ea56a24d2d..1de76f1cd5 100644 --- a/frame/evm/precompile/Cargo.toml +++ b/frame/evm/precompile/Cargo.toml @@ -15,7 +15,7 @@ darwinia-evm-precompile-empty = { default-features = false, path = "contracts darwinia-evm-precompile-issuing = { default-features = false, path = "contracts/issuing" } darwinia-evm-precompile-kton = { default-features = false, path = "contracts/kton" } darwinia-evm-precompile-simple = { default-features = false, path = "contracts/simple" } -darwinia-evm-precompile-withdraw = { default-features = false, path = "contracts/withdraw" } +darwinia-evm-precompile-transfer = { default-features = false, path = "contracts/transfer" } [features] default = ["std"] @@ -25,5 +25,5 @@ std = [ "darwinia-evm-precompile-issuing/std", "darwinia-evm-precompile-kton/std", "darwinia-evm-precompile-simple/std", - "darwinia-evm-precompile-withdraw/std", + "darwinia-evm-precompile-transfer/std", ] diff --git a/frame/evm/precompile/contracts/withdraw/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml similarity index 81% rename from frame/evm/precompile/contracts/withdraw/Cargo.toml rename to frame/evm/precompile/contracts/transfer/Cargo.toml index 433b8825ef..63807f3d8b 100644 --- a/frame/evm/precompile/contracts/withdraw/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -4,7 +4,7 @@ description = "Withdraw precompile for EVM pallet." edition = "2018" homepage = "https://darwinia.network/" license = "GPL-3.0" -name = "darwinia-evm-precompile-withdraw" +name = "darwinia-evm-precompile-transfer" readme = "README.md" repository = "https://github.com/darwinia-network/darwinia-common/" version = "2.4.0" @@ -27,6 +27,12 @@ sp-io = { default-features = false, git = "https://github.com/darwini sp-runtime = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } sp-std = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } +ethabi = { default-features = false, git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std" } +sha3 = { version = "0.9.1", default-features = false } +ethereum-types = { version = "0.11.0", default-features = false } +dvm-ethereum = { default-features = false, path = "../../.././../dvm" } +log = { version = "0.4.14" } + [features] default = ["std"] @@ -40,12 +46,16 @@ crates-std = [ "codec/std", "evm/std", "ripemd160/std", + "sha3/std", + "ethereum-types/std", ] darwinia-std = [ "darwinia-evm/std", "darwinia-support/std", "dp-evm/std", + "ethabi/std", + "dvm-ethereum/std", ] substrate-std = [ diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs new file mode 100644 index 0000000000..4162f21eb9 --- /dev/null +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -0,0 +1,232 @@ +use crate::util; +use crate::AccountId; +use codec::Decode; +use core::str::FromStr; +use darwinia_evm::AddressMapping; +use darwinia_evm::{Account, AccountBasic, Config, Module, Runner}; +use darwinia_support::evm::POW_9; +use dvm_ethereum::{ + account_basic::{KtonRemainBalance, RemainBalanceOp}, + KtonBalance, +}; +use ethabi::{Function, Param, ParamType, Token}; +use evm::{Context, ExitError, ExitReason, ExitSucceed}; +use frame_support::{ensure, traits::Currency}; +use sha3::Digest; +use sp_core::{H160, U256}; +use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; +use sp_std::{borrow::ToOwned, marker::PhantomData, prelude::*, vec::Vec}; + +const TRANSFER_AND_CALL_ACTION: &[u8] = b"transfer_and_call(address,uint256)"; +const WITHDRAW_ACTION: &[u8] = b"withdraw(bytes32,uint256)"; +const KTON_PRECOMPILE: &str = "0000000000000000000000000000000000000016"; + +/// Kton Precompile Contract is used to support the exchange of KTON native asset between darwinia and dvm contract +/// +/// The contract address: 0000000000000000000000000000000000000016 +pub struct Kton { + _maker: PhantomData, +} + +pub enum KtonAction { + /// Transfer from substrate account to wkton contract + TransferAndCall(TACallData), + /// Withdraw from wkton contract to substrate account + Withdraw(WithdrawData), +} + +impl KtonAction { + pub fn execute( + input: &[u8], + target_limit: Option, + context: &Context, + ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + let helper = U256::from(POW_9); + let action = which_action::(&input)?; + + match action { + KtonAction::TransferAndCall(call_data) => { + // Ensure wkton is a contract + ensure!( + !Module::::is_contract_code_empty(&call_data.wkton_address), + ExitError::Other("Wkton must be a contract!".into()) + ); + // Ensure context's apparent_value is zero, since the transfer value is encoded in input field + ensure!( + context.apparent_value == U256::zero(), + ExitError::Other("The value in tx must be zero!".into()) + ); + // Ensure caller's balance is enough + ensure!( + T::KtonAccountBasic::account_basic(&context.caller).balance >= call_data.value, + ExitError::OutOfFund + ); + + // Transfer kton from sender to KTON wrapped contract + T::KtonAccountBasic::transfer( + &context.caller, + &call_data.wkton_address, + call_data.value, + )?; + // Call WKTON wrapped contract deposit + let precompile_address = H160::from_str(KTON_PRECOMPILE).unwrap_or_default(); + let raw_input = make_call_data(context.caller, call_data.value)?; + if let Ok(call_res) = T::Runner::call( + precompile_address, + call_data.wkton_address, + raw_input.to_vec(), + U256::zero(), + target_limit.unwrap_or_default(), + None, + None, + T::config(), + ) { + match call_res.exit_reason { + ExitReason::Succeed(_) => { + log::debug!("Transfer and call execute success."); + } + _ => return Err(ExitError::Other("Call in Kton precompile failed".into())), + } + } + + Ok((ExitSucceed::Returned, vec![], 20000)) + } + KtonAction::Withdraw(wd) => { + // Ensure wkton is a contract + ensure!( + !Module::::is_contract_code_empty(&context.caller), + ExitError::Other("The caller must be wkton contract!".into()) + ); + // Ensure context's apparent_value is zero + ensure!( + context.apparent_value == U256::zero(), + ExitError::Other("The value in tx must be zero!".into()) + ); + // Ensure caller's balance is enough + let caller_kton = T::KtonAccountBasic::account_basic(&context.caller); + ensure!(caller_kton.balance >= wd.kton_value, ExitError::OutOfFund); + + // Transfer + let new_wkton_balance = caller_kton.balance.saturating_sub(wd.kton_value); + T::KtonAccountBasic::mutate_account_basic( + &context.caller, + Account { + nonce: caller_kton.nonce, + balance: new_wkton_balance, + }, + ); + let (currency_value, remain_balance) = wd.kton_value.div_mod(helper); + ::KtonCurrency::deposit_creating( + &wd.to_account_id, + currency_value.low_u128().unique_saturated_into(), + ); + >>::inc_remaining_balance( + &wd.to_account_id, + remain_balance.low_u128().saturated_into(), + ); + + Ok((ExitSucceed::Returned, vec![], 20000)) + } + } + } +} + +/// which action depends on the function selector +pub fn which_action( + input_data: &[u8], +) -> Result, ExitError> { + let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; + let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; + if &input_data[0..4] == transfer_and_call_action { + let decoded_data = TACallData::decode(&input_data[4..])?; + return Ok(KtonAction::TransferAndCall(decoded_data)); + } else if &input_data[0..4] == withdraw_action { + let decoded_data = WithdrawData::decode(&input_data[4..])?; + return Ok(KtonAction::Withdraw(decoded_data)); + } + Err(ExitError::Other("Invalid Action!".into())) +} + +#[derive(Debug, PartialEq, Eq)] +pub struct TACallData { + wkton_address: H160, + value: U256, +} + +impl TACallData { + pub fn decode(data: &[u8]) -> Result { + let tokens = ethabi::decode(&[ParamType::Address, ParamType::Uint(256)], &data) + .map_err(|_| ExitError::Other("ethabi decoded error".into()))?; + match (tokens[0].clone(), tokens[1].clone()) { + (Token::Address(eth_wkton_address), Token::Uint(eth_value)) => Ok(TACallData { + wkton_address: util::e2s_address(eth_wkton_address), + value: util::e2s_u256(eth_value), + }), + _ => Err(ExitError::Other("Invlid call data".into())), + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct WithdrawData { + pub to_account_id: AccountId, + pub kton_value: U256, +} + +impl WithdrawData { + pub fn decode(data: &[u8]) -> Result { + let tokens = ethabi::decode(&[ParamType::FixedBytes(32), ParamType::Uint(256)], &data) + .map_err(|_| ExitError::Other("ethabi decoded error".into()))?; + match (tokens[0].clone(), tokens[1].clone()) { + (Token::FixedBytes(address), Token::Uint(eth_value)) => Ok(WithdrawData { + to_account_id: ::AccountId::decode( + &mut address.as_ref(), + ) + .map_err(|_| ExitError::Other("Invalid destination address".into()))?, + kton_value: util::e2s_u256(eth_value), + }), + _ => Err(ExitError::Other("Invlid withdraw input data".into())), + } + } +} + +/// which action depends on the function selector +pub fn which_kton_action( + input_data: &[u8], +) -> Result, ExitError> { + let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; + let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; + if &input_data[0..4] == transfer_and_call_action { + let decoded_data = TACallData::decode(&input_data[4..])?; + return Ok(KtonAction::TransferAndCall(decoded_data)); + } else if &input_data[0..4] == withdraw_action { + let decoded_data = WithdrawData::decode(&input_data[4..])?; + return Ok(KtonAction::Withdraw(decoded_data)); + } + Err(ExitError::Other("Invalid Action!".into())) +} + +fn make_call_data( + sp_address: sp_core::H160, + sp_value: sp_core::U256, +) -> Result, ExitError> { + let eth_address = util::s2e_address(sp_address); + let eth_value = util::s2e_u256(sp_value); + let func = Function { + name: "deposit".to_owned(), + inputs: vec![ + Param { + name: "address".to_owned(), + kind: ParamType::Address, + }, + Param { + name: "value".to_owned(), + kind: ParamType::Uint(256), + }, + ], + outputs: vec![], + constant: false, + }; + func.encode_input(&[Token::Address(eth_address), Token::Uint(eth_value)]) + .map_err(|_| ExitError::Other("Make call data error happened".into())) +} diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs new file mode 100644 index 0000000000..8fdfbcfe38 --- /dev/null +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -0,0 +1,82 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2021 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Darwinia is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Darwinia. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +mod kton; +pub mod util; +mod withdraw; + +use frame_support::traits::{Currency, ExistenceRequirement}; +use kton::Kton; +use sha3::Digest; +use sp_core::{H160, U256}; +use sp_runtime::traits::UniqueSaturatedInto; +use sp_std::marker::PhantomData; +use sp_std::prelude::*; +use sp_std::vec::Vec; + +use codec::Decode; +use darwinia_evm::{AddressMapping, Config}; +use darwinia_support::evm::POW_9; +use dp_evm::Precompile; +use ethabi::{Function, Param, ParamType, Token}; +use evm::{Context, ExitError, ExitSucceed}; +use kton::KtonAction; +use withdraw::WithDraw; + +pub type AccountId = ::AccountId; + +pub enum TransferAction { + RingBack, + KtonAction, + _Impossible(PhantomData), +} + +impl Precompile for TransferAction { + fn execute( + input: &[u8], + target_gas: Option, + context: &Context, + ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + match which_action::(&input) { + Ok(TransferAction::RingBack) => { + WithDraw::::execute(&input, target_gas, context)?; + } + Ok(TransferAction::KtonAction) => { + KtonAction::::execute(&input, target_gas, context)?; + } + _ => { + return Err(ExitError::Other("Invalid input data length".into())); + } + } + Err(ExitError::Other("Invalid input data length".into())) + } +} + +fn which_action( + data: &[u8], +) -> Result, ExitError> { + if data.len() == 32 { + return Ok(TransferAction::RingBack); + } else if data.len() == 68 { + return Ok(TransferAction::KtonAction); + } else { + return Err(ExitError::Other("Invalid input data length".into())); + } +} diff --git a/frame/evm/precompile/contracts/transfer/src/util.rs b/frame/evm/precompile/contracts/transfer/src/util.rs new file mode 100644 index 0000000000..4c26022b5c --- /dev/null +++ b/frame/evm/precompile/contracts/transfer/src/util.rs @@ -0,0 +1,51 @@ +pub fn e2s_address(eth_address: ethereum_types::H160) -> sp_core::H160 { + let eth_address_bytes = eth_address.to_fixed_bytes(); + sp_core::H160::from_slice(ð_address_bytes) +} + +pub fn s2e_address(sp_address: sp_core::H160) -> ethereum_types::H160 { + let sp_address_bytes = sp_address.to_fixed_bytes(); + ethereum_types::H160::from_slice(&sp_address_bytes) +} + +pub fn e2s_u256(eth_value: ethereum_types::U256) -> sp_core::U256 { + let mut value_bytes = [0u8; 32]; + eth_value.to_big_endian(&mut value_bytes); + sp_core::U256::from_big_endian(&value_bytes) +} + +pub fn s2e_u256(sp_value: sp_core::U256) -> ethereum_types::U256 { + let mut value_bytes = [0u8; 32]; + sp_value.to_big_endian(&mut value_bytes); + ethereum_types::U256::from_big_endian(&value_bytes) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + + #[test] + fn test_address() { + let eth_address = + ethereum_types::H160::from_str("Aa01a1bEF0557fa9625581a293F3AA7770192632").unwrap(); + let sp_address = + sp_core::H160::from_str("Aa01a1bEF0557fa9625581a293F3AA7770192632").unwrap(); + let output = e2s_address(eth_address); + assert_eq!(output.0, sp_address.0); + + let output = s2e_address(sp_address); + assert_eq!(output.0, eth_address.0); + } + + #[test] + fn test_value() { + let eth_value = ethereum_types::U256::from(200); + let sp_value = sp_core::U256::from(200); + let output = e2s_u256(eth_value); + assert_eq!(output, sp_value); + + let output = s2e_u256(sp_value); + assert_eq!(output, eth_value); + } +} diff --git a/frame/evm/precompile/contracts/withdraw/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/withdraw.rs similarity index 70% rename from frame/evm/precompile/contracts/withdraw/src/lib.rs rename to frame/evm/precompile/contracts/transfer/src/withdraw.rs index 8014fb3f54..3bebc2eec9 100644 --- a/frame/evm/precompile/contracts/withdraw/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/withdraw.rs @@ -1,37 +1,13 @@ -// This file is part of Darwinia. -// -// Copyright (C) 2018-2021 Darwinia Network -// SPDX-License-Identifier: GPL-3.0 -// -// Darwinia is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Darwinia is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Darwinia. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] - -use frame_support::traits::{Currency, ExistenceRequirement}; -use sp_core::U256; -use sp_runtime::traits::UniqueSaturatedInto; -use sp_std::marker::PhantomData; -use sp_std::prelude::*; -use sp_std::vec::Vec; - +use crate::AccountId; use codec::Decode; use darwinia_evm::{AddressMapping, Config}; use darwinia_support::evm::POW_9; -use dp_evm::Precompile; +use ethabi::{Function, Param, ParamType, Token}; use evm::{Context, ExitError, ExitSucceed}; - -type AccountId = ::AccountId; +use frame_support::traits::{Currency, ExistenceRequirement}; +use sp_core::{H160, U256}; +use sp_runtime::traits::UniqueSaturatedInto; +use sp_std::{borrow::ToOwned, marker::PhantomData, prelude::*, vec::Vec}; /// WithDraw Precompile Contract, used to withdraw balance from evm account to darwinia account /// @@ -40,13 +16,13 @@ pub struct WithDraw { _maker: PhantomData, } -impl Precompile for WithDraw { +impl WithDraw { /// The Withdraw process is divided into two part: /// 1. parse the withdrawal address from the input parameter and get the contract address and value from the context /// 2. transfer from the contract address to withdrawal address /// /// Input data: 32-bit substrate withdrawal public key - fn execute( + pub(crate) fn execute( input: &[u8], _: Option, context: &Context, diff --git a/frame/evm/precompile/src/lib.rs b/frame/evm/precompile/src/lib.rs index 06e088cffe..6f84a985d6 100644 --- a/frame/evm/precompile/src/lib.rs +++ b/frame/evm/precompile/src/lib.rs @@ -39,7 +39,7 @@ pub type DarwiniaPrecompiles = ( darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000012 darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000013 darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000014 - darwinia_evm_precompile_withdraw::WithDraw, // 0x0000000000000000000000000000000000000015 + darwinia_evm_precompile_transfer::TransferAction, // 0x0000000000000000000000000000000000000015 darwinia_evm_precompile_kton::Kton, // 0x0000000000000000000000000000000000000016 darwinia_evm_precompile_issuing::Issuing, // 0x0000000000000000000000000000000000000017 ); From fda883a95ccfedaee7b5917d47c56eb484d71fd5 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 31 May 2021 16:55:37 +0800 Subject: [PATCH 02/45] Delete kton precompile --- Cargo.lock | 27 -- Cargo.toml | 1 - frame/evm/precompile/Cargo.toml | 2 - .../evm/precompile/contracts/kton/Cargo.toml | 71 ----- .../evm/precompile/contracts/kton/src/lib.rs | 270 ------------------ .../evm/precompile/contracts/kton/src/util.rs | 51 ---- .../precompile/contracts/transfer/src/lib.rs | 29 +- frame/evm/precompile/src/lib.rs | 4 +- 8 files changed, 18 insertions(+), 437 deletions(-) delete mode 100644 frame/evm/precompile/contracts/kton/Cargo.toml delete mode 100644 frame/evm/precompile/contracts/kton/src/lib.rs delete mode 100644 frame/evm/precompile/contracts/kton/src/util.rs diff --git a/Cargo.lock b/Cargo.lock index aca64d75c5..5595c4668a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1679,7 +1679,6 @@ version = "2.4.0" dependencies = [ "darwinia-evm-precompile-empty", "darwinia-evm-precompile-issuing", - "darwinia-evm-precompile-kton", "darwinia-evm-precompile-simple", "darwinia-evm-precompile-transfer", ] @@ -1757,32 +1756,6 @@ dependencies = [ "evm", ] -[[package]] -name = "darwinia-evm-precompile-kton" -version = "2.4.0" -dependencies = [ - "array-bytes", - "darwinia-evm", - "darwinia-support", - "dp-evm", - "dvm-ethereum", - "ethabi", - "ethereum-types", - "evm", - "frame-support", - "frame-system", - "hex", - "log", - "pallet-timestamp", - "parity-scale-codec", - "ripemd160", - "sha3 0.9.1", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "darwinia-evm-precompile-modexp" version = "2.4.0" diff --git a/Cargo.toml b/Cargo.toml index a32dda13ed..d11b0233ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,6 @@ members = [ "frame/evm/precompile/contracts/dispatch", "frame/evm/precompile/contracts/ed25519", "frame/evm/precompile/contracts/empty", - "frame/evm/precompile/contracts/kton", "frame/evm/precompile/contracts/modexp", "frame/evm/precompile/contracts/simple", "frame/evm/precompile/contracts/transfer", diff --git a/frame/evm/precompile/Cargo.toml b/frame/evm/precompile/Cargo.toml index 1de76f1cd5..7830e7579d 100644 --- a/frame/evm/precompile/Cargo.toml +++ b/frame/evm/precompile/Cargo.toml @@ -13,7 +13,6 @@ version = "2.4.0" # darwinia darwinia-evm-precompile-empty = { default-features = false, path = "contracts/empty" } darwinia-evm-precompile-issuing = { default-features = false, path = "contracts/issuing" } -darwinia-evm-precompile-kton = { default-features = false, path = "contracts/kton" } darwinia-evm-precompile-simple = { default-features = false, path = "contracts/simple" } darwinia-evm-precompile-transfer = { default-features = false, path = "contracts/transfer" } @@ -23,7 +22,6 @@ default = ["std"] std = [ "darwinia-evm-precompile-empty/std", "darwinia-evm-precompile-issuing/std", - "darwinia-evm-precompile-kton/std", "darwinia-evm-precompile-simple/std", "darwinia-evm-precompile-transfer/std", ] diff --git a/frame/evm/precompile/contracts/kton/Cargo.toml b/frame/evm/precompile/contracts/kton/Cargo.toml deleted file mode 100644 index 093b0acd84..0000000000 --- a/frame/evm/precompile/contracts/kton/Cargo.toml +++ /dev/null @@ -1,71 +0,0 @@ -[package] -authors = ["Darwinia Network "] -description = "Withdraw precompile for EVM pallet." -edition = "2018" -homepage = "https://darwinia.network/" -license = "GPL-3.0" -name = "darwinia-evm-precompile-kton" -readme = "README.md" -repository = "https://github.com/darwinia-network/darwinia-common/" -version = "2.4.0" - -[dependencies] -# crates -array-bytes = { version = "1.1.0" } -codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } -ethereum-types = { version = "0.11.0", default-features = false } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } -hex = { version = "0.4.3", default-features = false } -log = { version = "0.4.14" } -ripemd160 = { version = "0.9.1", default-features = false } -sha3 = { version = "0.9.1", default-features = false } -# darwinia -darwinia-evm = { default-features = false, path = "../../../" } -darwinia-support = { default-features = false, path = "../../.././../support" } -dp-evm = { default-features = false, path = "../../../../../primitives/evm" } -dvm-ethereum = { default-features = false, path = "../../.././../dvm" } -ethabi = { default-features = false, git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std" } -# substrate -frame-support = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } -frame-system = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } -pallet-timestamp = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } -sp-core = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } -sp-io = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } -sp-runtime = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } -sp-std = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } - -[features] -default = ["std"] - -std = [ - "crates-std", - "darwinia-std", - "substrate-std", -] - -crates-std = [ - "codec/std", - "ethereum-types/std", - "evm/std", - "hex/std", - "ripemd160/std", - "sha3/std", -] - -darwinia-std = [ - "darwinia-evm/std", - "darwinia-support/std", - "dp-evm/std", - "dvm-ethereum/std", - "ethabi/std", -] - -substrate-std = [ - "frame-support/std", - "frame-system/std", - "pallet-timestamp/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/frame/evm/precompile/contracts/kton/src/lib.rs b/frame/evm/precompile/contracts/kton/src/lib.rs deleted file mode 100644 index 50a9ce61a4..0000000000 --- a/frame/evm/precompile/contracts/kton/src/lib.rs +++ /dev/null @@ -1,270 +0,0 @@ -// This file is part of Darwinia. -// -// Copyright (C) 2018-2021 Darwinia Network -// SPDX-License-Identifier: GPL-3.0 -// -// Darwinia is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Darwinia is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Darwinia. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] - -mod util; - -use codec::Decode; -use core::str::FromStr; -use ethabi::{Function, Param, ParamType, Token}; -use evm::{Context, ExitError, ExitReason, ExitSucceed}; -use frame_support::{ensure, traits::Currency}; -use sha3::Digest; -use sp_core::{H160, U256}; -use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; -use sp_std::{borrow::ToOwned, marker::PhantomData, prelude::*, vec::Vec}; - -use darwinia_evm::{Account, AccountBasic, Config, Module, Runner}; -use darwinia_support::evm::POW_9; -use dp_evm::Precompile; -use dvm_ethereum::{ - account_basic::{KtonRemainBalance, RemainBalanceOp}, - KtonBalance, -}; - -type AccountId = ::AccountId; - -const TRANSFER_AND_CALL_ACTION: &[u8] = b"transfer_and_call(address,uint256)"; -const WITHDRAW_ACTION: &[u8] = b"withdraw(bytes32,uint256)"; -const KTON_PRECOMPILE: &str = "0000000000000000000000000000000000000016"; -/// Kton Precompile Contract is used to support the exchange of KTON native asset between darwinia and dvm contract -/// -/// The contract address: 0000000000000000000000000000000000000016 -pub struct Kton { - _maker: PhantomData, -} - -impl Precompile for Kton { - /// There are two actions, one is `transfer_and_call` and the other is `withdraw` - /// 1. Transfer_and_call Action, triggered by the user sending a transaction to the kton precompile - /// special evm address, eg(0000000000000000000000000000000000000016). and transfer the sender's - /// kton balance to the deployed wkton contract in dvm. The input contain two parts: - /// - p1: The wkton address, it is important to note that if this address is wrong, the balance cannot be recovered. - /// - p2: The transfer value - /// 2. WithDraw Action, the user sends transaction to wkton contract triggering this kton precompile to be called - /// within the wkton contract, and transfer the balance from wkton balanceof to the darwinia network. The input contain two parts: - /// - p1: The to account id, a withdraw darwinia public key. - /// - p2: The withdraw value - fn execute( - input: &[u8], - target_limit: Option, - context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { - let helper = U256::from(POW_9); - let action = which_action::(&input)?; - - match action { - Action::TransferAndCall(call_data) => { - // Ensure wkton is a contract - ensure!( - !crate::Module::::is_contract_code_empty(&call_data.wkton_address), - ExitError::Other("Wkton must be a contract!".into()) - ); - // Ensure context's apparent_value is zero, since the transfer value is encoded in input field - ensure!( - context.apparent_value == U256::zero(), - ExitError::Other("The value in tx must be zero!".into()) - ); - // Ensure caller's balance is enough - ensure!( - T::KtonAccountBasic::account_basic(&context.caller).balance >= call_data.value, - ExitError::OutOfFund - ); - - // Transfer kton from sender to KTON wrapped contract - T::KtonAccountBasic::transfer( - &context.caller, - &call_data.wkton_address, - call_data.value, - )?; - // Call WKTON wrapped contract deposit - let precompile_address = H160::from_str(KTON_PRECOMPILE).unwrap_or_default(); - let raw_input = make_call_data(context.caller, call_data.value)?; - if let Ok(call_res) = T::Runner::call( - precompile_address, - call_data.wkton_address, - raw_input.to_vec(), - U256::zero(), - target_limit.unwrap_or_default(), - None, - None, - T::config(), - ) { - match call_res.exit_reason { - ExitReason::Succeed(_) => { - log::debug!("Transfer and call execute success."); - } - _ => return Err(ExitError::Other("Call in Kton precompile failed".into())), - } - } - - Ok((ExitSucceed::Returned, vec![], 20000)) - } - Action::Withdraw(wd) => { - // Ensure wkton is a contract - ensure!( - !crate::Module::::is_contract_code_empty(&context.caller), - ExitError::Other("The caller must be wkton contract!".into()) - ); - // Ensure context's apparent_value is zero - ensure!( - context.apparent_value == U256::zero(), - ExitError::Other("The value in tx must be zero!".into()) - ); - // Ensure caller's balance is enough - let caller_kton = T::KtonAccountBasic::account_basic(&context.caller); - ensure!(caller_kton.balance >= wd.kton_value, ExitError::OutOfFund); - - // Transfer - let new_wkton_balance = caller_kton.balance.saturating_sub(wd.kton_value); - T::KtonAccountBasic::mutate_account_basic( - &context.caller, - Account { - nonce: caller_kton.nonce, - balance: new_wkton_balance, - }, - ); - let (currency_value, remain_balance) = wd.kton_value.div_mod(helper); - ::KtonCurrency::deposit_creating( - &wd.to_account_id, - currency_value.low_u128().unique_saturated_into(), - ); - >>::inc_remaining_balance( - &wd.to_account_id, - remain_balance.low_u128().saturated_into(), - ); - - Ok((ExitSucceed::Returned, vec![], 20000)) - } - } - } -} - -/// Action about KTON precompile -pub enum Action { - /// Transfer from substrate account to wkton contract - TransferAndCall(CallData), - /// Withdraw from wkton contract to substrate account - Withdraw(WithdrawData), -} - -/// which action depends on the function selector -pub fn which_action(input_data: &[u8]) -> Result, ExitError> { - let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; - let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; - if &input_data[0..4] == transfer_and_call_action { - let decoded_data = CallData::decode(&input_data[4..])?; - return Ok(Action::TransferAndCall(decoded_data)); - } else if &input_data[0..4] == withdraw_action { - let decoded_data = WithdrawData::decode(&input_data[4..])?; - return Ok(Action::Withdraw(decoded_data)); - } - Err(ExitError::Other("Invalid Action!".into())) -} - -#[derive(Debug, PartialEq, Eq)] -pub struct CallData { - wkton_address: H160, - value: U256, -} - -impl CallData { - pub fn decode(data: &[u8]) -> Result { - let tokens = ethabi::decode(&[ParamType::Address, ParamType::Uint(256)], &data) - .map_err(|_| ExitError::Other("ethabi decoded error".into()))?; - match (tokens[0].clone(), tokens[1].clone()) { - (Token::Address(eth_wkton_address), Token::Uint(eth_value)) => Ok(CallData { - wkton_address: util::e2s_address(eth_wkton_address), - value: util::e2s_u256(eth_value), - }), - _ => Err(ExitError::Other("Invlid call data".into())), - } - } -} - -#[derive(Debug, PartialEq, Eq)] -pub struct WithdrawData { - pub to_account_id: AccountId, - pub kton_value: U256, -} - -impl WithdrawData { - pub fn decode(data: &[u8]) -> Result { - let tokens = ethabi::decode(&[ParamType::FixedBytes(32), ParamType::Uint(256)], &data) - .map_err(|_| ExitError::Other("ethabi decoded error".into()))?; - match (tokens[0].clone(), tokens[1].clone()) { - (Token::FixedBytes(address), Token::Uint(eth_value)) => Ok(WithdrawData { - to_account_id: ::AccountId::decode( - &mut address.as_ref(), - ) - .map_err(|_| ExitError::Other("Invalid destination address".into()))?, - kton_value: util::e2s_u256(eth_value), - }), - _ => Err(ExitError::Other("Invlid withdraw input data".into())), - } - } -} - -fn make_call_data( - sp_address: sp_core::H160, - sp_value: sp_core::U256, -) -> Result, ExitError> { - let eth_address = util::s2e_address(sp_address); - let eth_value = util::s2e_u256(sp_value); - let func = Function { - name: "deposit".to_owned(), - inputs: vec![ - Param { - name: "address".to_owned(), - kind: ParamType::Address, - }, - Param { - name: "value".to_owned(), - kind: ParamType::Uint(256), - }, - ], - outputs: vec![], - constant: false, - }; - func.encode_input(&[Token::Address(eth_address), Token::Uint(eth_value)]) - .map_err(|_| ExitError::Other("Make call data error happened".into())) -} - -#[cfg(test)] -mod tests { - use super::*; - use std::str::FromStr; - - #[test] - fn test_make_input() { - let mock_address = - sp_core::H160::from_str("Aa01a1bEF0557fa9625581a293F3AA7770192632").unwrap(); - let mock_value_1 = sp_core::U256::from(30); - let expected_str = "0x47e7ef24000000000000000000000000aa01a1bef0557fa9625581a293f3aa7770192632000000000000000000000000000000000000000000000000000000000000001e"; - - let encoded_str = - array_bytes::bytes2hex("0x", make_call_data(mock_address, mock_value_1).unwrap()); - assert_eq!(encoded_str, expected_str); - - let mock_value_2 = sp_core::U256::from(25); - let encoded_str = - array_bytes::bytes2hex("0x", make_call_data(mock_address, mock_value_2).unwrap()); - assert_ne!(encoded_str, expected_str); - } -} diff --git a/frame/evm/precompile/contracts/kton/src/util.rs b/frame/evm/precompile/contracts/kton/src/util.rs deleted file mode 100644 index 4c26022b5c..0000000000 --- a/frame/evm/precompile/contracts/kton/src/util.rs +++ /dev/null @@ -1,51 +0,0 @@ -pub fn e2s_address(eth_address: ethereum_types::H160) -> sp_core::H160 { - let eth_address_bytes = eth_address.to_fixed_bytes(); - sp_core::H160::from_slice(ð_address_bytes) -} - -pub fn s2e_address(sp_address: sp_core::H160) -> ethereum_types::H160 { - let sp_address_bytes = sp_address.to_fixed_bytes(); - ethereum_types::H160::from_slice(&sp_address_bytes) -} - -pub fn e2s_u256(eth_value: ethereum_types::U256) -> sp_core::U256 { - let mut value_bytes = [0u8; 32]; - eth_value.to_big_endian(&mut value_bytes); - sp_core::U256::from_big_endian(&value_bytes) -} - -pub fn s2e_u256(sp_value: sp_core::U256) -> ethereum_types::U256 { - let mut value_bytes = [0u8; 32]; - sp_value.to_big_endian(&mut value_bytes); - ethereum_types::U256::from_big_endian(&value_bytes) -} - -#[cfg(test)] -mod tests { - use super::*; - use std::str::FromStr; - - #[test] - fn test_address() { - let eth_address = - ethereum_types::H160::from_str("Aa01a1bEF0557fa9625581a293F3AA7770192632").unwrap(); - let sp_address = - sp_core::H160::from_str("Aa01a1bEF0557fa9625581a293F3AA7770192632").unwrap(); - let output = e2s_address(eth_address); - assert_eq!(output.0, sp_address.0); - - let output = s2e_address(sp_address); - assert_eq!(output.0, eth_address.0); - } - - #[test] - fn test_value() { - let eth_value = ethereum_types::U256::from(200); - let sp_value = sp_core::U256::from(200); - let output = e2s_u256(eth_value); - assert_eq!(output, sp_value); - - let output = s2e_u256(sp_value); - assert_eq!(output, eth_value); - } -} diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index 8fdfbcfe38..b78e8ea124 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -42,41 +42,44 @@ use withdraw::WithDraw; pub type AccountId = ::AccountId; -pub enum TransferAction { +/// Transfer Precompile Contract, used to support the exchange of KTON and RING tranfer. +/// +/// The contract address: 0000000000000000000000000000000000000015 +pub enum Transfer { + /// Transfer RING bach from dvm to darwinia RingBack, - KtonAction, + /// Transfer KTON between darwinia and dvm contract + KtonTransfer, _Impossible(PhantomData), } -impl Precompile for TransferAction { +impl Precompile for Transfer { fn execute( input: &[u8], target_gas: Option, context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { match which_action::(&input) { - Ok(TransferAction::RingBack) => { + Ok(Transfer::RingBack) => { WithDraw::::execute(&input, target_gas, context)?; } - Ok(TransferAction::KtonAction) => { + Ok(Transfer::KtonTransfer) => { KtonAction::::execute(&input, target_gas, context)?; } _ => { - return Err(ExitError::Other("Invalid input data length".into())); + return Err(ExitError::Other("Invalid action".into())); } } - Err(ExitError::Other("Invalid input data length".into())) + Err(ExitError::Other("Invalid action".into())) } } -fn which_action( - data: &[u8], -) -> Result, ExitError> { +fn which_action(data: &[u8]) -> Result, ExitError> { if data.len() == 32 { - return Ok(TransferAction::RingBack); + return Ok(Transfer::RingBack); } else if data.len() == 68 { - return Ok(TransferAction::KtonAction); + return Ok(Transfer::KtonTransfer); } else { - return Err(ExitError::Other("Invalid input data length".into())); + return Err(ExitError::Other("Invalid action".into())); } } diff --git a/frame/evm/precompile/src/lib.rs b/frame/evm/precompile/src/lib.rs index 6f84a985d6..e5bd8a9099 100644 --- a/frame/evm/precompile/src/lib.rs +++ b/frame/evm/precompile/src/lib.rs @@ -39,7 +39,7 @@ pub type DarwiniaPrecompiles = ( darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000012 darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000013 darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000014 - darwinia_evm_precompile_transfer::TransferAction, // 0x0000000000000000000000000000000000000015 - darwinia_evm_precompile_kton::Kton, // 0x0000000000000000000000000000000000000016 + darwinia_evm_precompile_transfer::Transfer, // 0x0000000000000000000000000000000000000015 + darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000016 darwinia_evm_precompile_issuing::Issuing, // 0x0000000000000000000000000000000000000017 ); From b324924f95ec54c326650cfe58caf08d2ab4ed46 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 31 May 2021 17:08:00 +0800 Subject: [PATCH 03/45] Rename action things --- .../precompile/contracts/transfer/src/kton.rs | 43 +++++++------------ .../precompile/contracts/transfer/src/lib.rs | 12 +++--- .../contracts/transfer/src/withdraw.rs | 14 +++--- 3 files changed, 27 insertions(+), 42 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 4162f21eb9..fb0be8a225 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -21,21 +21,14 @@ const TRANSFER_AND_CALL_ACTION: &[u8] = b"transfer_and_call(address,uint256)"; const WITHDRAW_ACTION: &[u8] = b"withdraw(bytes32,uint256)"; const KTON_PRECOMPILE: &str = "0000000000000000000000000000000000000016"; -/// Kton Precompile Contract is used to support the exchange of KTON native asset between darwinia and dvm contract -/// -/// The contract address: 0000000000000000000000000000000000000016 -pub struct Kton { - _maker: PhantomData, -} - -pub enum KtonAction { +pub enum Kton { /// Transfer from substrate account to wkton contract - TransferAndCall(TACallData), + TransferAndCall(CallData), /// Withdraw from wkton contract to substrate account Withdraw(WithdrawData), } -impl KtonAction { +impl Kton { pub fn execute( input: &[u8], target_limit: Option, @@ -45,7 +38,7 @@ impl KtonAction { let action = which_action::(&input)?; match action { - KtonAction::TransferAndCall(call_data) => { + Kton::TransferAndCall(call_data) => { // Ensure wkton is a contract ensure!( !Module::::is_contract_code_empty(&call_data.wkton_address), @@ -91,7 +84,7 @@ impl KtonAction { Ok((ExitSucceed::Returned, vec![], 20000)) } - KtonAction::Withdraw(wd) => { + Kton::Withdraw(wd) => { // Ensure wkton is a contract ensure!( !Module::::is_contract_code_empty(&context.caller), @@ -132,33 +125,31 @@ impl KtonAction { } /// which action depends on the function selector -pub fn which_action( - input_data: &[u8], -) -> Result, ExitError> { +pub fn which_action(input_data: &[u8]) -> Result, ExitError> { let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; if &input_data[0..4] == transfer_and_call_action { - let decoded_data = TACallData::decode(&input_data[4..])?; - return Ok(KtonAction::TransferAndCall(decoded_data)); + let decoded_data = CallData::decode(&input_data[4..])?; + return Ok(Kton::TransferAndCall(decoded_data)); } else if &input_data[0..4] == withdraw_action { let decoded_data = WithdrawData::decode(&input_data[4..])?; - return Ok(KtonAction::Withdraw(decoded_data)); + return Ok(Kton::Withdraw(decoded_data)); } Err(ExitError::Other("Invalid Action!".into())) } #[derive(Debug, PartialEq, Eq)] -pub struct TACallData { +pub struct CallData { wkton_address: H160, value: U256, } -impl TACallData { +impl CallData { pub fn decode(data: &[u8]) -> Result { let tokens = ethabi::decode(&[ParamType::Address, ParamType::Uint(256)], &data) .map_err(|_| ExitError::Other("ethabi decoded error".into()))?; match (tokens[0].clone(), tokens[1].clone()) { - (Token::Address(eth_wkton_address), Token::Uint(eth_value)) => Ok(TACallData { + (Token::Address(eth_wkton_address), Token::Uint(eth_value)) => Ok(CallData { wkton_address: util::e2s_address(eth_wkton_address), value: util::e2s_u256(eth_value), }), @@ -191,17 +182,15 @@ impl WithdrawData { } /// which action depends on the function selector -pub fn which_kton_action( - input_data: &[u8], -) -> Result, ExitError> { +pub fn which_kton_action(input_data: &[u8]) -> Result, ExitError> { let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; if &input_data[0..4] == transfer_and_call_action { - let decoded_data = TACallData::decode(&input_data[4..])?; - return Ok(KtonAction::TransferAndCall(decoded_data)); + let decoded_data = CallData::decode(&input_data[4..])?; + return Ok(Kton::TransferAndCall(decoded_data)); } else if &input_data[0..4] == withdraw_action { let decoded_data = WithdrawData::decode(&input_data[4..])?; - return Ok(KtonAction::Withdraw(decoded_data)); + return Ok(Kton::Withdraw(decoded_data)); } Err(ExitError::Other("Invalid Action!".into())) } diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index b78e8ea124..c32b8508e6 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -22,8 +22,6 @@ mod kton; pub mod util; mod withdraw; -use frame_support::traits::{Currency, ExistenceRequirement}; -use kton::Kton; use sha3::Digest; use sp_core::{H160, U256}; use sp_runtime::traits::UniqueSaturatedInto; @@ -37,8 +35,9 @@ use darwinia_support::evm::POW_9; use dp_evm::Precompile; use ethabi::{Function, Param, ParamType, Token}; use evm::{Context, ExitError, ExitSucceed}; -use kton::KtonAction; -use withdraw::WithDraw; + +use kton::Kton; +use withdraw::RingBack; pub type AccountId = ::AccountId; @@ -61,10 +60,10 @@ impl Precompile for Transfer { ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { match which_action::(&input) { Ok(Transfer::RingBack) => { - WithDraw::::execute(&input, target_gas, context)?; + RingBack::::transfer(&input, target_gas, context)?; } Ok(Transfer::KtonTransfer) => { - KtonAction::::execute(&input, target_gas, context)?; + Kton::::execute(&input, target_gas, context)?; } _ => { return Err(ExitError::Other("Invalid action".into())); @@ -75,6 +74,7 @@ impl Precompile for Transfer { } fn which_action(data: &[u8]) -> Result, ExitError> { + // TODO: change the way of select action if data.len() == 32 { return Ok(Transfer::RingBack); } else if data.len() == 68 { diff --git a/frame/evm/precompile/contracts/transfer/src/withdraw.rs b/frame/evm/precompile/contracts/transfer/src/withdraw.rs index 3bebc2eec9..323fb9494c 100644 --- a/frame/evm/precompile/contracts/transfer/src/withdraw.rs +++ b/frame/evm/precompile/contracts/transfer/src/withdraw.rs @@ -2,27 +2,23 @@ use crate::AccountId; use codec::Decode; use darwinia_evm::{AddressMapping, Config}; use darwinia_support::evm::POW_9; -use ethabi::{Function, Param, ParamType, Token}; use evm::{Context, ExitError, ExitSucceed}; use frame_support::traits::{Currency, ExistenceRequirement}; -use sp_core::{H160, U256}; +use sp_core::U256; use sp_runtime::traits::UniqueSaturatedInto; -use sp_std::{borrow::ToOwned, marker::PhantomData, prelude::*, vec::Vec}; +use sp_std::{marker::PhantomData, prelude::*, vec::Vec}; -/// WithDraw Precompile Contract, used to withdraw balance from evm account to darwinia account -/// -/// The contract address: 0000000000000000000000000000000000000015 -pub struct WithDraw { +pub struct RingBack { _maker: PhantomData, } -impl WithDraw { +impl RingBack { /// The Withdraw process is divided into two part: /// 1. parse the withdrawal address from the input parameter and get the contract address and value from the context /// 2. transfer from the contract address to withdrawal address /// /// Input data: 32-bit substrate withdrawal public key - pub(crate) fn execute( + pub(crate) fn transfer( input: &[u8], _: Option, context: &Context, From 9fb363b44819cebc5b005837f61ac07d374b5396 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 31 May 2021 17:23:57 +0800 Subject: [PATCH 04/45] Add prefix to ringback and kton execution --- .../precompile/contracts/transfer/src/kton.rs | 16 +--------------- .../evm/precompile/contracts/transfer/src/lib.rs | 11 ++++------- .../transfer/src/{withdraw.rs => ring.rs} | 0 3 files changed, 5 insertions(+), 22 deletions(-) rename frame/evm/precompile/contracts/transfer/src/{withdraw.rs => ring.rs} (100%) diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index fb0be8a225..0f8cdce5d4 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -29,7 +29,7 @@ pub enum Kton { } impl Kton { - pub fn execute( + pub fn transfer( input: &[u8], target_limit: Option, context: &Context, @@ -181,20 +181,6 @@ impl WithdrawData { } } -/// which action depends on the function selector -pub fn which_kton_action(input_data: &[u8]) -> Result, ExitError> { - let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; - let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; - if &input_data[0..4] == transfer_and_call_action { - let decoded_data = CallData::decode(&input_data[4..])?; - return Ok(Kton::TransferAndCall(decoded_data)); - } else if &input_data[0..4] == withdraw_action { - let decoded_data = WithdrawData::decode(&input_data[4..])?; - return Ok(Kton::Withdraw(decoded_data)); - } - Err(ExitError::Other("Invalid Action!".into())) -} - fn make_call_data( sp_address: sp_core::H160, sp_value: sp_core::U256, diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index c32b8508e6..ba4182c02a 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -19,8 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] mod kton; +mod ring; pub mod util; -mod withdraw; use sha3::Digest; use sp_core::{H160, U256}; @@ -37,7 +37,7 @@ use ethabi::{Function, Param, ParamType, Token}; use evm::{Context, ExitError, ExitSucceed}; use kton::Kton; -use withdraw::RingBack; +use ring::RingBack; pub type AccountId = ::AccountId; @@ -63,7 +63,7 @@ impl Precompile for Transfer { RingBack::::transfer(&input, target_gas, context)?; } Ok(Transfer::KtonTransfer) => { - Kton::::execute(&input, target_gas, context)?; + Kton::::transfer(&input, target_gas, context)?; } _ => { return Err(ExitError::Other("Invalid action".into())); @@ -74,12 +74,9 @@ impl Precompile for Transfer { } fn which_action(data: &[u8]) -> Result, ExitError> { - // TODO: change the way of select action if data.len() == 32 { return Ok(Transfer::RingBack); - } else if data.len() == 68 { - return Ok(Transfer::KtonTransfer); } else { - return Err(ExitError::Other("Invalid action".into())); + return Ok(Transfer::KtonTransfer); } } diff --git a/frame/evm/precompile/contracts/transfer/src/withdraw.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs similarity index 100% rename from frame/evm/precompile/contracts/transfer/src/withdraw.rs rename to frame/evm/precompile/contracts/transfer/src/ring.rs From c2c042256aa06cf02a77adb2b276c1d2397e3836 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Mon, 31 May 2021 23:00:51 +0800 Subject: [PATCH 05/45] Update ci test precompile address --- .../precompile/contracts/transfer/src/kton.rs | 10 ++++++++-- .../precompile/contracts/transfer/src/lib.rs | 19 ++++++------------- script_tests/tests/test_kton.js | 2 +- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 0f8cdce5d4..3646d495de 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -31,7 +31,7 @@ pub enum Kton { impl Kton { pub fn transfer( input: &[u8], - target_limit: Option, + target_gas: Option, context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { let helper = U256::from(POW_9); @@ -69,7 +69,7 @@ impl Kton { call_data.wkton_address, raw_input.to_vec(), U256::zero(), - target_limit.unwrap_or_default(), + target_gas.unwrap_or_default(), None, None, T::config(), @@ -138,6 +138,12 @@ pub fn which_action(input_data: &[u8]) -> Result bool { + let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; + let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; + &data[0..4] == transfer_and_call_action || &data[0..4] == withdraw_action +} + #[derive(Debug, PartialEq, Eq)] pub struct CallData { wkton_address: H160, diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index ba4182c02a..b49b05bc32 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -59,24 +59,17 @@ impl Precompile for Transfer { context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { match which_action::(&input) { - Ok(Transfer::RingBack) => { - RingBack::::transfer(&input, target_gas, context)?; - } - Ok(Transfer::KtonTransfer) => { - Kton::::transfer(&input, target_gas, context)?; - } - _ => { - return Err(ExitError::Other("Invalid action".into())); - } + Ok(Transfer::RingBack) => RingBack::::transfer(&input, target_gas, context), + Ok(Transfer::KtonTransfer) => Kton::::transfer(&input, target_gas, context), + _ => Err(ExitError::Other("Invalid action".into())), } - Err(ExitError::Other("Invalid action".into())) } } fn which_action(data: &[u8]) -> Result, ExitError> { - if data.len() == 32 { - return Ok(Transfer::RingBack); + if !kton::is_kton_action(data) { + Ok(Transfer::RingBack) } else { - return Ok(Transfer::KtonTransfer); + Ok(Transfer::KtonTransfer) } } diff --git a/script_tests/tests/test_kton.js b/script_tests/tests/test_kton.js index c0de6a8a63..c0ad560213 100644 --- a/script_tests/tests/test_kton.js +++ b/script_tests/tests/test_kton.js @@ -311,7 +311,7 @@ const abi = [ const jsontest = new web3.eth.Contract(abi); jsontest.options.from = conf.address; jsontest.options.gas = conf.gas; -const addressTo = "0x0000000000000000000000000000000000000016"; +const addressTo = "0x0000000000000000000000000000000000000015"; describe("Test Kton Precompile", function () { after(() => { From 520fad2815e04250954ee97fdf1f993a98a78e77 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 1 Jun 2021 15:06:19 +0800 Subject: [PATCH 06/45] Add test for is_kton_transfer --- Cargo.lock | 1 + .../precompile/contracts/transfer/Cargo.toml | 3 ++ .../precompile/contracts/transfer/src/kton.rs | 38 ++++++++++++++++++- .../precompile/contracts/transfer/src/lib.rs | 32 +++++++--------- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5595c4668a..e869c56539 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1794,6 +1794,7 @@ dependencies = [ name = "darwinia-evm-precompile-transfer" version = "2.4.0" dependencies = [ + "array-bytes", "darwinia-evm", "darwinia-support", "dp-evm", diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index 63807f3d8b..20bc39274b 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -33,6 +33,9 @@ ethereum-types = { version = "0.11.0", default-features = false } dvm-ethereum = { default-features = false, path = "../../.././../dvm" } log = { version = "0.4.14" } +[dev-dependencies] +array-bytes = { version = "1.1.0" } + [features] default = ["std"] diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 3646d495de..c7f10fa737 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -138,7 +138,7 @@ pub fn which_action(input_data: &[u8]) -> Result bool { +pub fn is_kton_transfer(data: &[u8]) -> bool { let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; &data[0..4] == transfer_and_call_action || &data[0..4] == withdraw_action @@ -211,3 +211,39 @@ fn make_call_data( func.encode_input(&[Token::Address(eth_address), Token::Uint(eth_value)]) .map_err(|_| ExitError::Other("Make call data error happened".into())) } + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + + #[test] + fn test_make_input() { + let mock_address = + sp_core::H160::from_str("Aa01a1bEF0557fa9625581a293F3AA7770192632").unwrap(); + let mock_value_1 = sp_core::U256::from(30); + let expected_str = "0x47e7ef24000000000000000000000000aa01a1bef0557fa9625581a293f3aa7770192632000000000000000000000000000000000000000000000000000000000000001e"; + + let encoded_str = + array_bytes::bytes2hex("0x", make_call_data(mock_address, mock_value_1).unwrap()); + assert_eq!(encoded_str, expected_str); + + let mock_value_2 = sp_core::U256::from(25); + let encoded_str = + array_bytes::bytes2hex("0x", make_call_data(mock_address, mock_value_2).unwrap()); + assert_ne!(encoded_str, expected_str); + } + + #[test] + fn test_is_kton_transfer() { + let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; + let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; + + let data = vec![0; 32]; + assert!(!is_kton_transfer(&data)); + let data1 = transfer_and_call_action; + assert!(is_kton_transfer(&data1)); + let data2 = withdraw_action; + assert!(is_kton_transfer(&data2)); + } +} diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index b49b05bc32..27f385b58d 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -22,28 +22,22 @@ mod kton; mod ring; pub mod util; -use sha3::Digest; -use sp_core::{H160, U256}; -use sp_runtime::traits::UniqueSaturatedInto; -use sp_std::marker::PhantomData; -use sp_std::prelude::*; +// --- substrate --- use sp_std::vec::Vec; - -use codec::Decode; -use darwinia_evm::{AddressMapping, Config}; -use darwinia_support::evm::POW_9; +use sp_std::{marker::PhantomData, prelude::*}; +// --- darwinia --- use dp_evm::Precompile; -use ethabi::{Function, Param, ParamType, Token}; -use evm::{Context, ExitError, ExitSucceed}; - use kton::Kton; use ring::RingBack; +// --- crate --- +use evm::{Context, ExitError, ExitSucceed}; pub type AccountId = ::AccountId; /// Transfer Precompile Contract, used to support the exchange of KTON and RING tranfer. /// /// The contract address: 0000000000000000000000000000000000000015 +#[derive(PartialEq, Eq, Debug)] pub enum Transfer { /// Transfer RING bach from dvm to darwinia RingBack, @@ -58,18 +52,18 @@ impl Precompile for Transfer { target_gas: Option, context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { - match which_action::(&input) { - Ok(Transfer::RingBack) => RingBack::::transfer(&input, target_gas, context), - Ok(Transfer::KtonTransfer) => Kton::::transfer(&input, target_gas, context), + match which_transfer::(&input) { + Transfer::RingBack => RingBack::::transfer(&input, target_gas, context), + Transfer::KtonTransfer => Kton::::transfer(&input, target_gas, context), _ => Err(ExitError::Other("Invalid action".into())), } } } -fn which_action(data: &[u8]) -> Result, ExitError> { - if !kton::is_kton_action(data) { - Ok(Transfer::RingBack) +fn which_transfer(data: &[u8]) -> Transfer { + if !kton::is_kton_transfer(data) { + Transfer::RingBack } else { - Ok(Transfer::KtonTransfer) + Transfer::KtonTransfer } } From 229514c7569fe091fab6fac3e244fb0ac9ced4b8 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 1 Jun 2021 15:26:10 +0800 Subject: [PATCH 07/45] Clean code --- .../precompile/contracts/transfer/Cargo.toml | 21 +++--- .../precompile/contracts/transfer/src/kton.rs | 70 ++++++++++--------- .../precompile/contracts/transfer/src/ring.rs | 13 ++-- script_tests/tests/test_kton.js | 2 +- 4 files changed, 55 insertions(+), 51 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index 20bc39274b..f974173cc0 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -11,13 +11,18 @@ version = "2.4.0" [dependencies] # crates -codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } -evm = { version = "0.25.0", features = ["with-codec"], default-features = false } -ripemd160 = { version = "0.9", default-features = false } +codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } +evm = { version = "0.25.0", features = ["with-codec"], default-features = false } +ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std", default-features = false } +ethereum-types = { version = "0.11.0", default-features = false } +log = { version = "0.4.14" } +ripemd160 = { version = "0.9", default-features = false } +sha3 = { version = "0.9.1", default-features = false } # darwinia darwinia-evm = { default-features = false, path = "../../../" } darwinia-support = { default-features = false, path = "../../../../support" } dp-evm = { default-features = false, path = "../../../../../primitives/evm" } +dvm-ethereum = { default-features = false, path = "../../.././../dvm" } # substrate frame-support = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } frame-system = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } @@ -27,12 +32,6 @@ sp-io = { default-features = false, git = "https://github.com/darwini sp-runtime = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } sp-std = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } -ethabi = { default-features = false, git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std" } -sha3 = { version = "0.9.1", default-features = false } -ethereum-types = { version = "0.11.0", default-features = false } -dvm-ethereum = { default-features = false, path = "../../.././../dvm" } -log = { version = "0.4.14" } - [dev-dependencies] array-bytes = { version = "1.1.0" } @@ -48,16 +47,16 @@ std = [ crates-std = [ "codec/std", "evm/std", + "ethereum-types/std", "ripemd160/std", "sha3/std", - "ethereum-types/std", ] darwinia-std = [ + "ethabi/std", "darwinia-evm/std", "darwinia-support/std", "dp-evm/std", - "ethabi/std", "dvm-ethereum/std", ] diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index c7f10fa737..917bf3fe1b 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -1,25 +1,28 @@ +// --- substrate --- +use sp_core::{H160, U256}; +use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; +use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; +// --- darwinia --- use crate::util; use crate::AccountId; -use codec::Decode; -use core::str::FromStr; -use darwinia_evm::AddressMapping; -use darwinia_evm::{Account, AccountBasic, Config, Module, Runner}; +use darwinia_evm::{Account, AccountBasic, Module, Runner}; use darwinia_support::evm::POW_9; use dvm_ethereum::{ account_basic::{KtonRemainBalance, RemainBalanceOp}, KtonBalance, }; +// --- crates --- +use codec::Decode; +use core::str::FromStr; use ethabi::{Function, Param, ParamType, Token}; use evm::{Context, ExitError, ExitReason, ExitSucceed}; use frame_support::{ensure, traits::Currency}; use sha3::Digest; -use sp_core::{H160, U256}; -use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; -use sp_std::{borrow::ToOwned, marker::PhantomData, prelude::*, vec::Vec}; const TRANSFER_AND_CALL_ACTION: &[u8] = b"transfer_and_call(address,uint256)"; const WITHDRAW_ACTION: &[u8] = b"withdraw(bytes32,uint256)"; -const KTON_PRECOMPILE: &str = "0000000000000000000000000000000000000016"; +// const KTON_PRECOMPILE: &str = "0000000000000000000000000000000000000016"; +const KTON_PRECOMPILE: &str = "0000000000000000000000000000000000000015"; pub enum Kton { /// Transfer from substrate account to wkton contract @@ -137,13 +140,37 @@ pub fn which_action(input_data: &[u8]) -> Result bool { let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; &data[0..4] == transfer_and_call_action || &data[0..4] == withdraw_action } +fn make_call_data( + sp_address: sp_core::H160, + sp_value: sp_core::U256, +) -> Result, ExitError> { + let eth_address = util::s2e_address(sp_address); + let eth_value = util::s2e_u256(sp_value); + let func = Function { + name: "deposit".to_owned(), + inputs: vec![ + Param { + name: "address".to_owned(), + kind: ParamType::Address, + }, + Param { + name: "value".to_owned(), + kind: ParamType::Uint(256), + }, + ], + outputs: vec![], + constant: false, + }; + func.encode_input(&[Token::Address(eth_address), Token::Uint(eth_value)]) + .map_err(|_| ExitError::Other("Make call data error happened".into())) +} + #[derive(Debug, PartialEq, Eq)] pub struct CallData { wkton_address: H160, @@ -187,31 +214,6 @@ impl WithdrawData { } } -fn make_call_data( - sp_address: sp_core::H160, - sp_value: sp_core::U256, -) -> Result, ExitError> { - let eth_address = util::s2e_address(sp_address); - let eth_value = util::s2e_u256(sp_value); - let func = Function { - name: "deposit".to_owned(), - inputs: vec![ - Param { - name: "address".to_owned(), - kind: ParamType::Address, - }, - Param { - name: "value".to_owned(), - kind: ParamType::Uint(256), - }, - ], - outputs: vec![], - constant: false, - }; - func.encode_input(&[Token::Address(eth_address), Token::Uint(eth_value)]) - .map_err(|_| ExitError::Other("Make call data error happened".into())) -} - #[cfg(test)] mod tests { use super::*; diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 323fb9494c..4e7fff2ac8 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -1,12 +1,15 @@ -use crate::AccountId; -use codec::Decode; -use darwinia_evm::{AddressMapping, Config}; -use darwinia_support::evm::POW_9; -use evm::{Context, ExitError, ExitSucceed}; +// --- substrate --- use frame_support::traits::{Currency, ExistenceRequirement}; use sp_core::U256; use sp_runtime::traits::UniqueSaturatedInto; use sp_std::{marker::PhantomData, prelude::*, vec::Vec}; +// --- darwinia --- +use crate::AccountId; +use darwinia_evm::{AddressMapping, Config}; +use darwinia_support::evm::POW_9; +// --- crates --- +use codec::Decode; +use evm::{Context, ExitError, ExitSucceed}; pub struct RingBack { _maker: PhantomData, diff --git a/script_tests/tests/test_kton.js b/script_tests/tests/test_kton.js index c0ad560213..fa1ee954de 100644 --- a/script_tests/tests/test_kton.js +++ b/script_tests/tests/test_kton.js @@ -6,7 +6,7 @@ const web3 = new Web3(conf.host); web3.eth.accounts.wallet.add(conf.privKey); // Wkton bytecode const bytecode = - "60806040526040805190810160405280600c81526020017f57726170706564204b544f4e00000000000000000000000000000000000000008152506000908051906020019061004f92919061010c565b506040805190810160405280600581526020017f574b544f4e0000000000000000000000000000000000000000000000000000008152506001908051906020019061009b92919061010c565b506012600260006101000a81548160ff021916908360ff1602179055506016600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561010657600080fd5b506101b1565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061014d57805160ff191683800117855561017b565b8280016001018555821561017b579182015b8281111561017a57825182559160200191906001019061015f565b5b509050610188919061018c565b5090565b6101ae91905b808211156101aa576000816000905550600101610192565b5090565b90565b610f3680620001c16000396000f3006080604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063040cf020146100bf57806306fdde03146100fa578063095ea7b31461018a57806318160ddd146101ef57806323b872dd1461021a578063313ce5671461029f57806347e7ef24146102d057806370a082311461031d57806395d89b4114610374578063a9059cbb14610404578063b548602014610469578063dd62ed3e146104c0575b600080fd5b3480156100cb57600080fd5b506100f8600480360381019080803560001916906020019092919080359060200190929190505050610537565b005b34801561010657600080fd5b5061010f610786565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014f578082015181840152602081019050610134565b50505050905090810190601f16801561017c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561019657600080fd5b506101d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610824565b604051808215151515815260200191505060405180910390f35b3480156101fb57600080fd5b50610204610916565b6040518082815260200191505060405180910390f35b34801561022657600080fd5b50610285600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610920565b604051808215151515815260200191505060405180910390f35b3480156102ab57600080fd5b506102b4610c6d565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102dc57600080fd5b5061031b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c80565b005b34801561032957600080fd5b5061035e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610df4565b6040518082815260200191505060405180910390f35b34801561038057600080fd5b50610389610e0c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c95780820151818401526020810190506103ae565b50505050905090810190601f1680156103f65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561041057600080fd5b5061044f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610eaa565b604051808215151515815260200191505060405180910390f35b34801561047557600080fd5b5061047e610ebf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104cc57600080fd5b50610521600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ee5565b6040518082815260200191505060405180910390f35b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561058757600080fd5b8160036000828254039250508190555081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660405180807f776974686472617728627974657333322c75696e743235362900000000000000815250601901905060405180910390207c0100000000000000000000000000000000000000000000000000000000900484846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001828152602001925050506000604051808303816000875af1925050509050801515610745576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f574b544f4e3a2057495448445241575f4641494c45440000000000000000000081525060200191505060405180910390fd5b82600019167fa4dfdde26c326c8cced668e6a665f4efc3f278bdc9101cdedc4f725abd63a1ee836040518082815260200191505060405180910390a2505050565b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561081c5780601f106107f15761010080835404028352916020019161081c565b820191906000526020600020905b8154815290600101906020018083116107ff57829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b6000600354905090565b600081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561097057600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614158015610a4857507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b15610b635781600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ad857600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b600260009054906101000a900460ff1681565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d45576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f574b544f4e3a205045524d495353494f4e00000000000000000000000000000081525060200191505060405180910390fd5b8060036000828254019250508190555080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c826040518082815260200191505060405180910390a25050565b60046020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ea25780601f10610e7757610100808354040283529160200191610ea2565b820191906000526020600020905b815481529060010190602001808311610e8557829003601f168201915b505050505081565b6000610eb7338484610920565b905092915050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60056020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820b92fe8da73c1c47346ad917559ce98eaafbc3323d4a8081f89fa3acc508cff610029"; + "60806040526040805190810160405280600d81526020017f5772617070656420434b544f4e00000000000000000000000000000000000000815250600090805190602001906200005192919062000112565b506040805190810160405280600681526020017f57434b544f4e0000000000000000000000000000000000000000000000000000815250600190805190602001906200009f92919062000112565b506012600260006101000a81548160ff021916908360ff1602179055506015600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200010b57600080fd5b50620001c1565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200015557805160ff191683800117855562000186565b8280016001018555821562000186579182015b828111156200018557825182559160200191906001019062000168565b5b50905062000195919062000199565b5090565b620001be91905b80821115620001ba576000816000905550600101620001a0565b5090565b90565b61100280620001d16000396000f3006080604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063040cf020146100bf57806306fdde03146100fa578063095ea7b31461018a57806318160ddd146101ef57806323b872dd1461021a578063313ce5671461029f57806347e7ef24146102d057806370a082311461031d57806395d89b4114610374578063a9059cbb14610404578063b548602014610469578063dd62ed3e146104c0575b600080fd5b3480156100cb57600080fd5b506100f8600480360381019080803560001916906020019092919080359060200190929190505050610537565b005b34801561010657600080fd5b5061010f6107ec565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014f578082015181840152602081019050610134565b50505050905090810190601f16801561017c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561019657600080fd5b506101d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061088a565b604051808215151515815260200191505060405180910390f35b3480156101fb57600080fd5b5061020461097c565b6040518082815260200191505060405180910390f35b34801561022657600080fd5b50610285600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610986565b604051808215151515815260200191505060405180910390f35b3480156102ab57600080fd5b506102b4610cd3565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102dc57600080fd5b5061031b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610ce6565b005b34801561032957600080fd5b5061035e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ec0565b6040518082815260200191505060405180910390f35b34801561038057600080fd5b50610389610ed8565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c95780820151818401526020810190506103ae565b50505050905090810190601f1680156103f65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561041057600080fd5b5061044f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f76565b604051808215151515815260200191505060405180910390f35b34801561047557600080fd5b5061047e610f8b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104cc57600080fd5b50610521600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fb1565b6040518082815260200191505060405180910390f35b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561058757600080fd5b8160036000828254039250508190555081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660405180807f776974686472617728627974657333322c75696e743235362900000000000000815250601901905060405180910390207c0100000000000000000000000000000000000000000000000000000000900484846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001828152602001925050506000604051808303816000875af1925050509050801515610745576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f574b544f4e3a2057495448445241575f4641494c45440000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a382600019167fa4dfdde26c326c8cced668e6a665f4efc3f278bdc9101cdedc4f725abd63a1ee836040518082815260200191505060405180910390a2505050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108825780601f1061085757610100808354040283529160200191610882565b820191906000526020600020905b81548152906001019060200180831161086557829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b6000600354905090565b600081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156109d657600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614158015610aae57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b15610bc95781600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610b3e57600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b600260009054906101000a900460ff1681565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610dab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f574b544f4e3a205045524d495353494f4e00000000000000000000000000000081525060200191505060405180910390fd5b8060036000828254019250508190555080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a38173ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c826040518082815260200191505060405180910390a25050565b60046020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f6e5780601f10610f4357610100808354040283529160200191610f6e565b820191906000526020600020905b815481529060010190602001808311610f5157829003601f168201915b505050505081565b6000610f83338484610986565b905092915050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60056020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820e2f50a774ba846fa1c029233d81ae94557ebb22046bdc94b10c813c83a2c94660029"; const abi = [ { constant: false, From 15fb6f77a6493abf11c208045fd0293cf786c83f Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 1 Jun 2021 16:35:37 +0800 Subject: [PATCH 08/45] Update caller address --- frame/evm/precompile/contracts/transfer/Cargo.toml | 4 ++-- frame/evm/precompile/contracts/transfer/src/kton.rs | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index f974173cc0..1d61803587 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -46,14 +46,14 @@ std = [ crates-std = [ "codec/std", - "evm/std", + "ethabi/std", "ethereum-types/std", + "evm/std", "ripemd160/std", "sha3/std", ] darwinia-std = [ - "ethabi/std", "darwinia-evm/std", "darwinia-support/std", "dp-evm/std", diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 917bf3fe1b..b7aea8915a 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -21,8 +21,7 @@ use sha3::Digest; const TRANSFER_AND_CALL_ACTION: &[u8] = b"transfer_and_call(address,uint256)"; const WITHDRAW_ACTION: &[u8] = b"withdraw(bytes32,uint256)"; -// const KTON_PRECOMPILE: &str = "0000000000000000000000000000000000000016"; -const KTON_PRECOMPILE: &str = "0000000000000000000000000000000000000015"; +const CALLER_PRECOMPILE: &str = "0000000000000000000000000000000000000015"; pub enum Kton { /// Transfer from substrate account to wkton contract @@ -65,7 +64,7 @@ impl Kton { call_data.value, )?; // Call WKTON wrapped contract deposit - let precompile_address = H160::from_str(KTON_PRECOMPILE).unwrap_or_default(); + let precompile_address = H160::from_str(CALLER_PRECOMPILE).unwrap_or_default(); let raw_input = make_call_data(context.caller, call_data.value)?; if let Ok(call_res) = T::Runner::call( precompile_address, From 4e1d0b3a68a82c868f07818db67189bb68b02c13 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 1 Jun 2021 22:06:48 +0800 Subject: [PATCH 09/45] Fix the failed unit test --- frame/dvm/src/mock.rs | 25 ++++++++++++++----- .../precompile/contracts/transfer/src/lib.rs | 5 ++-- .../precompile/contracts/transfer/src/ring.rs | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index ce9c1aabac..ba5ffb6b48 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -22,17 +22,20 @@ use crate::{ *, }; use codec::{Decode, Encode}; -use darwinia_evm::{AddressMapping, EnsureAddressTruncated, FeeCalculator, IssuingHandler}; +use darwinia_evm::{AddressMapping, EnsureAddressTruncated, FeeCalculator}; +use dp_evm::Precompile; use ethereum::{TransactionAction, TransactionSignature}; -use frame_support::{traits::GenesisBuild, ConsensusEngineId, PalletId}; +use evm::{Context, ExitError, ExitSucceed}; +use frame_support::{traits::GenesisBuild, ConsensusEngineId}; use frame_system::mocking::*; use rlp::*; use sp_core::{H160, H256, U256}; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, - AccountId32, DispatchResult, Perbill, RuntimeDebug, + AccountId32, Perbill, RuntimeDebug, }; +use sp_std::{marker::PhantomData, vec::Vec}; darwinia_support::impl_test_account_data! {} @@ -136,7 +139,6 @@ impl FindAuthor for EthereumFindAuthor { frame_support::parameter_types! { pub const TransactionByteFee: u64 = 1; pub const ChainId: u64 = 42; - pub const EVMPalletId: PalletId = PalletId(*b"py/evmpa"); pub const BlockGasLimit: U256 = U256::MAX; } @@ -150,6 +152,17 @@ impl AddressMapping for HashedAddressMapping { } } +pub struct RingBack(PhantomData); +impl Precompile for RingBack { + fn execute( + input: &[u8], + target_gas: Option, + context: &Context, + ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + darwinia_evm_precompile_transfer::ring::RingBack::::transfer(&input, target_gas, context) + } +} + impl darwinia_evm::Config for Test { type FeeCalculator = FixedGasPrice; type GasWeightMapping = (); @@ -163,7 +176,7 @@ impl darwinia_evm::Config for Test { darwinia_evm_precompile_simple::Sha256, darwinia_evm_precompile_simple::Ripemd160, darwinia_evm_precompile_simple::Identity, - darwinia_evm_precompile_withdraw::WithDraw, + RingBack, ); type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; @@ -173,7 +186,7 @@ impl darwinia_evm::Config for Test { type IssuingHandler = (); } -impl Config for Test { +impl dvm_ethereum::Config for Test { type Event = (); type FindAuthor = EthereumFindAuthor; type StateRoot = IntermediateStateRoot; diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index 27f385b58d..b21a02b3de 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -18,8 +18,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -mod kton; -mod ring; +pub mod kton; +pub mod ring; pub mod util; // --- substrate --- @@ -37,7 +37,6 @@ pub type AccountId = ::AccountId; /// Transfer Precompile Contract, used to support the exchange of KTON and RING tranfer. /// /// The contract address: 0000000000000000000000000000000000000015 -#[derive(PartialEq, Eq, Debug)] pub enum Transfer { /// Transfer RING bach from dvm to darwinia RingBack, diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 4e7fff2ac8..a755872004 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -21,7 +21,7 @@ impl RingBack { /// 2. transfer from the contract address to withdrawal address /// /// Input data: 32-bit substrate withdrawal public key - pub(crate) fn transfer( + pub fn transfer( input: &[u8], _: Option, context: &Context, From edcbcf854531ba45be67608d5b5a4a7564d896d4 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 2 Jun 2021 15:39:56 +0800 Subject: [PATCH 10/45] Check input length --- frame/evm/precompile/contracts/transfer/src/lib.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index b21a02b3de..050388d24b 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -52,17 +52,20 @@ impl Precompile for Transfer { context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { match which_transfer::(&input) { - Transfer::RingBack => RingBack::::transfer(&input, target_gas, context), - Transfer::KtonTransfer => Kton::::transfer(&input, target_gas, context), + Ok(Transfer::RingBack) => RingBack::::transfer(&input, target_gas, context), + Ok(Transfer::KtonTransfer) => Kton::::transfer(&input, target_gas, context), _ => Err(ExitError::Other("Invalid action".into())), } } } -fn which_transfer(data: &[u8]) -> Transfer { +fn which_transfer(data: &[u8]) -> Result, ExitError> { + if data.len() < 4 { + return Err(ExitError::Other("Invalid input data!".into())); + } if !kton::is_kton_transfer(data) { - Transfer::RingBack + Ok(Transfer::RingBack) } else { - Transfer::KtonTransfer + Ok(Transfer::KtonTransfer) } } From 3580efab09827e0629eeaa95f45948b6bf04b981 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 3 Jun 2021 14:20:43 +0800 Subject: [PATCH 11/45] Update conflict issues --- Cargo.lock | 3 +- bin/node/runtime/pangolin/Cargo.toml | 6 +-- bin/node/runtime/pangolin/src/pallets/evm_.rs | 8 +--- frame/evm/precompile/Cargo.toml | 27 ----------- .../precompile/contracts/transfer/src/lib.rs | 15 ++++--- frame/evm/precompile/src/lib.rs | 45 ------------------- frame/support/src/lib.rs | 1 + 7 files changed, 14 insertions(+), 91 deletions(-) delete mode 100644 frame/evm/precompile/Cargo.toml delete mode 100644 frame/evm/precompile/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 3c4a954fe1..3993f26bd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5732,9 +5732,8 @@ dependencies = [ "darwinia-ethereum-relay", "darwinia-evm", "darwinia-evm-precompile-issuing", - "darwinia-evm-precompile-kton", "darwinia-evm-precompile-simple", - "darwinia-evm-precompile-withdraw", + "darwinia-evm-precompile-transfer", "darwinia-header-mmr", "darwinia-header-mmr-rpc-runtime-api", "darwinia-relay-authorities", diff --git a/bin/node/runtime/pangolin/Cargo.toml b/bin/node/runtime/pangolin/Cargo.toml index e00b033603..072200b918 100644 --- a/bin/node/runtime/pangolin/Cargo.toml +++ b/bin/node/runtime/pangolin/Cargo.toml @@ -31,9 +31,8 @@ darwinia-ethereum-issuing = { default-features = false, path = "../../ darwinia-ethereum-relay = { default-features = false, path = "../../../../frame/bridge/ethereum/relay" } darwinia-evm = { default-features = false, path = "../../../../frame/evm" } darwinia-evm-precompile-issuing = { default-features = false, path = "../../../../frame/evm/precompile/contracts/issuing" } -darwinia-evm-precompile-kton = { default-features = false, path = "../../../../frame/evm/precompile/contracts/kton" } darwinia-evm-precompile-simple = { default-features = false, path = "../../../../frame/evm/precompile/contracts/simple" } -darwinia-evm-precompile-withdraw = { default-features = false, path = "../../../../frame/evm/precompile/contracts/withdraw" } +darwinia-evm-precompile-transfer = { default-features = false, path = "../../../../frame/evm/precompile/contracts/transfer" } darwinia-header-mmr = { default-features = false, path = "../../../../frame/header-mmr" } darwinia-header-mmr-rpc-runtime-api = { default-features = false, path = "../../../../frame/header-mmr/rpc/runtime-api" } darwinia-relay-authorities = { default-features = false, path = "../../../../frame/bridge/relay-authorities" } @@ -129,9 +128,8 @@ std = [ "darwinia-ethereum-relay/std", "darwinia-evm/std", "darwinia-evm-precompile-issuing/std", - "darwinia-evm-precompile-kton/std", "darwinia-evm-precompile-simple/std", - "darwinia-evm-precompile-withdraw/std", + "darwinia-evm-precompile-transfer/std", "darwinia-header-mmr/std", "darwinia-header-mmr-rpc-runtime-api/std", "darwinia-relay-authorities/std", diff --git a/bin/node/runtime/pangolin/src/pallets/evm_.rs b/bin/node/runtime/pangolin/src/pallets/evm_.rs index 566d04e24c..c29a3e7d5d 100644 --- a/bin/node/runtime/pangolin/src/pallets/evm_.rs +++ b/bin/node/runtime/pangolin/src/pallets/evm_.rs @@ -1,7 +1,6 @@ pub use darwinia_evm_precompile_issuing::Issuing; -pub use darwinia_evm_precompile_kton::Kton as KtonPrecompile; pub use darwinia_evm_precompile_simple::{ECRecover, Identity, Ripemd160, Sha256}; -pub use darwinia_evm_precompile_withdraw::WithDraw; +pub use darwinia_evm_precompile_transfer::Transfer; // --- crates.io --- use evm::{Context, ExitError, ExitSucceed}; @@ -32,10 +31,7 @@ impl PrecompileSet for PangolinPrecompiles { _ if address == to_address(4) => Some(Identity::execute(input, target_gas, context)), // Darwinia precompiles _ if address == to_address(21) => { - Some(>::execute(input, target_gas, context)) - } - _ if address == to_address(22) => { - Some(>::execute(input, target_gas, context)) + Some(>::execute(input, target_gas, context)) } _ if address == to_address(23) => { Some(>::execute(input, target_gas, context)) diff --git a/frame/evm/precompile/Cargo.toml b/frame/evm/precompile/Cargo.toml deleted file mode 100644 index 7830e7579d..0000000000 --- a/frame/evm/precompile/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -authors = ["Darwinia Network "] -description = "Withdraw precompile for EVM pallet." -edition = "2018" -homepage = "https://darwinia.network/" -license = "GPL-3.0" -name = "darwinia-evm-precompile" -readme = "README.md" -repository = "https://github.com/darwinia-network/darwinia-common/" -version = "2.4.0" - -[dependencies] -# darwinia -darwinia-evm-precompile-empty = { default-features = false, path = "contracts/empty" } -darwinia-evm-precompile-issuing = { default-features = false, path = "contracts/issuing" } -darwinia-evm-precompile-simple = { default-features = false, path = "contracts/simple" } -darwinia-evm-precompile-transfer = { default-features = false, path = "contracts/transfer" } - -[features] -default = ["std"] - -std = [ - "darwinia-evm-precompile-empty/std", - "darwinia-evm-precompile-issuing/std", - "darwinia-evm-precompile-simple/std", - "darwinia-evm-precompile-transfer/std", -] diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index 050388d24b..8fdcf5de03 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -23,9 +23,9 @@ pub mod ring; pub mod util; // --- substrate --- -use sp_std::vec::Vec; -use sp_std::{marker::PhantomData, prelude::*}; +use sp_std::{marker::PhantomData, vec::Vec}; // --- darwinia --- +use darwinia_support::evm::SELECTOR; use dp_evm::Precompile; use kton::Kton; use ring::RingBack; @@ -35,12 +35,10 @@ use evm::{Context, ExitError, ExitSucceed}; pub type AccountId = ::AccountId; /// Transfer Precompile Contract, used to support the exchange of KTON and RING tranfer. -/// -/// The contract address: 0000000000000000000000000000000000000015 pub enum Transfer { - /// Transfer RING bach from dvm to darwinia + /// Transfer RING back from DVM to Darwinia RingBack, - /// Transfer KTON between darwinia and dvm contract + /// Transfer KTON between Darwinia and DVM contract KtonTransfer, _Impossible(PhantomData), } @@ -59,8 +57,11 @@ impl Precompile for Transfer { } } +/// There are two types of transfers: RING transfer and KTON transfer +/// +/// The RingBack has only one action, while KtonTransfer has two: `transfer and call`, `withdraw`. fn which_transfer(data: &[u8]) -> Result, ExitError> { - if data.len() < 4 { + if (data.len() as u32) < SELECTOR { return Err(ExitError::Other("Invalid input data!".into())); } if !kton::is_kton_transfer(data) { diff --git a/frame/evm/precompile/src/lib.rs b/frame/evm/precompile/src/lib.rs deleted file mode 100644 index e5bd8a9099..0000000000 --- a/frame/evm/precompile/src/lib.rs +++ /dev/null @@ -1,45 +0,0 @@ -// This file is part of Darwinia. -// -// Copyright (C) 2018-2021 Darwinia Network -// SPDX-License-Identifier: GPL-3.0 -// -// Darwinia is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Darwinia is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Darwinia. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] - -pub type DarwiniaPrecompiles = ( - darwinia_evm_precompile_simple::ECRecover, // 0x0000000000000000000000000000000000000001 - darwinia_evm_precompile_simple::Sha256, // 0x0000000000000000000000000000000000000002 - darwinia_evm_precompile_simple::Ripemd160, // 0x0000000000000000000000000000000000000003 - darwinia_evm_precompile_simple::Identity, // 0x0000000000000000000000000000000000000004 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000005 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000006 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000007 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000008 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000009 - darwinia_evm_precompile_empty::Empty, // 0x000000000000000000000000000000000000000a - darwinia_evm_precompile_empty::Empty, // 0x000000000000000000000000000000000000000b - darwinia_evm_precompile_empty::Empty, // 0x000000000000000000000000000000000000000c - darwinia_evm_precompile_empty::Empty, // 0x000000000000000000000000000000000000000d - darwinia_evm_precompile_empty::Empty, // 0x000000000000000000000000000000000000000e - darwinia_evm_precompile_empty::Empty, // 0x000000000000000000000000000000000000000f - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000010 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000011 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000012 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000013 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000014 - darwinia_evm_precompile_transfer::Transfer, // 0x0000000000000000000000000000000000000015 - darwinia_evm_precompile_empty::Empty, // 0x0000000000000000000000000000000000000016 - darwinia_evm_precompile_issuing::Issuing, // 0x0000000000000000000000000000000000000017 -); diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index ad01df50b2..d2c3ad918b 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -36,6 +36,7 @@ pub mod evm { pub const POW_9: u32 = 1_000_000_000; pub const INTERNAL_CALLER: H160 = H160::zero(); + pub const SELECTOR: u32 = 4; } #[cfg(test)] From 148e14a9def08ae2edb46bc4afcd55a256d00736 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 3 Jun 2021 14:46:01 +0800 Subject: [PATCH 12/45] Default choose ring back --- frame/evm/precompile/contracts/transfer/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index 8fdcf5de03..ce21da5045 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -64,9 +64,8 @@ fn which_transfer(data: &[u8]) -> Result, E if (data.len() as u32) < SELECTOR { return Err(ExitError::Other("Invalid input data!".into())); } - if !kton::is_kton_transfer(data) { - Ok(Transfer::RingBack) - } else { - Ok(Transfer::KtonTransfer) + if kton::is_kton_transfer(data) { + return Ok(Transfer::KtonTransfer); } + Ok(Transfer::RingBack) } From ed57840e375acfe4f24839b141b497984c7254fc Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 3 Jun 2021 14:50:01 +0800 Subject: [PATCH 13/45] Revert unit test change --- frame/dvm/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index acec162c06..4e2e6d13ce 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -188,7 +188,7 @@ impl darwinia_evm::Config for Test { type IssuingHandler = (); } -impl dvm_ethereum::Config for Test { +impl Config for Test { type Event = (); type FindAuthor = EthereumFindAuthor; type StateRoot = IntermediateStateRoot; From 38b4ed6ae6d0da0e468bfb84707385aabd7215e5 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 3 Jun 2021 14:56:39 +0800 Subject: [PATCH 14/45] Format --- frame/evm/precompile/contracts/transfer/Cargo.toml | 2 +- frame/evm/precompile/contracts/transfer/src/kton.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index 1d61803587..7270ec771b 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -16,7 +16,7 @@ evm = { version = "0.25.0", features = ["with-codec"], default-featur ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std", default-features = false } ethereum-types = { version = "0.11.0", default-features = false } log = { version = "0.4.14" } -ripemd160 = { version = "0.9", default-features = false } +ripemd160 = { version = "0.9.1", default-features = false } sha3 = { version = "0.9.1", default-features = false } # darwinia darwinia-evm = { default-features = false, path = "../../../" } diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index b7aea8915a..0db2a2a3f9 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -1,4 +1,5 @@ // --- substrate --- +use frame_support::{ensure, traits::Currency}; use sp_core::{H160, U256}; use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; @@ -16,7 +17,6 @@ use codec::Decode; use core::str::FromStr; use ethabi::{Function, Param, ParamType, Token}; use evm::{Context, ExitError, ExitReason, ExitSucceed}; -use frame_support::{ensure, traits::Currency}; use sha3::Digest; const TRANSFER_AND_CALL_ACTION: &[u8] = b"transfer_and_call(address,uint256)"; @@ -30,7 +30,7 @@ pub enum Kton { Withdraw(WithdrawData), } -impl Kton { +impl Kton { pub fn transfer( input: &[u8], target_gas: Option, From dfa2a7812a8cd0e0a638891327c39204a1a2feba Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 3 Jun 2021 15:39:52 +0800 Subject: [PATCH 15/45] Selector to usize --- .../precompile/contracts/transfer/src/kton.rs | 25 ++++++++++--------- .../precompile/contracts/transfer/src/lib.rs | 2 +- frame/support/src/lib.rs | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 0db2a2a3f9..c965a338a1 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -7,7 +7,7 @@ use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; use crate::util; use crate::AccountId; use darwinia_evm::{Account, AccountBasic, Module, Runner}; -use darwinia_support::evm::POW_9; +use darwinia_support::evm::{POW_9, SELECTOR}; use dvm_ethereum::{ account_basic::{KtonRemainBalance, RemainBalanceOp}, KtonBalance, @@ -128,21 +128,21 @@ impl Kton { /// which action depends on the function selector pub fn which_action(input_data: &[u8]) -> Result, ExitError> { - let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; - let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; - if &input_data[0..4] == transfer_and_call_action { - let decoded_data = CallData::decode(&input_data[4..])?; + let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..SELECTOR]; + let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..SELECTOR]; + if &input_data[0..SELECTOR] == transfer_and_call_action { + let decoded_data = CallData::decode(&input_data[SELECTOR..])?; return Ok(Kton::TransferAndCall(decoded_data)); - } else if &input_data[0..4] == withdraw_action { - let decoded_data = WithdrawData::decode(&input_data[4..])?; + } else if &input_data[0..SELECTOR] == withdraw_action { + let decoded_data = WithdrawData::decode(&input_data[SELECTOR..])?; return Ok(Kton::Withdraw(decoded_data)); } Err(ExitError::Other("Invalid Action!".into())) } pub fn is_kton_transfer(data: &[u8]) -> bool { - let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; - let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; - &data[0..4] == transfer_and_call_action || &data[0..4] == withdraw_action + let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..SELECTOR]; + let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..SELECTOR]; + &data[0..SELECTOR] == transfer_and_call_action || &data[0..SELECTOR] == withdraw_action } fn make_call_data( @@ -237,8 +237,9 @@ mod tests { #[test] fn test_is_kton_transfer() { - let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..4]; - let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..4]; + let transfer_and_call_action = + &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..SELECTOR]; + let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..SELECTOR]; let data = vec![0; 32]; assert!(!is_kton_transfer(&data)); diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index ce21da5045..271c9fba97 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -61,7 +61,7 @@ impl Precompile for Transfer { /// /// The RingBack has only one action, while KtonTransfer has two: `transfer and call`, `withdraw`. fn which_transfer(data: &[u8]) -> Result, ExitError> { - if (data.len() as u32) < SELECTOR { + if data.len() < SELECTOR { return Err(ExitError::Other("Invalid input data!".into())); } if kton::is_kton_transfer(data) { diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index d2c3ad918b..056599fea8 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -36,7 +36,7 @@ pub mod evm { pub const POW_9: u32 = 1_000_000_000; pub const INTERNAL_CALLER: H160 = H160::zero(); - pub const SELECTOR: u32 = 4; + pub const SELECTOR: usize = 4; } #[cfg(test)] From 2306c8a38cb04a1368797635688d8c783660af35 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 3 Jun 2021 16:59:22 +0800 Subject: [PATCH 16/45] For fix unit test --- frame/dvm/src/mock.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 4e2e6d13ce..ccc26ac481 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -154,16 +154,16 @@ impl AddressMapping for HashedAddressMapping { } } -pub struct RingBack(PhantomData); -impl Precompile for RingBack { - fn execute( - input: &[u8], - target_gas: Option, - context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { - darwinia_evm_precompile_transfer::ring::RingBack::::transfer(&input, target_gas, context) - } -} +// pub struct RingBack(PhantomData); +// impl Precompile for RingBack { +// fn execute( +// input: &[u8], +// target_gas: Option, +// context: &Context, +// ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { +// darwinia_evm_precompile_transfer::ring::RingBack::::transfer(&input, target_gas, context) +// } +// } impl darwinia_evm::Config for Test { type FeeCalculator = FixedGasPrice; @@ -178,7 +178,8 @@ impl darwinia_evm::Config for Test { darwinia_evm_precompile_simple::Sha256, darwinia_evm_precompile_simple::Ripemd160, darwinia_evm_precompile_simple::Identity, - RingBack, + darwinia_evm_precompile_transfer::Transfer, + // RingBack, ); type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; From e4b8711bd3ebd42ee6cc1bb4dd20a8f0702ee9cd Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Fri, 4 Jun 2021 01:49:36 +0800 Subject: [PATCH 17/45] fix typo --- frame/evm/precompile/contracts/transfer/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index 271c9fba97..9f36ebc54f 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -34,7 +34,7 @@ use evm::{Context, ExitError, ExitSucceed}; pub type AccountId = ::AccountId; -/// Transfer Precompile Contract, used to support the exchange of KTON and RING tranfer. +/// Transfer Precompile Contract, used to support the exchange of KTON and RING transfer. pub enum Transfer { /// Transfer RING back from DVM to Darwinia RingBack, From 2b0f5e3708863bb701771c61153800b3120d8447 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 3 Jun 2021 18:01:04 +0800 Subject: [PATCH 18/45] Rename ring transfer --- frame/dvm/src/mock.rs | 23 +++++++++---------- .../precompile/contracts/transfer/src/lib.rs | 6 ++--- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index ccc26ac481..4e2e6d13ce 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -154,16 +154,16 @@ impl AddressMapping for HashedAddressMapping { } } -// pub struct RingBack(PhantomData); -// impl Precompile for RingBack { -// fn execute( -// input: &[u8], -// target_gas: Option, -// context: &Context, -// ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { -// darwinia_evm_precompile_transfer::ring::RingBack::::transfer(&input, target_gas, context) -// } -// } +pub struct RingBack(PhantomData); +impl Precompile for RingBack { + fn execute( + input: &[u8], + target_gas: Option, + context: &Context, + ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + darwinia_evm_precompile_transfer::ring::RingBack::::transfer(&input, target_gas, context) + } +} impl darwinia_evm::Config for Test { type FeeCalculator = FixedGasPrice; @@ -178,8 +178,7 @@ impl darwinia_evm::Config for Test { darwinia_evm_precompile_simple::Sha256, darwinia_evm_precompile_simple::Ripemd160, darwinia_evm_precompile_simple::Identity, - darwinia_evm_precompile_transfer::Transfer, - // RingBack, + RingBack, ); type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index 9f36ebc54f..da5f443774 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -37,7 +37,7 @@ pub type AccountId = ::AccountId; /// Transfer Precompile Contract, used to support the exchange of KTON and RING transfer. pub enum Transfer { /// Transfer RING back from DVM to Darwinia - RingBack, + RingTransfer, /// Transfer KTON between Darwinia and DVM contract KtonTransfer, _Impossible(PhantomData), @@ -50,7 +50,7 @@ impl Precompile for Transfer { context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { match which_transfer::(&input) { - Ok(Transfer::RingBack) => RingBack::::transfer(&input, target_gas, context), + Ok(Transfer::RingTransfer) => RingBack::::transfer(&input, target_gas, context), Ok(Transfer::KtonTransfer) => Kton::::transfer(&input, target_gas, context), _ => Err(ExitError::Other("Invalid action".into())), } @@ -67,5 +67,5 @@ fn which_transfer(data: &[u8]) -> Result, E if kton::is_kton_transfer(data) { return Ok(Transfer::KtonTransfer); } - Ok(Transfer::RingBack) + Ok(Transfer::RingTransfer) } From 2dded42ad5778dfbec1b9b35e832dd14f61520ab Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Sat, 5 Jun 2021 00:09:19 +0800 Subject: [PATCH 19/45] Use the same way with pangolin runtime --- frame/dvm/src/mock.rs | 58 ++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 4e2e6d13ce..50cd6380ec 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -25,7 +25,7 @@ use crate::{ }; use codec::{Decode, Encode}; use darwinia_evm::{AddressMapping, EnsureAddressTruncated, FeeCalculator}; -use dp_evm::Precompile; +use dp_evm::{Precompile, PrecompileSet}; use ethereum::{TransactionAction, TransactionSignature}; use evm::{Context, ExitError, ExitSucceed}; use frame_support::{traits::GenesisBuild, ConsensusEngineId}; @@ -154,17 +154,45 @@ impl AddressMapping for HashedAddressMapping { } } -pub struct RingBack(PhantomData); -impl Precompile for RingBack { +// pub struct RingBack(PhantomData); +// // impl Precompile for RingBack { +// impl Precompile for RingBack { +// fn execute( +// input: &[u8], +// target_gas: Option, +// context: &Context, +// ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { +// // darwinia_evm_precompile_transfer::ring::RingBack::::transfer(&input, target_gas, context) +// darwinia_evm_precompile_transfer::kton::Kton::::transfer(&input, target_gas, context) +// } +// } + +pub struct PangolinPrecompiles(PhantomData); +impl PrecompileSet for PangolinPrecompiles { fn execute( + address: H160, input: &[u8], target_gas: Option, context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { - darwinia_evm_precompile_transfer::ring::RingBack::::transfer(&input, target_gas, context) + ) -> Option, u64), ExitError>> { + let to_address = |n: u64| -> H160 { H160::from_low_u64_be(n) }; + + match address { + // Ethereum precompiles + // _ if address == to_address(1) => Some(darwinia_evm_precompile_simple::ECRecover::execute(input, target_gas, context)), + // _ if address == to_address(2) => Some(darwinia_evm_precompile_simple::Sha256::execute(input, target_gas, context)), + // _ if address == to_address(3) => Some(darwinia_evm_precompile_simple::Ripemd160::execute(input, target_gas, context)), + // _ if address == to_address(4) => Some(darwinia_evm_precompile_simple::Identity::execute(input, target_gas, context)), + // Darwinia precompiles + _ if address == to_address(21) => { + Some(>::execute(input, target_gas, context)) + } + _ => None, + } } } + impl darwinia_evm::Config for Test { type FeeCalculator = FixedGasPrice; type GasWeightMapping = (); @@ -173,13 +201,15 @@ impl darwinia_evm::Config for Test { type RingCurrency = Ring; type KtonCurrency = Kton; type Event = (); - type Precompiles = ( - darwinia_evm_precompile_simple::ECRecover, - darwinia_evm_precompile_simple::Sha256, - darwinia_evm_precompile_simple::Ripemd160, - darwinia_evm_precompile_simple::Identity, - RingBack, - ); + // type Precompiles = ( + // darwinia_evm_precompile_simple::ECRecover, + // darwinia_evm_precompile_simple::Sha256, + // darwinia_evm_precompile_simple::Ripemd160, + // darwinia_evm_precompile_simple::Identity, + // // darwinia_evm_precompile_transfer::Transfer, + // RingBack, + // ); + type Precompiles = PangolinPrecompiles; type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; type Runner = darwinia_evm::runner::stack::Runner; @@ -206,8 +236,8 @@ frame_support::construct_runtime! { Timestamp: pallet_timestamp::{Pallet, Call, Storage}, Ring: darwinia_balances::::{Pallet, Call, Storage, Config}, Kton: darwinia_balances::::{Pallet, Call, Storage}, - EVM: darwinia_evm::{Pallet, Call, Storage}, - Ethereum: dvm_ethereum::{Pallet, Call, Storage}, + EVM: darwinia_evm::{Pallet, Call, Storage, Config}, + Ethereum: dvm_ethereum::{Pallet, Call, Storage, Config}, } } From df38d28c784de8f1718823260c594c91e1ef7655 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Mon, 7 Jun 2021 23:14:05 +0800 Subject: [PATCH 20/45] update format --- .../precompile/contracts/transfer/src/lib.rs | 10 +++-- primitives/evm/src/precompile.rs | 43 ++++++++++--------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index da5f443774..df2ca78180 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -42,16 +42,18 @@ pub enum Transfer { KtonTransfer, _Impossible(PhantomData), } - -impl Precompile for Transfer { +impl Precompile for Transfer +where + T: dvm_ethereum::Config, +{ fn execute( input: &[u8], target_gas: Option, context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { match which_transfer::(&input) { - Ok(Transfer::RingTransfer) => RingBack::::transfer(&input, target_gas, context), - Ok(Transfer::KtonTransfer) => Kton::::transfer(&input, target_gas, context), + Ok(Transfer::RingTransfer) => >::transfer(&input, target_gas, context), + Ok(Transfer::KtonTransfer) => >::transfer(&input, target_gas, context), _ => Err(ExitError::Other("Invalid action".into())), } } diff --git a/primitives/evm/src/precompile.rs b/primitives/evm/src/precompile.rs index c0bd97e2f7..bec306410d 100644 --- a/primitives/evm/src/precompile.rs +++ b/primitives/evm/src/precompile.rs @@ -34,19 +34,6 @@ pub trait PrecompileSet { context: &Context, ) -> Option, u64), ExitError>>; } - -/// One single precompile used by EVM engine. -pub trait Precompile { - /// Try to execute the precompile. Calculate the amount of gas needed with given `input` and - /// `target_gas`. Return `Ok(status, output, gas_used)` if the execution is - /// successful. Otherwise return `Err(_)`. - fn execute( - input: &[u8], - target_gas: Option, - context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError>; -} - #[impl_for_tuples(30)] #[tuple_types_no_default_trait_bound] impl PrecompileSet for Tuple { @@ -71,26 +58,40 @@ impl PrecompileSet for Tuple { } } -pub trait LinearCostPrecompile { - const BASE: u64; - const WORD: u64; - - fn execute(input: &[u8], cost: u64) -> core::result::Result<(ExitSucceed, Vec), ExitError>; +/// One single precompile used by EVM engine. +pub trait Precompile { + /// Try to execute the precompile. Calculate the amount of gas needed with given `input` and + /// `target_gas`. Return `Ok(status, output, gas_used)` if the execution is + /// successful. Otherwise return `Err(_)`. + fn execute( + input: &[u8], + target_gas: Option, + context: &Context, + ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError>; } - -impl Precompile for T { +impl Precompile for T +where + T: LinearCostPrecompile, +{ fn execute( input: &[u8], target_gas: Option, _: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { let cost = ensure_linear_cost(target_gas, input.len() as u64, T::BASE, T::WORD)?; - let (succeed, out) = T::execute(input, cost)?; + Ok((succeed, out, cost)) } } +pub trait LinearCostPrecompile { + const BASE: u64; + const WORD: u64; + + fn execute(input: &[u8], cost: u64) -> core::result::Result<(ExitSucceed, Vec), ExitError>; +} + /// Linear gas cost fn ensure_linear_cost( target_gas: Option, From b8e5dc209775e6812090461c73c45ac4c6894206 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Mon, 7 Jun 2021 23:14:51 +0800 Subject: [PATCH 21/45] need help (tmp) --- bin/node/runtime/pangolin/src/pallets/evm_.rs | 6 +- frame/dvm/src/mock.rs | 194 ++++++++---------- 2 files changed, 86 insertions(+), 114 deletions(-) diff --git a/bin/node/runtime/pangolin/src/pallets/evm_.rs b/bin/node/runtime/pangolin/src/pallets/evm_.rs index c29a3e7d5d..338793eb59 100644 --- a/bin/node/runtime/pangolin/src/pallets/evm_.rs +++ b/bin/node/runtime/pangolin/src/pallets/evm_.rs @@ -30,9 +30,9 @@ impl PrecompileSet for PangolinPrecompiles { _ if address == to_address(3) => Some(Ripemd160::execute(input, target_gas, context)), _ if address == to_address(4) => Some(Identity::execute(input, target_gas, context)), // Darwinia precompiles - _ if address == to_address(21) => { - Some(>::execute(input, target_gas, context)) - } + _ if address == to_address(21) => Some( as Precompile>::execute( + input, target_gas, context, + )), _ if address == to_address(23) => { Some(>::execute(input, target_gas, context)) } diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 50cd6380ec..f031f19e0a 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -18,26 +18,26 @@ //! Test utilities -use crate::{ - self as dvm_ethereum, - account_basic::{DvmAccountBasic, KtonRemainBalance, RingRemainBalance}, - *, -}; +// --- crates.io --- use codec::{Decode, Encode}; -use darwinia_evm::{AddressMapping, EnsureAddressTruncated, FeeCalculator}; -use dp_evm::{Precompile, PrecompileSet}; use ethereum::{TransactionAction, TransactionSignature}; use evm::{Context, ExitError, ExitSucceed}; +use rlp::*; +// --- substrate --- use frame_support::{traits::GenesisBuild, ConsensusEngineId}; use frame_system::mocking::*; -use rlp::*; use sp_core::{H160, H256, U256}; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, AccountId32, Perbill, RuntimeDebug, }; -use sp_std::{marker::PhantomData, vec::Vec}; +use sp_std::prelude::*; +// --- darwinia --- +use crate::{self as dvm_ethereum, account_basic::*, *}; +use darwinia_evm::{runner::stack::Runner, AddressMapping, EnsureAddressTruncated, FeeCalculator}; +use darwinia_evm_precompile_simple::*; +use dp_evm::{Precompile, PrecompileSet}; darwinia_support::impl_test_account_data! {} @@ -52,7 +52,6 @@ frame_support::parameter_types! { pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } - impl frame_system::Config for Test { type BaseCallFilter = (); type BlockWeights = (); @@ -85,7 +84,6 @@ frame_support::parameter_types! { pub const MaxLocks: u32 = 10; pub const ExistentialDeposit: u64 = 500; } - impl darwinia_balances::Config for Test { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; @@ -97,7 +95,6 @@ impl darwinia_balances::Config for Test { type Event = (); type BalanceInfo = AccountData; } - impl darwinia_balances::Config for Test { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; @@ -113,7 +110,6 @@ impl darwinia_balances::Config for Test { frame_support::parameter_types! { pub const MinimumPeriod: u64 = 6000 / 2; } - impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = (); @@ -127,7 +123,6 @@ impl FeeCalculator for FixedGasPrice { 1.into() } } - pub struct EthereumFindAuthor; impl FindAuthor for EthereumFindAuthor { fn find_author<'a, I>(_digests: I) -> Option @@ -137,15 +132,7 @@ impl FindAuthor for EthereumFindAuthor { Some(address_build(0).address) } } - -frame_support::parameter_types! { - pub const TransactionByteFee: u64 = 1; - pub const ChainId: u64 = 42; - pub const BlockGasLimit: U256 = U256::MAX; -} - pub struct HashedAddressMapping; - impl AddressMapping for HashedAddressMapping { fn into_account_id(address: H160) -> AccountId32 { let mut data = [0u8; 32]; @@ -153,22 +140,8 @@ impl AddressMapping for HashedAddressMapping { AccountId32::from(Into::<[u8; 32]>::into(data)) } } - -// pub struct RingBack(PhantomData); -// // impl Precompile for RingBack { -// impl Precompile for RingBack { -// fn execute( -// input: &[u8], -// target_gas: Option, -// context: &Context, -// ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { -// // darwinia_evm_precompile_transfer::ring::RingBack::::transfer(&input, target_gas, context) -// darwinia_evm_precompile_transfer::kton::Kton::::transfer(&input, target_gas, context) -// } -// } - -pub struct PangolinPrecompiles(PhantomData); -impl PrecompileSet for PangolinPrecompiles { +pub struct PangolinPrecompiles; +impl PrecompileSet for PangolinPrecompiles { fn execute( address: H160, input: &[u8], @@ -179,20 +152,28 @@ impl PrecompileSet for PangolinPrecompiles { match address { // Ethereum precompiles - // _ if address == to_address(1) => Some(darwinia_evm_precompile_simple::ECRecover::execute(input, target_gas, context)), - // _ if address == to_address(2) => Some(darwinia_evm_precompile_simple::Sha256::execute(input, target_gas, context)), - // _ if address == to_address(3) => Some(darwinia_evm_precompile_simple::Ripemd160::execute(input, target_gas, context)), - // _ if address == to_address(4) => Some(darwinia_evm_precompile_simple::Identity::execute(input, target_gas, context)), + _ if address == to_address(1) => Some(ECRecover::execute(input, target_gas, context)), + _ if address == to_address(2) => Some(Sha256::execute(input, target_gas, context)), + _ if address == to_address(3) => Some(Ripemd160::execute(input, target_gas, context)), + _ if address == to_address(4) => Some(Identity::execute(input, target_gas, context)), // Darwinia precompiles - _ if address == to_address(21) => { - Some(>::execute(input, target_gas, context)) - } + _ if address == to_address(21) => Some( as Precompile>::execute( + input, target_gas, context + )), + // _ if address == to_address(23) => { + // Some(>::execute(input, target_gas, context)) + // } _ => None, } } } - - +frame_support::parameter_types! { + pub const TransactionByteFee: u64 = 1; + pub const ChainId: u64 = 42; + pub const BlockGasLimit: U256 = U256::MAX; +} impl darwinia_evm::Config for Test { type FeeCalculator = FixedGasPrice; type GasWeightMapping = (); @@ -201,18 +182,10 @@ impl darwinia_evm::Config for Test { type RingCurrency = Ring; type KtonCurrency = Kton; type Event = (); - // type Precompiles = ( - // darwinia_evm_precompile_simple::ECRecover, - // darwinia_evm_precompile_simple::Sha256, - // darwinia_evm_precompile_simple::Ripemd160, - // darwinia_evm_precompile_simple::Identity, - // // darwinia_evm_precompile_transfer::Transfer, - // RingBack, - // ); - type Precompiles = PangolinPrecompiles; + type Precompiles = PangolinPrecompiles; type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; - type Runner = darwinia_evm::runner::stack::Runner; + type Runner = Runner; type RingAccountBasic = DvmAccountBasic; type KtonAccountBasic = DvmAccountBasic; type IssuingHandler = (); @@ -247,59 +220,6 @@ pub struct AccountInfo { pub private_key: H256, } -fn address_build(seed: u8) -> AccountInfo { - let private_key = H256::from_slice(&[(seed + 1) as u8; 32]); //H256::from_low + 1) as u64); - let secret_key = secp256k1::SecretKey::parse_slice(&private_key[..]).unwrap(); - let public_key = &secp256k1::PublicKey::from_secret_key(&secret_key).serialize()[1..65]; - let address = H160::from(H256::from_slice(&Keccak256::digest(public_key)[..])); - - let mut data = [0u8; 32]; - data[0..20].copy_from_slice(&address[..]); - - AccountInfo { - private_key, - account_id: AccountId32::from(Into::<[u8; 32]>::into(data)), - address, - } -} - -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. -pub fn new_test_ext(accounts_len: usize) -> (Vec, sp_io::TestExternalities) { - // sc_cli::init_logger(""); - let mut ext = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - let pairs = (0..accounts_len) - .map(|i| address_build(i as u8)) - .collect::>(); - - let balances: Vec<_> = (0..accounts_len) - .map(|i| (pairs[i].account_id.clone(), 100_000_000_000)) - .collect(); - - darwinia_balances::GenesisConfig:: { balances } - .assimilate_storage(&mut ext) - .unwrap(); - - (pairs, ext.into()) -} - -pub fn contract_address(sender: H160, nonce: u64) -> H160 { - let mut rlp = RlpStream::new_list(2); - rlp.append(&sender); - rlp.append(&nonce); - - H160::from_slice(&Keccak256::digest(&rlp.out())[12..]) -} - -pub fn storage_address(sender: H160, slot: H256) -> H256 { - H256::from_slice(&Keccak256::digest( - [&H256::from(sender)[..], &slot[..]].concat().as_slice(), - )) -} - pub struct UnsignedTransaction { pub nonce: U256, pub gas_price: U256, @@ -308,7 +228,6 @@ pub struct UnsignedTransaction { pub value: U256, pub input: Vec, } - impl UnsignedTransaction { fn signing_rlp_append(&self, s: &mut RlpStream) { s.begin_list(9); @@ -353,3 +272,56 @@ impl UnsignedTransaction { } } } + +fn address_build(seed: u8) -> AccountInfo { + let private_key = H256::from_slice(&[(seed + 1) as u8; 32]); //H256::from_low + 1) as u64); + let secret_key = secp256k1::SecretKey::parse_slice(&private_key[..]).unwrap(); + let public_key = &secp256k1::PublicKey::from_secret_key(&secret_key).serialize()[1..65]; + let address = H160::from(H256::from_slice(&Keccak256::digest(public_key)[..])); + + let mut data = [0u8; 32]; + data[0..20].copy_from_slice(&address[..]); + + AccountInfo { + private_key, + account_id: AccountId32::from(Into::<[u8; 32]>::into(data)), + address, + } +} + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext(accounts_len: usize) -> (Vec, sp_io::TestExternalities) { + // sc_cli::init_logger(""); + let mut ext = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + let pairs = (0..accounts_len) + .map(|i| address_build(i as u8)) + .collect::>(); + + let balances: Vec<_> = (0..accounts_len) + .map(|i| (pairs[i].account_id.clone(), 100_000_000_000)) + .collect(); + + darwinia_balances::GenesisConfig:: { balances } + .assimilate_storage(&mut ext) + .unwrap(); + + (pairs, ext.into()) +} + +pub fn contract_address(sender: H160, nonce: u64) -> H160 { + let mut rlp = RlpStream::new_list(2); + rlp.append(&sender); + rlp.append(&nonce); + + H160::from_slice(&Keccak256::digest(&rlp.out())[12..]) +} + +pub fn storage_address(sender: H160, slot: H256) -> H256 { + H256::from_slice(&Keccak256::digest( + [&H256::from(sender)[..], &slot[..]].concat().as_slice(), + )) +} From 87ac5b9c86b11d34937df6eeb81aed7b02a8cfc4 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 12:21:03 +0800 Subject: [PATCH 22/45] Fix ring transfer remaining balance issue --- Cargo.lock | 1 + .../precompile/contracts/transfer/Cargo.toml | 1 + .../precompile/contracts/transfer/src/kton.rs | 6 +- .../precompile/contracts/transfer/src/ring.rs | 63 +++++++++++-------- frame/support/Cargo.toml | 1 + frame/support/src/lib.rs | 1 + 6 files changed, 43 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3993f26bd3..34f146e720 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1956,6 +1956,7 @@ dependencies = [ name = "darwinia-support" version = "2.4.0" dependencies = [ + "array-bytes", "ethereum-primitives", "frame-support", "impl-trait-for-tuples", diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index 7270ec771b..68fd395d76 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -11,6 +11,7 @@ version = "2.4.0" [dependencies] # crates +array-bytes = { version = "1.1.0" } codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } evm = { version = "0.25.0", features = ["with-codec"], default-features = false } ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std", default-features = false } diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index c965a338a1..ddcd5593ee 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -7,7 +7,7 @@ use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; use crate::util; use crate::AccountId; use darwinia_evm::{Account, AccountBasic, Module, Runner}; -use darwinia_support::evm::{POW_9, SELECTOR}; +use darwinia_support::evm::{POW_9, SELECTOR, TRANSFER_ADDR}; use dvm_ethereum::{ account_basic::{KtonRemainBalance, RemainBalanceOp}, KtonBalance, @@ -21,7 +21,6 @@ use sha3::Digest; const TRANSFER_AND_CALL_ACTION: &[u8] = b"transfer_and_call(address,uint256)"; const WITHDRAW_ACTION: &[u8] = b"withdraw(bytes32,uint256)"; -const CALLER_PRECOMPILE: &str = "0000000000000000000000000000000000000015"; pub enum Kton { /// Transfer from substrate account to wkton contract @@ -64,7 +63,8 @@ impl Kton { call_data.value, )?; // Call WKTON wrapped contract deposit - let precompile_address = H160::from_str(CALLER_PRECOMPILE).unwrap_or_default(); + let precompile_address: H160 = + array_bytes::hex2array_unchecked!(TRANSFER_ADDR, 20).into(); let raw_input = make_call_data(context.caller, call_data.value)?; if let Ok(call_res) = T::Runner::call( precompile_address, diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index a755872004..04a8f1d2ae 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -1,12 +1,16 @@ // --- substrate --- -use frame_support::traits::{Currency, ExistenceRequirement}; +use frame_support::{ensure, traits::Currency}; use sp_core::U256; -use sp_runtime::traits::UniqueSaturatedInto; +use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; use sp_std::{marker::PhantomData, prelude::*, vec::Vec}; // --- darwinia --- use crate::AccountId; -use darwinia_evm::{AddressMapping, Config}; -use darwinia_support::evm::POW_9; +use darwinia_evm::{Account, AccountBasic, Config}; +use darwinia_support::evm::{POW_9, TRANSFER_ADDR}; +use dvm_ethereum::{ + account_basic::{RemainBalanceOp, RingRemainBalance}, + RingBalance, +}; // --- crates --- use codec::Decode; use evm::{Context, ExitError, ExitSucceed}; @@ -15,7 +19,7 @@ pub struct RingBack { _maker: PhantomData, } -impl RingBack { +impl RingBack { /// The Withdraw process is divided into two part: /// 1. parse the withdrawal address from the input parameter and get the contract address and value from the context /// 2. transfer from the contract address to withdrawal address @@ -27,34 +31,39 @@ impl RingBack { context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { // Decode input data + let helper = U256::from(POW_9); let input = InputData::::decode(&input)?; + let (source, value) = (context.address, context.apparent_value); + let source_account = T::RingAccountBasic::account_basic(&source); - let helper = U256::from(POW_9); - let contract_address = T::AddressMapping::into_account_id(context.address); - let context_value = context.apparent_value.div_mod(helper).0; - let context_value = context_value.low_u128().unique_saturated_into(); + // Ensure the context address should be precompile address + ensure!( + source == array_bytes::hex2array_unchecked!(TRANSFER_ADDR, 20).into(), + ExitError::Other("Invalid context address".into()) + ); + // Ensure the context address balance is enough + ensure!(source_account.balance >= value, ExitError::OutOfFund); - let result = T::RingCurrency::transfer( - &contract_address, + // Transfer + let new_source_balance = source_account.balance.saturating_sub(value); + T::RingAccountBasic::mutate_account_basic( + &source, + Account { + nonce: source_account.nonce, + balance: new_source_balance, + }, + ); + let (currency_value, remain_balance) = context.apparent_value.div_mod(helper); + ::RingCurrency::deposit_creating( &input.dest, - context_value, - ExistenceRequirement::AllowDeath, + currency_value.low_u128().unique_saturated_into(), + ); + >>::inc_remaining_balance( + &input.dest, + remain_balance.low_u128().saturated_into(), ); - match result { - Ok(()) => Ok((ExitSucceed::Returned, vec![], 10000)), - Err(error) => match error { - sp_runtime::DispatchError::BadOrigin => Err(ExitError::Other("BadOrigin".into())), - sp_runtime::DispatchError::CannotLookup => { - Err(ExitError::Other("CannotLookup".into())) - } - sp_runtime::DispatchError::Other(message) => Err(ExitError::Other(message.into())), - sp_runtime::DispatchError::Module { message, .. } => { - Err(ExitError::Other(message.unwrap_or("Module Error").into())) - } - _ => Err(ExitError::Other("Module Error".into())), - }, - } + Ok((ExitSucceed::Returned, vec![], 10000)) } } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index d3daaf9ce9..448431d656 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -11,6 +11,7 @@ version = "2.4.0" [dependencies] # crates +array-bytes = { version = "1.1.0" } codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false, features = ["derive"] } impl-trait-for-tuples = { version = "0.2.1" } num-traits = { version = "0.2.14", default-features = false } diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 056599fea8..e007f0344a 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -37,6 +37,7 @@ pub mod evm { pub const POW_9: u32 = 1_000_000_000; pub const INTERNAL_CALLER: H160 = H160::zero(); pub const SELECTOR: usize = 4; + pub const TRANSFER_ADDR: &'static str = "0x0000000000000000000000000000000000000015"; } #[cfg(test)] From 30ec57864d8d272e729c5bb7d26b4d119fddfe28 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 12:30:34 +0800 Subject: [PATCH 23/45] Fix conflict and add licenses --- .../precompile/contracts/transfer/src/kton.rs | 40 +++++++++++-------- .../precompile/contracts/transfer/src/lib.rs | 18 +++++++++ .../precompile/contracts/transfer/src/ring.rs | 18 +++++++++ .../precompile/contracts/transfer/src/util.rs | 18 +++++++++ 4 files changed, 77 insertions(+), 17 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 8f2ba2fb6c..7dd4db2a0b 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -1,28 +1,38 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2021 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Darwinia is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Darwinia. If not, see . + // --- substrate --- use frame_support::{ensure, traits::Currency}; use sp_core::{H160, U256}; use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; -<<<<<<< HEAD:frame/evm/precompile/contracts/transfer/src/kton.rs -use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; +// use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; // --- darwinia --- use crate::util; use crate::AccountId; -use darwinia_evm::{Account, AccountBasic, Module, Runner}; +use darwinia_evm::{Account, AccountBasic, Pallet, Runner}; use darwinia_support::evm::{POW_9, SELECTOR, TRANSFER_ADDR}; -======= -use sp_std::{borrow::ToOwned, marker::PhantomData, prelude::*, vec::Vec}; - -use darwinia_evm::{Account, AccountBasic, Config, Pallet, Runner}; -use darwinia_support::evm::POW_9; -use dp_evm::Precompile; ->>>>>>> master:frame/evm/precompile/contracts/kton/src/lib.rs use dvm_ethereum::{ account_basic::{KtonRemainBalance, RemainBalanceOp}, KtonBalance, }; +use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; // --- crates --- use codec::Decode; -use core::str::FromStr; use ethabi::{Function, Param, ParamType, Token}; use evm::{Context, ExitError, ExitReason, ExitSucceed}; use sha3::Digest; @@ -50,7 +60,7 @@ impl Kton { Kton::TransferAndCall(call_data) => { // Ensure wkton is a contract ensure!( - !crate::Pallet::::is_contract_code_empty(&call_data.wkton_address), + !>::is_contract_code_empty(&call_data.wkton_address), ExitError::Other("Wkton must be a contract!".into()) ); // Ensure context's apparent_value is zero, since the transfer value is encoded in input field @@ -97,11 +107,7 @@ impl Kton { Kton::Withdraw(wd) => { // Ensure wkton is a contract ensure!( -<<<<<<< HEAD:frame/evm/precompile/contracts/transfer/src/kton.rs - !Module::::is_contract_code_empty(&context.caller), -======= - !crate::Pallet::::is_contract_code_empty(&context.caller), ->>>>>>> master:frame/evm/precompile/contracts/kton/src/lib.rs + !>::is_contract_code_empty(&context.caller), ExitError::Other("The caller must be wkton contract!".into()) ); // Ensure context's apparent_value is zero diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index df2ca78180..c1572ebc6e 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -16,6 +16,24 @@ // You should have received a copy of the GNU General Public License // along with Darwinia. If not, see . +// This file is part of Darwinia. +// +// Copyright (C) 2018-2021 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Darwinia is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Darwinia. If not, see . + #![cfg_attr(not(feature = "std"), no_std)] pub mod kton; diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 04a8f1d2ae..2f38ca8305 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -1,3 +1,21 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2021 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Darwinia is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Darwinia. If not, see . + // --- substrate --- use frame_support::{ensure, traits::Currency}; use sp_core::U256; diff --git a/frame/evm/precompile/contracts/transfer/src/util.rs b/frame/evm/precompile/contracts/transfer/src/util.rs index 4c26022b5c..4fb28214f9 100644 --- a/frame/evm/precompile/contracts/transfer/src/util.rs +++ b/frame/evm/precompile/contracts/transfer/src/util.rs @@ -1,3 +1,21 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2021 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Darwinia is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Darwinia. If not, see . + pub fn e2s_address(eth_address: ethereum_types::H160) -> sp_core::H160 { let eth_address_bytes = eth_address.to_fixed_bytes(); sp_core::H160::from_slice(ð_address_bytes) From 23fa19001805040a53a76b0d2ef91533af9ed57e Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 12:35:52 +0800 Subject: [PATCH 24/45] Skip these test now --- frame/dvm/src/mock.rs | 31 ++----------------------------- frame/dvm/src/tests.rs | 3 +++ 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index f031f19e0a..3891ab2eb8 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -140,35 +140,7 @@ impl AddressMapping for HashedAddressMapping { AccountId32::from(Into::<[u8; 32]>::into(data)) } } -pub struct PangolinPrecompiles; -impl PrecompileSet for PangolinPrecompiles { - fn execute( - address: H160, - input: &[u8], - target_gas: Option, - context: &Context, - ) -> Option, u64), ExitError>> { - let to_address = |n: u64| -> H160 { H160::from_low_u64_be(n) }; - match address { - // Ethereum precompiles - _ if address == to_address(1) => Some(ECRecover::execute(input, target_gas, context)), - _ if address == to_address(2) => Some(Sha256::execute(input, target_gas, context)), - _ if address == to_address(3) => Some(Ripemd160::execute(input, target_gas, context)), - _ if address == to_address(4) => Some(Identity::execute(input, target_gas, context)), - // Darwinia precompiles - _ if address == to_address(21) => Some( as Precompile>::execute( - input, target_gas, context - )), - // _ if address == to_address(23) => { - // Some(>::execute(input, target_gas, context)) - // } - _ => None, - } - } -} frame_support::parameter_types! { pub const TransactionByteFee: u64 = 1; pub const ChainId: u64 = 42; @@ -182,7 +154,8 @@ impl darwinia_evm::Config for Test { type RingCurrency = Ring; type KtonCurrency = Kton; type Event = (); - type Precompiles = PangolinPrecompiles; + // TODO: Add more precompiles to run withdraw unit test. + type Precompiles = (); type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; type Runner = Runner; diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index dc0438e1e1..524725870f 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -374,6 +374,7 @@ fn call_should_handle_errors() { } #[test] +#[ignore] fn withdraw_with_enough_balance() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; @@ -408,6 +409,7 @@ fn withdraw_with_enough_balance() { } #[test] +#[ignore] fn withdraw_without_enough_balance_should_fail() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; @@ -450,6 +452,7 @@ fn withdraw_without_enough_balance_should_fail() { }); } #[test] +#[ignore] fn withdraw_with_invalid_input_length_should_failed() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; From df66b2b697c0c20ec84a571ec4b1254eac0d34f6 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 15:09:53 +0800 Subject: [PATCH 25/45] Fix unit test part 1 --- frame/dvm/src/mock.rs | 44 +++++++++++++++++-- frame/dvm/src/tests.rs | 5 +-- .../precompile/contracts/transfer/src/lib.rs | 1 + 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 3891ab2eb8..03ade37a04 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -36,8 +36,10 @@ use sp_std::prelude::*; // --- darwinia --- use crate::{self as dvm_ethereum, account_basic::*, *}; use darwinia_evm::{runner::stack::Runner, AddressMapping, EnsureAddressTruncated, FeeCalculator}; -use darwinia_evm_precompile_simple::*; +use darwinia_evm_precompile_simple::{ECRecover, Identity, Ripemd160, Sha256}; +use darwinia_evm_precompile_transfer::Transfer; use dp_evm::{Precompile, PrecompileSet}; +use sp_std::marker::PhantomData; darwinia_support::impl_test_account_data! {} @@ -146,6 +148,35 @@ frame_support::parameter_types! { pub const ChainId: u64 = 42; pub const BlockGasLimit: U256 = U256::MAX; } + +pub struct MockPrecompiles(PhantomData); +impl PrecompileSet for MockPrecompiles +where + R: darwinia_evm_precompile_transfer::dvm_ethereum::Config, +{ + fn execute( + address: H160, + input: &[u8], + target_gas: Option, + context: &Context, + ) -> Option, u64), ExitError>> { + let to_address = |n: u64| -> H160 { H160::from_low_u64_be(n) }; + + match address { + // Ethereum precompiles + _ if address == to_address(1) => Some(ECRecover::execute(input, target_gas, context)), + _ if address == to_address(2) => Some(Sha256::execute(input, target_gas, context)), + _ if address == to_address(3) => Some(Ripemd160::execute(input, target_gas, context)), + _ if address == to_address(4) => Some(Identity::execute(input, target_gas, context)), + // Darwinia precompiles + _ if address == to_address(21) => Some( as Precompile>::execute( + input, target_gas, context, + )), + _ => None, + } + } +} + impl darwinia_evm::Config for Test { type FeeCalculator = FixedGasPrice; type GasWeightMapping = (); @@ -154,8 +185,7 @@ impl darwinia_evm::Config for Test { type RingCurrency = Ring; type KtonCurrency = Kton; type Event = (); - // TODO: Add more precompiles to run withdraw unit test. - type Precompiles = (); + type Precompiles = MockPrecompiles; type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; type Runner = Runner; @@ -164,6 +194,14 @@ impl darwinia_evm::Config for Test { type IssuingHandler = (); } +impl darwinia_evm_precompile_transfer::dvm_ethereum::Config for Test { + type Event = (); + type FindAuthor = EthereumFindAuthor; + type StateRoot = IntermediateStateRoot; + type RingCurrency = Ring; + type KtonCurrency = Kton; +} + impl Config for Test { type Event = (); type FindAuthor = EthereumFindAuthor; diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index 524725870f..bff76a69bc 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -35,7 +35,7 @@ use std::str::FromStr; // constructor() public { _mint(msg.sender, 2**256 - 1); } // } const ERC20_CONTRACT_BYTECODE: &str = "608060405234801561001057600080fd5b50610041337fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61004660201b60201c565b610291565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156100e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b6101028160025461020960201b610c7c1790919060201c565b60028190555061015d816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461020960201b610c7c1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600080828401905083811015610287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b610e3a806102a06000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806370a082311161005b57806370a08231146101fd578063a457c2d714610255578063a9059cbb146102bb578063dd62ed3e1461032157610088565b8063095ea7b31461008d57806318160ddd146100f357806323b872dd146101115780633950935114610197575b600080fd5b6100d9600480360360408110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610399565b604051808215151515815260200191505060405180910390f35b6100fb6103b7565b6040518082815260200191505060405180910390f35b61017d6004803603606081101561012757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506103c1565b604051808215151515815260200191505060405180910390f35b6101e3600480360360408110156101ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061049a565b604051808215151515815260200191505060405180910390f35b61023f6004803603602081101561021357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061054d565b6040518082815260200191505060405180910390f35b6102a16004803603604081101561026b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610595565b604051808215151515815260200191505060405180910390f35b610307600480360360408110156102d157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610662565b604051808215151515815260200191505060405180910390f35b6103836004803603604081101561033757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610680565b6040518082815260200191505060405180910390f35b60006103ad6103a6610707565b848461070f565b6001905092915050565b6000600254905090565b60006103ce848484610906565b61048f846103da610707565b61048a85604051806060016040528060288152602001610d7060289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610440610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b61070f565b600190509392505050565b60006105436104a7610707565b8461053e85600160006104b8610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610c7c90919063ffffffff16565b61070f565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006106586105a2610707565b8461065385604051806060016040528060258152602001610de160259139600160006105cc610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b61070f565b6001905092915050565b600061067661066f610707565b8484610906565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610795576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180610dbd6024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561081b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610d286022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561098c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180610d986025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610d056023913960400191505060405180910390fd5b610a7d81604051806060016040528060268152602001610d4a602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610b10816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610c7c90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610c69576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610c2e578082015181840152602081019050610c13565b50505050905090810190601f168015610c5b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610cfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b809150509291505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a72315820c7a5ffabf642bda14700b2de42f8c57b36621af020441df825de45fd2b3e1c5c64736f6c63430005100032"; -const WITHDRAW_DVM_ADDRESS: &str = "0000000000000000000000000000000000000005"; +const WITHDRAW_DVM_ADDRESS: &str = "0000000000000000000000000000000000000015"; const WITH_DRAW_INPUT: &str = "723908ee9dc8e509d4b93251bd57f68c09bd9d04471c193fabd8f26c54284a4b"; fn default_erc20_creation_unsigned_transaction() -> UnsignedTransaction { @@ -374,7 +374,6 @@ fn call_should_handle_errors() { } #[test] -#[ignore] fn withdraw_with_enough_balance() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; @@ -409,7 +408,6 @@ fn withdraw_with_enough_balance() { } #[test] -#[ignore] fn withdraw_without_enough_balance_should_fail() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; @@ -452,7 +450,6 @@ fn withdraw_without_enough_balance_should_fail() { }); } #[test] -#[ignore] fn withdraw_with_invalid_input_length_should_failed() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index c1572ebc6e..c5761d0b54 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -51,6 +51,7 @@ use ring::RingBack; use evm::{Context, ExitError, ExitSucceed}; pub type AccountId = ::AccountId; +pub use dvm_ethereum::{self, Call, Config, Event, Pallet}; /// Transfer Precompile Contract, used to support the exchange of KTON and RING transfer. pub enum Transfer { From d17f5e474889738b1f3cdbec746ab349b51741ec Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 15:28:59 +0800 Subject: [PATCH 26/45] Fix unit test part 2 --- frame/dvm/src/mock.rs | 2 +- frame/dvm/src/tests.rs | 34 ---------------------------------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 03ade37a04..234a6ae5d6 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -202,7 +202,7 @@ impl darwinia_evm_precompile_transfer::dvm_ethereum::Config for Test { type KtonCurrency = Kton; } -impl Config for Test { +impl dvm_ethereum::Config for Test { type Event = (); type FindAuthor = EthereumFindAuthor; type StateRoot = IntermediateStateRoot; diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index bff76a69bc..cec70e75df 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -373,40 +373,6 @@ fn call_should_handle_errors() { }); } -#[test] -fn withdraw_with_enough_balance() { - let (pairs, mut ext) = new_test_ext(1); - let alice = &pairs[0]; - - ext.execute_with(|| { - let t = sign_transaction(alice, default_withdraw_unsigned_transaction()); - assert_ok!(Ethereum::execute( - alice.address, - t.input.clone(), - t.value, - t.gas_limit, - None, - Some(t.nonce), - t.action, - None, - )); - - // Check caller balance - assert_eq!( - ::RingAccountBasic::account_basic(&alice.address).balance, - U256::from(70_000_000_000_000_000_000u128) - ); - // Check the target balance - let input_bytes: Vec = array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT); - let dest = - ::AccountId::decode(&mut &input_bytes[..]).unwrap(); - assert_eq!( - ::RingCurrency::free_balance(dest), - 30000000000 - ); - }); -} - #[test] fn withdraw_without_enough_balance_should_fail() { let (pairs, mut ext) = new_test_ext(1); From bd6b4d6accf12621b77af8b028b42ddf2d124d27 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 16:41:27 +0800 Subject: [PATCH 27/45] Update comments --- frame/evm/precompile/contracts/transfer/src/lib.rs | 2 +- frame/evm/src/lib.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index c5761d0b54..a8810f00b9 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -51,7 +51,7 @@ use ring::RingBack; use evm::{Context, ExitError, ExitSucceed}; pub type AccountId = ::AccountId; -pub use dvm_ethereum::{self, Call, Config, Event, Pallet}; +pub use dvm_ethereum; /// Transfer Precompile Contract, used to support the exchange of KTON and RING transfer. pub enum Transfer { diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index 5b373d674c..58e338c6db 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -431,11 +431,14 @@ pub trait AddressMapping { fn into_account_id(address: H160) -> A; } -/// Get account basic info +/// Account basic info operations pub trait AccountBasic { fn account_basic(address: &H160) -> Account; fn mutate_account_basic(address: &H160, new: Account); fn transfer(source: &H160, target: &H160, value: U256) -> Result<(), ExitError>; + fn account(account_id: &AccountId32) -> Account { + self.account_basic() + } } /// Config that outputs the current transaction gas price. From d44e5f495c2efa9e079eebfdb9487a29c6412e75 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 17:19:27 +0800 Subject: [PATCH 28/45] Add `account_balance`, `mutate_account_balance` --- frame/dvm/src/account_basic.rs | 80 +++++++++---------- frame/dvm/src/tests.rs | 75 ++++------------- .../precompile/contracts/transfer/src/kton.rs | 10 +-- .../precompile/contracts/transfer/src/ring.rs | 10 +-- frame/evm/src/lib.rs | 50 ++++-------- 5 files changed, 73 insertions(+), 152 deletions(-) diff --git a/frame/dvm/src/account_basic.rs b/frame/dvm/src/account_basic.rs index ccd7457544..d6084eda00 100644 --- a/frame/dvm/src/account_basic.rs +++ b/frame/dvm/src/account_basic.rs @@ -101,7 +101,7 @@ impl RemainBalanceOp> for KtonRemainBalance { } pub struct DvmAccountBasic(sp_std::marker::PhantomData<(T, C, RB)>); -impl AccountBasic for DvmAccountBasic +impl AccountBasic for DvmAccountBasic where RB: RemainBalanceOp, C: Currency, @@ -110,6 +110,35 @@ where fn account_basic(address: &H160) -> EVMAccount { let account_id = ::AddressMapping::into_account_id(*address); let nonce = >::account_nonce(&account_id); + + EVMAccount { + nonce: nonce.saturated_into::().into(), + balance: Self::account_balance(&account_id), + } + } + + /// Mutate the basic account + fn mutate_account_basic(address: &H160, new_balance: U256) { + let account_id = ::AddressMapping::into_account_id(*address); + Self::mutate_account_balance(&account_id, new_balance) + } + + /// Transfer value + fn transfer(source: &H160, target: &H160, value: U256) -> Result<(), ExitError> { + let source_account = Self::account_basic(source); + ensure!(source_account.balance >= value, ExitError::OutOfGas); + let new_source_balance = source_account.balance.saturating_sub(value); + Self::mutate_account_basic(source, new_source_balance); + + let target_account = Self::account_basic(target); + let new_target_balance = target_account.balance.saturating_add(value); + Self::mutate_account_basic(target, new_target_balance); + + Ok(()) + } + + /// Get account balance + fn account_balance(account_id: &T::AccountId) -> U256 { let helper = U256::from(POW_9); // Get balance from Currency @@ -125,24 +154,20 @@ where .checked_add(remaining_balance) .unwrap_or_default(); - EVMAccount { - nonce: nonce.saturated_into::().into(), - balance: final_balance, - } + final_balance } - /// Mutate the basic account - fn mutate_account_basic(address: &H160, new: EVMAccount) { + /// Mutate account balance + fn mutate_account_balance(account_id: &T::AccountId, new_balance: U256) { let helper = U256::from(POW_9); - let account_id = ::AddressMapping::into_account_id(*address); - let current = Self::account_basic(address); + let current = Self::account_balance(account_id); let dvm_balance: U256 = RB::remaining_balance(&account_id) .saturated_into::() .into(); - let nb = new.balance; - match current.balance { + let nb = new_balance; + match current { cb if cb > nb => { let diff = cb - nb; let (diff_balance, diff_remaining_balance) = diff.div_mod(helper); @@ -207,11 +232,9 @@ where let ring_existential_deposit = U256::from(ring_existential_deposit) * helper; let kton_existential_deposit = U256::from(kton_existential_deposit) * helper; - let ring_account = T::RingAccountBasic::account_basic(address); - let kton_account = T::KtonAccountBasic::account_basic(address); - if ring_account.balance < ring_existential_deposit - && kton_account.balance < kton_existential_deposit - { + let ring_account = T::RingAccountBasic::account_balance(&account_id); + let kton_account = T::KtonAccountBasic::account_balance(&account_id); + if ring_account < ring_existential_deposit && kton_account < kton_existential_deposit { >>::remove_remaining_balance( &account_id, ); @@ -220,29 +243,4 @@ where ); } } - - fn transfer(source: &H160, target: &H160, value: U256) -> Result<(), ExitError> { - let source_account = Self::account_basic(source); - ensure!(source_account.balance >= value, ExitError::OutOfGas); - let new_source_balance = source_account.balance.saturating_sub(value); - Self::mutate_account_basic( - source, - EVMAccount { - nonce: source_account.nonce, - balance: new_source_balance, - }, - ); - - let target_account = Self::account_basic(target); - let new_target_balance = target_account.balance.saturating_add(value); - Self::mutate_account_basic( - target, - EVMAccount { - nonce: target_account.nonce, - balance: new_target_balance, - }, - ); - - Ok(()) - } } diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index cec70e75df..d64aaf81c1 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -457,10 +457,7 @@ fn mutate_account_works_well() { let origin_balance = U256::from(123_456_789_000_000_090u128); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: origin_balance, - }, + origin_balance, ); assert_balance!(test_addr, origin_balance, 123456789, 90); @@ -476,19 +473,13 @@ fn mutate_account_inc_balance_by_10() { let origin_balance = U256::from(600_000_000_090u128); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: origin_balance, - }, + origin_balance, ); let new_balance = origin_balance.saturating_add(U256::from(10)); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: new_balance, - }, + new_balance, ); assert_balance!(test_addr, new_balance, 600, 100); }); @@ -503,19 +494,13 @@ fn mutate_account_inc_balance_by_999_999_910() { let origin_balance = U256::from(600_000_000_090u128); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: origin_balance, - }, + origin_balance, ); let new_balance = origin_balance.saturating_add(U256::from(999999910u128)); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: new_balance, - }, + new_balance, ); assert_balance!(test_addr, new_balance, 601, 0); }); @@ -530,19 +515,13 @@ fn mutate_account_inc_by_1000_000_000() { let origin_balance = U256::from(600_000_000_090u128); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(10), - balance: origin_balance, - }, + origin_balance, ); let new_balance = origin_balance.saturating_add(U256::from(1000_000_000u128)); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: new_balance, - }, + new_balance, ); assert_balance!(test_addr, new_balance, 601, 90); }); @@ -557,19 +536,13 @@ fn mutate_account_dec_balance_by_90() { let origin_balance = U256::from(600_000_000_090u128); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: origin_balance, - }, + origin_balance, ); let new_balance = origin_balance.saturating_sub(U256::from(90)); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: new_balance, - }, + new_balance, ); assert_balance!(test_addr, new_balance, 600, 0); }); @@ -583,19 +556,13 @@ fn mutate_account_dec_balance_by_990() { let origin_balance = U256::from(600_000_000_090u128); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: origin_balance, - }, + origin_balance, ); let new_balance = origin_balance.saturating_sub(U256::from(990)); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: new_balance, - }, + new_balance, ); assert_balance!(test_addr, new_balance, 599, 1_000_000_090 - 990); }); @@ -609,19 +576,13 @@ fn mutate_account_dec_balance_existential_by_90() { let origin_balance = U256::from(500_000_000_090u128); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: origin_balance, - }, + origin_balance, ); let new_balance = origin_balance.saturating_sub(U256::from(90)); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: new_balance, - }, + new_balance, ); assert_balance!(test_addr, new_balance, 500, 0); }); @@ -635,19 +596,13 @@ fn mutate_account_dec_balance_existential_by_990() { let origin_balance = U256::from(500_000_000_090u128); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: origin_balance, - }, + origin_balance, ); let new_balance = origin_balance.saturating_sub(U256::from(990)); ::RingAccountBasic::mutate_account_basic( &test_addr, - Account { - nonce: U256::from(0), - balance: new_balance, - }, + new_balance, ); assert_balance!(test_addr, U256::zero(), 0, 0); diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 7dd4db2a0b..e29a093b0c 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -24,7 +24,7 @@ use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; // --- darwinia --- use crate::util; use crate::AccountId; -use darwinia_evm::{Account, AccountBasic, Pallet, Runner}; +use darwinia_evm::{AccountBasic, Pallet, Runner}; use darwinia_support::evm::{POW_9, SELECTOR, TRANSFER_ADDR}; use dvm_ethereum::{ account_basic::{KtonRemainBalance, RemainBalanceOp}, @@ -121,13 +121,7 @@ impl Kton { // Transfer let new_wkton_balance = caller_kton.balance.saturating_sub(wd.kton_value); - T::KtonAccountBasic::mutate_account_basic( - &context.caller, - Account { - nonce: caller_kton.nonce, - balance: new_wkton_balance, - }, - ); + T::KtonAccountBasic::mutate_account_basic(&context.caller, new_wkton_balance); let (currency_value, remain_balance) = wd.kton_value.div_mod(helper); ::KtonCurrency::deposit_creating( &wd.to_account_id, diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 2f38ca8305..4c1901df41 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -23,7 +23,7 @@ use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; use sp_std::{marker::PhantomData, prelude::*, vec::Vec}; // --- darwinia --- use crate::AccountId; -use darwinia_evm::{Account, AccountBasic, Config}; +use darwinia_evm::{AccountBasic, Config}; use darwinia_support::evm::{POW_9, TRANSFER_ADDR}; use dvm_ethereum::{ account_basic::{RemainBalanceOp, RingRemainBalance}, @@ -64,13 +64,7 @@ impl RingBack { // Transfer let new_source_balance = source_account.balance.saturating_sub(value); - T::RingAccountBasic::mutate_account_basic( - &source, - Account { - nonce: source_account.nonce, - balance: new_source_balance, - }, - ); + T::RingAccountBasic::mutate_account_basic(&source, new_source_balance); let (currency_value, remain_balance) = context.apparent_value.div_mod(helper); ::RingCurrency::deposit_creating( &input.dest, diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index 58e338c6db..364251fbba 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -89,8 +89,8 @@ pub mod pallet { /// EVM execution runner. type Runner: Runner; /// The account basic mapping way - type RingAccountBasic: AccountBasic; - type KtonAccountBasic: AccountBasic; + type RingAccountBasic: AccountBasic; + type KtonAccountBasic: AccountBasic; /// Issuing contracts handler type IssuingHandler: IssuingHandler; @@ -162,20 +162,8 @@ pub mod pallet { fn build(&self) { let extra_genesis_builder: fn(&Self) = |config: &GenesisConfig| { for (address, account) in &config.accounts { - T::RingAccountBasic::mutate_account_basic( - &address, - Account { - balance: account.balance, - nonce: account.nonce, - }, - ); - T::KtonAccountBasic::mutate_account_basic( - &address, - Account { - balance: account.balance, - nonce: account.nonce, - }, - ); + T::RingAccountBasic::mutate_account_basic(&address, account.balance); + T::KtonAccountBasic::mutate_account_basic(&address, account.balance); AccountCodes::::insert(address, &account.code); for (index, value) in &account.storage { AccountStorages::::insert(address, index, value); @@ -382,13 +370,7 @@ pub mod pallet { let account = T::RingAccountBasic::account_basic(address); let new_account_balance = account.balance.saturating_sub(value); - T::RingAccountBasic::mutate_account_basic( - &address, - Account { - nonce: account.nonce, - balance: new_account_balance, - }, - ); + T::RingAccountBasic::mutate_account_basic(&address, new_account_balance); } /// Deposit fee. @@ -396,13 +378,7 @@ pub mod pallet { let account = T::RingAccountBasic::account_basic(address); let new_account_balance = account.balance.saturating_add(value); - T::RingAccountBasic::mutate_account_basic( - &address, - Account { - nonce: account.nonce, - balance: new_account_balance, - }, - ); + T::RingAccountBasic::mutate_account_basic(&address, new_account_balance); } } } @@ -432,13 +408,17 @@ pub trait AddressMapping { } /// Account basic info operations -pub trait AccountBasic { +pub trait AccountBasic { + /// Get the account basic in EVM format. fn account_basic(address: &H160) -> Account; - fn mutate_account_basic(address: &H160, new: Account); + /// Mutate the basic account + fn mutate_account_basic(address: &H160, new_balance: U256); + /// Transfer value fn transfer(source: &H160, target: &H160, value: U256) -> Result<(), ExitError>; - fn account(account_id: &AccountId32) -> Account { - self.account_basic() - } + /// Get account balance + fn account_balance(account_id: &T::AccountId) -> U256; + /// Mutate account balance + fn mutate_account_balance(account_id: &T::AccountId, balance: U256); } /// Config that outputs the current transaction gas price. From 16ab4f765f74e4bcb569311367e59eeb3251c4fa Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 17:53:37 +0800 Subject: [PATCH 29/45] Rename `mutate_account_basic` to `mutate_account_basic_balance` --- frame/dvm/src/account_basic.rs | 6 ++-- frame/dvm/src/tests.rs | 30 +++++++++---------- .../precompile/contracts/transfer/src/kton.rs | 5 +++- .../precompile/contracts/transfer/src/ring.rs | 2 +- frame/evm/src/lib.rs | 10 +++---- frame/evm/src/tests.rs | 2 +- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/frame/dvm/src/account_basic.rs b/frame/dvm/src/account_basic.rs index d6084eda00..1eb294876d 100644 --- a/frame/dvm/src/account_basic.rs +++ b/frame/dvm/src/account_basic.rs @@ -118,7 +118,7 @@ where } /// Mutate the basic account - fn mutate_account_basic(address: &H160, new_balance: U256) { + fn mutate_account_basic_balance(address: &H160, new_balance: U256) { let account_id = ::AddressMapping::into_account_id(*address); Self::mutate_account_balance(&account_id, new_balance) } @@ -128,11 +128,11 @@ where let source_account = Self::account_basic(source); ensure!(source_account.balance >= value, ExitError::OutOfGas); let new_source_balance = source_account.balance.saturating_sub(value); - Self::mutate_account_basic(source, new_source_balance); + Self::mutate_account_basic_balance(source, new_source_balance); let target_account = Self::account_basic(target); let new_target_balance = target_account.balance.saturating_add(value); - Self::mutate_account_basic(target, new_target_balance); + Self::mutate_account_basic_balance(target, new_target_balance); Ok(()) } diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index d64aaf81c1..ed0e578119 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -455,7 +455,7 @@ fn mutate_account_works_well() { ext.execute_with(|| { let test_addr = H160::from_str("1000000000000000000000000000000000000001").unwrap(); let origin_balance = U256::from(123_456_789_000_000_090u128); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, origin_balance, ); @@ -471,13 +471,13 @@ fn mutate_account_inc_balance_by_10() { let test_addr = H160::from_str("1000000000000000000000000000000000000001").unwrap(); // origin let origin_balance = U256::from(600_000_000_090u128); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, origin_balance, ); let new_balance = origin_balance.saturating_add(U256::from(10)); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, new_balance, ); @@ -492,13 +492,13 @@ fn mutate_account_inc_balance_by_999_999_910() { let test_addr = H160::from_str("1000000000000000000000000000000000000001").unwrap(); // origin let origin_balance = U256::from(600_000_000_090u128); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, origin_balance, ); let new_balance = origin_balance.saturating_add(U256::from(999999910u128)); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, new_balance, ); @@ -513,13 +513,13 @@ fn mutate_account_inc_by_1000_000_000() { let test_addr = H160::from_str("1000000000000000000000000000000000000001").unwrap(); // origin let origin_balance = U256::from(600_000_000_090u128); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, origin_balance, ); let new_balance = origin_balance.saturating_add(U256::from(1000_000_000u128)); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, new_balance, ); @@ -534,13 +534,13 @@ fn mutate_account_dec_balance_by_90() { let test_addr = H160::from_str("1000000000000000000000000000000000000001").unwrap(); // origin let origin_balance = U256::from(600_000_000_090u128); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, origin_balance, ); let new_balance = origin_balance.saturating_sub(U256::from(90)); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, new_balance, ); @@ -554,13 +554,13 @@ fn mutate_account_dec_balance_by_990() { let test_addr = H160::from_str("1000000000000000000000000000000000000001").unwrap(); // origin let origin_balance = U256::from(600_000_000_090u128); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, origin_balance, ); let new_balance = origin_balance.saturating_sub(U256::from(990)); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, new_balance, ); @@ -574,13 +574,13 @@ fn mutate_account_dec_balance_existential_by_90() { let test_addr = H160::from_str("1000000000000000000000000000000000000001").unwrap(); // origin let origin_balance = U256::from(500_000_000_090u128); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, origin_balance, ); let new_balance = origin_balance.saturating_sub(U256::from(90)); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, new_balance, ); @@ -594,13 +594,13 @@ fn mutate_account_dec_balance_existential_by_990() { let test_addr = H160::from_str("1000000000000000000000000000000000000001").unwrap(); // origin let origin_balance = U256::from(500_000_000_090u128); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, origin_balance, ); let new_balance = origin_balance.saturating_sub(U256::from(990)); - ::RingAccountBasic::mutate_account_basic( + ::RingAccountBasic::mutate_account_basic_balance( &test_addr, new_balance, ); diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index e29a093b0c..ca57993413 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -121,7 +121,10 @@ impl Kton { // Transfer let new_wkton_balance = caller_kton.balance.saturating_sub(wd.kton_value); - T::KtonAccountBasic::mutate_account_basic(&context.caller, new_wkton_balance); + T::KtonAccountBasic::mutate_account_basic_balance( + &context.caller, + new_wkton_balance, + ); let (currency_value, remain_balance) = wd.kton_value.div_mod(helper); ::KtonCurrency::deposit_creating( &wd.to_account_id, diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 4c1901df41..fa8da46ac8 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -64,7 +64,7 @@ impl RingBack { // Transfer let new_source_balance = source_account.balance.saturating_sub(value); - T::RingAccountBasic::mutate_account_basic(&source, new_source_balance); + T::RingAccountBasic::mutate_account_basic_balance(&source, new_source_balance); let (currency_value, remain_balance) = context.apparent_value.div_mod(helper); ::RingCurrency::deposit_creating( &input.dest, diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index 364251fbba..d979d1a498 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -162,8 +162,8 @@ pub mod pallet { fn build(&self) { let extra_genesis_builder: fn(&Self) = |config: &GenesisConfig| { for (address, account) in &config.accounts { - T::RingAccountBasic::mutate_account_basic(&address, account.balance); - T::KtonAccountBasic::mutate_account_basic(&address, account.balance); + T::RingAccountBasic::mutate_account_basic_balance(&address, account.balance); + T::KtonAccountBasic::mutate_account_basic_balance(&address, account.balance); AccountCodes::::insert(address, &account.code); for (index, value) in &account.storage { AccountStorages::::insert(address, index, value); @@ -370,7 +370,7 @@ pub mod pallet { let account = T::RingAccountBasic::account_basic(address); let new_account_balance = account.balance.saturating_sub(value); - T::RingAccountBasic::mutate_account_basic(&address, new_account_balance); + T::RingAccountBasic::mutate_account_basic_balance(&address, new_account_balance); } /// Deposit fee. @@ -378,7 +378,7 @@ pub mod pallet { let account = T::RingAccountBasic::account_basic(address); let new_account_balance = account.balance.saturating_add(value); - T::RingAccountBasic::mutate_account_basic(&address, new_account_balance); + T::RingAccountBasic::mutate_account_basic_balance(&address, new_account_balance); } } } @@ -412,7 +412,7 @@ pub trait AccountBasic { /// Get the account basic in EVM format. fn account_basic(address: &H160) -> Account; /// Mutate the basic account - fn mutate_account_basic(address: &H160, new_balance: U256); + fn mutate_account_basic_balance(address: &H160, new_balance: U256); /// Transfer value fn transfer(source: &H160, target: &H160, value: U256) -> Result<(), ExitError>; /// Get account balance diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs index 2da5463a97..a82166836a 100644 --- a/frame/evm/src/tests.rs +++ b/frame/evm/src/tests.rs @@ -123,7 +123,7 @@ impl AccountBasic for RawAccountBasic { } } - fn mutate_account_basic(address: &H160, new: Account) { + fn mutate_account_basic_balance(address: &H160, new: Account) { let account_id = T::AddressMapping::into_account_id(*address); let current = T::RingAccountBasic::account_basic(address); From 5ffebd837526c3d91ba31148650fe5bbd441ccc5 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 18:13:28 +0800 Subject: [PATCH 30/45] Use unified muta_* --- Cargo.lock | 1 - .../precompile/contracts/transfer/Cargo.toml | 2 -- .../precompile/contracts/transfer/src/kton.rs | 29 +++++------------- .../precompile/contracts/transfer/src/lib.rs | 9 ++---- .../precompile/contracts/transfer/src/ring.rs | 30 ++++++------------- 5 files changed, 20 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34f146e720..a14a83766a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1787,7 +1787,6 @@ dependencies = [ "darwinia-evm", "darwinia-support", "dp-evm", - "dvm-ethereum", "ethabi", "ethereum-types", "evm", diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index 68fd395d76..e46242e71d 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -23,7 +23,6 @@ sha3 = { version = "0.9.1", default-features = false } darwinia-evm = { default-features = false, path = "../../../" } darwinia-support = { default-features = false, path = "../../../../support" } dp-evm = { default-features = false, path = "../../../../../primitives/evm" } -dvm-ethereum = { default-features = false, path = "../../.././../dvm" } # substrate frame-support = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } frame-system = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } @@ -58,7 +57,6 @@ darwinia-std = [ "darwinia-evm/std", "darwinia-support/std", "dp-evm/std", - "dvm-ethereum/std", ] substrate-std = [ diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index ca57993413..01850220e4 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -17,19 +17,13 @@ // along with Darwinia. If not, see . // --- substrate --- -use frame_support::{ensure, traits::Currency}; +use frame_support::ensure; use sp_core::{H160, U256}; -use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; -// use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; // --- darwinia --- use crate::util; use crate::AccountId; -use darwinia_evm::{AccountBasic, Pallet, Runner}; -use darwinia_support::evm::{POW_9, SELECTOR, TRANSFER_ADDR}; -use dvm_ethereum::{ - account_basic::{KtonRemainBalance, RemainBalanceOp}, - KtonBalance, -}; +use darwinia_evm::{AccountBasic, Config, Pallet, Runner}; +use darwinia_support::evm::{SELECTOR, TRANSFER_ADDR}; use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; // --- crates --- use codec::Decode; @@ -47,13 +41,12 @@ pub enum Kton { Withdraw(WithdrawData), } -impl Kton { +impl Kton { pub fn transfer( input: &[u8], target_gas: Option, context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { - let helper = U256::from(POW_9); let action = which_action::(&input)?; match action { @@ -125,16 +118,10 @@ impl Kton { &context.caller, new_wkton_balance, ); - let (currency_value, remain_balance) = wd.kton_value.div_mod(helper); - ::KtonCurrency::deposit_creating( - &wd.to_account_id, - currency_value.low_u128().unique_saturated_into(), - ); - >>::inc_remaining_balance( - &wd.to_account_id, - remain_balance.low_u128().saturated_into(), - ); + let target_balance = T::KtonAccountBasic::account_balance(&wd.to_account_id); + let new_target_balance = target_balance.saturating_add(wd.kton_value); + T::KtonAccountBasic::mutate_account_balance(&wd.to_account_id, new_target_balance); Ok((ExitSucceed::Returned, vec![], 20000)) } } @@ -142,7 +129,7 @@ impl Kton { } /// which action depends on the function selector -pub fn which_action(input_data: &[u8]) -> Result, ExitError> { +pub fn which_action(input_data: &[u8]) -> Result, ExitError> { let transfer_and_call_action = &sha3::Keccak256::digest(&TRANSFER_AND_CALL_ACTION)[0..SELECTOR]; let withdraw_action = &sha3::Keccak256::digest(&WITHDRAW_ACTION)[0..SELECTOR]; if &input_data[0..SELECTOR] == transfer_and_call_action { diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index a8810f00b9..d5f13118d8 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -43,6 +43,7 @@ pub mod util; // --- substrate --- use sp_std::{marker::PhantomData, vec::Vec}; // --- darwinia --- +use darwinia_evm::Config; use darwinia_support::evm::SELECTOR; use dp_evm::Precompile; use kton::Kton; @@ -51,7 +52,6 @@ use ring::RingBack; use evm::{Context, ExitError, ExitSucceed}; pub type AccountId = ::AccountId; -pub use dvm_ethereum; /// Transfer Precompile Contract, used to support the exchange of KTON and RING transfer. pub enum Transfer { @@ -61,10 +61,7 @@ pub enum Transfer { KtonTransfer, _Impossible(PhantomData), } -impl Precompile for Transfer -where - T: dvm_ethereum::Config, -{ +impl Precompile for Transfer { fn execute( input: &[u8], target_gas: Option, @@ -81,7 +78,7 @@ where /// There are two types of transfers: RING transfer and KTON transfer /// /// The RingBack has only one action, while KtonTransfer has two: `transfer and call`, `withdraw`. -fn which_transfer(data: &[u8]) -> Result, ExitError> { +fn which_transfer(data: &[u8]) -> Result, ExitError> { if data.len() < SELECTOR { return Err(ExitError::Other("Invalid input data!".into())); } diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index fa8da46ac8..cdef741ae8 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -17,27 +17,21 @@ // along with Darwinia. If not, see . // --- substrate --- -use frame_support::{ensure, traits::Currency}; -use sp_core::U256; -use sp_runtime::{traits::UniqueSaturatedInto, SaturatedConversion}; +use frame_support::ensure; use sp_std::{marker::PhantomData, prelude::*, vec::Vec}; // --- darwinia --- use crate::AccountId; use darwinia_evm::{AccountBasic, Config}; -use darwinia_support::evm::{POW_9, TRANSFER_ADDR}; -use dvm_ethereum::{ - account_basic::{RemainBalanceOp, RingRemainBalance}, - RingBalance, -}; +use darwinia_support::evm::TRANSFER_ADDR; // --- crates --- use codec::Decode; use evm::{Context, ExitError, ExitSucceed}; -pub struct RingBack { +pub struct RingBack { _maker: PhantomData, } -impl RingBack { +impl RingBack { /// The Withdraw process is divided into two part: /// 1. parse the withdrawal address from the input parameter and get the contract address and value from the context /// 2. transfer from the contract address to withdrawal address @@ -49,7 +43,6 @@ impl RingBack { context: &Context, ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { // Decode input data - let helper = U256::from(POW_9); let input = InputData::::decode(&input)?; let (source, value) = (context.address, context.apparent_value); let source_account = T::RingAccountBasic::account_basic(&source); @@ -65,17 +58,12 @@ impl RingBack { // Transfer let new_source_balance = source_account.balance.saturating_sub(value); T::RingAccountBasic::mutate_account_basic_balance(&source, new_source_balance); - let (currency_value, remain_balance) = context.apparent_value.div_mod(helper); - ::RingCurrency::deposit_creating( - &input.dest, - currency_value.low_u128().unique_saturated_into(), - ); - >>::inc_remaining_balance( - &input.dest, - remain_balance.low_u128().saturated_into(), - ); - Ok((ExitSucceed::Returned, vec![], 10000)) + let target_balance = T::RingAccountBasic::account_balance(&input.dest); + let new_target_balance = target_balance.saturating_add(value); + T::RingAccountBasic::mutate_account_balance(&input.dest, new_target_balance); + + Ok((ExitSucceed::Returned, vec![], 20000)) } } From 989775b5313551ba13757e927ff518be86d32945 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 19:18:00 +0800 Subject: [PATCH 31/45] Run tests --- frame/dvm/src/mock.rs | 16 ++++------------ frame/dvm/src/tests.rs | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 234a6ae5d6..03b235a4f8 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -152,7 +152,7 @@ frame_support::parameter_types! { pub struct MockPrecompiles(PhantomData); impl PrecompileSet for MockPrecompiles where - R: darwinia_evm_precompile_transfer::dvm_ethereum::Config, + R: darwinia_evm::Config, { fn execute( address: H160, @@ -169,9 +169,9 @@ where _ if address == to_address(3) => Some(Ripemd160::execute(input, target_gas, context)), _ if address == to_address(4) => Some(Identity::execute(input, target_gas, context)), // Darwinia precompiles - _ if address == to_address(21) => Some( as Precompile>::execute( - input, target_gas, context, - )), + _ if address == to_address(21) => { + Some(>::execute(input, target_gas, context)) + } _ => None, } } @@ -194,14 +194,6 @@ impl darwinia_evm::Config for Test { type IssuingHandler = (); } -impl darwinia_evm_precompile_transfer::dvm_ethereum::Config for Test { - type Event = (); - type FindAuthor = EthereumFindAuthor; - type StateRoot = IntermediateStateRoot; - type RingCurrency = Ring; - type KtonCurrency = Kton; -} - impl dvm_ethereum::Config for Test { type Event = (); type FindAuthor = EthereumFindAuthor; diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index ed0e578119..525c7d006e 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -21,7 +21,7 @@ use crate::{ Call, *, }; use codec::Decode; -use darwinia_evm::{Account, AddressMapping}; +use darwinia_evm::AddressMapping; use ethereum::TransactionSignature; use frame_support::{assert_err, assert_noop, assert_ok, unsigned::ValidateUnsigned}; use mock::*; @@ -415,6 +415,41 @@ fn withdraw_without_enough_balance_should_fail() { assert_eq!(::RingCurrency::free_balance(&dest), 0); }); } + +#[test] +fn withdraw_with_enough_balance() { + let (pairs, mut ext) = new_test_ext(1); + let alice = &pairs[0]; + + ext.execute_with(|| { + let t = sign_transaction(alice, default_withdraw_unsigned_transaction()); + assert_ok!(Ethereum::execute( + alice.address, + t.input.clone(), + t.value, + t.gas_limit, + None, + Some(t.nonce), + t.action, + None, + )); + + // Check caller balance + assert_eq!( + ::RingAccountBasic::account_basic(&alice.address).balance, + U256::from(70_000_000_000_000_000_000u128) + ); + // Check the target balance + let input_bytes: Vec = array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT); + let dest = + ::AccountId::decode(&mut &input_bytes[..]).unwrap(); + assert_eq!( + ::RingCurrency::free_balance(dest), + 30000000000 + ); + }); +} + #[test] fn withdraw_with_invalid_input_length_should_failed() { let (pairs, mut ext) = new_test_ext(1); From 1ff55c973c536b05f70bb175f6ef506a27687b94 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 8 Jun 2021 19:26:07 +0800 Subject: [PATCH 32/45] Make review work easier --- frame/dvm/src/tests.rs | 66 +++++++++---------- .../precompile/contracts/transfer/Cargo.toml | 4 +- .../precompile/contracts/transfer/src/kton.rs | 38 +++++------ 3 files changed, 53 insertions(+), 55 deletions(-) diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index 525c7d006e..fa11fcf9fc 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -22,6 +22,7 @@ use crate::{ }; use codec::Decode; use darwinia_evm::AddressMapping; +use darwinia_support::evm::TRANSFER_ADDR; use ethereum::TransactionSignature; use frame_support::{assert_err, assert_noop, assert_ok, unsigned::ValidateUnsigned}; use mock::*; @@ -35,7 +36,6 @@ use std::str::FromStr; // constructor() public { _mint(msg.sender, 2**256 - 1); } // } const ERC20_CONTRACT_BYTECODE: &str = "608060405234801561001057600080fd5b50610041337fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61004660201b60201c565b610291565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156100e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b6101028160025461020960201b610c7c1790919060201c565b60028190555061015d816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461020960201b610c7c1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600080828401905083811015610287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b610e3a806102a06000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806370a082311161005b57806370a08231146101fd578063a457c2d714610255578063a9059cbb146102bb578063dd62ed3e1461032157610088565b8063095ea7b31461008d57806318160ddd146100f357806323b872dd146101115780633950935114610197575b600080fd5b6100d9600480360360408110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610399565b604051808215151515815260200191505060405180910390f35b6100fb6103b7565b6040518082815260200191505060405180910390f35b61017d6004803603606081101561012757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506103c1565b604051808215151515815260200191505060405180910390f35b6101e3600480360360408110156101ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061049a565b604051808215151515815260200191505060405180910390f35b61023f6004803603602081101561021357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061054d565b6040518082815260200191505060405180910390f35b6102a16004803603604081101561026b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610595565b604051808215151515815260200191505060405180910390f35b610307600480360360408110156102d157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610662565b604051808215151515815260200191505060405180910390f35b6103836004803603604081101561033757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610680565b6040518082815260200191505060405180910390f35b60006103ad6103a6610707565b848461070f565b6001905092915050565b6000600254905090565b60006103ce848484610906565b61048f846103da610707565b61048a85604051806060016040528060288152602001610d7060289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610440610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b61070f565b600190509392505050565b60006105436104a7610707565b8461053e85600160006104b8610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610c7c90919063ffffffff16565b61070f565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006106586105a2610707565b8461065385604051806060016040528060258152602001610de160259139600160006105cc610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b61070f565b6001905092915050565b600061067661066f610707565b8484610906565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610795576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180610dbd6024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561081b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610d286022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561098c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180610d986025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610d056023913960400191505060405180910390fd5b610a7d81604051806060016040528060268152602001610d4a602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610b10816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610c7c90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610c69576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610c2e578082015181840152602081019050610c13565b50505050905090810190601f168015610c5b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610cfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b809150509291505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a72315820c7a5ffabf642bda14700b2de42f8c57b36621af020441df825de45fd2b3e1c5c64736f6c63430005100032"; -const WITHDRAW_DVM_ADDRESS: &str = "0000000000000000000000000000000000000015"; const WITH_DRAW_INPUT: &str = "723908ee9dc8e509d4b93251bd57f68c09bd9d04471c193fabd8f26c54284a4b"; fn default_erc20_creation_unsigned_transaction() -> UnsignedTransaction { @@ -54,7 +54,7 @@ fn default_withdraw_unsigned_transaction() -> UnsignedTransaction { nonce: U256::zero(), gas_price: U256::from(1), gas_limit: U256::from(0x100000), - action: ethereum::TransactionAction::Call(H160::from_str(WITHDRAW_DVM_ADDRESS).unwrap()), + action: ethereum::TransactionAction::Call(H160::from_str(TRANSFER_ADDR).unwrap()), value: U256::from(30000000000000000000u128), input: array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT), } @@ -374,79 +374,79 @@ fn call_should_handle_errors() { } #[test] -fn withdraw_without_enough_balance_should_fail() { +fn withdraw_with_enough_balance() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; ext.execute_with(|| { - let mut unsigned_tx = default_withdraw_unsigned_transaction(); - unsigned_tx.value = U256::from(120000000000000000000u128); - let t = sign_transaction(alice, unsigned_tx); - - let res = Ethereum::execute( + let t = sign_transaction(alice, default_withdraw_unsigned_transaction()); + assert_ok!(Ethereum::execute( alice.address, - t.input, + t.input.clone(), t.value, t.gas_limit, None, Some(t.nonce), t.action, None, - ); - - assert_err!( - res, - DispatchError::Module { - index: 4, - error: 0, - message: Some("BalanceLow") - } - ); + )); // Check caller balance assert_eq!( ::RingAccountBasic::account_basic(&alice.address).balance, - U256::from(100000000000000000000u128) + U256::from(70_000_000_000_000_000_000u128) ); - // Check target balance + // Check the target balance let input_bytes: Vec = array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT); let dest = ::AccountId::decode(&mut &input_bytes[..]).unwrap(); - assert_eq!(::RingCurrency::free_balance(&dest), 0); + assert_eq!( + ::RingCurrency::free_balance(dest), + 30000000000 + ); }); } #[test] -fn withdraw_with_enough_balance() { +fn withdraw_without_enough_balance_should_fail() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; ext.execute_with(|| { - let t = sign_transaction(alice, default_withdraw_unsigned_transaction()); - assert_ok!(Ethereum::execute( + let mut unsigned_tx = default_withdraw_unsigned_transaction(); + unsigned_tx.value = U256::from(120000000000000000000u128); + let t = sign_transaction(alice, unsigned_tx); + + let res = Ethereum::execute( alice.address, - t.input.clone(), + t.input, t.value, t.gas_limit, None, Some(t.nonce), t.action, None, - )); + ); + + assert_err!( + res, + DispatchError::Module { + index: 4, + error: 0, + message: Some("BalanceLow") + } + ); // Check caller balance assert_eq!( ::RingAccountBasic::account_basic(&alice.address).balance, - U256::from(70_000_000_000_000_000_000u128) + U256::from(100000000000000000000u128) ); - // Check the target balance + // Check target balance let input_bytes: Vec = array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT); let dest = ::AccountId::decode(&mut &input_bytes[..]).unwrap(); - assert_eq!( - ::RingCurrency::free_balance(dest), - 30000000000 - ); + assert_eq!(::RingCurrency::free_balance(&dest), 0); }); } diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index e46242e71d..bd645f0642 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -13,8 +13,8 @@ version = "2.4.0" # crates array-bytes = { version = "1.1.0" } codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } -evm = { version = "0.25.0", features = ["with-codec"], default-features = false } ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std", default-features = false } +evm = { version = "0.25.0", features = ["with-codec"], default-features = false } ethereum-types = { version = "0.11.0", default-features = false } log = { version = "0.4.14" } ripemd160 = { version = "0.9.1", default-features = false } @@ -33,7 +33,7 @@ sp-runtime = { default-features = false, git = "https://github.com/darwini sp-std = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } [dev-dependencies] -array-bytes = { version = "1.1.0" } +array-bytes = { version = "1.1.0" } [features] default = ["std"] diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 01850220e4..bc26aade7c 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -19,12 +19,12 @@ // --- substrate --- use frame_support::ensure; use sp_core::{H160, U256}; +use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; // --- darwinia --- use crate::util; use crate::AccountId; use darwinia_evm::{AccountBasic, Config, Pallet, Runner}; use darwinia_support::evm::{SELECTOR, TRANSFER_ADDR}; -use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; // --- crates --- use codec::Decode; use ethabi::{Function, Param, ParamType, Token}; @@ -51,9 +51,10 @@ impl Kton { match action { Kton::TransferAndCall(call_data) => { + let (caller, wkton, value) = (context.caller, call_data.wkton_address, call_data.value); // Ensure wkton is a contract ensure!( - !>::is_contract_code_empty(&call_data.wkton_address), + !>::is_contract_code_empty(&wkton), ExitError::Other("Wkton must be a contract!".into()) ); // Ensure context's apparent_value is zero, since the transfer value is encoded in input field @@ -63,23 +64,19 @@ impl Kton { ); // Ensure caller's balance is enough ensure!( - T::KtonAccountBasic::account_basic(&context.caller).balance >= call_data.value, + T::KtonAccountBasic::account_basic(&caller).balance >= value, ExitError::OutOfFund ); // Transfer kton from sender to KTON wrapped contract - T::KtonAccountBasic::transfer( - &context.caller, - &call_data.wkton_address, - call_data.value, - )?; + T::KtonAccountBasic::transfer(&caller,&wkton, value)?; // Call WKTON wrapped contract deposit let precompile_address: H160 = array_bytes::hex2array_unchecked!(TRANSFER_ADDR, 20).into(); - let raw_input = make_call_data(context.caller, call_data.value)?; + let raw_input = make_call_data(caller, value)?; if let Ok(call_res) = T::Runner::call( precompile_address, - call_data.wkton_address, + wkton, raw_input.to_vec(), U256::zero(), target_gas.unwrap_or_default(), @@ -98,9 +95,10 @@ impl Kton { Ok((ExitSucceed::Returned, vec![], 20000)) } Kton::Withdraw(wd) => { + let (source, to, value) = (context.caller, wd.to_account_id, wd.kton_value); // Ensure wkton is a contract ensure!( - !>::is_contract_code_empty(&context.caller), + !>::is_contract_code_empty(&source), ExitError::Other("The caller must be wkton contract!".into()) ); // Ensure context's apparent_value is zero @@ -108,20 +106,20 @@ impl Kton { context.apparent_value == U256::zero(), ExitError::Other("The value in tx must be zero!".into()) ); - // Ensure caller's balance is enough - let caller_kton = T::KtonAccountBasic::account_basic(&context.caller); - ensure!(caller_kton.balance >= wd.kton_value, ExitError::OutOfFund); + // Ensure source's balance is enough + let source_kton = T::KtonAccountBasic::account_basic(&source); + ensure!(source_kton.balance >= value, ExitError::OutOfFund); // Transfer - let new_wkton_balance = caller_kton.balance.saturating_sub(wd.kton_value); + let new_source_kton_balance = source_kton.balance.saturating_sub(value); T::KtonAccountBasic::mutate_account_basic_balance( - &context.caller, - new_wkton_balance, + &source, + new_source_kton_balance, ); - let target_balance = T::KtonAccountBasic::account_balance(&wd.to_account_id); - let new_target_balance = target_balance.saturating_add(wd.kton_value); - T::KtonAccountBasic::mutate_account_balance(&wd.to_account_id, new_target_balance); + let target_kton = T::KtonAccountBasic::account_balance(&to); + let new_target_kton_balance = target_kton.saturating_add(value); + T::KtonAccountBasic::mutate_account_balance(&to, new_target_kton_balance); Ok((ExitSucceed::Returned, vec![], 20000)) } } From 70d9fc32c49c33d9b48e750ff10fd4e49acab392 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 9 Jun 2021 00:18:18 +0800 Subject: [PATCH 33/45] Fix ci test --- frame/evm/src/tests.rs | 31 ++++++++++++++++----------- script_tests/tests/1_test-transfer.js | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs index a82166836a..d9ad84634f 100644 --- a/frame/evm/src/tests.rs +++ b/frame/evm/src/tests.rs @@ -109,7 +109,7 @@ impl FeeCalculator for FixedGasPrice { } pub struct RawAccountBasic(sp_std::marker::PhantomData); -impl AccountBasic for RawAccountBasic { +impl AccountBasic for RawAccountBasic { /// Get the account basic in EVM format. fn account_basic(address: &H160) -> Account { let account_id = T::AddressMapping::into_account_id(*address); @@ -123,23 +123,23 @@ impl AccountBasic for RawAccountBasic { } } - fn mutate_account_basic_balance(address: &H160, new: Account) { + fn mutate_account_basic_balance(address: &H160, new_balance: U256) { let account_id = T::AddressMapping::into_account_id(*address); let current = T::RingAccountBasic::account_basic(address); - if current.nonce < new.nonce { - // ASSUME: in one single EVM transaction, the nonce will not increase more than - // `u128::max_value()`. - for _ in 0..(new.nonce - current.nonce).low_u128() { - >::inc_account_nonce(&account_id); - } - } + // if current.nonce < new.nonce { + // // ASSUME: in one single EVM transaction, the nonce will not increase more than + // // `u128::max_value()`. + // for _ in 0..(new.nonce - current.nonce).low_u128() { + // >::inc_account_nonce(&account_id); + // } + // } - if current.balance > new.balance { - let diff = current.balance - new.balance; + if current.balance > new_balance { + let diff = current.balance - new_balance; T::RingCurrency::slash(&account_id, diff.low_u128().unique_saturated_into()); - } else if current.balance < new.balance { - let diff = new.balance - current.balance; + } else if current.balance < new_balance { + let diff = new_balance - current.balance; T::RingCurrency::deposit_creating(&account_id, diff.low_u128().unique_saturated_into()); } } @@ -147,6 +147,11 @@ impl AccountBasic for RawAccountBasic { fn transfer(_source: &H160, _target: &H160, _value: U256) -> Result<(), ExitError> { Ok(()) } + + fn account_balance(_account_id: &T::AccountId) -> U256 { + U256::default() + } + fn mutate_account_balance(_account_id: &T::AccountId, _balance: U256) {} } /// Ensure that the origin is root. diff --git a/script_tests/tests/1_test-transfer.js b/script_tests/tests/1_test-transfer.js index 822411cd34..6430fdcbc7 100644 --- a/script_tests/tests/1_test-transfer.js +++ b/script_tests/tests/1_test-transfer.js @@ -141,7 +141,7 @@ describe("Test Transfer Balance", function () { it("Get sender balance after withdraw", async function () { const balanceFrom = web3.utils.fromWei(await web3.eth.getBalance(addressFrom), "ether"); - expect(balanceFrom).to.be.equal("123366.78888448799999999"); + expect(balanceFrom).to.be.equal("123366.78887448799999999"); expect(await web3.eth.getTransactionCount(addressFrom, "latest")).to.eq(5); }); }); From d3bce700dba5cfb526a3799eb6b7ff816822a03b Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 9 Jun 2021 11:41:32 +0800 Subject: [PATCH 34/45] Use new array_bytes function --- frame/evm/precompile/contracts/transfer/Cargo.toml | 4 +--- .../evm/precompile/contracts/transfer/src/kton.rs | 14 +++++--------- .../evm/precompile/contracts/transfer/src/ring.rs | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index 1219e62c59..5bde13b1fb 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -11,6 +11,7 @@ version = "2.4.0" [dependencies] # crates +array-bytes = { version = "1.3.3" } codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std", default-features = false } evm = { version = "0.25.0", features = ["with-codec"], default-features = false } @@ -31,9 +32,6 @@ sp-io = { default-features = false, git = "https://github.com/darwini sp-runtime = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } sp-std = { default-features = false, git = "https://github.com/darwinia-network/substrate.git", tag = "darwinia-v0.11.1" } -[dev-dependencies] -array-bytes = { version = "1.3.3" } - [features] default = ["std"] diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index bc26aade7c..7263dc3b3e 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -51,7 +51,8 @@ impl Kton { match action { Kton::TransferAndCall(call_data) => { - let (caller, wkton, value) = (context.caller, call_data.wkton_address, call_data.value); + let (caller, wkton, value) = + (context.caller, call_data.wkton_address, call_data.value); // Ensure wkton is a contract ensure!( !>::is_contract_code_empty(&wkton), @@ -69,13 +70,11 @@ impl Kton { ); // Transfer kton from sender to KTON wrapped contract - T::KtonAccountBasic::transfer(&caller,&wkton, value)?; + T::KtonAccountBasic::transfer(&caller, &wkton, value)?; // Call WKTON wrapped contract deposit - let precompile_address: H160 = - array_bytes::hex2array_unchecked!(TRANSFER_ADDR, 20).into(); let raw_input = make_call_data(caller, value)?; if let Ok(call_res) = T::Runner::call( - precompile_address, + array_bytes::hex_into_unchecked(TRANSFER_ADDR), wkton, raw_input.to_vec(), U256::zero(), @@ -112,10 +111,7 @@ impl Kton { // Transfer let new_source_kton_balance = source_kton.balance.saturating_sub(value); - T::KtonAccountBasic::mutate_account_basic_balance( - &source, - new_source_kton_balance, - ); + T::KtonAccountBasic::mutate_account_basic_balance(&source, new_source_kton_balance); let target_kton = T::KtonAccountBasic::account_balance(&to); let new_target_kton_balance = target_kton.saturating_add(value); diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index cdef741ae8..319a127bc1 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -49,7 +49,7 @@ impl RingBack { // Ensure the context address should be precompile address ensure!( - source == array_bytes::hex2array_unchecked!(TRANSFER_ADDR, 20).into(), + source == array_bytes::hex_into_unchecked(TRANSFER_ADDR), ExitError::Other("Invalid context address".into()) ); // Ensure the context address balance is enough From 1922adb8fafd10889dcac85e885e40db66ecaffd Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 9 Jun 2021 11:49:39 +0800 Subject: [PATCH 35/45] Chores things --- Cargo.lock | 1 - frame/evm/precompile/contracts/transfer/src/ring.rs | 6 +++--- frame/evm/src/tests.rs | 8 -------- frame/support/Cargo.toml | 1 - 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b45d3e5a44..fad46ae9a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1955,7 +1955,6 @@ dependencies = [ name = "darwinia-support" version = "2.4.0" dependencies = [ - "array-bytes", "ethereum-primitives", "frame-support", "impl-trait-for-tuples", diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 319a127bc1..74c1bc5742 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -44,7 +44,7 @@ impl RingBack { ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { // Decode input data let input = InputData::::decode(&input)?; - let (source, value) = (context.address, context.apparent_value); + let (source, to, value) = (context.address, input.dest, context.apparent_value); let source_account = T::RingAccountBasic::account_basic(&source); // Ensure the context address should be precompile address @@ -59,9 +59,9 @@ impl RingBack { let new_source_balance = source_account.balance.saturating_sub(value); T::RingAccountBasic::mutate_account_basic_balance(&source, new_source_balance); - let target_balance = T::RingAccountBasic::account_balance(&input.dest); + let target_balance = T::RingAccountBasic::account_balance(&to); let new_target_balance = target_balance.saturating_add(value); - T::RingAccountBasic::mutate_account_balance(&input.dest, new_target_balance); + T::RingAccountBasic::mutate_account_balance(&to, new_target_balance); Ok((ExitSucceed::Returned, vec![], 20000)) } diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs index d9ad84634f..6f3f0e2b99 100644 --- a/frame/evm/src/tests.rs +++ b/frame/evm/src/tests.rs @@ -127,14 +127,6 @@ impl AccountBasic for RawAccountBasic { let account_id = T::AddressMapping::into_account_id(*address); let current = T::RingAccountBasic::account_basic(address); - // if current.nonce < new.nonce { - // // ASSUME: in one single EVM transaction, the nonce will not increase more than - // // `u128::max_value()`. - // for _ in 0..(new.nonce - current.nonce).low_u128() { - // >::inc_account_nonce(&account_id); - // } - // } - if current.balance > new_balance { let diff = current.balance - new_balance; T::RingCurrency::slash(&account_id, diff.low_u128().unique_saturated_into()); diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 448431d656..d3daaf9ce9 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -11,7 +11,6 @@ version = "2.4.0" [dependencies] # crates -array-bytes = { version = "1.1.0" } codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false, features = ["derive"] } impl-trait-for-tuples = { version = "0.2.1" } num-traits = { version = "0.2.14", default-features = false } From 6c0d94ca17a43560823cbd847799c8ee928953f5 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Wed, 9 Jun 2021 14:15:04 +0800 Subject: [PATCH 36/45] Add unit tests --- Cargo.lock | 2 + frame/dvm/Cargo.toml | 2 + frame/dvm/src/tests.rs | 369 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 361 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fad46ae9a9..9caf3ab4ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2344,11 +2344,13 @@ dependencies = [ "dp-storage", "dp_consensus", "dvm-rpc-runtime-api", + "ethabi", "ethereum", "ethereum-types", "evm", "frame-support", "frame-system", + "hex", "libsecp256k1", "log", "pallet-timestamp", diff --git a/frame/dvm/Cargo.toml b/frame/dvm/Cargo.toml index 4e79971d8a..d65212f1d8 100644 --- a/frame/dvm/Cargo.toml +++ b/frame/dvm/Cargo.toml @@ -39,6 +39,8 @@ sp-std = { default-features = false, git = "https://github.com/darwini [dev-dependencies] # crates.io array-bytes = { version = "1.3.3" } +ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std", default-features = false } +hex = "0.4.3" # darwinia darwinia-balances = { path = "../balances" } darwinia-evm-precompile-simple = { path = "../evm/precompile/contracts/simple" } diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index fa11fcf9fc..8f0b4fa2e4 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -23,6 +23,7 @@ use crate::{ use codec::Decode; use darwinia_evm::AddressMapping; use darwinia_support::evm::TRANSFER_ADDR; +use ethabi::{Function, Param, ParamType, Token}; use ethereum::TransactionSignature; use frame_support::{assert_err, assert_noop, assert_ok, unsigned::ValidateUnsigned}; use mock::*; @@ -36,16 +37,18 @@ use std::str::FromStr; // constructor() public { _mint(msg.sender, 2**256 - 1); } // } const ERC20_CONTRACT_BYTECODE: &str = "608060405234801561001057600080fd5b50610041337fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61004660201b60201c565b610291565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156100e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b6101028160025461020960201b610c7c1790919060201c565b60028190555061015d816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461020960201b610c7c1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600080828401905083811015610287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b610e3a806102a06000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806370a082311161005b57806370a08231146101fd578063a457c2d714610255578063a9059cbb146102bb578063dd62ed3e1461032157610088565b8063095ea7b31461008d57806318160ddd146100f357806323b872dd146101115780633950935114610197575b600080fd5b6100d9600480360360408110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610399565b604051808215151515815260200191505060405180910390f35b6100fb6103b7565b6040518082815260200191505060405180910390f35b61017d6004803603606081101561012757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506103c1565b604051808215151515815260200191505060405180910390f35b6101e3600480360360408110156101ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061049a565b604051808215151515815260200191505060405180910390f35b61023f6004803603602081101561021357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061054d565b6040518082815260200191505060405180910390f35b6102a16004803603604081101561026b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610595565b604051808215151515815260200191505060405180910390f35b610307600480360360408110156102d157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610662565b604051808215151515815260200191505060405180910390f35b6103836004803603604081101561033757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610680565b6040518082815260200191505060405180910390f35b60006103ad6103a6610707565b848461070f565b6001905092915050565b6000600254905090565b60006103ce848484610906565b61048f846103da610707565b61048a85604051806060016040528060288152602001610d7060289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610440610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b61070f565b600190509392505050565b60006105436104a7610707565b8461053e85600160006104b8610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610c7c90919063ffffffff16565b61070f565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006106586105a2610707565b8461065385604051806060016040528060258152602001610de160259139600160006105cc610707565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b61070f565b6001905092915050565b600061067661066f610707565b8484610906565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610795576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180610dbd6024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561081b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610d286022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561098c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180610d986025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610d056023913960400191505060405180910390fd5b610a7d81604051806060016040528060268152602001610d4a602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610bbc9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610b10816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610c7c90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610c69576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610c2e578082015181840152602081019050610c13565b50505050905090810190601f168015610c5b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610cfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b809150509291505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a72315820c7a5ffabf642bda14700b2de42f8c57b36621af020441df825de45fd2b3e1c5c64736f6c63430005100032"; +const WKTON_CONTRACT_BYTECODE: &str = "60806040526040805190810160405280600d81526020017f5772617070656420434b544f4e00000000000000000000000000000000000000815250600090805190602001906200005192919062000112565b506040805190810160405280600681526020017f57434b544f4e0000000000000000000000000000000000000000000000000000815250600190805190602001906200009f92919062000112565b506012600260006101000a81548160ff021916908360ff1602179055506015600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200010b57600080fd5b50620001c1565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200015557805160ff191683800117855562000186565b8280016001018555821562000186579182015b828111156200018557825182559160200191906001019062000168565b5b50905062000195919062000199565b5090565b620001be91905b80821115620001ba576000816000905550600101620001a0565b5090565b90565b61100280620001d16000396000f3006080604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063040cf020146100bf57806306fdde03146100fa578063095ea7b31461018a57806318160ddd146101ef57806323b872dd1461021a578063313ce5671461029f57806347e7ef24146102d057806370a082311461031d57806395d89b4114610374578063a9059cbb14610404578063b548602014610469578063dd62ed3e146104c0575b600080fd5b3480156100cb57600080fd5b506100f8600480360381019080803560001916906020019092919080359060200190929190505050610537565b005b34801561010657600080fd5b5061010f6107ec565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014f578082015181840152602081019050610134565b50505050905090810190601f16801561017c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561019657600080fd5b506101d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061088a565b604051808215151515815260200191505060405180910390f35b3480156101fb57600080fd5b5061020461097c565b6040518082815260200191505060405180910390f35b34801561022657600080fd5b50610285600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610986565b604051808215151515815260200191505060405180910390f35b3480156102ab57600080fd5b506102b4610cd3565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102dc57600080fd5b5061031b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610ce6565b005b34801561032957600080fd5b5061035e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ec0565b6040518082815260200191505060405180910390f35b34801561038057600080fd5b50610389610ed8565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c95780820151818401526020810190506103ae565b50505050905090810190601f1680156103f65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561041057600080fd5b5061044f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f76565b604051808215151515815260200191505060405180910390f35b34801561047557600080fd5b5061047e610f8b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104cc57600080fd5b50610521600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fb1565b6040518082815260200191505060405180910390f35b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561058757600080fd5b8160036000828254039250508190555081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660405180807f776974686472617728627974657333322c75696e743235362900000000000000815250601901905060405180910390207c0100000000000000000000000000000000000000000000000000000000900484846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808360001916600019168152602001828152602001925050506000604051808303816000875af1925050509050801515610745576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f574b544f4e3a2057495448445241575f4641494c45440000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a382600019167fa4dfdde26c326c8cced668e6a665f4efc3f278bdc9101cdedc4f725abd63a1ee836040518082815260200191505060405180910390a2505050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108825780601f1061085757610100808354040283529160200191610882565b820191906000526020600020905b81548152906001019060200180831161086557829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b6000600354905090565b600081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156109d657600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614158015610aae57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b15610bc95781600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610b3e57600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b600260009054906101000a900460ff1681565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610dab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f574b544f4e3a205045524d495353494f4e00000000000000000000000000000081525060200191505060405180910390fd5b8060036000828254019250508190555080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a38173ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c826040518082815260200191505060405180910390a25050565b60046020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f6e5780601f10610f4357610100808354040283529160200191610f6e565b820191906000526020600020905b815481529060010190602001808311610f5157829003601f168201915b505050505081565b6000610f83338484610986565b905092915050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60056020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820e2f50a774ba846fa1c029233d81ae94557ebb22046bdc94b10c813c83a2c94660029"; const WITH_DRAW_INPUT: &str = "723908ee9dc8e509d4b93251bd57f68c09bd9d04471c193fabd8f26c54284a4b"; +const WKTON_ADDRESS: &str = "32dcab0ef3fb2de2fce1d2e0799d36239671f04a"; -fn default_erc20_creation_unsigned_transaction() -> UnsignedTransaction { +fn creation_contract(code: &str, nonce: u64) -> UnsignedTransaction { UnsignedTransaction { - nonce: U256::zero(), + nonce: U256::from(nonce), gas_price: U256::from(1), gas_limit: U256::from(0x100000), action: ethereum::TransactionAction::Create, value: U256::zero(), - input: array_bytes::hex2bytes_unchecked(ERC20_CONTRACT_BYTECODE), + input: array_bytes::hex2bytes_unchecked(code), } } @@ -60,6 +63,147 @@ fn default_withdraw_unsigned_transaction() -> UnsignedTransaction { } } +fn deploy_wkton_contract(account: &AccountInfo, code: &str, nonce: u64) { + let raw_tx = creation_contract(code, nonce); + let t = sign_transaction(account, raw_tx); + assert_ok!(Ethereum::execute( + account.address, + t.input, + t.value, + t.gas_limit, + Some(t.gas_price), + Some(t.nonce), + t.action, + None, + )); +} + +fn send_kton_transfer_and_call_tx(sender: &AccountInfo, address: H160, value: U256, nonce: u64) { + let raw_tx = UnsignedTransaction { + nonce: U256::from(nonce), + gas_price: U256::from(1), + gas_limit: U256::from(0x300000), + action: ethereum::TransactionAction::Call(H160::from_str(TRANSFER_ADDR).unwrap()), + value: U256::from(0), + input: transfer_and_call(address, value), + }; + let t = sign_transaction(sender, raw_tx); + assert_ok!(Ethereum::execute( + sender.address, + t.input.clone(), + t.value, + t.gas_limit, + None, + Some(t.nonce), + t.action, + None, + )); +} + +fn send_kton_withdraw_tx(sender: &AccountInfo, to_id: Vec, value: U256, nonce: u64) { + let data = withdraw(to_id, value); + let raw_tx = UnsignedTransaction { + nonce: U256::from(nonce), + gas_price: U256::from(1), + gas_limit: U256::from(0x300000), + action: ethereum::TransactionAction::Call(H160::from_str(WKTON_ADDRESS).unwrap()), + value: U256::from(0), + input: data, + }; + let t = sign_transaction(sender, raw_tx); + assert_ok!(Ethereum::execute( + sender.address, + t.input.clone(), + t.value, + t.gas_limit, + None, + Some(t.nonce), + t.action, + None, + )); +} + +fn get_wkton_balance(sender: &AccountInfo, nonce: u64) -> U256 { + let raw_tx = UnsignedTransaction { + nonce: U256::from(nonce), + gas_price: U256::from(1), + gas_limit: U256::from(0x300000), + action: ethereum::TransactionAction::Call(H160::from_str(WKTON_ADDRESS).unwrap()), + value: U256::from(0), + input: array_bytes::hex2bytes_unchecked(hex::encode(wkton_balance_input(sender.address))), + }; + let t = sign_transaction(sender, raw_tx); + if let Ok((_, _, res)) = Ethereum::execute( + sender.address, + t.input.clone(), + t.value, + t.gas_limit, + None, + Some(t.nonce), + t.action, + None, + ) { + match res { + CallOrCreateInfo::Call(info) => return U256::from_big_endian(&info.value), + CallOrCreateInfo::Create(_) => return U256::default(), + }; + } + U256::default() +} + +fn wkton_balance_input(address: H160) -> Vec { + let func = Function { + name: "balanceOf".to_owned(), + inputs: vec![Param { + name: "address".to_owned(), + kind: ParamType::Address, + }], + outputs: vec![], + constant: false, + }; + func.encode_input(&[Token::Address(address)]).unwrap() +} + +fn transfer_and_call(address: H160, value: U256) -> Vec { + let func = Function { + name: "transfer_and_call".to_owned(), + inputs: vec![ + Param { + name: "address".to_owned(), + kind: ParamType::Address, + }, + Param { + name: "value".to_owned(), + kind: ParamType::Uint(256), + }, + ], + outputs: vec![], + constant: false, + }; + func.encode_input(&[Token::Address(address), Token::Uint(value)]) + .unwrap() +} + +fn withdraw(to: Vec, value: U256) -> Vec { + let func = Function { + name: "withdraw".to_owned(), + inputs: vec![ + Param { + name: "to".to_owned(), + kind: ParamType::FixedBytes(32), + }, + Param { + name: "value".to_owned(), + kind: ParamType::Uint(256), + }, + ], + outputs: vec![], + constant: false, + }; + func.encode_input(&[Token::FixedBytes(to), Token::Uint(value)]) + .unwrap() +} + fn sign_transaction(account: &AccountInfo, unsign_tx: UnsignedTransaction) -> Transaction { unsign_tx.sign(&account.private_key) } @@ -89,7 +233,7 @@ fn transaction_should_increment_nonce() { let alice = &pairs[0]; ext.execute_with(|| { - let t = sign_transaction(alice, default_erc20_creation_unsigned_transaction()); + let t = sign_transaction(alice, creation_contract(ERC20_CONTRACT_BYTECODE, 0)); assert_ok!(Ethereum::execute( alice.address, t.input, @@ -114,7 +258,7 @@ fn transaction_without_enough_gas_should_not_work() { ext.execute_with(|| { let mut transaction = - sign_transaction(alice, default_erc20_creation_unsigned_transaction()); + sign_transaction(alice, creation_contract(ERC20_CONTRACT_BYTECODE, 0)); transaction.gas_price = U256::from(11_000_000); assert_err!( @@ -131,7 +275,7 @@ fn transaction_with_invalid_nonce_should_not_work() { ext.execute_with(|| { // nonce is 0 - let mut transaction = default_erc20_creation_unsigned_transaction(); + let mut transaction = creation_contract(ERC20_CONTRACT_BYTECODE, 0); transaction.nonce = U256::from(1); let signed = transaction.sign(&alice.private_key); @@ -144,7 +288,7 @@ fn transaction_with_invalid_nonce_should_not_work() { .and_requires((alice.address, U256::from(0))) .build() ); - let t = sign_transaction(alice, default_erc20_creation_unsigned_transaction()); + let t = sign_transaction(alice, creation_contract(ERC20_CONTRACT_BYTECODE, 0)); // nonce is 1 assert_ok!(Ethereum::execute( @@ -177,7 +321,7 @@ fn contract_constructor_should_get_executed() { let alice_storage_address = storage_address(alice.address, H256::zero()); ext.execute_with(|| { - let t = sign_transaction(alice, default_erc20_creation_unsigned_transaction()); + let t = sign_transaction(alice, creation_contract(ERC20_CONTRACT_BYTECODE, 0)); assert_ok!(Ethereum::execute( alice.address, t.input, @@ -207,7 +351,7 @@ fn source_should_be_derived_from_signature() { ext.execute_with(|| { Ethereum::transact( Origin::none(), - sign_transaction(alice, default_erc20_creation_unsigned_transaction()), + sign_transaction(alice, creation_contract(ERC20_CONTRACT_BYTECODE, 0)), ) .expect("Failed to execute transaction"); @@ -225,7 +369,7 @@ fn invalid_signature_should_be_ignored() { let (pairs, mut ext) = new_test_ext(1); let alice = &pairs[0]; - let mut transaction = sign_transaction(alice, default_erc20_creation_unsigned_transaction()); + let mut transaction = sign_transaction(alice, creation_contract(ERC20_CONTRACT_BYTECODE, 0)); transaction.signature = TransactionSignature::new( 0x78, H256::from_slice(&[55u8; 32]), @@ -248,7 +392,7 @@ fn contract_should_be_created_at_given_address() { let erc20_address = contract_address(alice.address, 0); ext.execute_with(|| { - let t = sign_transaction(alice, default_erc20_creation_unsigned_transaction()); + let t = sign_transaction(alice, creation_contract(ERC20_CONTRACT_BYTECODE, 0)); assert_ok!(Ethereum::execute( alice.address, t.input, @@ -271,7 +415,7 @@ fn transaction_should_generate_correct_gas_used() { let expected_gas = U256::from(891328); ext.execute_with(|| { - let t = sign_transaction(alice, default_erc20_creation_unsigned_transaction()); + let t = sign_transaction(alice, creation_contract(ERC20_CONTRACT_BYTECODE, 0)); let (_, _, info) = Ethereum::execute( alice.address, t.input, @@ -484,6 +628,207 @@ fn withdraw_with_invalid_input_length_should_failed() { }); } +#[test] +fn test_kton_transfer_and_call_works() { + let (pairs, mut ext) = new_test_ext(1); + let alice = &pairs[0]; + + ext.execute_with(|| { + // Give alice some kton token + ::KtonAccountBasic::mutate_account_basic_balance( + &alice.address, + 70_000_000_000_000_000_000u128.into(), + ); + + // Create wkton contract + deploy_wkton_contract(alice, WKTON_CONTRACT_BYTECODE, 0); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(70_000_000_000_000_000_000u128) + ); + + // Transfer and call + send_kton_transfer_and_call_tx( + alice, + H160::from_str(WKTON_ADDRESS).unwrap(), + 30_000_000_000_000_000_000u128.into(), + 1, + ); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(40_000_000_000_000_000_000u128) + ); + assert_eq!( + get_wkton_balance(alice, 2), + U256::from(30_000_000_000_000_000_000u128) + ); + + // Transfer and call + send_kton_transfer_and_call_tx( + alice, + H160::from_str(WKTON_ADDRESS).unwrap(), + 30_000_000_000_000_000_000u128.into(), + 3, + ); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(10_000_000_000_000_000_000u128) + ); + assert_eq!( + get_wkton_balance(alice, 4), + U256::from(60_000_000_000_000_000_000u128) + ); + }); +} + +#[test] +fn test_kton_transfer_and_call_out_of_fund() { + let (pairs, mut ext) = new_test_ext(1); + let alice = &pairs[0]; + + ext.execute_with(|| { + // Give alice some kton token + ::KtonAccountBasic::mutate_account_basic_balance( + &alice.address, + 70_000_000_000_000_000_000u128.into(), + ); + + // Create wkton contract + deploy_wkton_contract(alice, WKTON_CONTRACT_BYTECODE, 0); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(70_000_000_000_000_000_000u128) + ); + + // Transfer and call + send_kton_transfer_and_call_tx( + alice, + H160::from_str(WKTON_ADDRESS).unwrap(), + 90_000_000_000_000_000_000u128.into(), + 1, + ); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(70_000_000_000_000_000_000u128) + ); + assert_eq!(get_wkton_balance(alice, 2), U256::from(0)); + }); +} + +#[test] +fn test_kton_withdraw() { + let (pairs, mut ext) = new_test_ext(1); + let alice = &pairs[0]; + + ext.execute_with(|| { + // Give alice some kton token + ::KtonAccountBasic::mutate_account_basic_balance( + &alice.address, + 70_000_000_000_000_000_000u128.into(), + ); + // Create wkton contract + deploy_wkton_contract(alice, WKTON_CONTRACT_BYTECODE, 0); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(70_000_000_000_000_000_000u128) + ); + + // Transfer and call + send_kton_transfer_and_call_tx( + alice, + H160::from_str(WKTON_ADDRESS).unwrap(), + 30_000_000_000_000_000_000u128.into(), + 1, + ); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(40_000_000_000_000_000_000u128) + ); + assert_eq!( + get_wkton_balance(alice, 2), + U256::from(30_000_000_000_000_000_000u128) + ); + + // withdraw + let input_bytes: Vec = array_bytes::hex2bytes_unchecked( + "0x64766d3a00000000000000aa01a1bef0557fa9625581a293f3aa777019263256", + ); + send_kton_withdraw_tx( + alice, + input_bytes.clone(), + U256::from(10_000_000_000_000_000_000u128), + 3, + ); + let to_id = + ::AccountId::decode(&mut &input_bytes[..]).unwrap(); + assert_eq!( + ::KtonAccountBasic::account_balance(&to_id), + U256::from(10_000_000_000_000_000_000u128) + ); + assert_eq!( + get_wkton_balance(alice, 4), + U256::from(20_000_000_000_000_000_000u128) + ); + }); +} + +#[test] +fn test_kton_withdraw_out_of_fund() { + let (pairs, mut ext) = new_test_ext(1); + let alice = &pairs[0]; + + ext.execute_with(|| { + // Give alice some kton token + ::KtonAccountBasic::mutate_account_basic_balance( + &alice.address, + 70_000_000_000_000_000_000u128.into(), + ); + // Create wkton contract + deploy_wkton_contract(alice, WKTON_CONTRACT_BYTECODE, 0); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(70_000_000_000_000_000_000u128) + ); + + // Transfer and call + send_kton_transfer_and_call_tx( + alice, + H160::from_str(WKTON_ADDRESS).unwrap(), + 30_000_000_000_000_000_000u128.into(), + 1, + ); + assert_eq!( + ::KtonAccountBasic::account_basic(&alice.address).balance, + U256::from(40_000_000_000_000_000_000u128) + ); + assert_eq!( + get_wkton_balance(alice, 2), + U256::from(30_000_000_000_000_000_000u128) + ); + + // withdraw + let input_bytes: Vec = array_bytes::hex2bytes_unchecked( + "0x64766d3a00000000000000aa01a1bef0557fa9625581a293f3aa777019263256", + ); + send_kton_withdraw_tx( + alice, + input_bytes.clone(), + U256::from(70_000_000_000_000_000_000u128), + 3, + ); + let to_id = + ::AccountId::decode(&mut &input_bytes[..]).unwrap(); + assert_eq!( + ::KtonAccountBasic::account_balance(&to_id), + U256::from(0) + ); + assert_eq!( + get_wkton_balance(alice, 4), + U256::from(30_000_000_000_000_000_000u128) + ); + }); +} + #[test] fn mutate_account_works_well() { let (_, mut ext) = new_test_ext(1); From 34dab80fbc76c66c9172a089a2aa2f0e74c73ec2 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Thu, 10 Jun 2021 14:52:48 +0800 Subject: [PATCH 37/45] Update trait bound --- bin/node/runtime/pangolin/src/pallets/evm_.rs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/bin/node/runtime/pangolin/src/pallets/evm_.rs b/bin/node/runtime/pangolin/src/pallets/evm_.rs index 338793eb59..61dcec455d 100644 --- a/bin/node/runtime/pangolin/src/pallets/evm_.rs +++ b/bin/node/runtime/pangolin/src/pallets/evm_.rs @@ -14,28 +14,24 @@ use dp_evm::{Precompile, PrecompileSet}; use dvm_ethereum::account_basic::{DvmAccountBasic, KtonRemainBalance, RingRemainBalance}; pub struct PangolinPrecompiles(PhantomData); -impl PrecompileSet for PangolinPrecompiles { +impl PrecompileSet for PangolinPrecompiles { fn execute( address: H160, input: &[u8], target_gas: Option, context: &Context, ) -> Option, u64), ExitError>> { - let to_address = |n: u64| -> H160 { H160::from_low_u64_be(n) }; + let addr = |n: u64| -> H160 { H160::from_low_u64_be(n) }; match address { // Ethereum precompiles - _ if address == to_address(1) => Some(ECRecover::execute(input, target_gas, context)), - _ if address == to_address(2) => Some(Sha256::execute(input, target_gas, context)), - _ if address == to_address(3) => Some(Ripemd160::execute(input, target_gas, context)), - _ if address == to_address(4) => Some(Identity::execute(input, target_gas, context)), + _ if address == addr(1) => Some(ECRecover::execute(input, target_gas, context)), + _ if address == addr(2) => Some(Sha256::execute(input, target_gas, context)), + _ if address == addr(3) => Some(Ripemd160::execute(input, target_gas, context)), + _ if address == addr(4) => Some(Identity::execute(input, target_gas, context)), // Darwinia precompiles - _ if address == to_address(21) => Some( as Precompile>::execute( - input, target_gas, context, - )), - _ if address == to_address(23) => { - Some(>::execute(input, target_gas, context)) - } + _ if address == addr(21) => Some(>::execute(input, target_gas, context)), + _ if address == addr(23) => Some(>::execute(input, target_gas, context)), _ => None, } } From 9a6f6fcba545fba0b463d64704c220ac1791b2fd Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 15 Jun 2021 12:05:27 +0800 Subject: [PATCH 38/45] Remove test hex crate --- Cargo.lock | 1 - frame/dvm/Cargo.toml | 1 - frame/dvm/src/tests.rs | 40 ++++++++++++++++++++++------------------ 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9caf3ab4ed..9c39e03c70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2350,7 +2350,6 @@ dependencies = [ "evm", "frame-support", "frame-system", - "hex", "libsecp256k1", "log", "pallet-timestamp", diff --git a/frame/dvm/Cargo.toml b/frame/dvm/Cargo.toml index d65212f1d8..aa390acb80 100644 --- a/frame/dvm/Cargo.toml +++ b/frame/dvm/Cargo.toml @@ -40,7 +40,6 @@ sp-std = { default-features = false, git = "https://github.com/darwini # crates.io array-bytes = { version = "1.3.3" } ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std", default-features = false } -hex = "0.4.3" # darwinia darwinia-balances = { path = "../balances" } darwinia-evm-precompile-simple = { path = "../evm/precompile/contracts/simple" } diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index 8f0b4fa2e4..683b48e86d 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -16,19 +16,23 @@ // You should have received a copy of the GNU General Public License // along with Darwinia. If not, see . +// --- crates --- +use array_bytes::{bytes2hex, hex2bytes_unchecked}; +use codec::Decode; +use ethabi::{Function, Param, ParamType, Token}; +use ethereum::TransactionSignature; +use std::str::FromStr; +// --- darwinia --- use crate::{ account_basic::{RemainBalanceOp, RingRemainBalance}, Call, *, }; -use codec::Decode; use darwinia_evm::AddressMapping; use darwinia_support::evm::TRANSFER_ADDR; -use ethabi::{Function, Param, ParamType, Token}; -use ethereum::TransactionSignature; -use frame_support::{assert_err, assert_noop, assert_ok, unsigned::ValidateUnsigned}; use mock::*; +// --- substrate --- +use frame_support::{assert_err, assert_noop, assert_ok, unsigned::ValidateUnsigned}; use sp_runtime::transaction_validity::{InvalidTransaction, TransactionSource}; -use std::str::FromStr; // This ERC-20 contract mints the maximum amount of tokens to the contract creator. // pragma solidity ^0.5.0; @@ -48,7 +52,7 @@ fn creation_contract(code: &str, nonce: u64) -> UnsignedTransaction { gas_limit: U256::from(0x100000), action: ethereum::TransactionAction::Create, value: U256::zero(), - input: array_bytes::hex2bytes_unchecked(code), + input: hex2bytes_unchecked(code), } } @@ -59,7 +63,7 @@ fn default_withdraw_unsigned_transaction() -> UnsignedTransaction { gas_limit: U256::from(0x100000), action: ethereum::TransactionAction::Call(H160::from_str(TRANSFER_ADDR).unwrap()), value: U256::from(30000000000000000000u128), - input: array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT), + input: hex2bytes_unchecked(WITH_DRAW_INPUT), } } @@ -130,7 +134,7 @@ fn get_wkton_balance(sender: &AccountInfo, nonce: u64) -> U256 { gas_limit: U256::from(0x300000), action: ethereum::TransactionAction::Call(H160::from_str(WKTON_ADDRESS).unwrap()), value: U256::from(0), - input: array_bytes::hex2bytes_unchecked(hex::encode(wkton_balance_input(sender.address))), + input: hex2bytes_unchecked(bytes2hex("0x", wkton_balance_input(sender.address))), }; let t = sign_transaction(sender, raw_tx); if let Ok((_, _, res)) = Ethereum::execute( @@ -460,7 +464,7 @@ fn call_should_handle_errors() { gas_limit: U256::from(0x100000), action: ethereum::TransactionAction::Create, value: U256::zero(), - input: array_bytes::hex2bytes_unchecked(contract), + input: hex2bytes_unchecked(contract), } .sign(&alice.private_key); assert_ok!(Ethereum::execute( @@ -475,9 +479,9 @@ fn call_should_handle_errors() { )); let contract_address: Vec = - array_bytes::hex2bytes_unchecked("32dcab0ef3fb2de2fce1d2e0799d36239671f04a"); - let foo: Vec = array_bytes::hex2bytes_unchecked("c2985578"); - let bar: Vec = array_bytes::hex2bytes_unchecked("febb0f7e"); + hex2bytes_unchecked("32dcab0ef3fb2de2fce1d2e0799d36239671f04a"); + let foo: Vec = hex2bytes_unchecked("c2985578"); + let bar: Vec = hex2bytes_unchecked("febb0f7e"); // calling foo will succeed let (_, _, info) = Ethereum::execute( @@ -494,7 +498,7 @@ fn call_should_handle_errors() { match info { CallOrCreateInfo::Call(info) => { assert_eq!( - array_bytes::bytes2hex("0x", info.value), + bytes2hex("0x", info.value), "0x0000000000000000000000000000000000000000000000000000000000000001".to_owned() ); } @@ -541,7 +545,7 @@ fn withdraw_with_enough_balance() { U256::from(70_000_000_000_000_000_000u128) ); // Check the target balance - let input_bytes: Vec = array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT); + let input_bytes: Vec = hex2bytes_unchecked(WITH_DRAW_INPUT); let dest = ::AccountId::decode(&mut &input_bytes[..]).unwrap(); assert_eq!( @@ -587,7 +591,7 @@ fn withdraw_without_enough_balance_should_fail() { U256::from(100000000000000000000u128) ); // Check target balance - let input_bytes: Vec = array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT); + let input_bytes: Vec = hex2bytes_unchecked(WITH_DRAW_INPUT); let dest = ::AccountId::decode(&mut &input_bytes[..]).unwrap(); assert_eq!(::RingCurrency::free_balance(&dest), 0); @@ -621,7 +625,7 @@ fn withdraw_with_invalid_input_length_should_failed() { U256::from(100000000000000000000u128) ); // Check target balance - let input_bytes: Vec = array_bytes::hex2bytes_unchecked(WITH_DRAW_INPUT); + let input_bytes: Vec = hex2bytes_unchecked(WITH_DRAW_INPUT); let dest = ::AccountId::decode(&mut &input_bytes[..]).unwrap(); assert_eq!(::RingCurrency::free_balance(&dest), 0); @@ -750,7 +754,7 @@ fn test_kton_withdraw() { ); // withdraw - let input_bytes: Vec = array_bytes::hex2bytes_unchecked( + let input_bytes: Vec = hex2bytes_unchecked( "0x64766d3a00000000000000aa01a1bef0557fa9625581a293f3aa777019263256", ); send_kton_withdraw_tx( @@ -807,7 +811,7 @@ fn test_kton_withdraw_out_of_fund() { ); // withdraw - let input_bytes: Vec = array_bytes::hex2bytes_unchecked( + let input_bytes: Vec = hex2bytes_unchecked( "0x64766d3a00000000000000aa01a1bef0557fa9625581a293f3aa777019263256", ); send_kton_withdraw_tx( From 2f667f3c8bcaa12d328ee95e9c19f8eecd1905c3 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 15 Jun 2021 17:19:23 +0800 Subject: [PATCH 39/45] Replace `hex_into_unchecked` with `hex_try_into` --- frame/evm/precompile/contracts/transfer/src/kton.rs | 4 +++- frame/evm/precompile/contracts/transfer/src/ring.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 7263dc3b3e..ec3c3e5101 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -74,7 +74,9 @@ impl Kton { // Call WKTON wrapped contract deposit let raw_input = make_call_data(caller, value)?; if let Ok(call_res) = T::Runner::call( - array_bytes::hex_into_unchecked(TRANSFER_ADDR), + array_bytes::hex_try_into(TRANSFER_ADDR).map_err(|e| { + ExitError::Other(format!("Invalid transfer addr: {:?}", e).into()) + })?, wkton, raw_input.to_vec(), U256::zero(), diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 74c1bc5742..e8b157ce92 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -48,8 +48,10 @@ impl RingBack { let source_account = T::RingAccountBasic::account_basic(&source); // Ensure the context address should be precompile address + let transfer_addr = array_bytes::hex_try_into(TRANSFER_ADDR) + .map_err(|e| ExitError::Other(format!("Invalid transfer addr: {:?}", e).into()))?; ensure!( - source == array_bytes::hex_into_unchecked(TRANSFER_ADDR), + source == transfer_addr, ExitError::Other("Invalid context address".into()) ); // Ensure the context address balance is enough From 4502d1a82e3d868f8e6c8894a78cd692e6230d10 Mon Sep 17 00:00:00 2001 From: HackFisher Date: Tue, 15 Jun 2021 17:48:25 +0800 Subject: [PATCH 40/45] format is std? can not use std in runtime --- frame/evm/precompile/contracts/transfer/src/kton.rs | 2 +- frame/evm/precompile/contracts/transfer/src/ring.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index ec3c3e5101..2f28ce6763 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -75,7 +75,7 @@ impl Kton { let raw_input = make_call_data(caller, value)?; if let Ok(call_res) = T::Runner::call( array_bytes::hex_try_into(TRANSFER_ADDR).map_err(|e| { - ExitError::Other(format!("Invalid transfer addr: {:?}", e).into()) + ExitError::Other("Invalid transfer address".into()) })?, wkton, raw_input.to_vec(), diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index e8b157ce92..8309bafe5f 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -49,7 +49,7 @@ impl RingBack { // Ensure the context address should be precompile address let transfer_addr = array_bytes::hex_try_into(TRANSFER_ADDR) - .map_err(|e| ExitError::Other(format!("Invalid transfer addr: {:?}", e).into()))?; + .map_err(|e| ExitError::Other("Invalid transfer address".into()))?; ensure!( source == transfer_addr, ExitError::Other("Invalid context address".into()) From ef5b9ffa2279a4101e91b290391b84def5b66dc8 Mon Sep 17 00:00:00 2001 From: ouwenkg <2630582710@qq.com> Date: Tue, 15 Jun 2021 17:56:40 +0800 Subject: [PATCH 41/45] Remove unused variable --- frame/evm/precompile/contracts/transfer/src/kton.rs | 5 ++--- frame/evm/precompile/contracts/transfer/src/ring.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 2f28ce6763..690e1ca6bc 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -74,9 +74,8 @@ impl Kton { // Call WKTON wrapped contract deposit let raw_input = make_call_data(caller, value)?; if let Ok(call_res) = T::Runner::call( - array_bytes::hex_try_into(TRANSFER_ADDR).map_err(|e| { - ExitError::Other("Invalid transfer address".into()) - })?, + array_bytes::hex_try_into(TRANSFER_ADDR) + .map_err(|_| ExitError::Other("Invalid transfer address".into()))?, wkton, raw_input.to_vec(), U256::zero(), diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 8309bafe5f..13c4e6471d 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -49,7 +49,7 @@ impl RingBack { // Ensure the context address should be precompile address let transfer_addr = array_bytes::hex_try_into(TRANSFER_ADDR) - .map_err(|e| ExitError::Other("Invalid transfer address".into()))?; + .map_err(|_| ExitError::Other("Invalid transfer address".into()))?; ensure!( source == transfer_addr, ExitError::Other("Invalid context address".into()) From cd8cf2883c661a86e8fc9e67cfdf2e374efc5142 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 22 Jun 2021 16:15:15 +0800 Subject: [PATCH 42/45] eliminate warning --- frame/dvm-dynamic-fee/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/dvm-dynamic-fee/src/lib.rs b/frame/dvm-dynamic-fee/src/lib.rs index 0101a53240..cf81cf393a 100644 --- a/frame/dvm-dynamic-fee/src/lib.rs +++ b/frame/dvm-dynamic-fee/src/lib.rs @@ -26,9 +26,9 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use sp_core::U256; + use sp_inherents::IsFatalError; #[cfg(feature = "std")] - use sp_inherents::InherentDataProvider as InherentDataProviderT; - use sp_inherents::{Error, IsFatalError}; + use sp_inherents::{Error, InherentDataProvider as InherentDataProviderT}; // --- darwinia --- use darwinia_evm::FeeCalculator; From 23bd486bad2ca600ce6d2c09664900bb109b2c15 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 22 Jun 2021 16:23:44 +0800 Subject: [PATCH 43/45] generic `AccountId` in runtime --- bin/node/runtime/pangolin/src/pallets/evm_.rs | 4 +- frame/dvm/src/mock.rs | 10 ++-- frame/evm/src/lib.rs | 53 +++++++++++-------- frame/evm/src/tests.rs | 4 +- 4 files changed, 40 insertions(+), 31 deletions(-) diff --git a/bin/node/runtime/pangolin/src/pallets/evm_.rs b/bin/node/runtime/pangolin/src/pallets/evm_.rs index 61dcec455d..2f90b2a3ca 100644 --- a/bin/node/runtime/pangolin/src/pallets/evm_.rs +++ b/bin/node/runtime/pangolin/src/pallets/evm_.rs @@ -45,8 +45,8 @@ frame_support::parameter_types! { impl Config for Runtime { type FeeCalculator = dvm_dynamic_fee::Pallet; type GasWeightMapping = (); - type CallOrigin = EnsureAddressTruncated; - type AddressMapping = ConcatAddressMapping; + type CallOrigin = EnsureAddressTruncated; + type AddressMapping = ConcatAddressMapping; type RingCurrency = Ring; type KtonCurrency = Kton; type Event = Event; diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 03b235a4f8..14f090f325 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -137,9 +137,11 @@ impl FindAuthor for EthereumFindAuthor { pub struct HashedAddressMapping; impl AddressMapping for HashedAddressMapping { fn into_account_id(address: H160) -> AccountId32 { - let mut data = [0u8; 32]; - data[0..20].copy_from_slice(&address[..]); - AccountId32::from(Into::<[u8; 32]>::into(data)) + let mut raw_account = [0u8; 32]; + + raw_account[0..20].copy_from_slice(&address[..]); + + raw_account.into() } } @@ -180,7 +182,7 @@ where impl darwinia_evm::Config for Test { type FeeCalculator = FixedGasPrice; type GasWeightMapping = (); - type CallOrigin = EnsureAddressTruncated; + type CallOrigin = EnsureAddressTruncated; type AddressMapping = HashedAddressMapping; type RingCurrency = Ring; type KtonCurrency = Kton; diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index 510e91323c..63f9b92932 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -48,9 +48,9 @@ use frame_system::RawOrigin; use sp_core::{H160, H256, U256}; use sp_runtime::{ traits::{BadOrigin, UniqueSaturatedInto}, - AccountId32, DispatchResult, + DispatchResult, }; -use sp_std::prelude::*; +use sp_std::{marker::PhantomData, prelude::*}; static ISTANBUL_CONFIG: EvmConfig = EvmConfig::istanbul(); @@ -399,8 +399,8 @@ pub trait EnsureAddressOrigin { ) -> Result; } -pub trait AddressMapping { - fn into_account_id(address: H160) -> A; +pub trait AddressMapping { + fn into_account_id(address: H160) -> AccountId; } /// Account basic info operations @@ -453,39 +453,46 @@ impl IssuingHandler for () { } } -/// Ensure that the address is truncated hash of the origin. Only works if the account id is -/// `AccountId32`. -pub struct EnsureAddressTruncated; -impl EnsureAddressOrigin for EnsureAddressTruncated +/// Ensure that the address is truncated hash of the origin. +pub struct EnsureAddressTruncated(PhantomData); +impl EnsureAddressOrigin for EnsureAddressTruncated where - OuterOrigin: Into, OuterOrigin>> + From>, + AccountId: AsRef<[u8; 32]>, + OuterOrigin: Into, OuterOrigin>> + From>, { - type Success = AccountId32; + type Success = AccountId; - fn try_address_origin(address: &H160, origin: OuterOrigin) -> Result { + fn try_address_origin(address: &H160, origin: OuterOrigin) -> Result { origin.into().and_then(|o| match o { - RawOrigin::Signed(who) if AsRef::<[u8; 32]>::as_ref(&who)[0..20] == address[0..20] => { - Ok(who) - } + RawOrigin::Signed(who) if who.as_ref()[0..20] == address[0..20] => Ok(who), r => Err(OuterOrigin::from(r)), }) } } -pub struct ConcatAddressMapping; +pub struct ConcatAddressMapping(PhantomData); /// The ConcatAddressMapping used for transfer from evm 20-length to substrate 32-length address /// The concat rule inclued three parts: /// 1. AccountId Prefix: concat("dvm", "0x00000000000000"), length: 11 byetes /// 2. EVM address: the original evm address, length: 20 bytes /// 3. CheckSum: byte_xor(AccountId Prefix + EVM address), length: 1 bytes -impl AddressMapping for ConcatAddressMapping { - fn into_account_id(address: H160) -> AccountId32 { - let mut data = [0u8; 32]; - data[0..4].copy_from_slice(b"dvm:"); - data[11..31].copy_from_slice(&address[..]); - let checksum: u8 = data[1..31].iter().fold(data[0], |sum, &byte| sum ^ byte); - data[31] = checksum; - AccountId32::from(data) +impl AddressMapping for ConcatAddressMapping +where + AccountId: From<[u8; 32]>, +{ + fn into_account_id(address: H160) -> AccountId { + let mut raw_account = [0u8; 32]; + + raw_account[0..4].copy_from_slice(b"dvm:"); + raw_account[11..31].copy_from_slice(&address[..]); + + let checksum: u8 = raw_account[1..31] + .iter() + .fold(raw_account[0], |sum, &byte| sum ^ byte); + + raw_account[31] = checksum; + + raw_account.into() } } diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs index 6f3f0e2b99..6cdc55701e 100644 --- a/frame/evm/src/tests.rs +++ b/frame/evm/src/tests.rs @@ -25,7 +25,7 @@ use sp_core::H256; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, - RuntimeDebug, + AccountId32, RuntimeDebug, }; // --- darwinia --- use crate::{self as darwinia_evm, runner::stack::Runner, *}; @@ -167,7 +167,7 @@ impl Config for Test { type GasWeightMapping = (); type CallOrigin = EnsureAddressRoot; - type AddressMapping = ConcatAddressMapping; + type AddressMapping = ConcatAddressMapping; type RingCurrency = Ring; type KtonCurrency = Kton; From 8e789da2d56faf38de7af8b5b5d425f518dc1b7d Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 22 Jun 2021 19:27:55 +0800 Subject: [PATCH 44/45] more clear `address_build` --- frame/dvm/src/mock.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 14f090f325..2c79adf191 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -279,18 +279,28 @@ impl UnsignedTransaction { } fn address_build(seed: u8) -> AccountInfo { - let private_key = H256::from_slice(&[(seed + 1) as u8; 32]); //H256::from_low + 1) as u64); - let secret_key = secp256k1::SecretKey::parse_slice(&private_key[..]).unwrap(); - let public_key = &secp256k1::PublicKey::from_secret_key(&secret_key).serialize()[1..65]; - let address = H160::from(H256::from_slice(&Keccak256::digest(public_key)[..])); + let raw_private_key = [seed + 1; 32]; + let secret_key = secp256k1::SecretKey::parse_slice(&raw_private_key).unwrap(); + let raw_public_key = &secp256k1::PublicKey::from_secret_key(&secret_key).serialize()[1..65]; + let raw_address = { + let mut s = [0; 20]; - let mut data = [0u8; 32]; - data[0..20].copy_from_slice(&address[..]); + s.copy_from_slice(&Keccak256::digest(raw_public_key)[12..]); + + s + }; + let raw_account = { + let mut s = [0; 32]; + + s[..20].copy_from_slice(&raw_address); + + s + }; AccountInfo { - private_key, - account_id: AccountId32::from(Into::<[u8; 32]>::into(data)), - address, + private_key: raw_private_key.into(), + account_id: raw_account.into(), + address: raw_address.into(), } } From e40d781a6199e71edde61f3347291875413aa99a Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 22 Jun 2021 19:37:18 +0800 Subject: [PATCH 45/45] remove unused flag --- frame/dvm/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/dvm/Cargo.toml b/frame/dvm/Cargo.toml index aa390acb80..f46a2f00ac 100644 --- a/frame/dvm/Cargo.toml +++ b/frame/dvm/Cargo.toml @@ -39,7 +39,7 @@ sp-std = { default-features = false, git = "https://github.com/darwini [dev-dependencies] # crates.io array-bytes = { version = "1.3.3" } -ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std", default-features = false } +ethabi = { git = "https://github.com/darwinia-network/ethabi.git", branch = "xavier-no-std" } # darwinia darwinia-balances = { path = "../balances" } darwinia-evm-precompile-simple = { path = "../evm/precompile/contracts/simple" }