Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose
args: --locked --verbose
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
7 changes: 4 additions & 3 deletions src/benches/eth_deploy_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ use criterion::{BatchSize, BenchmarkId, Criterion, Throughput};
use secp256k1::SecretKey;

use crate::test_utils::{address_from_secret_key, create_eth_transaction, deploy_evm, SUBMIT};
use crate::types::Wei;

const INITIAL_BALANCE: u64 = 1000;
const INITIAL_BALANCE: Wei = Wei::new_u64(1000);
const INITIAL_NONCE: u64 = 0;
const TRANSFER_AMOUNT: u64 = 0;
const TRANSFER_AMOUNT: Wei = Wei::zero();

pub(crate) fn eth_deploy_code_benchmark(c: &mut Criterion) {
let mut runner = deploy_evm();
let mut rng = rand::thread_rng();
let source_account = SecretKey::random(&mut rng);
runner.create_address(
address_from_secret_key(&source_account),
INITIAL_BALANCE.into(),
INITIAL_BALANCE,
INITIAL_NONCE.into(),
);
let inputs: Vec<_> = [1, 4, 8, 12, 16]
Expand Down
2 changes: 1 addition & 1 deletion src/benches/eth_erc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) fn eth_erc20_benchmark(c: &mut Criterion) {
let source_account = SecretKey::random(&mut rng);
runner.create_address(
address_from_secret_key(&source_account),
INITIAL_BALANCE.into(),
crate::types::Wei::new_u64(INITIAL_BALANCE),
INITIAL_NONCE.into(),
);
let calling_account_id = "some-account.near".to_string();
Expand Down
5 changes: 3 additions & 2 deletions src/benches/eth_standard_precompiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use secp256k1::SecretKey;

use crate::test_utils::standard_precompiles::{PrecompilesConstructor, PrecompilesContract};
use crate::test_utils::{address_from_secret_key, deploy_evm, sign_transaction, SUBMIT};
use crate::types::Wei;

const INITIAL_BALANCE: u64 = 1000;
const INITIAL_BALANCE: Wei = Wei::new_u64(1000);
const INITIAL_NONCE: u64 = 0;

pub(crate) fn eth_standard_precompiles_benchmark(c: &mut Criterion) {
Expand All @@ -14,7 +15,7 @@ pub(crate) fn eth_standard_precompiles_benchmark(c: &mut Criterion) {
let source_account = SecretKey::random(&mut rng);
runner.create_address(
address_from_secret_key(&source_account),
INITIAL_BALANCE.into(),
INITIAL_BALANCE,
INITIAL_NONCE.into(),
);
let calling_account_id = "some-account.near".to_string();
Expand Down
9 changes: 5 additions & 4 deletions src/benches/eth_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,25 @@ use criterion::{BatchSize, Criterion};
use secp256k1::SecretKey;

use crate::test_utils::{address_from_secret_key, create_eth_transaction, deploy_evm, SUBMIT};
use crate::types::Wei;

const INITIAL_BALANCE: u64 = 1000;
const INITIAL_BALANCE: Wei = Wei::new_u64(1000);
const INITIAL_NONCE: u64 = 0;
const TRANSFER_AMOUNT: u64 = 123;
const TRANSFER_AMOUNT: Wei = Wei::new_u64(123);

pub(crate) fn eth_transfer_benchmark(c: &mut Criterion) {
let mut runner = deploy_evm();
let mut rng = rand::thread_rng();
let source_account = SecretKey::random(&mut rng);
runner.create_address(
address_from_secret_key(&source_account),
INITIAL_BALANCE.into(),
INITIAL_BALANCE,
INITIAL_NONCE.into(),
);
let dest_account = address_from_secret_key(&SecretKey::random(&mut rng));
let transaction = create_eth_transaction(
Some(dest_account),
TRANSFER_AMOUNT.into(),
TRANSFER_AMOUNT,
vec![],
Some(runner.chain_id),
&source_account,
Expand Down
67 changes: 42 additions & 25 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::precompiles;
use crate::prelude::{Address, TryInto, Vec, H256, U256};
use crate::sdk;
use crate::storage::{address_to_key, bytes_to_key, storage_to_key, KeyPrefix, KeyPrefixU8};
use crate::types::{u256_to_arr, AccountId};
use crate::types::{u256_to_arr, AccountId, Wei};

/// Errors with the EVM engine.
#[derive(Debug, Clone, Eq, PartialEq)]
Expand Down Expand Up @@ -92,6 +92,20 @@ impl ExitIntoResult for ExitReason {
}
}

pub enum EngineStateError {
NotFound,
DeserializationFailed,
}

impl AsRef<[u8]> for EngineStateError {
fn as_ref(&self) -> &[u8] {
match self {
Self::NotFound => b"ERR_STATE_NOT_FOUND",
Self::DeserializationFailed => b"ERR_STATE_CORRUPTED",
}
}
}

/// Engine internal state, mostly configuration.
/// Should not contain anything large or enumerable.
#[derive(BorshSerialize, BorshDeserialize, Default)]
Expand Down Expand Up @@ -134,8 +148,8 @@ const CONFIG: &Config = &Config::istanbul();
const STATE_KEY: &[u8; 5] = b"STATE";

impl Engine {
pub fn new(origin: Address) -> Self {
Self::new_with_state(Engine::get_state(), origin)
pub fn new(origin: Address) -> Result<Self, EngineStateError> {
Engine::get_state().map(|state| Self::new_with_state(state, origin))
}

pub fn new_with_state(state: EngineState, origin: Address) -> Self {
Expand All @@ -151,10 +165,11 @@ impl Engine {
}

/// Fails if state is not found.
pub fn get_state() -> EngineState {
pub fn get_state() -> Result<EngineState, EngineStateError> {
match sdk::read_storage(&bytes_to_key(KeyPrefix::Config, STATE_KEY)) {
None => Default::default(),
Some(bytes) => EngineState::try_from_slice(&bytes).expect("ERR_DESER"),
None => Err(EngineStateError::NotFound),
Some(bytes) => EngineState::try_from_slice(&bytes)
.map_err(|_| EngineStateError::DeserializationFailed),
}
}

Expand All @@ -171,8 +186,7 @@ impl Engine {
}

pub fn get_code_size(address: &Address) -> usize {
// TODO: Seems this can be optimized to only read the register length.
Engine::get_code(&address).len()
sdk::read_storage_len(&address_to_key(KeyPrefix::Code, address)).unwrap_or(0)
}

pub fn set_nonce(address: &Address, nonce: &U256) {
Expand Down Expand Up @@ -205,21 +219,22 @@ impl Engine {
.unwrap_or_else(U256::zero)
}

pub fn set_balance(address: &Address, balance: &U256) {
pub fn set_balance(address: &Address, balance: &Wei) {
sdk::write_storage(
&address_to_key(KeyPrefix::Balance, address),
&u256_to_arr(balance),
&balance.to_bytes(),
);
}

pub fn remove_balance(address: &Address) {
sdk::remove_storage(&address_to_key(KeyPrefix::Balance, address))
}

pub fn get_balance(address: &Address) -> U256 {
sdk::read_storage(&address_to_key(KeyPrefix::Balance, address))
pub fn get_balance(address: &Address) -> Wei {
let raw = sdk::read_storage(&address_to_key(KeyPrefix::Balance, address))
.map(|value| U256::from_big_endian(&value))
.unwrap_or_else(U256::zero)
.unwrap_or_else(U256::zero);
Wei::new(raw)
}

pub fn remove_storage(address: &Address, key: &H256) {
Expand All @@ -240,7 +255,7 @@ impl Engine {
let balance = Self::get_balance(address);
let nonce = Self::get_nonce(address);
let code_len = Self::get_code_size(address);
balance == U256::zero() && nonce == U256::zero() && code_len == 0
balance.is_zero() && nonce.is_zero() && code_len == 0
}

/// Removes all storage for the given address.
Expand Down Expand Up @@ -272,20 +287,20 @@ impl Engine {

pub fn deploy_code_with_input(&mut self, input: Vec<u8>) -> EngineResult<SubmitResult> {
let origin = self.origin();
let value = U256::zero();
let value = Wei::zero();
self.deploy_code(origin, value, input)
}

pub fn deploy_code(
&mut self,
origin: Address,
value: U256,
value: Wei,
input: Vec<u8>,
) -> EngineResult<SubmitResult> {
let mut executor = self.make_executor();
let address = executor.create_address(CreateScheme::Legacy { caller: origin });
let (status, result) = (
executor.transact_create(origin, value, input, u64::MAX),
executor.transact_create(origin, value.raw(), input, u64::MAX),
address,
);

Expand All @@ -306,19 +321,20 @@ impl Engine {
pub fn call_with_args(&mut self, args: FunctionCallArgs) -> EngineResult<SubmitResult> {
let origin = self.origin();
let contract = Address(args.contract);
let value = U256::zero();
let value = Wei::zero();
self.call(origin, contract, value, args.input)
}

pub fn call(
&mut self,
origin: Address,
contract: Address,
value: U256,
value: Wei,
input: Vec<u8>,
) -> EngineResult<SubmitResult> {
let mut executor = self.make_executor();
let (status, result) = executor.transact_call(origin, contract, value, input, u64::MAX);
let (status, result) =
executor.transact_call(origin, contract, value.raw(), input, u64::MAX);

let used_gas = executor.used_gas();
let (values, logs) = executor.into_state().deconstruct();
Expand Down Expand Up @@ -362,18 +378,19 @@ impl Engine {
let origin = Address::from_slice(&args.sender);
let contract = Address::from_slice(&args.address);
let value = U256::from_big_endian(&args.amount);
self.view(origin, contract, value, args.input)
self.view(origin, contract, Wei::new(value), args.input)
}

pub fn view(
&self,
origin: Address,
contract: Address,
value: U256,
value: Wei,
input: Vec<u8>,
) -> EngineResult<Vec<u8>> {
let mut executor = self.make_executor();
let (status, result) = executor.transact_call(origin, contract, value, input, u64::MAX);
let (status, result) =
executor.transact_call(origin, contract, value.raw(), input, u64::MAX);
status.into_result()?;
Ok(result)
}
Expand Down Expand Up @@ -492,7 +509,7 @@ impl evm::backend::Backend for Engine {
fn basic(&self, address: Address) -> Basic {
Basic {
nonce: Engine::get_nonce(&address),
balance: Engine::get_balance(&address),
balance: Engine::get_balance(&address).raw(),
}
}

Expand Down Expand Up @@ -531,7 +548,7 @@ impl ApplyBackend for Engine {
reset_storage,
} => {
Engine::set_nonce(&address, &basic.nonce);
Engine::set_balance(&address, &basic.balance);
Engine::set_balance(&address, &Wei::new(basic.balance));
if let Some(code) = code {
Engine::set_code(&address, &code)
}
Expand Down
Loading