Skip to content

Commit

Permalink
refactor(protocol): add batch transfer and burn for BridgedERC721 (#1…
Browse files Browse the repository at this point in the history
…7058)

Co-authored-by: Keszey Dániel <keszeyd@MacBook-Pro.local>
Co-authored-by: D <51912515+adaki2004@users.noreply.github.com>
Co-authored-by: adaki2004 <adaki2004@users.noreply.github.com>
Co-authored-by: dantaik <dantaik@users.noreply.github.com>
  • Loading branch information
5 people authored May 9, 2024
1 parent a659417 commit cfc8fa8
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 24 deletions.
30 changes: 19 additions & 11 deletions packages/protocol/contracts/tokenvault/BridgedERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,41 @@ contract BridgedERC721 is EssentialContract, ERC721Upgradeable {

/// @dev Mints tokens.
/// @param _account Address to receive the minted token.
/// @param _tokenId ID of the token to mint.
function mint(
/// @param _tokenIds IDs of the tokens to mint.
function batchMint(
address _account,
uint256 _tokenId
uint256[] memory _tokenIds
)
external
whenNotPaused
onlyFromNamed(LibStrings.B_ERC721_VAULT)
nonReentrant
{
_safeMint(_account, _tokenId);
for (uint256 i; i < _tokenIds.length; ++i) {
_safeMint(_account, _tokenIds[i]);
}
}

/// @dev Burns tokens.
/// @param _tokenId ID of the token to burn.
function burn(uint256 _tokenId)
/// @param _tokenIds IDs of the tokens to burn.
function batchBurn(uint256[] memory _tokenIds)
external
whenNotPaused
onlyFromNamed(LibStrings.B_ERC721_VAULT)
nonReentrant
{
// Check if the caller is the owner of the token. Somehow this is not done inside the
// _burn() function below.
if (ownerOf(_tokenId) != msg.sender) {
revert BTOKEN_INVALID_BURN();
for (uint256 i; i < _tokenIds.length; ++i) {
// Check if the caller is the owner of the token. Somehow this is not done inside the
// _burn() function below.
if (ownerOf(_tokenIds[i]) != msg.sender) revert BTOKEN_INVALID_BURN();
_burn(_tokenIds[i]);
}
}

function safeBatchTransferFrom(address _from, address _to, uint256[] memory _tokenIds) public {
for (uint256 i; i < _tokenIds.length; ++i) {
safeTransferFrom(_from, _to, _tokenIds[i], "");
}
_burn(_tokenId);
}

/// @notice Gets the source token and source chain ID being bridged.
Expand Down
18 changes: 6 additions & 12 deletions packages/protocol/contracts/tokenvault/ERC721Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,7 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver {
}
} else {
token_ = _getOrDeployBridgedToken(_ctoken);
for (uint256 i; i < _tokenIds.length; ++i) {
BridgedERC721(token_).mint(_to, _tokenIds[i]);
}
BridgedERC721(token_).batchMint(_to, _tokenIds);
}
}

Expand All @@ -196,12 +194,10 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver {
CanonicalNFT storage _ctoken = bridgedToCanonical[_op.token];
if (_ctoken.addr != address(0)) {
ctoken_ = _ctoken;
for (uint256 i; i < _op.tokenIds.length; ++i) {
BridgedERC721(_op.token).safeTransferFrom(
msg.sender, address(this), _op.tokenIds[i]
);
BridgedERC721(_op.token).burn(_op.tokenIds[i]);
}
BridgedERC721(_op.token).safeBatchTransferFrom(
msg.sender, address(this), _op.tokenIds
);
BridgedERC721(_op.token).batchBurn(_op.tokenIds);
} else {
ctoken_ = CanonicalNFT({
chainId: uint64(block.chainid),
Expand All @@ -211,9 +207,7 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver {
});

for (uint256 i; i < _op.tokenIds.length; ++i) {
ERC721Upgradeable(_op.token).safeTransferFrom(
msg.sender, address(this), _op.tokenIds[i]
);
IERC721(_op.token).safeTransferFrom(msg.sender, address(this), _op.tokenIds[i]);
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/protocol/test/tokenvault/ERC721Vault.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,10 @@ contract ERC721VaultTest is TaikoTest {
// Also Vault cannot burn tokens it does not own (even if the priv key compromised)
vm.prank(address(destChainErc721Vault), address(destChainErc721Vault));
vm.expectRevert(BridgedERC721.BTOKEN_INVALID_BURN.selector);
BridgedERC721(deployedContract).burn(1);

tokenIds = new uint256[](1);
tokenIds[0] = 1;
BridgedERC721(deployedContract).batchBurn(tokenIds);

// After approve() ERC721Vault can transfer and burn
vm.prank(Alice, Alice);
Expand Down

0 comments on commit cfc8fa8

Please sign in to comment.