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

refactor(protocol): apply multiple improvements based on feedback from Open Zeppelin #18305

Merged
merged 16 commits into from
Oct 25, 2024
13 changes: 13 additions & 0 deletions packages/protocol/contracts/layer1/based/LibBonds.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ import "./TaikoData.sol";
/// @notice A library that offers helper functions to handle bonds.
/// @custom:security-contact [email protected]
library LibBonds {
/// @dev Emitted when tokens are deposited into a user's bond balance.
/// @param user The address of the user who deposited the tokens.
/// @param amount The amount of tokens deposited.
event BondDeposited(address indexed user, uint256 amount);

/// @dev Emitted when tokens are withdrawn from a user's bond balance.
/// @param user The address of the user who withdrew the tokens.
/// @param amount The amount of tokens withdrawn.
event BondWithdrawn(address indexed user, uint256 amount);

/// @dev Emitted when a token is credited back to a user's bond balance.
/// @param user The address of the user whose bond balance is credited.
/// @param blockId The ID of the block to credit for.
Expand All @@ -34,6 +44,7 @@ library LibBonds {
)
internal
{
emit BondDeposited(msg.sender, _amount);
_state.bondBalance[msg.sender] += _amount;
_tko(_resolver).transferFrom(msg.sender, address(this), _amount);
}
Expand All @@ -49,6 +60,7 @@ library LibBonds {
)
internal
{
emit BondWithdrawn(msg.sender, _amount);
_state.bondBalance[msg.sender] -= _amount;
_tko(_resolver).transfer(msg.sender, _amount);
}
Expand Down Expand Up @@ -76,6 +88,7 @@ library LibBonds {
_state.bondBalance[_user] = balance - _amount;
}
} else {
emit BondDeposited(msg.sender, _amount);
_tko(_resolver).transferFrom(_user, address(this), _amount);
}
emit BondDebited(_user, _blockId, _amount);
Expand Down
4 changes: 2 additions & 2 deletions packages/protocol/contracts/layer1/based/LibData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "./TaikoData.sol";
/// @notice A library that offers helper functions.
/// @custom:security-contact [email protected]
library LibData {
function blockV2toV1(TaikoData.BlockV2 memory _v2)
function blockV2ToV1(TaikoData.BlockV2 memory _v2)
internal
pure
returns (TaikoData.Block memory)
Expand All @@ -25,7 +25,7 @@ library LibData {
});
}

