--- eip: 101 title: Serenity Currency and Crypto Abstraction author: Vitalik Buterin status: Draft type: Standards Track category: Core created: 2015-11-15 --- ### Specification 1. Accounts now have only two fields in their RLP encoding: **code** and **storage**. 2. Ether is no longer stored in account objects directly; instead, at address `0`, we premine a contract which contains all ether holdings. The `eth.getBalance` command in web3 is remapped appropriately. 3. `msg.value` no longer exists as an opcode. 4. A transaction now only has four fields: **to**, **startgas**, **data** and **code**. 5. Aside from an RLP validity check, and checking that the **to** field is twenty bytes long, the **startgas** is an integer, and **code** is either empty or hashes to the **to** address, there are no other validity constraints; anything goes. However, the block gas limit remains, so miners are disincentivized from including junk. 6. Gas is charged for bytes in **code** at the same rate as **data**. 7. When a transaction is sent, if the receiving account does not yet exist, the account is created, and its code is set to the code provided in the transaction; otherwise the code is ignored. 8. A `tx.gas` opcode is added alongside the existing `msg.gas` at index `0x5c`; this new opcode allows the transaction to access the original amount of gas allotted for the transaction Note that `ECRECOVER`, sequence number/nonce incrementing and ether are now nowhere in the bottom-level spec (NOTE: ether is going to continue to have a privileged role in Casper PoS). To replicate existing functionality under the new model, we do the following. Simple user accounts can have the following default standardized code: ```python # We assume that data takes the following schema: # bytes 0-31: v (ECDSA sig) # bytes 32-63: r (ECDSA sig) # bytes 64-95: s (ECDSA sig) # bytes 96-127: sequence number (formerly called "nonce") # bytes 128-159: gasprice # bytes 172-191: to # bytes 192+: data # Get the hash for transaction signing ~mstore(0, msg.gas) ~calldatacopy(32, 96, ~calldatasize() - 96) h = sha3(96, ~calldatasize() - 96) # Call ECRECOVER contract to get the sender ~call(5000, 3, [h, ~calldataload(0), ~calldataload(32), ~calldataload(64)], 128, ref(addr), 32) # Check sender correctness assert addr == 0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1 # Check sequence number correctness assert ~calldataload(96) == self.storage[-1] # Increment sequence number self.storage[-1] += 1 # Make the sub-call and discard output ~call(msg.gas - 50000, ~calldataload(160), 192, ~calldatasize() - 192, 0, 0) # Pay for gas ~call(40000, 0, [SEND, block.coinbase, ~calldataload(128) * (tx.gas - msg.gas + 50000)], 96, 0, 0) ``` This essentially implements signature and nonce checking, and if both checks pass then it uses all remaining gas minus 50000 to send the actual desired call, and then finally pays for gas. Miners can follow the following algorithm upon receiving transactions: 1. Run the code for a maximum of 50000 gas, stopping if they see an operation or call that threatens to go over this limit 2. Upon seeing that operation, make sure that it leaves at last 50000 gas to spare (either by checking that the static gas consumption is small enough or by checking that it is a call with `msg.gas - 50000` as its gas limit parameter) 3. Pattern-match to make sure that gas payment code at the end is *exactly* the same as in the code above. This process ensures that miners *waste* at most 50000 gas before knowing whether or not it will be worth their while to include the transaction, and is also highly general so users can experiment with new cryptography (eg. ed25519, Lamport), ring signatures, quasi-native multisig, etc. Theoretically, one can even create an account for which the *valid signature* type is a valid Merkle branch of a receipt, creating a quasi-native alarm clock. If someone wants to send a transaction with nonzero value, instead of the current `msg.sender` approach, we compile into a three step process: 1. In the outer scope just before calling, call the ether contract to create a cheque for the desired amount 2. In the inner scope, if a contract uses the `msg.value` opcode anywhere in the function that is being called, then we have the contract cash out the cheque at the start of the function call and store the amount cashed out in a standardized address in memory 3. In the outer scope just after calling, send a message to the ether contract to disable the cheque if it has not yet been cashed ### Rationale This allows for a large increase in generality, particularly in a few areas: 1. Cryptographic algorithms used to secure accounts (we could reasonably say that Ethereum is quantum-safe, as one is perfectly free to secure one's account with Lamport signatures). The nonce-incrementing approach is now also open to revision on the part of account holders, allowing for experimentation in k-parallelizable nonce techniques, UTXO schemes, etc. 2. Moving ether up a level of abstraction, with the particular benefit of allowing ether and sub-tokens to be treated similarly by contracts 3. Reducing the level of indirection required for custom-policy accounts such as multisigs It also substantially simplifies and *purifies* the underlying Ethereum protocol, reducing the minimal consensus implementation complexity. ### Implementation Coming soon.