laitimes

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

author:MarsBit

原文作者:Anton Cheng

Original source: medium

Preface

In the past few days, an AA-related EIP3074 has been confirmed for the next Pectra hard fork, which has caused a lot of discussion in the community. There are many introductions about EIP3074 on Twitter and some memory block chain media, but because the actual changes of EIP3074 are a bit complicated and misunderstood, I hope to use this article today to clarify everyone's doubts about this EIP.

The main purpose of EIP3074 can be summed up in one sentence: to allow EOA (externally owned account) to have the functions of a contract wallet without the need to deploy a smart contract wallet. This means that the average wallet user can directly "upgrade" their EOA, just like installing the extension, without the need to deploy a new contract or change the existing address. So how exactly is it done?

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

The pre-EIP3074 transaction process

Most contracts are developed by relying on the msg.sender variable to determine who is coming, i.e. "the account calling this contract". If there is a series of consecutive contract calls, the msg.sender received by the receiver will be updated each time an outbound call (CALL) is made.

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

Every time you call, a new call frame will be opened, with a new msg.sender

Since contracts rely on msg.sender to determine the identity of the caller, it often unwittingly restricts the caller's UX. If Alice uses an EOA (alice.eth) to receive ERC20 tokens, then she must send a transaction from her EOA to create a condition like the caller msg.sender = alice.eth to call the contract for the transfer.

For the same reason, coupled with the need to approve the token contract before it can be used by other Dapps, many transactions must be completed by initiating two transactions with EOA.

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

Two transactions are required for one swap

These are the most criticized UX issues, and they are the two points that all AA articles will cover: you have to pay the fees in ETH yourself, and you can't use batch transactions.

Before we had EIP3074, we had to rely on contract wallets to solve these problems, because contract wallets can automatically package multiple transactions for you and let others pay the fees on your behalf. But this upgrade is not painless, you have to transfer all your assets to your new contract account, and use this new contract wallet as the main body for you to collect money and do contract interactions:

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

How to use a traditional "contract account" to solve the problem of fee payment and batch trading

As shown in the figure above, although multiple transactions can be sent through one contract, the entity that actually sends the call to the application contract has changed from EOA to a purple contract wallet, and the address we are recorded in the Dapp has also changed from the original alice.eth to smartalice.eth, which is regarded as two different entities.

This solution is actually very effective, but for many existing EOA users, migrating EOA is very costly, not only to find out all the positions that exist in different protocols, but also to find out that there is forgotten money or airdrop to receive one day, and to spend a lot of time to transfer ETH back to pay for gas. This may be one of the reasons why the contract is not common until today, after all, everyone who has just started to contact the memory blockchain may not use such a fancy wallet, nor will they want these more advanced functions, but they are too lazy to change after using it for a long time.

EIP3074 workaround

If we take a step back and think that we use msg.sender to verify the identity of the initiating trader, then we don't have to force it to call the "previous address" of this contract as long as we make sure that msg.sender has the proper authorization.

A good way to explain EIP3074 is to break the existing restriction that msg.sender must come from the previous calling address through a new OP code and a new wallet plug-in: invoker contract. Once we break this limitation, we can allow custom "proxy logic" to be written into the Invoker contract, creating a lot of variation.

A motivating use case of this EIP is that it allows any EOA to act like a smart contract wallet without deploying a contract.

EIP3074 new transaction flow chart is as follows:

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

Calls made after Invoker authentication will use the new AUTHCALL instead of the CALL. For the called contract, msg.sender becomes the EOA that was originally authorized to be signed.

New OP Code

This EIP does this through two new OP codes: AUTH and AUTHCALL. AUTH is the authorization step, which will confirm that the EOA holder has signed, authorize the invoker to make proxy calls, and then if the contract uses AUTHCALL instead of CALL, msg.sender can be copied as the EOA signer during the outgoing call.

