Skip to content

Commit

Permalink
fix: cap nonce value at 2^64-1 as per EIP-2681 (#163)
Browse files Browse the repository at this point in the history
* feat: replace DIFFICULTY with PREVRANDAO since merge (EIP-4399)

* fix: cap nonce value at 2^64-1 as per EIP-2681

* Recursively checkout submodules

---------

Co-authored-by: Wei Tang <wei@pacna.org>
  • Loading branch information
vimpunk and sorpaas authored May 21, 2023
1 parent 21972c2 commit 0e03560
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- uses: actions/checkout@v2
with:
repository: "rust-blockchain/evm-tests"
submodules: true
submodules: recursive
- name: Submodules
run: |
cd evm
Expand Down
5 changes: 5 additions & 0 deletions core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ pub enum ExitError {
/// Other normal errors.
#[cfg_attr(feature = "with-codec", codec(index = 13))]
Other(Cow<'static, str>),

/// Nonce reached maximum value of 2^64-1
/// https://eips.ethereum.org/EIPS/eip-2681
#[cfg_attr(feature = "with-codec", codec(index = 14))]
MaxNonce,
}

impl From<ExitError> for ExitReason {
Expand Down
5 changes: 2 additions & 3 deletions src/backend/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub struct MemoryVicinity {
#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MemoryAccount {
/// Account nonce.
pub nonce: U256,
pub nonce: u64,
/// Account balance.
pub balance: U256,
/// Full account storage.
Expand Down Expand Up @@ -210,8 +210,7 @@ impl<'vicinity> ApplyBackend for MemoryBackend<'vicinity> {
}

account.balance == U256::zero()
&& account.nonce == U256::zero()
&& account.code.is_empty()
&& account.nonce == 0 && account.code.is_empty()
};

if is_empty && delete_empty {
Expand Down
2 changes: 1 addition & 1 deletion src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct Basic {
/// Account balance.
pub balance: U256,
/// Account nonce.
pub nonce: U256,
pub nonce: u64,
}

pub use ethereum::Log;
Expand Down
20 changes: 13 additions & 7 deletions src/executor/stack/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ pub trait StackState<'config>: Backend {
fn is_cold(&self, address: H160) -> bool;
fn is_storage_cold(&self, address: H160, key: H256) -> bool;

fn inc_nonce(&mut self, address: H160);
fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError>;
fn set_storage(&mut self, address: H160, key: H256, value: H256);
fn reset_storage(&mut self, address: H160);
fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>);
Expand Down Expand Up @@ -568,7 +568,9 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
self.initialize_with_access_list(access_list);
}

self.state.inc_nonce(caller);
if let Err(e) = self.state.inc_nonce(caller) {
return (e.into(), Vec::new());
}

let context = Context {
caller,
Expand Down Expand Up @@ -616,7 +618,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
}

/// Get account nonce.
pub fn nonce(&self, address: H160) -> U256 {
pub fn nonce(&self, address: H160) -> u64 {
self.state.basic(address).nonce
}

Expand Down Expand Up @@ -702,6 +704,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
return Capture::Exit((ExitError::OutOfFund.into(), None, Vec::new()));
}

if let Err(e) = self.state.inc_nonce(caller) {
return Capture::Exit((e.into(), None, Vec::new()));
}

let after_gas = if take_l64 && self.config.call_l64_after_gas {
if self.config.estimate {
let initial_after_gas = self.state.metadata().gasometer.gas();
Expand All @@ -720,8 +726,6 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
let gas_limit = min(after_gas, target_gas);
try_or_fail!(self.state.metadata_mut().gasometer.record_cost(gas_limit));

self.state.inc_nonce(caller);

self.enter_substate(gas_limit, false);

{
Expand All @@ -730,7 +734,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new()));
}

if self.nonce(address) > U256::zero() {
if self.nonce(address) > 0 {
let _ = self.exit_substate(StackExitKind::Failed);
return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new()));
}
Expand All @@ -757,7 +761,9 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
}

if self.config.create_increase_nonce {
self.state.inc_nonce(address);
if let Err(e) = self.state.inc_nonce(address) {
return Capture::Exit((e.into(), None, Vec::new()));
}
}

let runtime = Runtime::new(
Expand Down
16 changes: 9 additions & 7 deletions src/executor/stack/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,14 @@ impl<'config> MemoryStackSubstate<'config> {
return Some(false);
}

if account.basic.nonce != U256::zero() {
if account.basic.nonce != 0 {
return Some(false);
}

if let Some(code) = &account.code {
return Some(
account.basic.balance == U256::zero()
&& account.basic.nonce == U256::zero()
&& account.basic.nonce == 0
&& code.is_empty(),
);
}
Expand Down Expand Up @@ -301,8 +301,10 @@ impl<'config> MemoryStackSubstate<'config> {
.expect("New account was just inserted")
}

pub fn inc_nonce<B: Backend>(&mut self, address: H160, backend: &B) {
self.account_mut(address, backend).basic.nonce += U256::one();
pub fn inc_nonce<B: Backend>(&mut self, address: H160, backend: &B) -> Result<(), ExitError> {
let nonce = &mut self.account_mut(address, backend).basic.nonce;
*nonce = nonce.checked_add(1).ok_or(ExitError::MaxNonce)?;
Ok(())
}

pub fn set_storage(&mut self, address: H160, key: H256, value: H256) {
Expand Down Expand Up @@ -497,7 +499,7 @@ impl<'backend, 'config, B: Backend> StackState<'config> for MemoryStackState<'ba
}

self.backend.basic(address).balance == U256::zero()
&& self.backend.basic(address).nonce == U256::zero()
&& self.backend.basic(address).nonce == 0
&& self.backend.code(address).len() == 0
}

Expand All @@ -513,8 +515,8 @@ impl<'backend, 'config, B: Backend> StackState<'config> for MemoryStackState<'ba
self.substate.is_storage_cold(address, key)
}

fn inc_nonce(&mut self, address: H160) {
self.substate.inc_nonce(address, self.backend);
fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError> {
self.substate.inc_nonce(address, self.backend)
}

fn set_storage(&mut self, address: H160, key: H256, value: H256) {
Expand Down

0 comments on commit 0e03560

Please sign in to comment.