diff --git a/processor/ethereum/erc20/src/tests.rs b/processor/ethereum/erc20/src/tests.rs index 2218e19b..037c7862 100644 --- a/processor/ethereum/erc20/src/tests.rs +++ b/processor/ethereum/erc20/src/tests.rs @@ -11,3 +11,5 @@ fn selector_collisions() { crate::abi::SeraiIERC20::transferFromWithInInstruction00081948E0Call::SELECTOR ); } + +// This is primarily tested via serai-processor-ethereum-router diff --git a/processor/ethereum/router/contracts/Router.sol b/processor/ethereum/router/contracts/Router.sol index dd0ad6e5..03eaac0e 100644 --- a/processor/ethereum/router/contracts/Router.sol +++ b/processor/ethereum/router/contracts/Router.sol @@ -441,6 +441,8 @@ contract Router is IRouterWithoutCollisions { unchecked { // The amount of bytes needed to represent the nonce uint256 bitsNeeded = 0; + // This only iterates up to 64-bits as this will never exceed 2**64 as a matter of + // practicality for (uint256 bits = 0; bits <= 64; bits += 8) { bool valueFits = nonce < (uint256(1) << bits); bool notPriorSet = bitsNeeded == 0; diff --git a/processor/ethereum/router/src/gas.rs b/processor/ethereum/router/src/gas.rs index 28dd799a..266ad586 100644 --- a/processor/ethereum/router/src/gas.rs +++ b/processor/ethereum/router/src/gas.rs @@ -225,6 +225,8 @@ impl Router { } /// The worst-case gas cost for a legacy transaction which executes this batch. + /// + /// This assumes the fee will be non-zero. pub fn execute_gas(&self, coin: Coin, fee_per_gas: U256, outs: &OutInstructions) -> u64 { // Unfortunately, we can't cache this in self, despite the following code being written such // that a common EVM instance could be used, as revm's types aren't Send/Sync and we expect the diff --git a/processor/ethereum/router/src/tests/mod.rs b/processor/ethereum/router/src/tests/mod.rs index bc086c62..403e871e 100644 --- a/processor/ethereum/router/src/tests/mod.rs +++ b/processor/ethereum/router/src/tests/mod.rs @@ -836,6 +836,7 @@ async fn fuzz_test_out_instructions_gas() { out_instructions.push((SeraiEthereumAddress::Address(address), amount_out)); } } + let out_instructions_original = out_instructions.clone(); let out_instructions = OutInstructions::from(out_instructions.as_slice()); // Randomly decide the coin @@ -852,13 +853,17 @@ async fn fuzz_test_out_instructions_gas() { Coin::Erc20(erc20.address()) }; - let fee_per_gas = U256::from(OsRng.next_u64() % 10); + let fee_per_gas = U256::from(1) + U256::from(OsRng.next_u64() % 10); let gas = test.router.execute_gas(coin, fee_per_gas, &out_instructions); let fee = U256::from(gas) * fee_per_gas; // All of these should have succeeded let (tx, gas_used) = test.execute(coin, fee, out_instructions.clone(), vec![true; out_instructions.0.len()]).await; let unused_gas = test.gas_unused_by_calls(&tx).await; - assert_eq!(gas_used + unused_gas, gas); + assert_eq!( + gas_used + unused_gas, + gas, + "{coin:?} {fee_per_gas:?} {out_instructions_original:?}" + ); } }