Note: When this EIP was first proposed, there was actually only one OP code, that is, AUTHCALL, and it directly signed the content (calldata) of the external call, which means that each external authorized call should be signed once. But then considering that a big use scenario of invoker is to help you do batch transactions, if you have to check the signature every time you do AUTHCALL, it will mean that if the user wants to do multiple transactions in batches, he will have to sign many times, and the experience is not very good. So the shift was made to give the invoker maximum flexibility, splitting an OPCode into two phases, and doing multiple AUTHCALLS as long as AUTH was done once in the same call frame.

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

The same is a transaction (1 tx), using two external AUTHCALLS to achieve the effect of batching

Pay attention to the details of the EIP

The role of Invoker

At first glance, this EIP looks terrifying, after all, "Allow contracts to represent my EOA" sounds like a Pandora's box that will lead to endless disasters. But I think it's because when we understand contracts, we often think of DeFi Protocols, which are usually scalable, have some trust assumptions, and are often hacked. All of this makes us distrust smart contracts. Therefore, many people's doubts about this EIP come from the security of the contract.

But I think a better way to understand it is to think of the invoker as part of a wallet, rather than a traditional contract. In other words, these two Opcodes should not be used by any DeFi protocol, instead, they should only be used by new wallet plugins.

In the future, wallets will have a layer of trust with Invoker: wallets will develop their own Invokers, or use open-source and audited Invokers, and only allow users to use Invokers that they have reviewed and trusted. In the future, our trust base for wallet providers will also include these invokers, which are a bit like choosing contract wallets and grouping them as part of the overall wallet.

The content of the signature

As mentioned earlier, the original proposal was to advocate a one-time signing of AUTHCALL, but after the decision to divide it into two phases, an important spirit was to give invoker most of the work that can be done by invoker, so the information that users must sign only contains the following points:

  1. type byte (0x04): In order to ensure that different types of signature results are not misused by others, the signature system on Ethereum will have a unique prefix. For example, general transactions, signed messages, EIP1559 have different prefixes.
  2. chain id:目前的链id
  3. nonce: the count of EOA's current transactions (the same as the nonce that is attached to a normal exchange)
  4. invoker:将会使用AUTHCALL的合约地址
  5. commit: 32 bytes, usually used in the invoker custom logic, you need to confirm the hash result of the user's signature confirmation. For example, if there is an invoker verification logic to ensure that the user has a signature on the calldata of AUTHCALL, the invoker needs to hash all the calldata thrown in by the caller in the contract verification process to see if it can check the signature.
Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

In fact, the content of this signature is not yet conclusive: the more controversial ones are chainId and nonce. In fact, at the beginning, the authors wanted to remove everything, leaving only type, invoker, and commit, so that all the implementation space was left to different invoker contracts. But such a proposal is too risky to be fed back by core devs:

(1).关于chainId

No chainId may allow cross-chain retransmission attacks: if two EVM chains support EIP3074 at the same time, then there may be a user authorizing an invoker on the first chain, but the signature is taken to the other chain, and used in a contract with the same address but different implementations, then the user's assets on the second chain will be at risk.

Supplement: Theoretically, deploying Invoker with a CREATE2 deployer can solve this problem, because the main risk of this problem is that there can be different contracts for the same address on different chains. For example, if I use a simple private key to deploy a seemingly legitimate and decentralized invoker to the mainnet with an address of 0xaaabbb, I wait for everyone to sign the EIP3074 authorization, and then deploy an invoker on Arbitrum at the same 0xaaabbb address that can make any external calls without verification, then I, the bad guy, can steal your EOA control on the Arbitrum chain.

How to solve this problem with CREATE2 deployer, because CREATE2 Op code will force the same contract code and the same salt (random number) to be deployed in order to deploy the same address. Therefore, through the contract deployed by the general CREATE2 Deployer, you can trust that this address does not exist on other chains, and if it exists, the contract content must be the same as that of the mainnet.

