diff --git a/processor/ethereum/router/contracts/Router.sol b/processor/ethereum/router/contracts/Router.sol index 7c7838cf..f7fe8c0e 100644 --- a/processor/ethereum/router/contracts/Router.sol +++ b/processor/ethereum/router/contracts/Router.sol @@ -185,6 +185,10 @@ contract Router is IRouterWithoutCollisions { // Read _nextNonce into memory as the nonce we'll use nonceUsed = _nextNonce; + // We overwrite the signature response with the Router contract's address concatenated with the + // nonce. This is safe until the nonce exceeds 2**96, which is infeasible to do on-chain + uint256 signatureResponseOverwrite = (uint256(uint160(address(this))) << 96) | nonceUsed; + // Declare memory to copy the signature out to bytes32 signatureC; bytes32 signatureS; @@ -199,7 +203,7 @@ contract Router is IRouterWithoutCollisions { // Overwrite the signature challenge with the chain ID mstore(add(message, 36), chainID) // Overwrite the signature response with the nonce - mstore(add(message, 68), nonceUsed) + mstore(add(message, 68), signatureResponseOverwrite) // Calculate the message hash messageHash := keccak256(add(message, 32), messageLen) diff --git a/processor/ethereum/router/src/gas.rs b/processor/ethereum/router/src/gas.rs index df5190d9..58819560 100644 --- a/processor/ethereum/router/src/gas.rs +++ b/processor/ethereum/router/src/gas.rs @@ -151,11 +151,11 @@ impl Router { the correct set of prices for the network they're operating on. */ /// The gas used by `confirmSeraiKey`. - pub const CONFIRM_NEXT_SERAI_KEY_GAS: u64 = 57_736; + pub const CONFIRM_NEXT_SERAI_KEY_GAS: u64 = 57_753; /// The gas used by `updateSeraiKey`. - pub const UPDATE_SERAI_KEY_GAS: u64 = 60_045; + pub const UPDATE_SERAI_KEY_GAS: u64 = 60_062; /// The gas used by `escapeHatch`. - pub const ESCAPE_HATCH_GAS: u64 = 61_094; + pub const ESCAPE_HATCH_GAS: u64 = 61_111; /// The key to use when performing gas estimations. /// @@ -278,7 +278,7 @@ impl Router { // Use a nonce of 1 ProjectivePoint::GENERATOR, &public_key, - &Self::execute_message(CHAIN_ID, 1, coin, shimmed_fee, outs.clone()), + &Self::execute_message(CHAIN_ID, self.address, 1, coin, shimmed_fee, outs.clone()), ); let s = Scalar::ONE + (c * private_key); let sig = Signature::new(c, s).unwrap(); diff --git a/processor/ethereum/router/src/lib.rs b/processor/ethereum/router/src/lib.rs index d5b2f3cf..02d5c0d9 100644 --- a/processor/ethereum/router/src/lib.rs +++ b/processor/ethereum/router/src/lib.rs @@ -292,13 +292,22 @@ impl Router { self.address } + /// Get the signature data signed in place of the actual signature. + fn signature_data(chain_id: U256, router_address: Address, nonce: u64) -> abi::Signature { + let mut s = [0; 32]; + s[.. 20].copy_from_slice(router_address.as_slice()); + s[24 ..].copy_from_slice(&nonce.to_be_bytes()); + abi::Signature { c: chain_id.into(), s: s.into() } + } + /// Get the message to be signed in order to confirm the next key for Serai. - pub fn confirm_next_serai_key_message(chain_id: U256, nonce: u64) -> Vec { - abi::confirmNextSeraiKeyCall::new((abi::Signature { - c: chain_id.into(), - s: U256::try_from(nonce).unwrap().into(), - },)) - .abi_encode() + pub fn confirm_next_serai_key_message( + chain_id: U256, + router_address: Address, + nonce: u64, + ) -> Vec { + abi::confirmNextSeraiKeyCall::new((Self::signature_data(chain_id, router_address, nonce),)) + .abi_encode() } /// Construct a transaction to confirm the next key representing Serai. @@ -313,9 +322,14 @@ impl Router { } /// Get the message to be signed in order to update the key for Serai. - pub fn update_serai_key_message(chain_id: U256, nonce: u64, key: &PublicKey) -> Vec { + pub fn update_serai_key_message( + chain_id: U256, + router_address: Address, + nonce: u64, + key: &PublicKey, + ) -> Vec { abi::updateSeraiKeyCall::new(( - abi::Signature { c: chain_id.into(), s: U256::try_from(nonce).unwrap().into() }, + Self::signature_data(chain_id, router_address, nonce), key.eth_repr().into(), )) .abi_encode() @@ -371,13 +385,14 @@ impl Router { /// Get the message to be signed in order to execute a series of `OutInstruction`s. pub fn execute_message( chain_id: U256, + router_address: Address, nonce: u64, coin: Coin, fee: U256, outs: OutInstructions, ) -> Vec { abi::executeCall::new(( - abi::Signature { c: chain_id.into(), s: U256::try_from(nonce).unwrap().into() }, + Self::signature_data(chain_id, router_address, nonce), Address::from(coin), fee, outs.0, @@ -399,12 +414,14 @@ impl Router { } /// Get the message to be signed in order to trigger the escape hatch. - pub fn escape_hatch_message(chain_id: U256, nonce: u64, escape_to: Address) -> Vec { - abi::escapeHatchCall::new(( - abi::Signature { c: chain_id.into(), s: U256::try_from(nonce).unwrap().into() }, - escape_to, - )) - .abi_encode() + pub fn escape_hatch_message( + chain_id: U256, + router_address: Address, + nonce: u64, + escape_to: Address, + ) -> Vec { + abi::escapeHatchCall::new((Self::signature_data(chain_id, router_address, nonce), escape_to)) + .abi_encode() } /// Construct a transaction to trigger the escape hatch. diff --git a/processor/ethereum/router/src/tests/escape_hatch.rs b/processor/ethereum/router/src/tests/escape_hatch.rs index 28be1a64..840ec9c5 100644 --- a/processor/ethereum/router/src/tests/escape_hatch.rs +++ b/processor/ethereum/router/src/tests/escape_hatch.rs @@ -8,7 +8,12 @@ use crate::tests::*; impl Test { pub(crate) fn escape_hatch_tx(&self, escape_to: Address) -> TxLegacy { - let msg = Router::escape_hatch_message(self.chain_id, self.state.next_nonce, escape_to); + let msg = Router::escape_hatch_message( + self.chain_id, + self.router.address(), + self.state.next_nonce, + escape_to, + ); let sig = sign(self.state.key.unwrap(), &msg); let mut tx = self.router.escape_hatch(escape_to, &sig); tx.gas_limit = Router::ESCAPE_HATCH_GAS + 5_000; diff --git a/processor/ethereum/router/src/tests/mod.rs b/processor/ethereum/router/src/tests/mod.rs index 191b4afd..6c6614fe 100644 --- a/processor/ethereum/router/src/tests/mod.rs +++ b/processor/ethereum/router/src/tests/mod.rs @@ -178,7 +178,11 @@ impl Test { } fn confirm_next_serai_key_tx(&self) -> TxLegacy { - let msg = Router::confirm_next_serai_key_message(self.chain_id, self.state.next_nonce); + let msg = Router::confirm_next_serai_key_message( + self.chain_id, + self.router.address(), + self.state.next_nonce, + ); let sig = sign(self.state.next_key.unwrap(), &msg); self.router.confirm_next_serai_key(&sig) @@ -227,7 +231,12 @@ impl Test { fn update_serai_key_tx(&self) -> ((Scalar, PublicKey), TxLegacy) { let next_key = test_key(); - let msg = Router::update_serai_key_message(self.chain_id, self.state.next_nonce, &next_key.1); + let msg = Router::update_serai_key_message( + self.chain_id, + self.router.address(), + self.state.next_nonce, + &next_key.1, + ); let sig = sign(self.state.key.unwrap(), &msg); (next_key, self.router.update_serai_key(&next_key.1, &sig)) @@ -275,6 +284,7 @@ impl Test { ) -> ([u8; 32], TxLegacy) { let msg = Router::execute_message( self.chain_id, + self.router.address(), self.state.next_nonce, coin, fee, @@ -468,11 +478,10 @@ async fn test_update_serai_key() { // But we shouldn't be able to update the key to None { + let router_address_u256: U256 = test.router.address().into_word().into(); + let s: U256 = (router_address_u256 << 96) | U256::from(test.state.next_nonce); let msg = crate::abi::updateSeraiKeyCall::new(( - crate::abi::Signature { - c: test.chain_id.into(), - s: U256::try_from(test.state.next_nonce).unwrap().into(), - }, + crate::abi::Signature { c: test.chain_id.into(), s: s.into() }, [0; 32].into(), )) .abi_encode(); @@ -822,7 +831,7 @@ async fn test_reentrancy() { #[tokio::test] async fn fuzz_test_out_instructions_gas() { - for _ in 0 .. 10 { + for _ in 0 .. 100 { let mut test = Test::new().await; test.confirm_next_serai_key().await; @@ -840,7 +849,7 @@ async fn fuzz_test_out_instructions_gas() { code.extend(&ext); out_instructions.push(( - SeraiEthereumAddress::Contract(ContractDeployment::new(100_000, ext).unwrap()), + SeraiEthereumAddress::Contract(ContractDeployment::new(100_000, code).unwrap()), amount_out, )); } else { @@ -906,33 +915,10 @@ async fn test_gas_increases_then_decreases() { expected *and the fee for it*. This fee is guaranteed to cost the reported amount of gas, resolving this issue. */ - #[rustfmt::skip] - let out_instructions = vec![ - (SeraiEthereumAddress::Address(**Address::from([73, 151, 53, 42, 64, 102, 196, 80, 244, 167, 149, 81, 236, 231, 65, 18, 68, 196, 173, 20])), U256::from(1u8)), - (SeraiEthereumAddress::Address(**Address::from([7, 232, 97, 33, 54, 141, 246, 45, 29, 138, 221, 30, 2, 179, 142, 165, 169, 45, 143, 126])), U256::from(1u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(1u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(1u8)), - (SeraiEthereumAddress::Address(**Address::from([73, 151, 53, 42, 64, 102, 196, 80, 244, 167, 149, 81, 236, 231, 65, 18, 68, 196, 173, 20])), U256::from(0u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(1u8)), - (SeraiEthereumAddress::Address(**Address::from([34, 132, 167, 44, 12, 171, 57, 177, 197, 88, 60, 255, 68, 75, 2, 139, 76, 138, 78, 222])), U256::from(1u8)), - (SeraiEthereumAddress::Address(**Address::from([221, 218, 210, 119, 213, 189, 65, 118, 205, 113, 19, 11, 83, 58, 129, 203, 123, 76, 202, 99])), U256::from(0u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(0u8)), - (SeraiEthereumAddress::Address(**Address::from([34, 132, 167, 44, 12, 171, 57, 177, 197, 88, 60, 255, 68, 75, 2, 139, 76, 138, 78, 222])), U256::from(0u8)), - (SeraiEthereumAddress::Address(**Address::from([82, 31, 116, 111, 9, 110, 56, 51, 122, 38, 10, 227, 36, 134, 181, 185, 255, 149, 195, 254])), U256::from(1u8)), - (SeraiEthereumAddress::Address(**Address::from([36, 68, 76, 140, 254, 107, 233, 107, 186, 85, 5, 37, 65, 201, 63, 17, 135, 244, 148, 1])), U256::from(1u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(1u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(0u8)), - (SeraiEthereumAddress::Address(**Address::from([34, 132, 167, 44, 12, 171, 57, 177, 197, 88, 60, 255, 68, 75, 2, 139, 76, 138, 78, 222])), U256::from(1u8)), - (SeraiEthereumAddress::Address(**Address::from([26, 54, 156, 184, 48, 50, 23, 219, 43, 54, 56, 131, 245, 126, 70, 17, 235, 56, 130, 124])), U256::from(1u8)), - (SeraiEthereumAddress::Address(**Address::from([152, 27, 239, 11, 196, 99, 61, 136, 23, 8, 58, 242, 166, 235, 106, 167, 45, 175, 69, 247])), U256::from(0u8)), - (SeraiEthereumAddress::Address(**Address::from([152, 27, 239, 11, 196, 99, 61, 136, 23, 8, 58, 242, 166, 235, 106, 167, 45, 175, 69, 247])), U256::from(0u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(0u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(0u8)), - (SeraiEthereumAddress::Address(**Address::from([7, 232, 97, 33, 54, 141, 246, 45, 29, 138, 221, 30, 2, 179, 142, 165, 169, 45, 143, 126])), U256::from(0u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(0u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(0u8)), - (SeraiEthereumAddress::Contract(ContractDeployment::new(100000, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()), U256::from(1u8)) - ]; + let out_instructions = vec![( + SeraiEthereumAddress::Contract(ContractDeployment::new(100240, vec![]).unwrap()), + U256::from(1u8), + )]; let mut test = Test::new().await; test.confirm_next_serai_key().await; @@ -940,12 +926,15 @@ async fn test_gas_increases_then_decreases() { let out_instructions = OutInstructions::from(out_instructions.as_slice()); let coin = { - let erc20 = Erc20::deploy(&test).await; - erc20.mint(&test, test.router.address(), U256::from(1_000_000_000)).await; - Coin::Erc20(erc20.address()) + let () = test + .provider + .raw_request("anvil_setBalance".into(), (test.router.address(), 1_000_000_000)) + .await + .unwrap(); + Coin::Ether }; - let fee_per_gas = U256::from(4); + let fee_per_gas = U256::from(1); let (gas, fee) = test.router.execute_gas_and_fee(coin, fee_per_gas, &out_instructions); assert!((U256::from(gas) * fee_per_gas) != fee); let (tx, gas_used) =