Skip to content
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

Add EIP: Set EOA account code for one transaction #8527

Merged
merged 7 commits into from
May 8, 2024
Merged

Conversation

vbuterin
Copy link
Contributor

@vbuterin vbuterin commented May 7, 2024

Add a new transaction type that adds a contract_code field and a signature, and converts the signing account (not necessarily the same as the tx.origin) into a smart contract wallet for the duration of that transaction. Intended to offer similar functionality to EIP-3074.

@vbuterin vbuterin requested a review from eth-bot as a code owner May 7, 2024 12:45
@github-actions github-actions bot added c-new Creates a brand new proposal s-draft This EIP is a Draft t-core labels May 7, 2024
@eth-bot
Copy link
Collaborator

eth-bot commented May 7, 2024

✅ All reviewers have approved.

@eth-bot eth-bot added e-consensus Waiting on editor consensus e-review Waiting on editor to review labels May 7, 2024
@eth-bot eth-bot changed the title EIP: Set EOA account code for one transaction Add EIP: Set EOA account code for one transaction May 7, 2024
rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, data, access_list, [[contract_code, y_parity, r, s], ...], signature_y_parity, signature_r, signature_s])
```

The intrinsic cost of the new transaction is inherited from [EIP-2930](./eip-2930.md), specifically `21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 * access list storage key count + 2400 * access list address count`. Additionally, we add a cost of `16 * non-zero calldata bytes + 4 * zero calldata bytes` over each `contract_code`, plus `PER_CONTRACT_CODE_BASE_COST` times the length of the `contract_code` array.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems expensive, can users not point to an already deployed contract and reduce data size of txn payload?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking is that that's what delegatecall forwarders are for. But happy to consider the direct-to-address option too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal proxy accounts have very little bytecode. Using ERC-1167 should be sufficient and keep this EIP lean


This EIP breaks the invariant that an account balance can only decrease as a result of transactions originating from that account. This has consequences for mempool design, and for other EIPs such as inclusion lists. However, these issues are common to any proposal that provides similar functionality, including EIP-3074.

## Security Considerations
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume it is, but just to confirm - this EIP doesn't allow storage modification of the EOA right?
e.g., SSTORE, etc

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


At the start of executing the transaction, for each `[contract_code, y_parity, r, s]` tuple:

1. Let `signer = ecrecover(keccak(MAGIC + contract_code), y_parity, r, s]`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that a signature is reusable and non revocable. That can then be reused and encapsulated into other transactions.
If the code is vulnerable (for any reason) the signer becomes vulnerable indefinitely

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Assuming 'MAGIC' is a constant value)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the code tuple contained the signer's nonce then the same revocation strategy as 3074 could be used. While that solves revocation, it's unclear to me if the tuples being reusable is a feature or a bug though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3074 includes the invokerAddress in the AUTH payload, so auth is only reusable by a single invoker, so perhaps the tuple also an address field to compare tx.origin against?

The [EIP-2718](./eip-2718.md) `TransactionPayload` for this transaction is

```
rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, data, access_list, [[contract_code, y_parity, r, s], ...], signature_y_parity, signature_r, signature_s])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A small suggestion: when y_parity is 0 or 1, it's a temporary setting code. When it's 2 or 3, it's secp256r1 and a permanent setting code. When it's 4 or 5, it's secp256k1 and a permanent setting code (currently not supported).

Your idea is very similar to mine, but you chose the tx type, so there's no need to add an opcode.
https://github.com/ethereum/EIPs/pull/8493/files

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a new field, don't overload yParity. We don't need more obscure parsing rules.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. If EIP7702 has already been implemented, the cost of adding a new algorithm isn't high.

  2. The risk of permanently upgrading an EOA to a CA is significant (as EOAs carry historical baggage), but addresses generated by algorithms like secp256r1 are not EOAs, so permanently setting code carries no additional risk.

  3. People need a more stable way to ensure deterministic deployments.

  4. Better backward compatibility: When temporary code setting is prohibited and only permanent code setting is allowed, simply reject that type and enable a new type.

  5. Prevent user errors: In the past, Ethereum used block heights to determine certain code behaviors, which wasn't user-friendly. We should directly reject user requests via a flag since upgrading an EOA to a CA is risky.

Copy link

@txgyy txgyy May 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a new field, don't overload yParity. We don't need more obscure parsing rules.

Yeah, a new flag like this:
0x00: Temporary upgrade And secp256k1
0x10: Permanent upgrade And secp256k1
0x01: Temporary upgrade And secp256r1
0x11: Permanent upgrade And secp256r1
...

3. Set the contract code of `signer` to `contract_code`.

