Skip to content

Commit

Permalink
refactor(protocol): remove bridged token impl dependencies from vaults (
Browse files Browse the repository at this point in the history
#17067)

Co-authored-by: dantaik <dantaik@users.noreply.github.com>
  • Loading branch information
dantaik and dantaik authored May 10, 2024
1 parent 583e8d8 commit 13ad99d
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 121 deletions.
4 changes: 0 additions & 4 deletions packages/protocol/contracts/tko/BridgedTaikoToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ contract BridgedTaikoToken is TaikoTokenBase, IBridgedERC20 {
_burn(msg.sender, _amount);
}

function owner() public view override(IBridgedERC20, OwnableUpgradeable) returns (address) {
return OwnableUpgradeable.owner();
}

/// @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
14 changes: 0 additions & 14 deletions packages/protocol/contracts/tokenvault/BaseNFTVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,6 @@ abstract contract BaseNFTVault is BaseVault {
uint256[] amounts;
}

/// @notice ERC1155 interface ID.
bytes4 internal constant ERC1155_INTERFACE_ID = 0xd9b67a26;

/// @notice ERC721 interface ID.
bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;

/// @notice Maximum number of tokens that can be transferred per transaction.
uint256 public constant MAX_TOKEN_PER_TXN = 10;

/// @notice Mapping to store bridged NFTs and their canonical counterparts.
mapping(address btoken => CanonicalNFT canonical) public bridgedToCanonical;

Expand Down Expand Up @@ -123,17 +114,12 @@ abstract contract BaseNFTVault is BaseVault {
error VAULT_INVALID_AMOUNT();
error VAULT_INTERFACE_NOT_SUPPORTED();
error VAULT_TOKEN_ARRAY_MISMATCH();
error VAULT_MAX_TOKEN_PER_TXN_EXCEEDED();

modifier withValidOperation(BridgeTransferOp memory _op) {
if (_op.tokenIds.length != _op.amounts.length) {
revert VAULT_TOKEN_ARRAY_MISMATCH();
}

if (_op.tokenIds.length > MAX_TOKEN_PER_TXN) {
revert VAULT_MAX_TOKEN_PER_TXN_EXCEEDED();
}

if (_op.token == address(0)) revert VAULT_INVALID_TOKEN();
_;
}
Expand Down
37 changes: 18 additions & 19 deletions packages/protocol/contracts/tokenvault/BridgedERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ pragma solidity 0.8.24;
import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
import "../common/EssentialContract.sol";
import "../common/LibStrings.sol";
import "./IBridgedERC1155.sol";
import "./LibBridgedToken.sol";

/// @title BridgedERC1155
/// @notice Contract for bridging ERC1155 tokens across different chains.
/// @custom:security-contact security@taiko.xyz
contract BridgedERC1155 is EssentialContract, ERC1155Upgradeable {
contract BridgedERC1155 is
EssentialContract,
IBridgedERC1155,
IBridgedERC1155Initializable,
ERC1155Upgradeable
{
/// @notice Address of the source token contract.
address public srcToken;

Expand All @@ -27,13 +33,7 @@ contract BridgedERC1155 is EssentialContract, ERC1155Upgradeable {
error BTOKEN_INVALID_PARAMS();
error BTOKEN_INVALID_TO_ADDR();

/// @notice Initializes the contract.
/// @param _owner The owner of this contract. msg.sender will be used if this value is zero.
/// @param _addressManager The address of the {AddressManager} contract.
/// @param _srcToken Address of the source token.
/// @param _srcChainId Source chain ID.
/// @param _symbol Symbol of the bridged token.
/// @param _name Name of the bridged token.
/// @inheritdoc IBridgedERC1155Initializable
function init(
address _owner,
address _addressManager,
Expand Down Expand Up @@ -61,10 +61,7 @@ contract BridgedERC1155 is EssentialContract, ERC1155Upgradeable {
name = _name;
}

/// @dev Mints tokens.
/// @param _to Address to receive the minted tokens.
/// @param _tokenIds ID of the token to mint.
/// @param _amounts Amount of tokens to mint.
/// @inheritdoc IBridgedERC1155
function mintBatch(
address _to,
uint256[] calldata _tokenIds,
Expand All @@ -78,9 +75,7 @@ contract BridgedERC1155 is EssentialContract, ERC1155Upgradeable {
_mintBatch(_to, _tokenIds, _amounts, "");
}

/// @dev Batch burns tokens.
/// @param _ids Array of IDs of the tokens to burn.
/// @param _amounts Amount of tokens to burn respectively.
/// @inheritdoc IBridgedERC1155
function burnBatch(
uint256[] calldata _ids,
uint256[] calldata _amounts
Expand All @@ -93,13 +88,17 @@ contract BridgedERC1155 is EssentialContract, ERC1155Upgradeable {
_burnBatch(msg.sender, _ids, _amounts);
}

/// @notice Gets the canonical token's address and chain ID.
/// @return The canonical token's address.
/// @return The canonical token's chain ID.
function canonical() public view returns (address, uint256) {
/// @inheritdoc IBridgedERC1155
function canonical() external view returns (address, uint256) {
return (srcToken, srcChainId);
}

function supportsInterface(bytes4 _interfaceId) public view override returns (bool) {
return _interfaceId == type(IBridgedERC1155).interfaceId
|| _interfaceId == type(IBridgedERC1155Initializable).interfaceId
|| super.supportsInterface(_interfaceId);
}

function _beforeTokenTransfer(
address _operator,
address _from,
Expand Down
58 changes: 27 additions & 31 deletions packages/protocol/contracts/tokenvault/BridgedERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity 0.8.24;

import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol";
import "../common/EssentialContract.sol";
import "../common/LibStrings.sol";
import "./IBridgedERC20.sol";
Expand All @@ -11,7 +12,14 @@ import "./LibBridgedToken.sol";
/// @notice An upgradeable ERC20 contract that represents tokens bridged from
/// another chain.
/// @custom:security-contact security@taiko.xyz
contract BridgedERC20 is EssentialContract, IBridgedERC20, ERC20Upgradeable {
contract BridgedERC20 is
EssentialContract,
IBridgedERC20,
IBridgedERC20Initializable,
IBridgedERC20Migratable,
IERC165Upgradeable,
ERC20Upgradeable
{
/// @dev Slot 1.
address public srcToken;

Expand Down Expand Up @@ -50,14 +58,7 @@ contract BridgedERC20 is EssentialContract, IBridgedERC20, ERC20Upgradeable {
error BTOKEN_INVALID_TO_ADDR();
error BTOKEN_MINT_DISALLOWED();

/// @notice Initializes the contract.
/// @param _owner The owner of this contract. msg.sender will be used if this value is zero.
/// @param _addressManager The address of the {AddressManager} contract.
/// @param _srcToken The source token address.
/// @param _srcChainId The source chain ID.
/// @param _decimals The number of decimal places of the source token.
/// @param _symbol The symbol of the token.
/// @param _name The name of the token.
/// @inheritdoc IBridgedERC20Initializable
function init(
address _owner,
address _addressManager,
Expand All @@ -81,9 +82,7 @@ contract BridgedERC20 is EssentialContract, IBridgedERC20, ERC20Upgradeable {
__srcDecimals = _decimals;
}

/// @notice Start or stop migration to/from a specified contract.
/// @param _migratingAddress The address migrating 'to' or 'from'.
/// @param _migratingInbound If false then signals migrating 'from', true if migrating 'into'.
/// @inheritdoc IBridgedERC20Migratable
function changeMigrationStatus(
address _migratingAddress,
bool _migratingInbound
Expand All @@ -102,9 +101,7 @@ contract BridgedERC20 is EssentialContract, IBridgedERC20, ERC20Upgradeable {
emit MigrationStatusChanged(_migratingAddress, _migratingInbound);
}

/// @notice Mints tokens to the specified account.
/// @param _account The address of the account to receive the tokens.
/// @param _amount The amount of tokens to mint.
/// @inheritdoc IBridgedERC20
function mint(address _account, uint256 _amount) external whenNotPaused nonReentrant {
// mint is disabled while migrating outbound.
if (isMigratingOut()) revert BTOKEN_MINT_DISALLOWED();
Expand All @@ -121,9 +118,7 @@ contract BridgedERC20 is EssentialContract, IBridgedERC20, ERC20Upgradeable {
_mint(_account, _amount);
}

/// @notice Burns tokens in case of 'migrating out' from msg.sender (EOA) or from the ERC20Vault
/// if bridging back to canonical token.
/// @param _amount The amount of tokens to burn.
/// @inheritdoc IBridgedERC20
function burn(uint256 _amount) external whenNotPaused nonReentrant {
if (isMigratingOut()) {
// Outbound migration
Expand All @@ -140,29 +135,30 @@ contract BridgedERC20 is EssentialContract, IBridgedERC20, ERC20Upgradeable {
_burn(msg.sender, _amount);
}

/// @inheritdoc IBridgedERC20
function canonical() external view returns (address, uint256) {
return (srcToken, srcChainId);
}

/// @notice Gets the number of decimal places of the token.
/// @return The number of decimal places of the token.
function decimals() public view override returns (uint8) {
return __srcDecimals;
}

/// @notice Gets the canonical token's address and chain ID.
/// @return The canonical token's address.
/// @return The canonical token's chain ID.
function canonical() public view returns (address, uint256) {
return (srcToken, srcChainId);
}

/// @notice Returns the owner.
/// @return The address of the owner.
function owner() public view override(IBridgedERC20, OwnableUpgradeable) returns (address) {
return OwnableUpgradeable.owner();
}

function isMigratingOut() public view returns (bool) {
return migratingAddress != address(0) && !migratingInbound;
}

function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {
return _interfaceId == type(IBridgedERC20).interfaceId
|| _interfaceId == type(IBridgedERC20Initializable).interfaceId
|| _interfaceId == type(IBridgedERC20Migratable).interfaceId
|| _interfaceId == type(IERC20Upgradeable).interfaceId
|| _interfaceId == type(IERC20MetadataUpgradeable).interfaceId
|| _interfaceId == type(IERC165Upgradeable).interfaceId;
}

function _beforeTokenTransfer(
address _from,
address _to,
Expand Down
38 changes: 16 additions & 22 deletions packages/protocol/contracts/tokenvault/BridgedERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ pragma solidity 0.8.24;
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "../common/EssentialContract.sol";
import "../common/LibStrings.sol";
import "./IBridgedERC721.sol";
import "./LibBridgedToken.sol";

/// @title BridgedERC721
/// @notice Contract for bridging ERC721 tokens across different chains.
/// @custom:security-contact security@taiko.xyz
contract BridgedERC721 is EssentialContract, ERC721Upgradeable {
contract BridgedERC721 is
EssentialContract,
IBridgedERC721,
IBridgedERC721Initializable,
ERC721Upgradeable
{
/// @notice Address of the source token contract.
address public srcToken;

Expand All @@ -22,13 +28,7 @@ contract BridgedERC721 is EssentialContract, ERC721Upgradeable {
error BTOKEN_INVALID_TO_ADDR();
error BTOKEN_INVALID_BURN();

/// @notice Initializes the contract.
/// @param _owner The owner of this contract. msg.sender will be used if this value is zero.
/// @param _addressManager The address of the {AddressManager} contract.
/// @param _srcToken Address of the source token.
/// @param _srcChainId Source chain ID.
/// @param _symbol Symbol of the bridged token.
/// @param _name Name of the bridged token.
/// @inheritdoc IBridgedERC721Initializable
function init(
address _owner,
address _addressManager,
Expand All @@ -49,9 +49,7 @@ contract BridgedERC721 is EssentialContract, ERC721Upgradeable {
srcChainId = _srcChainId;
}

/// @dev Mints tokens.
/// @param _account Address to receive the minted token.
/// @param _tokenId ID of the token to mint.
/// @inheritdoc IBridgedERC721
function mint(
address _account,
uint256 _tokenId
Expand All @@ -64,8 +62,7 @@ contract BridgedERC721 is EssentialContract, ERC721Upgradeable {
_safeMint(_account, _tokenId);
}

/// @dev Burns tokens.
/// @param _tokenId ID of the token to burn.
/// @inheritdoc IBridgedERC721
function burn(uint256 _tokenId)
external
whenNotPaused
Expand All @@ -80,10 +77,8 @@ contract BridgedERC721 is EssentialContract, ERC721Upgradeable {
_burn(_tokenId);
}

/// @notice Gets the source token and source chain ID being bridged.
/// @return The source token's address.
/// @return The source token's chain ID.
function source() public view returns (address, uint256) {
/// @inheritdoc IBridgedERC721
function canonical() external view returns (address, uint256) {
return (srcToken, srcChainId);
}

Expand All @@ -97,11 +92,10 @@ contract BridgedERC721 is EssentialContract, ERC721Upgradeable {
return LibBridgedToken.buildURI(srcToken, srcChainId, Strings.toString(_tokenId));
}

/// @notice Gets the canonical token's address and chain ID.
/// @return The canonical token's address.
/// @return The canonical token's chain ID.
function canonical() public view returns (address, uint256) {
return (srcToken, srcChainId);
function supportsInterface(bytes4 _interfaceId) public view override returns (bool) {
return _interfaceId == type(IBridgedERC721).interfaceId
|| _interfaceId == type(IBridgedERC721Initializable).interfaceId
|| super.supportsInterface(_interfaceId);
}

function _beforeTokenTransfer(
Expand Down
22 changes: 9 additions & 13 deletions packages/protocol/contracts/tokenvault/ERC1155Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol";
import "../libs/LibAddress.sol";
import "../common/LibStrings.sol";
import "./IBridgedERC1155.sol";
import "./BaseNFTVault.sol";
import "./BridgedERC1155.sol";

/// @title ERC1155Vault
/// @dev Labeled in AddressResolver as "erc1155_vault"
Expand Down Expand Up @@ -43,7 +43,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable {
if (_op.amounts[i] == 0) revert VAULT_INVALID_AMOUNT();
}
// Check token interface support
if (!_op.token.supportsInterface(ERC1155_INTERFACE_ID)) {
if (!_op.token.supportsInterface(type(IERC1155).interfaceId)) {
revert VAULT_INTERFACE_NOT_SUPPORTED();
}

Expand Down Expand Up @@ -220,7 +220,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable {
} else {
// Token does not live on this chain
token = _getOrDeployBridgedToken(ctoken);
BridgedERC1155(token).mintBatch(to, tokenIds, amounts);
IBridgedERC1155(token).mintBatch(to, tokenIds, amounts);
}
}

Expand All @@ -238,10 +238,10 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable {
CanonicalNFT storage _ctoken = bridgedToCanonical[_op.token];
if (_ctoken.addr != address(0)) {
ctoken_ = _ctoken;
BridgedERC1155(_op.token).safeBatchTransferFrom(
IERC1155(_op.token).safeBatchTransferFrom(
msg.sender, address(this), _op.tokenIds, _op.amounts, ""
);
BridgedERC1155(_op.token).burnBatch(_op.tokenIds, _op.amounts);
IBridgedERC1155(_op.token).burnBatch(_op.tokenIds, _op.amounts);
} else {
// is a ctoken token, meaning, it lives on this chain
ctoken_ = CanonicalNFT({
Expand All @@ -251,13 +251,9 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable {
name: safeName(_op.token)
});

IERC1155(_op.token).safeBatchTransferFrom({
from: msg.sender,
to: address(this),
ids: _op.tokenIds,
amounts: _op.amounts,
data: ""
});
IERC1155(_op.token).safeBatchTransferFrom(
msg.sender, address(this), _op.tokenIds, _op.amounts, ""
);
}
}
msgData_ = abi.encodeCall(
Expand Down Expand Up @@ -286,7 +282,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable {
/// @return btoken_ Address of the deployed bridged token contract.
function _deployBridgedToken(CanonicalNFT memory _ctoken) private returns (address btoken_) {
bytes memory data = abi.encodeCall(
BridgedERC1155.init,
IBridgedERC1155Initializable.init,
(owner(), addressManager, _ctoken.addr, _ctoken.chainId, _ctoken.symbol, _ctoken.name)
);

Expand Down
Loading

0 comments on commit 13ad99d

Please sign in to comment.