-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add support for Celo's stateful transfer precompile #11209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
supportive, because this can serve as a reference for additional precompile support.
left some pointers, re reusing the PrecompilesMap and inject dynamically.
we can likely clean up a few more things as well,
perhaps rethink how and where we call
foundry/crates/anvil/src/eth/backend/executor.rs
Lines 337 to 345 in 79d4ab2
let mut evm = new_evm_with_inspector(&mut *self.db, &env, &mut inspector); | |
if self.odyssey { | |
inject_precompiles(&mut evm, vec![(P256VERIFY, P256VERIFY_BASE_GAS_FEE)]); | |
} | |
if let Some(factory) = &self.precompile_factory { | |
inject_precompiles(&mut evm, factory.precompiles()); | |
} |
ideally we only have these in one location
/// Run a Celo chain | ||
#[arg(long)] | ||
pub celo: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, not convinced we want to add a new arg for every network that we can add custom precompiles for.
should we perhaps derive this from the chainid, although an additional celo flag doesnt really hurt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we only rely on the chainid, new networks won't work with anvil until they have been explicitly supported. And getting PRs with config for short-lived and local networks sounds annoying to me. Adding a flag seems the lesser evil to me.
We can still automatically detect the flags for the most important networks based on the chainid. But if we need a flag anyway, that falls into the "nice to have" category.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also enable the transfer
precompile by setting --hardfork cel2
, but I'm not sure if adding chain-specific hardforks is better than adding a flag for the chain itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is now redundant, because we can now dynamically inject precompiles into the regular evm with PrecompilesMap via
foundry/crates/anvil/src/evm.rs
Lines 28 to 29 in 79d4ab2
evm.precompiles_mut().apply_precompile(&addr, move |_| { | |
Some(DynPrecompile::from(move |input: PrecompileInput<'_>| func(input.data, gas))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In its current form, this can only be used to inject stateless precompiles. The PrecompileWithAddress
that is passed into this function does not take any context/state as parameter:
pub struct PrecompileWithAddress(pub Address, pub PrecompileFn);
pub type PrecompileFn = fn(&[u8], u64) -> PrecompileResult;
But now that PrecompilesMap
has gained a settable lookup
function, I can try to use that to include a stateful precompile. Unfortunately, the EvmInternals
in the PrecompileInput
don't provide access to the journal, so that I can't use the journal's transfer
method like I do in this PR. I might be able to use load_account
instead, since it returns a mutable Account
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the code with this approach and it looks much better now.
4465f77
to
64f1632
Compare
Motivation
The Celo blockchain makes use of a stateful
transfer
precompile. Implementing this in Anvil allows running more of our tests in Anvil.This PR is clearly far from being mergeable, but it serves two purposes:
Solution
The
PrecompilesMap
doesn't support stateful precompiles, so we need to use aPrecompileProvider
instead that has support for stateful precompiles. Changing the typing to only depend on thePrecompileProvider
trait (which would allow passingPrecompilesMap
or a statefulePrecompileProvider
on a case-by-case bases) proved difficult, so I instead added aHybridPrecompileProvider
which has support for stateful precompiles but can also pass along the precompiles from aPrecompilesMap
.The
HybridPrecompileProvider
implementation is also very limited due to additional typing problems described in the comment.PR Checklist