EIP-6968: Contract Secured Revenue on an EVM based L2
Contract Secured Revenue on an EVM based L2
Abstract
Contract Secured Revenue (CSR) allows smart contract developers to claim a percentage of all transaction fees paid by users when interacting with their smart contracts.
This EIP proposes the introduction of CSR on EVM-based L2s which would provide smart contract developers who deploy on L2s access to revenue streams and/or public goods.
Motivation
Using protocol rewards of an L1 to fund smart contract development would be a big change to the way the current market works. This EIP does not advocate for any changes to the existing Ethereum L1.
This EIP does advocate that L2s could begin to experiment with Contract Secured Revenue as a means of:
- creating a new revenue stream for smart contract developers
- creating a new way of funding public goods
- creating incentives for developers to deploy their dapps on your network
Specification
Parameters
Constant | Value |
---|---|
REVENUE_SHARE_QUOTIENT | 5 |
Fee Mechanism
The current EIP-1559 fee behavior is modified so that header.base_fee_per_gas * REVENUE_SHARE_QUOTIENT
per gas is reallocated proportionally, based on gas used, to each contract executed during the transaction.
Implicitly, this means that no fees are redistributed to externally owned accounts (EOA).
Gas Tracking
In order to fairly distribute the fee revenue, a new transaction-wide gas tracker is defined.
When executing a block, maintain a mapping gas_used_by_address
of address
to uint64
. This will track the amount of gas used by each address. For every EVM instruction that does not instantiate a new execution frame (e.g. CALL
, CALLCODE
, DELEGATECALL
, STATICCALL
, CREATE
, and CREATE2
), add the cost of the instruction to the address' current sum in the mapping.
For EVM instructions which do instantiate new frames, greater care must be taken to determine the cost of the instruction to the calling frame. For simplicity, this cost is defined to be the total cost of the operation minus the amount of gas passed to the child frame. The gas passed to the child frame is determined via EIP-150. The computed cost is added to the address' current sum in the mapping.
Additionally:
- If the address does not exist in the mapping, it's total gas used is
0
. - If the instructions throws an out-of-gas (OOG) error, all remaining gas allocated to execution frame is added to the current total gas used by the address.
- No other exceptional halt adds remaining gas to the counter for the address where the halt occurred.
Setting Revenue Recipient
Revenue recipients are tracked via a new transaction wide mapping revenue_recipient
of address
to address
. The default value for every key is the key itself. For example, unless set otherwise, the key 0xdead...beef
maps to the value 0xdead...beef
.
To set a different revenue recipient, a new instruction SETREVENUERECIPIENT
is introduced with the opcode 0x49
. The operation takes 1
stack element as input and outputs 0
stack elements.
The 20
least significant bytes of the input stack element is the address of the new revenue recipient for the instruction's caller. The revenue_recipient
entry is updated to reflect this.
The instruction costs 3
gas.
Dispersing Revenue
After a transaction completes, for every element (addr
, gas_used
) in gas_used_by_address
, increase the balance of revenue_recipient[addr]
by gas_used * (header.base_fee_per_gas // REVENUE_SHARE_QUOTIENT)
Rationale
Tracking Gas Proportionally
A simpler mechanism would be to send the full transaction revenue to the to
value of the transaction. This, however, does not accurately reward the composition of many different smart contracts and applications. Additionally, it is not compatible with smart contract wallets which, by definition, are often the first destination of a transaction.
Maintaining a transaction wide tracker of gas uses makes it possible to distribute revenue to contracts which are genuinely the most utilized.
Ephemeral Revenue Recipient Mapping
Constructing the revenue recipient mapping ephemerally during each transaction appears inefficient on the surface. This value is expected to be relatively static and even if it did need to change, the change could be facilitated by the recipient contract.
Unfortunately such a change is much more invasive for the EVM. The recipient value would need to be stored somewhere. This would require a modification to the account structure in the state trie. Also, the recipient value would need to be set at some point. This would necessitate either a modification to the CREATE*
opcodes or a new opcode, similar to SETREVENUERECIPIENT
, that would be called by initcode to "initialize" the recipient value.
Security Considerations
Increased Max Block Size/Complexity
Similar to EIP-1559, we must consider the effects this will have on block size. Depending on the method by which this is implemented, it could increase maximum block size in the event that a significant number of contracts opt-in to CSR.
Copyright
Copyright and related rights waived via CC0.