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): add EIP-2612 (permit extension) to bridged ERC20 tokens #17818

Merged
merged 17 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
279 changes: 279 additions & 0 deletions packages/protocol/contract_layout.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/protocol/contracts/tokenvault/BridgedERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ contract BridgedERC20 is
string calldata _name
)
external
virtual
initializer
{
// Check if provided parameters are valid
Expand Down Expand Up @@ -149,7 +150,7 @@ contract BridgedERC20 is
return migratingAddress != address(0) && !migratingInbound;
}

function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {
function supportsInterface(bytes4 _interfaceId) public pure virtual returns (bool) {
return _interfaceId == type(IBridgedERC20).interfaceId
|| _interfaceId == type(IBridgedERC20Initializable).interfaceId
|| _interfaceId == type(IBridgedERC20Migratable).interfaceId
Expand Down
119 changes: 119 additions & 0 deletions packages/protocol/contracts/tokenvault/BridgedERC20V2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "@openzeppelin/contracts-upgradeable/interfaces/IERC5267Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
import "./BridgedERC20.sol";

/// @title BridgedERC20V2
/// @notice An upgradeable ERC20 contract that represents tokens bridged from
/// another chain. This implementation adds ERC20Permit support to BridgedERC20.
///
/// Most of the code were copied from OZ's ERC20PermitUpgradeable.sol contract.
///
/// @custom:security-contact [email protected]
contract BridgedERC20V2 is BridgedERC20, IERC20PermitUpgradeable, EIP712Upgradeable {
using CountersUpgradeable for CountersUpgradeable.Counter;

// solhint-disable-next-line var-name-mixedcase
bytes32 private constant _PERMIT_TYPEHASH = keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
);

mapping(address => CountersUpgradeable.Counter) private _nonces;
uint256[49] private __gap;

error BTOKEN_DEADLINE_EXPIRED();
error BTOKEN_INVALID_SIG();

/// @inheritdoc IBridgedERC20Initializable
function init(
address _owner,
address _sharedAddressManager,
address _srcToken,
uint256 _srcChainId,
uint8 _decimals,
string calldata _symbol,
string calldata _name
)
external
virtual
override
initializer
{
// Check if provided parameters are valid
LibBridgedToken.validateInputs(_srcToken, _srcChainId);
__Essential_init(_owner, _sharedAddressManager);
__ERC20_init(_name, _symbol);
__EIP712_init_unchained(_name, "1");

// Set contract properties
srcToken = _srcToken;
srcChainId = _srcChainId;
__srcDecimals = _decimals;
}

/**
* @inheritdoc IERC20PermitUpgradeable
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
return _domainSeparatorV4();
}

/**
* @inheritdoc IERC20PermitUpgradeable
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
)
public
virtual
override
{
if (block.timestamp > deadline) revert BTOKEN_DEADLINE_EXPIRED();

bytes32 structHash = keccak256(
abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)
);

bytes32 hash = _hashTypedDataV4(structHash);

address signer = ECDSAUpgradeable.recover(hash, v, r, s);
if (signer != owner) revert BTOKEN_INVALID_SIG();

_approve(owner, spender, value);
}

/**
* @inheritdoc IERC20PermitUpgradeable
*/
function nonces(address owner) public view virtual override returns (uint256) {
return _nonces[owner].current();
}

function supportsInterface(bytes4 _interfaceId) public pure virtual override returns (bool) {
return _interfaceId == type(IERC20PermitUpgradeable).interfaceId
|| _interfaceId == type(IERC5267Upgradeable).interfaceId
|| super.supportsInterface(_interfaceId);
}

/**
dantaik marked this conversation as resolved.
Show resolved Hide resolved
* @dev "Consume a nonce": return the current value and increment.
*
* _Available since v4.1._
*/
function _useNonce(address owner) internal virtual returns (uint256 current) {
CountersUpgradeable.Counter storage nonce = _nonces[owner];
current = nonce.current();
nonce.increment();
}
}
17 changes: 17 additions & 0 deletions packages/protocol/deployments/gen-layouts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# Define the list of contracts to inspect
contracts=(
# Base contracts
"TaikoL1"
"TaikoL2"
"SignalService"
Expand All @@ -24,6 +25,22 @@ contracts=(
"QuotaManager"
"ProverSet"
"TokenUnlock"
# Hekla contracts
"HeklaTaikoL1"
# Mainnet contracts
"MainnetBridge"
"MainnetERC1155Vault"
"MainnetERC20Vault"
"MainnetERC721Vault"
"MainnetGuardianProver"
"MainnetProverSet"
"MainnetRiscZeroVerifier"
"MainnetRollupAddressManager"
"MainnetSgxVerifier"
"MainnetSharedAddressManager"
"MainnetSignalService"
"MainnetTaikoL1"
"MainnetTierRouter"
)

# Empty the output file initially
Expand Down
4 changes: 4 additions & 0 deletions packages/protocol/deployments/mainnet-contract-logs-L1.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
- `Init2()` called @tx`0x7311fee56f87294e336393b55939489bc1e810c402f304013475d04c90ca32a9`
- Upgraded from `0xF1cA1F1A068468E1dcF90dA6add185467de80943` to `0x9496502d7D121B3D5eF25cA6c58d4f7593398a17` @commit`e79a367ad` @tx`0xe1ef58455de0b0331228e487d54720290ed8a73f709d2146bd43330d4a360bd3`
- Upgraded from `0x9496502d7D121B3D5eF25cA6c58d4f7593398a17` to `0x2f7126f78365AD54EAB26fD7faEc60435008E2fD` @commit`bb2abc5` @tx`0x7d584f0a645cad61e634f64ffaf7e1bbfb92749878eb25b39ce0e5cf698897c7`
- todos:
- deploy and register BridgedERC20V2

#### taiko_token

Expand Down Expand Up @@ -148,6 +150,8 @@
- impl: `0x79BC0Aada00fcF6E7AB514Bfeb093b5Fae3653e3`
- logs:
- deployed on May 1, 2024 @commit`56dddf2b6`
- todos:
- deploy and register BridgedERC20V2

#### bridged_erc721

Expand Down
1 change: 1 addition & 0 deletions packages/protocol/deployments/mainnet-contract-logs-L2.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
- quota_manager: `0x0000000000000000000000000000000000000000`
- bridge_watchdog: `0x0000000000000000000000000000000000000000`
- todo:
- deploy and register BridgedERC20V2
- change owner to DelegateOwner
- logs:
- deployed on May 1, 2024 @commit`56dddf2b6`
Expand Down