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

feat(protocol): trigger simultaneous recurring TKO snapshots #16715

Merged
merged 53 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
abef644
Update TaikoL2.sol
dantaik Apr 11, 2024
19ceeb4
more
dantaik Apr 11, 2024
665fb16
fix
dantaik Apr 11, 2024
de3c699
Update TaikoL2.sol
dantaik Apr 11, 2024
2b7e8e5
Update TaikoL2.sol
dantaik Apr 11, 2024
e266e22
Update TaikoL2.sol
dantaik Apr 11, 2024
4b1faf2
rename
dantaik Apr 11, 2024
2f810e1
Update ISnapshot.sol
dantaik Apr 11, 2024
f72055b
more
dantaik Apr 12, 2024
858e0d1
Merge branch 'main' into synced_snapshot
dantaik Apr 12, 2024
50daa69
comment
dantaik Apr 12, 2024
0512cb3
more
dantaik Apr 12, 2024
5372314
Revert "more"
dantaik Apr 12, 2024
fa95bda
Update TaikoL2.sol
dantaik Apr 12, 2024
fa9bbaa
rename
dantaik Apr 12, 2024
62f5a26
more
dantaik Apr 12, 2024
b1772e9
Update TaikoToken.sol
dantaik Apr 12, 2024
6d899ba
Update LibStrings.sol
dantaik Apr 12, 2024
d97267d
Update TaikoL2.sol
dantaik Apr 12, 2024
8a0d80b
rename
dantaik Apr 12, 2024
cfa6dfe
Update BridgedERC20.sol
dantaik Apr 12, 2024
340e46a
Revert "rename"
dantaik Apr 12, 2024
a5aa52d
Revert "more"
dantaik Apr 12, 2024
766c9e9
more
dantaik Apr 12, 2024
0985d86
more
dantaik Apr 12, 2024
62bbe06
Update LibAutoSnapshot.sol
dantaik Apr 12, 2024
633f913
Update LibAutoSnapshot.sol
dantaik Apr 12, 2024
c464700
Merge branch 'main' into synced_snapshot
dantaik Apr 12, 2024
cf6c4bb
more
dantaik Apr 13, 2024
7f9ad39
Update LibAutoSnapshot.sol
dantaik Apr 13, 2024
9227586
fix
dantaik Apr 13, 2024
f8addd8
Update LibProposing.sol
dantaik Apr 13, 2024
2a5e748
Update TaikoL2.sol
dantaik Apr 13, 2024
5cf171f
Update TaikoL2.sol
dantaik Apr 13, 2024
b1894a6
more
dantaik Apr 14, 2024
f142029
rename
dantaik Apr 14, 2024
dee1e83
Update LibProposing.sol
dantaik Apr 14, 2024
8b22b19
Update TaikoL2.sol
dantaik Apr 14, 2024
7d36945
Merge branch 'main' into synced_snapshot
dantaik Apr 16, 2024
867d156
revert
dantaik Apr 16, 2024
1a065a5
Merge branch 'main' into synced_snapshot
dantaik Apr 16, 2024
7db0b3a
Update LibSnapshot.sol
dantaik Apr 16, 2024
679a73c
more
dantaik Apr 16, 2024
6f10750
Update pnpm-lock.yaml
dantaik Apr 16, 2024
79b7320
x
dantaik Apr 16, 2024
e0e04d9
Merge branch 'main' into synced_snapshot
davidtaikocha Apr 17, 2024
2f59200
Update LibSnapshot.sol
dantaik Apr 17, 2024
a578292
Update LibSnapshot.sol
dantaik Apr 17, 2024
7687c3b
Update BridgedERC20.sol
dantaik Apr 18, 2024
0fa8805
Merge branch 'main' into synced_snapshot
dantaik Apr 18, 2024
cb41cbc
Update BridgedERC20.sol
dantaik Apr 18, 2024
739d28d
Update BridgedERC20.sol
dantaik Apr 18, 2024
343035e
Merge branch 'main' into synced_snapshot
dantaik Apr 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions packages/protocol/contracts/L1/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ library TaikoData {
uint64 genesisHeight;
uint64 genesisTimestamp;
uint64 lastSyncedBlockId;
uint64 lastSynecdAt;
uint64 lastSynecdAt; // typo!
}