这里列几个常见的CREATE2 Deployer,连接到他们的repo或是etherscan:

  • Seaport keyless CREATE2
  • Deterministic-deployment-proxy
  • Safe-singleton-factory

(2). About the nonce

The absence of nonce may allow the invoker to obtain irrevocable authorization: if an invoker forgets to implement the logic that the signature cannot be reused (replay protection) today, it is possible that the bad guy can use the same user to initiate multiple AUTHCALLS without limit. If this nonce verification is retained, the user can invalidate all signatures that are now outside at any time by initiating a normal transaction, roughly as follows:

Suppose an EOA is now 10 = > its owner can make a simple Ethereum transaction, for example, transfer to himself = > Ethereum record of the EOA nonce will increase 1 to 11 = > and then verify AUTHCALL will use nonce = 11 to verify the seal, resulting in the invalidation of the previous signature.

The question involved here is how much freedom and flexibility this EIP should give invoker: without the restriction of chainId, invoker can allow users to enjoy the function of "one signature, all EVM chains are upgraded" through multi-chain deployment, and without the restriction of nonce, it can make wallet design invoker and EOA can make transactions synchronously to achieve more automation.

These details are still being discussed, and in the current state of the proposal, the author (SamWilsn) actually prefers to open up the maximum degree of freedom, but the core dev's position is more inclined not to add too many attack vectors at once, so the nonce and chainId are currently temporarily added back to the information that needs to be signed.

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

The discussion is ongoing, so you can join the forum to have your say

Preventive implementation of retransmission attacks

Although it is stated above that the nonce of EOA transactions must be covered by the signature, this is only to ensure that "the user can 100% invalidate the EIP3074 signature", and there is no limit to how many times a signature can be used.

This is because when AUTH is used, it will check whether this nonce is equal to the user's current EOA transaction nonce, as long as it is the same, it will be given, but it will not change the EOA nonce, so a signature can be verified by AUTH several times.

Invoker is obliged to implement some logic to prevent resend attacks, but there are many variations, such as making a nonce system like Uniswap Permit2, not using increments to ensure that multiple transactions can be sent in parallel, batch cancellations, etc.

Risks and common misconceptions

The following is a list of common misconceptions about this EIP:

1. EIP3074 made phishing scams easier?

With this EIP, the smart contract does have the ability to gain control of the EOA through a signature. But as mentioned earlier, the invoker should have a binding relationship with the wallet, and the wallet should reject all requests for signatures from unknown EIP3074.

Since each different signature has a different prefix, all wallets on the market will reject the EIP3074 proxy signature by default, so don't worry that your wallet does not support you to be scammed. (Nor does any wallet support blind signing of unknown transaction formats with a private key.) )

In addition to the fact that the wallet side needs to actively enable this feature, you don't expect the wallet to accept a website to "ask for a signature EIP3074" signature, because as mentioned above, this is not something that a normal DAPP would ask the wallet to do, so we can expect the wallet to only allow their own authenticated Invokers.

The difference between this and phishing websites is that wallets are expected to receive transaction requests from websites (Dapps), so phishing websites trick you into clicking buttons to send "malicious transaction requests" to the wallet, and if the wallet does not have good precautions, you may click to sign the transaction. The EIP 3074 signature is in a completely different form, and there is no reason for the wallet to allow the "escrow private key requirement" from the website, so there is no need to worry that your wallet will not be detected.

Here is the response of one of the authors, lightclient, to this problem.

Although in theory wallets should not enable the custom invoker function, it is possible that some wallets offer this advanced option in order to give users maximum freedom. If there is such a wallet, then there may be a phishing-like attack: for example, they make a cool website that tells you what you can do when you join Invoker, and trick users into signing up for some warnings from the wallet.

2. Wallet control that cannot be taken back

Someone wrote in the introduction to the EIP3074 that this could result in a single authorization that the user could not revoke, resulting in a loss of all control. This is also not true, in the current EIP, because the signature content is nonce, any user can send a transaction to invalidate the signed signature.