At the end of the transaction, set the `contract_code` of each `signer` back to empty.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I presume during transaction execution the EXTCODEHASH will return the contract_code, right?

@petejkim
Copy link
Contributor

petejkim commented May 7, 2024

Is it intended that the [contract_code, y_parity, r, s] be reusable or replayable indefinitely? Please correct me if I am wrong, but as it stands, I don't see a way to limit replayability.

I am asking because this was a huge point of contention for 3074, and many claimed contracts cannot be trusted to do the right thing, which led to the introduction of the nonce concept in 3074. (I don't agree that signing over the account's nonce is necessary btw)

@AmadiMichael
Copy link

Nice proposals. I've a few questions though

  • is contract_code a runtime or creation code?
  • What happens gas wise if contract_code executes selfdestruct?

@lightclient
Copy link
Member

just want to remind everyone this PR is going to be merged shortly so the discussion should continue on in the discussions-to link https://ethereum-magicians.org/t/eip-set-eoa-account-code-for-one-transaction/19923

At the end of the transaction, set the `contract_code` of each `signer` back to empty.

Note that the signer of any of the `contract_code` signatures, and the `tx.origin` of the transaction, are allowed to be different.

Copy link
Contributor

@Amxx Amxx May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Opcode restriction
For security reasons, some opcodes MUST not be executed in the context of an EOA:
- `SSTORE` (0x55): Setting storage under an EOA breaks common assumptions. Conflits could arise from a single EOA using multiple code vertsion (in multiple transactions) that interpret the storage layout under the account differently. Therefore, EOAs should be forbiden from performing `SSTORE` if the code is to be cleared at the end of the transaction. Any CALL performed by the code placed at the EOA's address is free to manipulate storage normally.
- `CREATE` (0xF0), `CREATE2` (0xF5) and `SELFDESTRUCT` (0xFF): There may be an expectation that transactions from a given sender should have consecutive nonces. This assumption would be broken if code placed at an EOA's address was to execute one or multiple operations that alter the sender account's nonce. Consequently, EOA performing a delegate transaction should not be able to use the `CREATE`, `CREATE2` or `SELFDESTRUCT` opcodes. Any CALL performed by the code placed at the EOA's address is free to create contracts normally.
Any attempts to execute one of these restricted operations in the context of one of the signers MUST throw an exception.
This restrictions only apply if the code placed at the signer's address is removed at the end of the transaction. If a flag is set to not set the code back to empty at the end of the transactions, then these restrictions do not apply.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with restricting CREATE, CREATE2 and SELFDESTRUCT but not sure what harm SSTORE poses. While the code stored at the address is deleted, all written storage slots can be cleared alongside it, that way it isn't persisted across different transactions.

I'd argue that the gas cost of SSTORE and SLOAD be the same as that of TLOAD and TSTORE since they'd behave exactly the same way in this scenario.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to be able to SSTORE.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also want to use storage, but that would be breaking invariants specified in other EIP

There is a restriction that account with no code should have no storage. If someone can find a référénce that would be great.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but I think if all written slots are cleared at the end of the transaction it doesn't break any invariants.

During the transaction it doesn't break any invariants too since if the code length, code or codehash is queried, it returns a non-default value.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a restriction that account with no code should have no storage. If someone can find a référénce that would be great.

Not so sure about this because a contract that sets storage at initialization but also returns 0 bytes at initialization has no bytecode but has > 0 storage slots set.

See here: https://twitter.com/AmadiMichaels/status/1641918500020137984?t=sy3aLWqR4we0tuA_kXV20w&s=19

Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>
At the start of executing the transaction, for each `[contract_code, y_parity, r, s]` tuple:

1. Let `signer = ecrecover(keccak(MAGIC + contract_code), y_parity, r, s]`.
2. Verify that the contract code of `signer` is empty.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is important to mention that the outcome of this "verification" is only whether the signer's code is set.
That is: if the ecrecover succeeds (doesn't return zero), AND the returned signer address doesn't have code, only then its code is set to contract_code.
In any other circumstance, it is left unmodified.

Copy link
Contributor

@g11tech g11tech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@eth-bot eth-bot enabled auto-merge (squash) May 8, 2024 17:38
Copy link
Collaborator

@eth-bot eth-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All Reviewers Have Approved; Performing Automatic Merge...

@eth-bot eth-bot merged commit e6ad402 into master May 8, 2024
11 checks passed
@eth-bot eth-bot deleted the vbuterin-patch-1 branch May 8, 2024 17:38
Copy link

@sriharikapu sriharikapu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats more elaborate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c-new Creates a brand new proposal e-consensus Waiting on editor consensus e-review Waiting on editor to review s-draft This EIP is a Draft t-core
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet