From b48cf95ed144e1f3906b491af8946f7d10a61558 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 30 Sep 2024 11:43:29 +0800 Subject: [PATCH 1/4] feat(protocol): check-in `HeklaTaikoToken` --- .../layer1/hekla/HeklaTaikoToken.sol | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol diff --git a/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol b/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol new file mode 100644 index 0000000000..8877027681 --- /dev/null +++ b/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20SnapshotUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../../shared/common/EssentialContract.sol"; + +/// @title HeklaTaikoToken +/// @notice The HeklaTaikoToken (TTKOh), in the protocol is used for prover collateral +/// in the form of bonds. It is an ERC20 token with 18 decimal places of +/// precision. +/// @dev Labeled in AddressResolver as "taiko_token" +/// @custom:security-contact security@taiko.xyz +contract HeklaTaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20VotesUpgradeable { + uint256[50] private __gap; + + error TKO_INVALID_ADDR(); + error TT_INVALID_PARAM(); + + /// @notice Initializes the contract. + /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. + /// @param _name The name of the token. + /// @param _symbol The symbol of the token. + /// @param _recipient The address to receive initial token minting. + /// @param _addressManager The AddressManager address. + function init( + address _owner, + string calldata _name, + string calldata _symbol, + address _recipient, + address _addressManager + ) + public + initializer + { + __Essential_init(_owner, _addressManager); + __ERC20_init(_name, _symbol); + __ERC20Snapshot_init(); + __ERC20Votes_init(); + __ERC20Permit_init(_name); + + // Mint 1 billion tokens + _mint(_recipient, 1_000_000_000 ether); + } + + /// @notice Burns tokens from the specified address. + /// @param _from The address to burn tokens from. + /// @param _amount The amount of tokens to burn. + function burn(address _from, uint256 _amount) public onlyOwner { + return _burn(_from, _amount); + } + + /// @notice Creates a new token snapshot. + function snapshot() public onlyFromOwnerOrNamed("snapshooter") returns (uint256) { + return _snapshot(); + } + + /// @notice Transfers tokens to a specified address. + /// @param _to The address to transfer tokens to. + /// @param _amount The amount of tokens to transfer. + /// @return A boolean indicating whether the transfer was successful or not. + function transfer(address _to, uint256 _amount) public override returns (bool) { + if (_to == address(this)) revert TKO_INVALID_ADDR(); + return super.transfer(_to, _amount); + } + + /// @notice Transfers tokens from one address to another. + /// @param _from The address to transfer tokens from. + /// @param _to The address to transfer tokens to. + /// @param _amount The amount of tokens to transfer. + /// @return A boolean indicating whether the transfer was successful or not. + function transferFrom( + address _from, + address _to, + uint256 _amount + ) + public + override + returns (bool) + { + if (_to == address(this)) revert TKO_INVALID_ADDR(); + return super.transferFrom(_from, _to, _amount); + } + + function _beforeTokenTransfer( + address _from, + address _to, + uint256 _amount + ) + internal + override(ERC20Upgradeable, ERC20SnapshotUpgradeable) + { + return super._beforeTokenTransfer(_from, _to, _amount); + } + + function _afterTokenTransfer( + address _from, + address _to, + uint256 _amount + ) + internal + override(ERC20Upgradeable, ERC20VotesUpgradeable) + { + return super._afterTokenTransfer(_from, _to, _amount); + } + + function _mint( + address _to, + uint256 _amount + ) + internal + override(ERC20Upgradeable, ERC20VotesUpgradeable) + { + return super._mint(_to, _amount); + } + + function _burn( + address _from, + uint256 _amount + ) + internal + override(ERC20Upgradeable, ERC20VotesUpgradeable) + { + return super._burn(_from, _amount); + } + + /// @notice Batch transfers tokens + /// @param recipients The list of addresses to transfer tokens to. + /// @param amounts The list of amounts for transfer. + /// @return true if the transfer is successful. + function batchTransfer( + address[] calldata recipients, + uint256[] calldata amounts + ) + external + returns (bool) + { + if (recipients.length != amounts.length) revert TT_INVALID_PARAM(); + for (uint256 i; i < recipients.length; ++i) { + _transfer(msg.sender, recipients[i], amounts[i]); + } + return true; + } +} From 8b0259fd2834d723f419a05114778825d7a9926e Mon Sep 17 00:00:00 2001 From: David Date: Mon, 30 Sep 2024 11:50:34 +0800 Subject: [PATCH 2/4] feat: add `symbol()` --- packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol b/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol index 8877027681..237101af7a 100644 --- a/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol +++ b/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol @@ -44,6 +44,10 @@ contract HeklaTaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20Vo _mint(_recipient, 1_000_000_000 ether); } + function symbol() public pure override returns (string memory) { + return "TAIKO"; + } + /// @notice Burns tokens from the specified address. /// @param _from The address to burn tokens from. /// @param _amount The amount of tokens to burn. From 54d22d3ddcf3c6d1dacecd2da41386ff2de69248 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 30 Sep 2024 11:52:09 +0800 Subject: [PATCH 3/4] chore: update comments --- packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol b/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol index 237101af7a..2055629e34 100644 --- a/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol +++ b/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol @@ -10,7 +10,9 @@ import "../../shared/common/EssentialContract.sol"; /// @notice The HeklaTaikoToken (TTKOh), in the protocol is used for prover collateral /// in the form of bonds. It is an ERC20 token with 18 decimal places of /// precision. -/// @dev Labeled in AddressResolver as "taiko_token" +/// @dev Labeled in AddressResolver as "taiko_token". +/// @dev Due to historical reasons, the Taiko Token on Hekla has a different storage layout compared +/// to the mainnet token contract. Therefore, we need to maintain this file. /// @custom:security-contact security@taiko.xyz contract HeklaTaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20VotesUpgradeable { uint256[50] private __gap; From 6261f9736026478ae5b87c5808760c6337eae16d Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Mon, 30 Sep 2024 11:59:01 +0800 Subject: [PATCH 4/4] Update HeklaTaikoToken.sol --- .../contracts/layer1/hekla/HeklaTaikoToken.sol | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol b/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol index 2055629e34..0b175f2d49 100644 --- a/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol +++ b/packages/protocol/contracts/layer1/hekla/HeklaTaikoToken.sol @@ -7,9 +7,7 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpg import "../../shared/common/EssentialContract.sol"; /// @title HeklaTaikoToken -/// @notice The HeklaTaikoToken (TTKOh), in the protocol is used for prover collateral -/// in the form of bonds. It is an ERC20 token with 18 decimal places of -/// precision. +/// @notice Taiko token for Taiko Hekla testnet. /// @dev Labeled in AddressResolver as "taiko_token". /// @dev Due to historical reasons, the Taiko Token on Hekla has a different storage layout compared /// to the mainnet token contract. Therefore, we need to maintain this file. @@ -46,10 +44,6 @@ contract HeklaTaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20Vo _mint(_recipient, 1_000_000_000 ether); } - function symbol() public pure override returns (string memory) { - return "TAIKO"; - } - /// @notice Burns tokens from the specified address. /// @param _from The address to burn tokens from. /// @param _amount The amount of tokens to burn. @@ -89,6 +83,14 @@ contract HeklaTaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20Vo return super.transferFrom(_from, _to, _amount); } + function name() public pure override returns (string memory) { + return "Taiko Token"; + } + + function symbol() public pure override returns (string memory) { + return "TAIKO"; + } + function _beforeTokenTransfer( address _from, address _to,