Frontrunning Post EIP-3074
Studying New Possibilities and Cause for Concern
Are you reading up on new EIPs for alpha, anon? One of my favourite pastimes is trying to predict the landscape of MEV in the near future. I sometimes find myself getting ideas for strategies that might be profitable later on, just not now.
Reading up on EIP-3074 was one of those moments. I’ll be sharing an interesting frontrunning strategy I came up with that could work post 3074.
I’m not usually one for posting predictions, but some interesting ideas came up from this that I felt should be published.
A Primer on EIP-3074
One glaring UX problem on Ethereum is the fact that Externally Owned Accounts (basically your wallet) can’t make multiple calls to different smart contracts in one tx (multicalls). That’s why we have the approve tx -> swap tx flow for ERC20 swaps on DEXs today. EIP-3074 solves this, among other things. It doesn’t let you make multicalls from your EOA directly, but it does allow a contract to make calls to other contracts as if it was coming from your EOA (i.e. msg.sender = EOA
) which achieves the same thing.
The EIP introduces two new opcodes, AUTH
and AUTHCALL
, and a new solidity built-in function authorize
. The contract we make the 3074-tx through is called an invoker. The flow is simple:
- a user signs a
commitment
(hash) of what they want their tx to do, and signs it - the user calls the invoker and passes in what contract they want to call, along with the calldata, and the signature of the commitment
- the invoker hashes the args to reconstruct the commitment
authorize(commitment, signature)
returns the user’s EOA address and also loads it in temporary storage by theAUTH
opcode- the invoker makes an
AUTHCALL
with the contract and calldata (likecontract.authcall(calldata);
) - the
msg.sender
in that authcall will be our user’s address even thought the invoker (a contract) is making the call
Note that since a signature and commitment is all that’s needed to get the EOA address, the user doesn’t have to submit this themselves. In fact, someone could pay the gas fees for them and submit it on their behalf. Sponsoring gas fees was also a motivation for the EIP.
An invoker contract will look something like this:
The commit hash would be regenerated by the invoker using the values passed in. This way, if a sponsor changes a value, the invoker will compute a different commit hash than the EOA signed, causing AUTH to recover a junk address. That might look something like this: pic.twitter.com/RN2Fpr0tLm
— ً (@lightclients) March 16, 2021
Extract and Rewrap
One way of thinking about 3074 txs is like multicalls that anyone can do on your behalf provided they have the commitment and your signature. The individuals calls to other contracts will look like regular internal contract calls to anyone viewing your transaction. This is where the fun part starts. If you’ve read Ethereum is a Dark Forest then you’ll know that advanced searchers are lurking in the mempool for any profitable transactions, even going so far as to look over internal calls that they can frontrun. What happens when a 3074 tx is making internal calls that we can not only frontrun, but extract and include in our tx instead? A quick example can demonstrate why a searcher would do that.
sandwich tx 1 (buy) sandwich tx {
victim's 3074 tx { - sandwich buy
- DEX swap (this is an internal call) vs - victim's DEX swap (that we extracted)
} - sandwich sell
sandwich tx 2 (sell) }
We were able to sandwich an incoming 3074 tx the traditional way (over 3 txs) or we could extract the commitment and signature details from the pending DEX swap and place it in our own tx, that way we could execute a sandwich in only one tx! We get some interesting results from this:
- we are paying a victim’s gas fees in exchange for screwing them over by sandwiching them (chaotic neutral?)
- we save on gas since we’re executing a sandwich in 1 tx
- we can take out a flashloan to sandwich a trade instead of putting up our own capital
What actually got me looking at EIP-3074 in the first place was because I wanted to take out a flashloan to execute a sandwich, which isn’t possible over 3 txs since I’d need to return what I borrowed in the same tx. Where arbitrage was the only strategy that could use flashloans, 3074 now opens up flashloans for use in many more MEV strategies.
I don’t think this sandwich scenario is any cause for concern, the existence of EIP-3074 didn’t create new a MEV opportunity it just changed how we could profit from it. Notice how even if we didn’t extract the internal call, the swap was still very much sandwichable. The only difference is someone with enough capital could have taken full advantage of the sandwich in the first scenario, whereas the second one doesn’t have any capital requirements (besides gas fees ofc). I think that’s pretty cool, it levels the playing field even more in my opinion.
That being said, that only applies with current MEV strategies. There’s no telling what 3074 opens up for searchers. Remember, unless implemented properly, a call to an invoker can be frontrun and a tx coming from your EOA can be included as an internal call in anyone’s tx. If developers want to mitigate against any unpredictable attacks they may want to add a address relayer
parameter to the sponsor
function above so the invoker can assert the sponsor is who we expect it to be (require(msg.sender == relayer);
). This at least preserves the current MEV status quo, and won’t add on to it.
But otherwise, gud eip honestly.