Aurora Labs is delighted to announce the EVM version 2.8.0 from the Engine team. It includes security enhancements, binary reproducibility, some finds from the fuzzers, and improvements to cross-contract calls.
Security Response Enhancements
We always are looking for ways to increase our responsiveness to the Aurora EVM. Two new admin functions were added to the EVM contract to allow us to control which parts of the EVM we need to pause. In this case, we have added the ability to pause Aurora EVM-specific precompiles with the
The golden standard of deployments is the ability to reproduce the exact build of a contract at any point in the future. Reproducible contracts are vital in terms of trust and transparency to ensure that we faithfully deploy a verified contract.
We have currently an ongoing audit with Sigma Prime, including a fuzzer, and another fuzz testing being run by BlockSec (explained here under "Fuzz Tests"). We have been patching minor Go-Ethereum compliance issues as they come in. We have found an unfortunate logic regression in the BN256 and modular exponentiation precompiles that have been fixed since.
Cross Contract Calls Status
Cross Contract calls, introduced on testnet in 2.7.0, need to be prepared for mainnet. It is currently undergoing an internal audit to ensure it is safe to use.
Extended Patch Notes
Do note that there has been more work done than the listed below but we are only sharing the highlights. For more details you can see the latest release pull request here.
More granular control over pausing certain functionality in the Aurora EVM was needed. In particular, we needed the ability to quickly pause the functionality, enabling ETH or ERC-20 tokens to be withdrawn from the Engine. This ability had been done by introducing two new functions to the Engine,
resume_precompiles, which allow the contract owner to enable/disable that new functionality.
While it is not currently possible to reproduce a build without a specific container environment, it is possible to utilize Docker and an image to achieve a reproducible build. A reproducible build is now possible by running the
cargo make --profile <profile> build-docker command. This command can then be run to ensure that the Engine at a granular level is reproducible down to the metadata.
EVM call stack too small (#638, aurora-is-near/sputnikvm#16)
The EVM call stack is too small on Rust and needs a limit of 1028 depth. Unfortunately, we observed that we had hit this limit.
BN256 precompile had a regression (#637)
BN256 had a regression from the previous release where (0,0) points resulted in a revert and not successfully executing as they do exist on the curve.
Modular exponentiation under estimated gas (c7e9b8e6)
Before execution can occur on precompile, we must estimate the gas before executing the code itself. Unfortunately, for some inputs with exponents of 0, the gas estimated was severely underestimated as 200 gwei. The math was updated to fix this:
gas = mul_complexity * iteration_count / 3
gas = mul_complexity * max(iteration_count, 1) / 3
After this patch, an input of
0x000000000000090000000000000000, which prior resulted in a gas value of 200 gwei, now correctly estimates 18,446,744,073,709,551,615 gwei.
This fix patches an issue causing some transactions to hit the max gas limit on NEAR at no cost to an adversary keen on draining NEAR balances of relayers. This patch had not affected Aurora's relayer RPC, but it may have affected others' relayer RPCs.
Minor improvements to Cross Contract Calls
Allow Cross Contract Calls to perform any possible NEAR call (#610)
We define a new data structure called NearPromise, which can model all possible promise actions on NEAR. This includes all batch actions and all promise combinators. The data type is recursive because long chains of callback are allowed in NEAR, and the "And" combinator can join any promises together.
The purpose of adding this definition is to allow users of the Cross Contract Call feature to make any transaction on NEAR that they could do if they had their NEAR account.
Note that this change is backwards compatible with the current Cross Contract Call feature because this PR adds a new variant to PromiseArgs, the type used in CrossContractCallArgs.
Only update the router contract version in storage if the deployment is successful (#616)
In the Cross Contract Call flow, we store the current version of each deployed sub-account in the Engine's storage. When a router contract needs to be updated (or the sub-account does not yet exist), we must deploy the new version and update the entry in storage. The storage update is done as a callback after the deployment. In this fix, we added logic to check that the deploy was successful before updating the version in storage.
Ensure the Cross Contract Call router attaches enough gas to execute (#622)
While working on the native token connector, we could not eagerly execute promises with callbacks using the Cross Contract Call mechanism. This problem was because the Cross Contract Call precompile needed to attach more NEAR gas to the router's execute a function when promises were involved. The amount of gas needed scales linearly with the number of callbacks. We fixed the issue and the Cross Contract Call precompile now accounts for the linearly increasing amount of gas needed for promises with callbacks.
Many thanks to our contributors to this release below.
- Oleksandr Anyshchenko email@example.com
- Michael Birch firstname.lastname@example.org
- Joshua J. Bouw email@example.com
- Roman Hodulák firstname.lastname@example.org
- Kirill email@example.com
- Alexey Lapitsky firstname.lastname@example.org
- Dmitry Strokov email@example.com
- Evgeny Ukhanov firstname.lastname@example.org