Clarified usage of CREATE

CREATE was originally intended for gas savings. While one sketch did move to
CREATE2, the security concerns around address collisions (requiring all init
codes not be malleable to achieve security) continue to justify this.

To resolve the gas estimation concerns raised in the prior commit, the
createAddress function has been made constant-gas.
This commit is contained in:
Luke Parker
2025-01-27 07:22:40 -05:00
parent a9625364df
commit ea00ba9ff8
5 changed files with 131 additions and 104 deletions

View File

@@ -56,42 +56,30 @@ async fn test_create_address() {
// The only meaningful patterns are < 0x80, == 0x80, and then each length greater > 0x80
// The following covers all three
let mut nonce = 1u64;
let mut gas = None;
while nonce.checked_add(nonce).is_some() {
let input =
(abi::CreateAddress::createAddressForSelfCall { nonce: U256::from(nonce) }).abi_encode();
// Make sure the function works as expected
let call =
TransactionRequest::default().to(address).input(TransactionInput::new(input.clone().into()));
assert_eq!(
&test
.provider
.call(
&TransactionRequest::default().to(address).input(TransactionInput::new(
(abi::CreateAddress::createAddressForSelfCall { nonce: U256::from(nonce) })
.abi_encode()
.into()
))
)
.await
.unwrap()
.as_ref()[12 ..],
&test.provider.call(&call).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 this_call = gas_used - initial_gas;
if gas.is_none() {
gas = Some(this_call);
}
assert_eq!(gas, Some(this_call));
nonce <<= 1;
}
let input =
(abi::CreateAddress::createAddressForSelfCall { nonce: U256::from(u64::MAX) }).abi_encode();
let gas = test
.provider
.estimate_gas(
&TransactionRequest::default().to(address).input(TransactionInput::new(input.clone().into())),
)
.await
.unwrap() -
calculate_initial_tx_gas(SpecId::CANCUN, &input, false, &[], 0).initial_gas;
let keccak256_gas_estimate = |len: u64| 30 + (6 * len.div_ceil(32));
let mut bytecode_len = 0;
while (keccak256_gas_estimate(bytecode_len) + keccak256_gas_estimate(85)) < gas {
bytecode_len += 32;
}
println!(
"Worst-case createAddress gas: {gas}, CREATE2 break-even is bytecode of length {bytecode_len}",
);
println!("createAddress gas: {}", gas.unwrap());
}