If the nonce is not included in the required signature format, this situation is still established in the case of "contract loopholes". In general contract implementation, nullifying a nonce is a simple one-step feature, and there are countless proven implementations where the chance of error is low unless a malicious invoker is encountered.

I think discussing this risk (or a similar multi-chain resend attack) is like discussing "the contract wallet could make you lose control permanently", and it's talking about the risk of a bug in the contract, which is not too difficult to guard against given the complexity of the issue.

Potential risks

I don't think the two points mentioned above: malicious invoker phishing sites, and permanent loss of control caused by bugs, are not feasible attacks. However, this EIP does still bring risks, and I think the greater risk will be in the attack on hardware wallets.

Software wallets have always had great risks: if you download a fake software wallet and deposit the private key into it, then your money will disappear directly, so everyone has a relatively high awareness of information security for software wallet apps. But hardware wallets used to be relatively secure, and as long as your hardware didn't drop, it was basically impossible for someone to read your private keys from them.

However, if there is an open-source hardware wallet that supports EIP3074 signature, it cannot be ruled out that someone will make some new apps, also pick up the hardware wallet, and promote it to users (for example, make a mobile app that can be used with Ledger). These malicious wallet apps can then trick you into signing a signature to gain control of your private keys. Of course, this premise is also to convince you that this new wallet app is real, but if they play the slogan of "working with established hardware wallets", many users may ignore this risk. Or in the future, more scams will try to attack the wallet app DNS, trick you into downloading fake Ledger apps, etc., which can be used to steal control of the private keys of existing hardware wallet users.

In general, as long as you continue to remember to choose your wallet carefully (whether it is software or hardware), you will not have the above problems. When the wallet launches a new Invoker function, remember to review the Invoker with the security indicators of "Review Contract Wallet", which can also effectively avoid some problems caused by bugs.

Revolutionize your application

Here are a few apps that I find interesting and worth looking forward to:

(1) Old address airdrop pick-up:

Now if you have an old address that receives an airdrop, you need to transfer some ETH back to be gas, and then transfer it out after receiving the airdrop, if you have a EIP3074, you can use the airdrop to pay the handling fee, directly sign to receive the airdrop, pay and transfer to the new address. Or some leftover ERC20 in old wallets can also be used to pay transaction fees.

(2) Sign the transaction to ENS:

In the past, the EOA transaction format was to sign and transfer to an address, but in the future, users can sign "which ENS to transfer to", and then transfer through invoker to parse the address, greatly increasing the UX of the transfer.

(3) Signed transactions with expiration dates:

There is no such parameter as the expiration date of the previous transaction content, if you have not been confirmed after signing out, you must cancel it manually after repenting, otherwise he will always be in the pending state. With Invoker, we can easily add the restriction of "invalid if the time is exceeded", and simply create a transaction format with an expiration date.

(4) More diverse wallet agents:

We can have more "proxy wallet" gameplay, and even increase the security of the wallet: use cold wallets to authorize different addresses, and specify that each address can only do specific transactions with different expiration times, for example: authorizing my metamask address once a month with a cold wallet can initiate up to 10 Uniswap transactions for me. In this way, we can have more flexibility in the security level of the "private key", and we will no longer be limited by the restriction that "different private keys cannot manage the same asset".

Resolve the EIP3074 included in the Prague upgrade: use cases, impacts, and risks

EIP3074 the future is promising!

The changes that could be made

I think there are several changes that may be brought to the overall market from a macro perspective:

1. The wallet is more differentiated and the user stickiness is higher

In the past, when I made a wallet, the most common thing I thought about was how to retain users: after all, everyone saved their own private keys, and they wanted to change to other wallets at any time, as long as they downloaded, installed, and imported the private keys, they would move immediately. Because what everyone can do is much the same, which is to send a transaction.

