EIP-5806 Delegate transaction

Obviously, choices like that are opinionated, but IMHO the fewer edge cases we have on the execution layer, the better. I am unsure of any good use cases for EOA’s CREATE2…

Also, noticed a separate thing: in EIP3074 there is the following disclaimer about sending value from users’ account: EIP-3074: AUTH and AUTHCALL opcodes.

Does it apply to EIP5086 as well?

And Create and create2 can be encapsulated by a deployer contract like


contract Deployer {
    function deploy(bytes memory bytecode) external payable returns (address addr) {
        assembly {
            addr := create(callvalue(), add(bytecode, 0x20), mload(bytecode))
        }
    }
    
    function deploy2(bytes memory bytecode, bytes32 salt) external payable returns (address addr) {
        assembly {
            addr := create2(callvalue(), add(bytecode, 0x20), mload(bytecode), salt)
        }
    }
}

I liked the fundamental idea of having the EOA being the “sender” used to compute the create2 address, but I agree the fewer edge cases the better. So I added create2 to the restricted opcodes.

As @RenanSouza2 pointed out, an EOA call use 5806 to batch calls to 0x4e59b44847b379578588920cA78FbF26c0B4956C, wich is probably sufficient for any usecase.

I think in the case of 5806 its much simpler. There is no invoker, and no authcall. The EOA “delegates” into a piece of logic (contract onchain). If that piece of logic does any call tat contain value, the value is taken from the caller, in that case the EOA. There is no special/edge case.

There is an interresting point about the available balance. My understanding is that when the transaction is being verified the maximum gas cost of the transaction is substracted BEFORE the execution happens. So the execution consider the worst case where all the gas is going to be consumed. Then after the execution, the gas that is not used is refunded.
If that is correct, then there should be no issue with the execution potentially draining the EOA’s balance. If that was to happen, the gas cost are already covered. After the execution, the EOA would have “dust” corresponding to the gas that was not used.

From the EIP3074:

  • Similarly, miners rely on the ability to statically pick a set of valid transactions from their transaction pool to include into a new block. Deducting value from the authorized account would break this ability, increasing the overhead and thus the time for block creation.

This thing will break, since the contract we delegate to may arbitrarily send value from the EOA.

In other words, to know whether X is valid, right now you only need to look onto the pending txs, take the sum of their fees and tx.value, and if the balance is enough after deducting those. Now, however a tx with nonce X could invalidate txs with nonce X+1 because the tx with nonce X could spend balance out of the name of the account.

Practically this means that no sorts of nonce gaps can be allowed with this EIP.

That is why all nonce-changing opcodes are restricted and cannot be called by the EOA. This includes create, create2 and selfdestruct.

For anyone interrested, I compiled some links to follow the implementation effort here:

(also include a test project to run against a node)

neat EIP! i was thinking of drafting something similar but then someone pointed me to this. one modification i would like to suggest is allowing to: nil, this would run the code in the calldata (similar to running a create tx, delegatecalling to the created contract and then destroying the contract) but without multiple steps and also without state changes. this would allow users to run ad-hoc scripts. (in fact i think contracts should be able to do this as well, but maybe that’s a different discussion).

allowing execution of code would improve tooling UX considerably i think. for instance the following proposal for vyper could make executing a script as easy as copy-pasting the bytecode produced by the compiler for a script function: VIP: `__script__()` function · Issue #3712 · vyperlang/vyper · GitHub