mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 13:39:25 +00:00
alloy-core 1.0, alloy 0.14, revm 0.22 (001)
This moves to Rust 1.86 as were prior on Rust 1.81, and the new alloy dependencies require 1.82. The revm API changes were notable for us. Instead of relying on a modified call instruction (with deep introspection into the EVM design), we now use the more recent and now more prominent Inspector API. This: 1) Lets us perform far less introspection 2) Forces us to rewrite the gas estimation code we just had audited Thankfully, it itself should be much easier to read/review, and our existing test suite has extensively validated it. This resolves 001 which was a concern for if/when this upgrade occurs. By doing it now, with a dedicated test case ensuring the issue we would have had with alloy-core 0.8 and `validate=false` isn't actively an issue, we resolve it.
This commit is contained in:
@@ -6,7 +6,7 @@ use alloy_consensus::TxLegacy;
|
||||
use alloy_rpc_types_eth::{TransactionInput, TransactionRequest};
|
||||
use alloy_provider::Provider;
|
||||
|
||||
use revm::{primitives::SpecId, interpreter::gas::calculate_initial_tx_gas};
|
||||
use revm::{primitives::hardfork::SpecId, interpreter::gas::calculate_initial_tx_gas};
|
||||
|
||||
use crate::tests::Test;
|
||||
|
||||
@@ -65,13 +65,13 @@ async fn test_create_address() {
|
||||
let call =
|
||||
TransactionRequest::default().to(address).input(TransactionInput::new(input.clone().into()));
|
||||
assert_eq!(
|
||||
&test.provider.call(&call).await.unwrap().as_ref()[12 ..],
|
||||
&test.provider.call(call.clone()).await.unwrap().as_ref()[12 ..],
|
||||
address.create(nonce).as_slice(),
|
||||
);
|
||||
|
||||
// Check the function is constant-gas
|
||||
let gas_used = test.provider.estimate_gas(&call).await.unwrap();
|
||||
let initial_gas = calculate_initial_tx_gas(SpecId::CANCUN, &input, false, &[], 0).initial_gas;
|
||||
let gas_used = test.provider.estimate_gas(call).await.unwrap();
|
||||
let initial_gas = calculate_initial_tx_gas(SpecId::CANCUN, &input, false, 0, 0, 0).initial_gas;
|
||||
let this_call = gas_used - initial_gas;
|
||||
if gas.is_none() {
|
||||
gas = Some(this_call);
|
||||
|
||||
@@ -86,13 +86,13 @@ impl Erc20 {
|
||||
let call = TransactionRequest::default().to(self.0).input(TransactionInput::new(
|
||||
abi::TestERC20::balanceOfCall::new((account,)).abi_encode().into(),
|
||||
));
|
||||
U256::abi_decode(&test.provider.call(&call).await.unwrap(), true).unwrap()
|
||||
U256::abi_decode(&test.provider.call(call).await.unwrap()).unwrap()
|
||||
}
|
||||
|
||||
pub(crate) async fn router_approval(&self, test: &Test, account: Address) -> U256 {
|
||||
let call = TransactionRequest::default().to(self.0).input(TransactionInput::new(
|
||||
abi::TestERC20::allowanceCall::new((test.router.address(), account)).abi_encode().into(),
|
||||
));
|
||||
U256::abi_decode(&test.provider.call(&call).await.unwrap(), true).unwrap()
|
||||
U256::abi_decode(&test.provider.call(call).await.unwrap()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ struct CalldataAgnosticGas;
|
||||
impl CalldataAgnosticGas {
|
||||
#[must_use]
|
||||
fn calculate(input: &[u8], mut constant_zero_bytes: usize, gas_used: u64) -> u64 {
|
||||
use revm::{primitives::SpecId, interpreter::gas::calculate_initial_tx_gas};
|
||||
use revm::{primitives::hardfork::SpecId, interpreter::gas::calculate_initial_tx_gas};
|
||||
|
||||
let mut without_variable_zero_bytes = Vec::with_capacity(input.len());
|
||||
for byte in input {
|
||||
@@ -76,9 +76,9 @@ impl CalldataAgnosticGas {
|
||||
}
|
||||
}
|
||||
gas_used +
|
||||
(calculate_initial_tx_gas(SpecId::CANCUN, &without_variable_zero_bytes, false, &[], 0)
|
||||
(calculate_initial_tx_gas(SpecId::CANCUN, &without_variable_zero_bytes, false, 0, 0, 0)
|
||||
.initial_gas -
|
||||
calculate_initial_tx_gas(SpecId::CANCUN, input, false, &[], 0).initial_gas)
|
||||
calculate_initial_tx_gas(SpecId::CANCUN, input, false, 0, 0, 0).initial_gas)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ struct RouterState {
|
||||
struct Test {
|
||||
#[allow(unused)]
|
||||
anvil: AnvilInstance,
|
||||
provider: Arc<RootProvider<SimpleRequest>>,
|
||||
provider: Arc<RootProvider>,
|
||||
chain_id: U256,
|
||||
router: Router,
|
||||
state: RouterState,
|
||||
@@ -173,8 +173,8 @@ impl Test {
|
||||
let call = TransactionRequest::default()
|
||||
.to(self.router.address())
|
||||
.input(TransactionInput::new(tx.input));
|
||||
let call_err = self.provider.call(&call).await.unwrap_err();
|
||||
call_err.as_error_resp().unwrap().as_decoded_error::<IRouterErrors>(true).unwrap()
|
||||
let call_err = self.provider.call(call).await.unwrap_err();
|
||||
call_err.as_error_resp().unwrap().as_decoded_interface_error::<IRouterErrors>().unwrap()
|
||||
}
|
||||
|
||||
fn confirm_next_serai_key_tx(&self) -> TxLegacy {
|
||||
@@ -574,11 +574,11 @@ async fn test_empty_execute() {
|
||||
TransactionRequest::default().to(token).input(TransactionInput::new(vec![].into()));
|
||||
// Check it returns the expected result
|
||||
assert_eq!(
|
||||
test.provider.call(&call).await.unwrap().as_ref(),
|
||||
test.provider.call(call.clone()).await.unwrap().as_ref(),
|
||||
U256::from(1).abi_encode().as_slice()
|
||||
);
|
||||
// Check it has the expected gas cost (16 is documented in `return_true_code`)
|
||||
assert_eq!(test.provider.estimate_gas(&call).await.unwrap(), 21_000 + 16);
|
||||
assert_eq!(test.provider.estimate_gas(call).await.unwrap(), 21_000 + 16);
|
||||
}
|
||||
|
||||
let gas = test.router.execute_gas(Coin::Erc20(token), U256::from(0), &[].as_slice().into());
|
||||
@@ -700,6 +700,35 @@ async fn test_eth_code_out_instruction() {
|
||||
assert_eq!(test.provider.get_code_at(deployed).await.unwrap().to_vec(), true.abi_encode());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_eth_code_out_instruction_reverts() {
|
||||
let mut test = Test::new().await;
|
||||
test.confirm_next_serai_key().await;
|
||||
let () = test
|
||||
.provider
|
||||
.raw_request("anvil_setBalance".into(), (test.router.address(), 1_000_000))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// [REVERT], which will cause `executeArbitraryCode`'s call to CREATE to fail
|
||||
let code = vec![0xfd];
|
||||
let amount_out = U256::from(0);
|
||||
let out_instructions = OutInstructions::from(
|
||||
[(
|
||||
SeraiEthereumAddress::Contract(ContractDeployment::new(50_000, code.clone()).unwrap()),
|
||||
amount_out,
|
||||
)]
|
||||
.as_slice(),
|
||||
);
|
||||
|
||||
let gas = test.router.execute_gas(Coin::Ether, U256::from(1), &out_instructions);
|
||||
let fee = U256::from(gas);
|
||||
let (tx, gas_used) = test.execute(Coin::Ether, fee, out_instructions, vec![true]).await;
|
||||
|
||||
let unused_gas = test.gas_unused_by_calls(&tx).await;
|
||||
assert_eq!(gas_used + unused_gas, gas);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_erc20_code_out_instruction() {
|
||||
let mut test = Test::new().await;
|
||||
|
||||
Reference in New Issue
Block a user