In the future, after the EIP3074, the UX of each EVM wallet may be more and more different: some may simply support ERC20 payment fees, and more advanced ones will have the aforementioned agents, subscription-based fees, batch transactions for all users, and so on. These will cause the gap between good wallets and ordinary wallets to be magnified, and will also increase the stickiness of users.

2. The wallet side may have more power (transaction ordering power)

In the future, there may be more competition in the area where wallets arrange orderflow for users. More and more users will be accustomed to delegate the steps of the real "send out transaction" to the wallet, and the wallet side can also make "only I can proxy the on-chain" transaction through invoker, compared to the traditional transactions that everyone (MEV searcher) can sort arbitrarily after exposing the mempool, the wallet side may also have an incentive to limit the order of these transactions and make a profit.

3. General contracts can return to a more basic design process

In the past, in order to improve UX, permit, multicall, meta-transaction, wrap ETH, etc. would be considered in the contract design. I've always hoped that the AA era will come soon, because I think that if these things don't need to be considered at the protocol layer, they can reduce a lot of security concerns, such as completely letting the wallet handle Wrap ETH can ensure that a protocol doesn't need to consider ETH transfer and re-entry risks at all. I think we can expect to see existing wallet providers such as Metamsk and Rabby immediately invest in the development of invoker, which greatly increases the opportunity to popularize batch transactions, and if batch transactions become popular in the future, it can save a lot of contract optimization in this area. (Don't inherit everyone's contract, MultiCall also helps save space for the entire network!)

4. Impact on the use of msg.sender and tx.origin in the contract

The last one is a more detailed topic related to contract developers.

Contracts often use msg.sender == tx.origin to do different restrictions. After the EIP3074, the user can bypass this check with a special EIP3074 transaction: the person who originally sent the transaction (tx.origin) can do AUTHCALL through a relay contract with his own signature, so that he can make an AUTHCALL from the relay contract and still meet the conditions of msg.sender == tx.origin.

Most contracts use msg.sender == tx.origin to check to ensure that msg.sender is EOA, so as not to trigger a re-entrancy attack when sending ETH back. This feature remains the same, because tx.origin must be an EOA, and msg.sender will also point to the original initiator, so you don't have to worry about accidentally interacting with the relay contract and causing unintended consequences.

However, this EIP will still affect some usecases, such as using tx.origin == msg.sender to prevent "the contract from controlling the behavior of subsequent transactions according to the state of one transaction". For example, if someone uses a contract mint NFT, as long as they do not succeed in mint the desired NFT, they will revert the entire transaction. But this usecase can actually be cracked through MEV and other methods by cooperating with the builder, so it is already an ineffective protection, and the impact is not great.

Another usecase that will be affected is to use the same conditions to prevent flashloans. In the past, if there was a contract that the user did not want to use through flashloan, you could use tx.origin == msg.sender to make sure that the person who came did not borrow money through flashloan. Now the initiator can borrow money from the flashloan and call AUTHCALL through the relay contract, which looks like msg.sender is actually using the contract with a large sum of money to the protocol party.

Theoretically, a good contract should not use tx.origin to make any judgments, as this will ruin the experience of AA wallets or meta-transactions, and using tx.origin has been widely promoted as bad practice. Therefore, although this EIP breaks some use cases, it does not have much impact on the whole.

epilogue

I'm looking forward to the next upgrade, after all, AA has been talking about it for so long, and I really see that there are only a handful of wallets that make abstract accounts, and I haven't waited for a large number of upgrades from EOA to contract wallets.

I think EIP3074 gives all wallet developers a lot of room for upgrades, because they can bring a big upgrade to users almost painlessly (without migration). I'm really looking forward to what new ways each wallet provider can come up with when it is really launched, and here is also a small wish, and finally EIP can enter the hard fork without restricting the freedom of nonce and chainId, so that there are more cross-chain wallets and other functions to look forward to.