function verifierContextV2toV1(IVerifier.ContextV2 memory _v2)
function verifierContextV2ToV1(IVerifier.ContextV2 memory _v2)
internal
pure
returns (IVerifier.Context memory)
Expand Down
10 changes: 6 additions & 4 deletions packages/protocol/contracts/layer1/based/LibProposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import "./LibVerifying.sol";
library LibProposing {
using LibAddress for address;

uint256 internal constant SECONDS_PER_BLOCK = 12;

struct Local {
TaikoData.SlotB b;
TaikoData.BlockParamsV2 params;
Expand Down Expand Up @@ -177,8 +179,8 @@ library LibProposing {
// The other constraint is that the timestamp needs to be larger than or equal the
// one in the previous L2 block.
if (
local.params.timestamp + _config.maxAnchorHeightOffset * 12 < block.timestamp
|| local.params.timestamp > block.timestamp
local.params.timestamp + _config.maxAnchorHeightOffset * SECONDS_PER_BLOCK
< block.timestamp || local.params.timestamp > block.timestamp
|| local.params.timestamp < parentBlk.proposedAt
) {
revert L1_INVALID_TIMESTAMP();
Expand All @@ -200,8 +202,8 @@ library LibProposing {
anchorBlockHash: blockhash(local.params.anchorBlockId),
difficulty: keccak256(abi.encode("TAIKO_DIFFICULTY", local.b.numBlocks)),
blobHash: 0, // to be initialized below
// To make sure each L2 block can be exexucated deterministiclly by the client
// without referering to its metadata on Ethereum, we need to encode
// To ensure each L2 block is executed deterministically by the client
// without needing to reference its metadata on Ethereum, it's essential to encode
// config.sharingPctg into the extraData.
extraData: _encodeBaseFeeConfig(_config.baseFeeConfig),
coinbase: local.params.coinbase,
Expand Down
5 changes: 2 additions & 3 deletions packages/protocol/contracts/layer1/based/LibProving.sol
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ library LibProving {
if (_batchProof.tier == 0) {
// In the case of per-transition proof, we verify the proof.
IVerifier(_resolver.resolve(local.tier.verifierName, false)).verifyProof(
LibData.verifierContextV2toV1(ctx_), ctx_.tran, local.proof
LibData.verifierContextV2ToV1(ctx_), ctx_.tran, local.proof
);
}
}
Expand Down Expand Up @@ -368,7 +368,6 @@ library LibProving {
revert L1_CANNOT_CONTEST();
}

// _checkIfContestable(/*_state,*/ tier.cooldownWindow, ts.timestamp);
// Burn the contest bond from the prover.
LibBonds.debitBond(
_state, _resolver, msg.sender, local.blockId, local.tier.contestBond
Expand Down Expand Up @@ -518,7 +517,7 @@ library LibProving {
if (_local.sameTransition) revert L1_ALREADY_PROVED();

// The code below will be executed if
// - 1) the transition is proved for the fist time, or
// - 1) the transition is proved for the first time, or
// - 2) the transition is contested.
reward = _rewardAfterFriction(_ts.validityBond);

Expand Down
10 changes: 7 additions & 3 deletions packages/protocol/contracts/layer1/based/LibUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import "./TaikoData.sol";
library LibUtils {
using LibMath for uint256;

uint256 internal constant SECONDS_IN_MINUTE = 60;

/// @dev Emitted when a block is verified.
/// @param blockId The ID of the verified block.
/// @param prover The prover whose transition is used for verifying the
Expand All @@ -26,7 +28,6 @@ library LibUtils {
uint256 indexed blockId, address indexed prover, bytes32 blockHash, uint16 tier
);

error L1_BLOCK_MISMATCH();
error L1_INVALID_BLOCK_ID();
error L1_INVALID_PARAMS();
error L1_INVALID_GENESIS_HASH();
Expand All @@ -47,6 +48,8 @@ library LibUtils {
TaikoData.BlockV2 storage blk = _state.blocks[0];
blk.nextTransitionId = 2;
blk.proposedAt = uint64(block.timestamp);
// TODO:
// blk.proposedIn = uint64(block.number);
blk.verifiedTransitionId = 1;
blk.metaHash = bytes32(uint256(1)); // Give the genesis metahash a non-zero value.

Expand Down Expand Up @@ -122,7 +125,7 @@ library LibUtils {
TaikoData.State storage _state,
TaikoData.Config memory _config,
uint64 _blockId,
uint32 _tid
uint24 _tid
)
internal
view
Expand Down Expand Up @@ -231,7 +234,8 @@ library LibUtils {
returns (bool)
{
unchecked {
uint256 deadline = _tsTimestamp.max(_lastUnpausedAt) + _windowMinutes * 60;
uint256 deadline =
_tsTimestamp.max(_lastUnpausedAt) + _windowMinutes * SECONDS_IN_MINUTE;
return block.timestamp >= deadline;
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts/layer1/based/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ library TaikoData {
// Ring buffer for transitions
mapping(
uint64 blockId_mod_blockRingBufferSize
=> mapping(uint32 transitionId => TransitionState ts)
=> mapping(uint24 transitionId => TransitionState ts)
) transitions;
bytes32 __reserve1; // Used as a ring buffer for Ether deposits
SlotA slotA; // slot 5
Expand Down
20 changes: 18 additions & 2 deletions packages/protocol/contracts/layer1/based/TaikoEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,26 @@ import "./TaikoData.sol";
/// L1 libraries.
/// @custom:security-contact [email protected]
abstract contract TaikoEvents {
/// @dev Emitted when token is credited back to a user's bond balance.
/// @dev Emitted when tokens are deposited into a user's bond balance.
/// @param user The address of the user who deposited the tokens.
/// @param amount The amount of tokens deposited.
event BondDeposited(address indexed user, uint256 amount);

/// @dev Emitted when tokens are withdrawn from a user's bond balance.
/// @param user The address of the user who withdrew the tokens.
/// @param amount The amount of tokens withdrawn.
event BondWithdrawn(address indexed user, uint256 amount);

/// @dev Emitted when a token is credited back to a user's bond balance.
/// @param user The address of the user whose bond balance is credited.
/// @param blockId The ID of the block to credit for.
/// @param amount The amount of tokens credited.
event BondCredited(address indexed user, uint256 blockId, uint256 amount);

/// @dev Emitted when token is debited from a user's bond balance.
/// @dev Emitted when a token is debited from a user's bond balance.
/// @param user The address of the user whose bond balance is debited.
/// @param blockId The ID of the block to debit for.
/// @param amount The amount of tokens debited.
event BondDebited(address indexed user, uint256 blockId, uint256 amount);

/// @dev DEPRECATED but used by node/client for syncing old blocks
Expand Down
8 changes: 4 additions & 4 deletions packages/protocol/contracts/layer1/based/TaikoL1.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
import "src/shared/common/EssentialContract.sol";
import "./LibData.sol";
import "./LibProposing.sol";
Expand All @@ -24,8 +25,6 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {

uint256[50] private __gap;

error L1_INVALID_PARAMS();

modifier whenProvingNotPaused() {
if (state.slotB.provingPaused) revert LibProving.L1_PROVING_PAUSED();
_;
Expand Down Expand Up @@ -177,7 +176,7 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
/// @return blk_ The block.
function getBlock(uint64 _blockId) external view returns (TaikoData.Block memory blk_) {
(TaikoData.BlockV2 memory blk,) = LibUtils.getBlock(state, getConfig(), _blockId);
blk_ = LibData.blockV2toV1(blk);
blk_ = LibData.blockV2ToV1(blk);
}

/// @inheritdoc ITaikoL1
Expand Down Expand Up @@ -226,7 +225,8 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
view
returns (TaikoData.TransitionState memory)
{
return LibUtils.getTransition(state, getConfig(), _blockId, _tid);
return
LibUtils.getTransition(state, getConfig(), _blockId, SafeCastUpgradeable.toUint24(_tid));
}

/// @notice Returns information about the last verified block.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ abstract contract ComposeVerifier is EssentialContract, IVerifier {
bytes proof;
}

error CV_DUPLICATE_SUBPROOF();
error CV_INVALID_CALLER();
error CV_INVALID_SUB_VERIFIER();
error CV_INVALID_SUBPROOF_LENGTH();
Expand Down Expand Up @@ -87,7 +86,7 @@ abstract contract ComposeVerifier is EssentialContract, IVerifier {
if (subProofs.length != numSubProofs_) revert CV_INVALID_SUBPROOF_LENGTH();

for (uint256 i; i < subProofs.length; ++i) {
if (subProofs[i].verifier == address(0)) revert CV_DUPLICATE_SUBPROOF();
if (subProofs[i].verifier == address(0)) revert CV_INVALID_SUB_VERIFIER();

// find the verifier
bool verifierFound;
Expand Down
4 changes: 3 additions & 1 deletion packages/protocol/contracts/layer2/based/TaikoL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ contract TaikoL2 is EssentialContract, IBlockHash {
emit Anchored(parentHash, parentGasExcess);
}

/// @notice Withdraw token or Ether from this address
/// @notice Withdraw token or Ether from this address.
/// Note: This contract receives a portion of L2 base fees, while the remainder is directed to
/// L2 block's coinbase address.
/// @param _token Token address or address(0) if Ether.
/// @param _to Withdraw to address.
function withdraw(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ contract TaikoL1LibProvingWithTiers is TaikoL1TestBase {
blockHash,
stateRoot,
LibTiers.TIER_SGX,
LibUtils.L1_BLOCK_MISMATCH.selector
LibProving.L1_BLOCK_MISMATCH.selector
);

parentHash = blockHash;
Expand Down