diff --git a/packages/protocol/contracts/L1/TaikoToken.sol b/packages/protocol/contracts/L1/TaikoToken.sol index 963923e64f2..d8dcceb16ed 100644 --- a/packages/protocol/contracts/L1/TaikoToken.sol +++ b/packages/protocol/contracts/L1/TaikoToken.sol @@ -10,7 +10,9 @@ import "../common/LibStrings.sol"; /// We use this contract to take 50 more slots to remove `ERC20SnapshotUpgradeable` from the parent /// contract list. /// We can simplify the code since we no longer need to maintain upgradability with Hekla. +// solhint-disable contract-name-camelcase abstract contract EssentialContract_ is EssentialContract { + // solhint-disable var-name-mixedcase uint256[50] private __slots_previously_used_by_ERC20SnapshotUpgradeable; } diff --git a/packages/protocol/contracts/L1/provers/GuardianProver.sol b/packages/protocol/contracts/L1/provers/GuardianProver.sol index 5e052dd08d9..6942a0b557c 100644 --- a/packages/protocol/contracts/L1/provers/GuardianProver.sol +++ b/packages/protocol/contracts/L1/provers/GuardianProver.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + import "../../common/LibStrings.sol"; import "../../verifiers/IVerifier.sol"; import "../tiers/ITierProvider.sol"; @@ -11,7 +14,10 @@ import "./Guardians.sol"; /// This prover uses itself as the verifier. /// @custom:security-contact security@taiko.xyz contract GuardianProver is IVerifier, Guardians { + using SafeERC20 for IERC20; + error GV_PERMISSION_DENIED(); + error GV_ZERO_ADDRESS(); uint256[50] private __gap; @@ -36,6 +42,25 @@ contract GuardianProver is IVerifier, Guardians { __Essential_init(_owner, _addressManager); } + /// @notice Enables unlimited allowance for Taiko L1 contract. + /// param _enable true if unlimited allowance is approved, false to set the allowance to 0. + function enableTaikoTokenAllowance(bool _enable) external onlyOwner { + address tko = resolve(LibStrings.B_TAIKO_TOKEN, false); + address taiko = resolve(LibStrings.B_TAIKO, false); + IERC20(tko).safeApprove(taiko, _enable ? type(uint256).max : 0); + } + + /// @dev Withdraws Taiko Token to a given address. + /// @param _to The recipient address. + /// @param _amount The amount of Taiko token to withdraw. Use 0 for all balance. + function withdrawTaikoToken(address _to, uint256 _amount) external onlyOwner { + if (_to == address(0)) revert GV_ZERO_ADDRESS(); + + IERC20 tko = IERC20(resolve(LibStrings.B_TAIKO_TOKEN, false)); + uint256 amount = _amount == 0 ? tko.balanceOf(address(this)) : _amount; + tko.safeTransfer(_to, amount); + } + /// @dev Called by guardians to approve a guardian proof /// @param _meta The block's metadata. /// @param _tran The valid transition. diff --git a/packages/protocol/contracts/tokenvault/BridgedERC20.sol b/packages/protocol/contracts/tokenvault/BridgedERC20.sol index be981e07593..8603d678e4b 100644 --- a/packages/protocol/contracts/tokenvault/BridgedERC20.sol +++ b/packages/protocol/contracts/tokenvault/BridgedERC20.sol @@ -9,7 +9,9 @@ import "./BridgedERC20Base.sol"; /// We use this contract to take 50 more slots to remove `ERC20SnapshotUpgradeable` from the parent /// contract list. /// We can simplify the code since we no longer need to maintain upgradability with Hekla. +// solhint-disable contract-name-camelcase abstract contract BridgedERC20Base_ is BridgedERC20Base { + // solhint-disable var-name-mixedcase uint256[50] private __slots_previously_used_by_ERC20SnapshotUpgradeable; } diff --git a/packages/protocol/script/DeployTaikoToken.s.sol b/packages/protocol/script/DeployTaikoToken.s.sol index 2903bd41571..4d7aa815a9a 100644 --- a/packages/protocol/script/DeployTaikoToken.s.sol +++ b/packages/protocol/script/DeployTaikoToken.s.sol @@ -20,13 +20,6 @@ contract DeployTaikoToken is DeployCapability { } function run() external broadcast { - // Deploy the shared address manager at first. - address sharedAddressManager = deployProxy({ - name: "shared_address_manager", - impl: address(new AddressManager()), - data: abi.encodeCall(AddressManager.init, (address(0))) - }); - // Deploy the TaikoToken contract, use securityCouncil address as the owner. deployProxy({ name: "taiko_token", diff --git a/packages/protocol/test/L1/TaikoL1TestBase.sol b/packages/protocol/test/L1/TaikoL1TestBase.sol index d7801923723..010c11e6920 100644 --- a/packages/protocol/test/L1/TaikoL1TestBase.sol +++ b/packages/protocol/test/L1/TaikoL1TestBase.sol @@ -123,6 +123,8 @@ abstract contract TaikoL1TestBase is TaikoTest { ); L1.init(address(0), address(addressManager), GENESIS_BLOCK_HASH); + + gp.enableTaikoTokenAllowance(true); printVariables("init "); }