diff --git a/packages/protocol/contracts/L1/libs/LibProposing.sol b/packages/protocol/contracts/L1/libs/LibProposing.sol index 1f31c8fe478..ef9832df312 100644 --- a/packages/protocol/contracts/L1/libs/LibProposing.sol +++ b/packages/protocol/contracts/L1/libs/LibProposing.sol @@ -141,16 +141,20 @@ library LibProposing { // - 1x state.taikoTokenBalances[addr] uint256 could theoretically // store the whole token supply unchecked { + // Calculate the time elapsed since the last block was proposed uint256 blockTime = block.timestamp - state.blocks[(b.numBlocks - 1) % config.blockRingBufferSize] .proposedAt; + // Reward only the first proposer in an L1 block. Subsequent + // proposeBlock transactions in the same L1 block will have + // blockTime as 0, and receive no reward if (blockTime > 0) { reward = (config.proposerRewardPerSecond * blockTime).min( config.proposerRewardMax ); - // Reward must be minted + // Reward the proposer TaikoToken(resolver.resolve("taiko_token", false)).mint( input.proposer, reward ); diff --git a/packages/website/pages/docs/concepts/proposing.mdx b/packages/website/pages/docs/concepts/proposing.mdx index a01b5593ae5..c798df602a7 100644 --- a/packages/website/pages/docs/concepts/proposing.mdx +++ b/packages/website/pages/docs/concepts/proposing.mdx @@ -41,3 +41,15 @@ The anchor transaction is required to be the first transaction in a Taiko block 1. Persisting `l1Height`, `l1Hash` and `l1SignalRoot` to the storage trie. These values can be used by bridges to validate cross-chain messages. 2. Ensuring that the previous 256 block hashes that are exposed to the EVM are correct. 3. Calculating the EIP-1559 `basefee` which will be used on L2. + +## How does the proposer earn Ether + +When the block is proposed, the TaikoL1 contract will set some L2 block metadata such as `meta.coinbase`, which is the sender of the proposeBlock() tx. When the L2 client builds the L2 block, it will set the `block.coinbase` to this `meta.coinbase` specified for the block on L1. The validity proof (ZKP) for this block must check that the `block.coinbase` is indeed the `meta.coinbase` recorded on L1. + +When the ZKP instance is returned from the `TaikoL1` contract with `getInstance()`, the `evidence.metaHash` for the proposed block is included. This is how the ZKP verifier can check that the L2's `block.coinbase` (and other block-level variables as well) are correctly set to what is specified in the metadata on L1. + +## How does the proposer earn TKO + +The first proposeBlock tx in the enclosing L1 block will earn the TKO reward. The proposer will receive either the maximum reward (specified in the L1 config), or the reward per second (also specified in the L1 config as well) times the block time, whichever is smaller. + +> Note: This is a temporary solution which may change soon, as we see an issue that can arise where the proposer will submit empty blocks to earn the reward. Check the comments in `LibProposing.sol:proposeBlock` for the latest design.