EIP-3074: AUTH and AUTHCALL opcodes

Whoops…I forgot one question: do you think that EIP-3074 could possibly be compatible with a batching implementation found in a L2, like the Optimism sequencer?

L2s have more flexibility, so they can define their accounts to have arbitrary functionality. But yes, it would be compatible.

I still think there is different way of thinking about contract wallet accounts that benefits significantly from EIP-3074 and L2s could support something similar, even if EIP-3074 doesn’t reach mainnet.

I agree wholeheartedly. In addition to a new paradigm for account management, an Invoker instance from EIP-3074 could be a foundation for organizations and enterprises to build upon. If the Invoker proved to be a stable, safe platform by itself that could control an account through a set of dispatched rules (which are predefined simple actions), then their investment into contract creation (of developing, of auditing, of deploying, etc.) becomes unnecessary as they would just deploy their strategies to the Invoker, accelerating the buy-in of the mainstream.

Unfortunately, mainnet acceptance will probably be difficult to achieve. Do you think that Optimism would be curious to consider 3074 and test the new opcodes in the OVM?

Created a small website that I’ll slowly add educational materials about how EIP-3074 can improve day-to-day lives. Currently just showcasing how much has been spent on approvals.

https://www.approvals.wtf/

1 Like

I have a question about this EIP, especially this line in the Behavior section:

  • If the gas available for the subcall would be less than gas, execution is invalid.

In Frontier, we had this rule also for CALL and CALLDATA but in EIP150 this was removed: the reason was that contracts (in most cases) used something like PUSH 23 GAS SUB CALL, where 23 here is the gas cost of CALL plus the cost of SUB (this thus relies all GAS to the call frame). The problem is, that if you increase the base cost of CALL, this mechanism breaks. This EIP is thus also subject to this case, if we ever change AUTHCALL costs then some contracts will break.

I don’t understand the rationale for it. The contract itself can check if there is enough gas left (can also be put in the commit, for instance). If there is not enough gas left, then revert the frame. I would suggest to use the rule from EIP150: if the GAS wants to send more GAS than currently is left, then send 63/64 of the available gas. Any safety checks can be handled by the contract implementation itself.

An idea was posted to replace WETH with a mapping using EIP-3074:

This would require the “Ether transfer” functionality to be enabled in EIP-3074.

We are working on a draft implementation at EthereumJS/VM: Implement EIP3074: AUTHCALL by jochem-brouwer · Pull Request #1788 · ethereumjs/ethereumjs-monorepo · GitHub

The EIP is really well written, I have not yet encountered any edge cases which are not covered by the spec (but might do so when writing tests).

2 Likes

Yes, a small thing:

Note that yParity is expected to be 0 or 1.

I think we should enforce this, so if yParity is not 0 and also not 1 then the operation is invalid, throw and consume all gas. (Maybe this is meant by this sentence already)

2 Likes

We have implemented the EIP in EthereumJS/VM: Implement EIP3074: Authcall by jochem-brouwer · Pull Request #1789 · ethereumjs/ethereumjs-monorepo · GitHub (it is targeted towards a develop branch so it will take some time to start using it directly from npm).

There is one more question I have which is not stated in the EIP. In case we are in a STATICCALL frame, are we allowed to AUTHCALL? Following EIP-214 logic it should throw if either value or valueExt is nonzero, but if both are zero, it should be allowed. Can this be specified in the EIP?

I believe it must throw the same way as CALL, since it’s defined as a list of changes:

AUTHCALL is interpreted the same as CALL, except […]

1 Like

Put up a change to auth to make it more future compatible. Comments welcome!

Had an interesting discussion today where it might be theoretically possible to create a single “meta-invoker” that enforces replay protection/revocable signatures/etc, which then delegate calls into app-specific “sub-invokers”. If that ends up being possible, the whitelisting process would only need to approve the one “meta-invoker” to cover 90% of use cases.

1 Like

This is now merged. Instead of pushing everything on the stack, auth now takes an address and a memory range.

Currently the memory range contains the commit and signature, and the address from the stack must match the address recovered from the signature.

In the future, should EIP-3074 get merged, auth can be modified to work with EOAs and smart contract wallets!

In the current EVM, tx.origin is the account from which the transaction originates (logically, the account “doing the thing”) as well as the account that pays the gas to execute the tx. They are synonymous.

With EIP-3074, this is no longer the case; these identities get split up: The logical originating account account “doing the thing” is the AUTH’d account, but the account paying the gas to initiate the transaction is the account making the AUTHCALL to remote control the AUTH’d account into “doing the thing”.

I think (correct me if I’m wrong), your implementation leaves tx.origin as the account paying the gas where I believe tx.origin should be the AUTH’d account performing, in spirit, the action.

I’m not sure if this is the proper venue to discuss, but what are your (and others’) thoughts on which account should be tx.origin… the account paying the gas or the account logically originating the action/“doing the thing”?

Edit: Way out of my depth, but what about a new “tx.gaspayer” identity to distinguish the two?

1 Like

That is correct.

I’m mostly indifferent to what tx.origin represents. I think there are arguments for it to be the “gas payer”, or the “first actor”, or just an alias to msg.sender. If we set tx.origin to authorized when AUTHCALLing, it would certainly make it harder to distinguish smart contract wallets from EOAs, which I suppose I support.

3 Likes

On balance, what msg.sender/tx.origin/gaspayer scheme do you (or anyone reading this) think makes the most sense in a post-merge, 3074-adopted world?

I’d love to see tx.origin aliased to msg.sender, personally. Elegant. Simple. Not sure how realistic.

1 Like

Seems like there are two implementations of this so far: quilt go-ethereum (adeitrichs) and ethereumjs (brouwer)

Are we aware of any others? Is there some common location (aside from this thread) for implementation writers to report their work on 3074?

Can my suggestion for setting tx.origin to the account being remote-controlled, not the gas payer, be added to the EIP?

I’m worried that adding an even more controversial change to the EIP will make it even less likely to be adopted.

Once the merge is complete, I think we can reopen the discussion with core devs and see where we stand?

1 Like

But it sounds like such a change is not controversial; more that nobody really seems to have an opinion one way or the other.

In this way, it’s more controversial not to make the change, isn’t it? Because I do have a very strong opinion on it.

Once the merge is complete, I think we can reopen the discussion with core devs and see where we stand?

Yes, I plan to voice my concern with the core devs group whenever it’s appropriate. Thanks for the reply.

From a perspective of secure contract design, I think having a shortcut for “remove authorisation” (= clear authorisation context) would be a nice addition, even at the expense of an extra opcode.

This can be current accomplished by sending “rubbish” to the AUTH instruction. Would auth(0, 0, 0) do the trick? The spec seems lenient at invalid input lengths.