struct SlotB {
Expand All @@ -149,7 +149,7 @@ library TaikoData {
bool provingPaused;
uint8 __reservedB1;
uint16 __reservedB2;
uint32 __reservedB3;
uint32 lastSnapshotIdx;
uint64 lastUnpausedAt;
}

Expand All @@ -164,7 +164,6 @@ library TaikoData {
uint64 blockId_mod_blockRingBufferSize
=> mapping(uint32 transitionId => TransitionState ts)
) transitions;
// Ring buffer for Ether deposits
bytes32 __reserve1;
SlotA slotA; // slot 5
SlotB slotB; // slot 6
Expand Down
6 changes: 6 additions & 0 deletions packages/protocol/contracts/L1/TaikoEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ abstract contract TaikoEvents {
/// @param slotB The SlotB data structure.
event StateVariablesUpdated(TaikoData.SlotB slotB);

/// @notice Emitted when the Taiko token snapshot is taken.
/// @param tkoAddress The Taiko token address.
/// @param snapshotIdx The snapshot index.
/// @param snapshotId The snapshot id.
event TaikoTokenSnapshot(address tkoAddress, uint256 snapshotIdx, uint256 snapshotId);

/// @dev Emitted when a block transition is proved or re-proved.
/// @param blockId The ID of the proven block.
/// @param tran The verified transition.
Expand Down
1 change: 0 additions & 1 deletion packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents, TaikoErrors {
// reset some previously used slots for future reuse
state.slotB.__reservedB1 = 0;
state.slotB.__reservedB2 = 0;
state.slotB.__reservedB3 = 0;
state.__reserve1 = 0;
}

Expand Down
6 changes: 5 additions & 1 deletion packages/protocol/contracts/L1/TaikoToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ contract TaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20VotesUp
}

/// @notice Creates a new token snapshot.
function snapshot() public onlyFromOwnerOrNamed(LibStrings.B_SNAPSHOOTER) returns (uint256) {
function snapshot() public onlyFromNamed(LibStrings.B_TAIKO) returns (uint256) {
return _snapshot();
}

Expand Down Expand Up @@ -84,6 +84,10 @@ contract TaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20VotesUp
return super.transferFrom(_from, _to, _amount);
}

function currentSnapshotId() public view returns (uint256) {
return _getCurrentSnapshotId();
}

function _beforeTokenTransfer(
address _from,
address _to,
Expand Down
17 changes: 16 additions & 1 deletion packages/protocol/contracts/L1/libs/LibProposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.24;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../../common/IAddressResolver.sol";
import "../../common/LibStrings.sol";
import "../../common/LibSnapshot.sol";
import "../../libs/LibAddress.sol";
import "../../libs/LibNetwork.sol";
import "../hooks/IHook.sol";
Expand Down Expand Up @@ -185,6 +185,8 @@ library LibProposing {

{
IERC20 tko = IERC20(_resolver.resolve(LibStrings.B_TAIKO_TOKEN, false));
_takeTaikoTokenSnapshot(_state, address(tko), b);

uint256 tkoBalance = tko.balanceOf(address(this));

// Run all hooks.
Expand Down Expand Up @@ -230,6 +232,19 @@ library LibProposing {
});
}

function _takeTaikoTokenSnapshot(
TaikoData.State storage _state,
address _taikoToken,
TaikoData.SlotB memory _slotB
)
private
{
uint32 idx = LibSnapshot.autoSnapshot(_taikoToken, block.number, _slotB.lastSnapshotIdx);
if (idx != 0) {
_state.slotB.lastSnapshotIdx = idx;
}
}

function _isProposerPermitted(
TaikoData.SlotB memory _slotB,
IAddressResolver _resolver
Expand Down
18 changes: 17 additions & 1 deletion packages/protocol/contracts/L2/TaikoL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import "../common/EssentialContract.sol";
import "../common/LibStrings.sol";
import "../common/LibSnapshot.sol";
import "../libs/LibAddress.sol";
import "../signal/ISignalService.sol";
import "./Lib1559Math.sol";
Expand Down Expand Up @@ -47,15 +47,24 @@ contract TaikoL2 is EssentialContract {
uint64 private __currentBlockTimestamp;

/// @notice The L1's chain ID.
/// @dev Slot 4.
uint64 public l1ChainId;

uint32 public lastSnapshotIdx;

uint256[46] private __gap;

/// @notice Emitted when the latest L1 block details are anchored to L2.
/// @param parentHash The hash of the parent block.
/// @param gasExcess The gas excess value used to calculate the base fee.
event Anchored(bytes32 parentHash, uint64 gasExcess);

/// @notice Emitted when the Taiko token snapshot is taken.
/// @param tkoAddress The Taiko token address.
/// @param snapshotIdx The snapshot index.
/// @param snapshotId The snapshot id.
event TaikoTokenSnapshot(address tkoAddress, uint256 snapshotIdx, uint256 snapshotId);

error L2_BASEFEE_MISMATCH();
error L2_INVALID_L1_CHAIN_ID();
error L2_INVALID_L2_CHAIN_ID();
Expand Down Expand Up @@ -105,6 +114,7 @@ contract TaikoL2 is EssentialContract {

/// @notice Anchors the latest L1 block details to L2 for cross-layer
/// message verification.
/// @dev The gas limit for this transaction is set to 250K in geth and raiko.
/// @dev This function can be called freely as the golden touch private key is publicly known,
/// but the Taiko node guarantees the first transaction of each block is always this anchor
/// transaction, and any subsequent calls will revert with L2_PUBLIC_INPUT_HASH_MISMATCH.
Expand Down Expand Up @@ -168,6 +178,12 @@ contract TaikoL2 is EssentialContract {
__currentBlockTimestamp = uint64(block.timestamp);
gasExcess = _gasExcess;

address tko = resolve(LibStrings.B_TAIKO_TOKEN, true);
if (tko != address(0)) {
uint32 idx = LibSnapshot.autoSnapshot(tko, _l1BlockId, lastSnapshotIdx);
if (idx != 0) lastSnapshotIdx = idx;
}

emit Anchored(_parentHash, _gasExcess);
}

Expand Down
47 changes: 47 additions & 0 deletions packages/protocol/contracts/common/LibSnapshot.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "./IAddressResolver.sol";
import "./LibStrings.sol";

/// @title ISnapshot
/// @custom:security-contact [email protected]
interface ISnapshot {
function snapshot() external returns (uint256);
}

/// @title LibSnapshot
/// @custom:security-contact [email protected]
library LibSnapshot {
uint256 public constant SNAPSHOT_INTERVAL = 7200; // uint = 1 L1 block

/// @notice Emitted when the Taiko token snapshot is taken.
/// @param tkoAddress The Taiko token address.
/// @param snapshotIdx The snapshot index.
/// @param snapshotId The snapshot id.
event TaikoTokenSnapshot(address tkoAddress, uint256 snapshotIdx, uint256 snapshotId);

/// @dev Takes a snapshot every 200,000 L1 blocks which is roughly 27 days.
/// @param _taikoToken The Taiko token address.
/// @param _blockId The L1's block ID.
/// @param _lastSnapshotIdx The latest snapshot's index.
/// @return The new snapshot's index, 0 if no new snapshot is taken.
function autoSnapshot(
address _taikoToken,
uint256 _blockId,
uint64 _lastSnapshotIdx
)
internal
returns (uint32)
{
if (_blockId % SNAPSHOT_INTERVAL != 0) return 0;

// if snapshotIdx = type(uint32).max, we can handle L1 block id up to 4e14.
uint32 snapshotIdx = uint32(_blockId / SNAPSHOT_INTERVAL + 1);
if (snapshotIdx == _lastSnapshotIdx) return 0;

uint256 snapshotId = ISnapshot(_taikoToken).snapshot();
emit TaikoTokenSnapshot(_taikoToken, snapshotIdx, snapshotId);
return snapshotIdx;
}
}
3 changes: 0 additions & 3 deletions packages/protocol/contracts/common/LibStrings.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ library LibStrings {
/// @notice bytes32 representation of the string "chain_pauser".
bytes32 internal constant B_CHAIN_PAUSER = bytes32("chain_pauser");

/// @notice bytes32 representation of the string "snapshooter".
bytes32 internal constant B_SNAPSHOOTER = bytes32("snapshooter");

/// @notice bytes32 representation of the string "withdrawer".
bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer");

Expand Down
27 changes: 22 additions & 5 deletions packages/protocol/contracts/tokenvault/BridgedERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ contract BridgedERC20 is
error BTOKEN_CANNOT_RECEIVE();
error BTOKEN_UNAUTHORIZED();

modifier onlyOwnerOrSnapshooter() {
if (msg.sender != owner() && msg.sender != snapshooter) {
revert BTOKEN_UNAUTHORIZED();
}
modifier onlyAuthorizedForSnapshot() {
if (!isAuthorizedForSnapshot(msg.sender)) revert BTOKEN_UNAUTHORIZED();
_;
}

Expand Down Expand Up @@ -81,7 +79,7 @@ contract BridgedERC20 is
}

/// @notice Creates a new token snapshot.
function snapshot() external onlyOwnerOrSnapshooter returns (uint256) {
function snapshot() external onlyAuthorizedForSnapshot returns (uint256) {
return _snapshot();
}

Expand Down Expand Up @@ -118,6 +116,25 @@ contract BridgedERC20 is
return __srcDecimals;
}

/// @notice Gets the current snapshot ID.
/// @return The current snapshot ID.
function currentSnapshotId() public view returns (uint256) {
return _getCurrentSnapshotId();
}

/// @notice Checks if an address can take a snapshot.
/// @param addr The address.
/// @return true if the address can perform a snapshot, false otherwise.
function isAuthorizedForSnapshot(address addr) public view returns (bool) {
if (addr == address(0)) return false;
if (addr == snapshooter) return true;
if (
addr == resolve(LibStrings.B_TAIKO, true)
&& address(this) == resolve(LibStrings.B_TAIKO_TOKEN, true)
) return true;
return false;
}

/// @notice Gets the canonical token's address and chain ID.
/// @return The canonical token's address.
/// @return The canonical token's chain ID.
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"eslint-plugin-promise": "^6.1.1",
"ethers": "^5.7.2",
"solc": "0.7.3",
"solhint": "^4.5.2",
"solhint": "^4.5.4",
"ts-node": "^10.9.2",
"typescript": "^5.2.2"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/test/L1/TaikoL1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ contract TaikoL1Test is TaikoL1TestBase {
}

function test_snapshot() external {
vm.prank(tko.owner(), tko.owner());
vm.prank(address(L1));
tko.snapshot();

uint256 totalSupplyAtSnapshot = tko.totalSupplyAt(1);
Expand Down
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading