Skip to content

Commit

Permalink
Merge pull request #27 from ronin-chain/test/support-ERC1155--batch
Browse files Browse the repository at this point in the history
test: support erc1155 batch
  • Loading branch information
nxqbao authored Apr 11, 2024
2 parents 0138197 + 10772a6 commit b6465de
Show file tree
Hide file tree
Showing 6 changed files with 305 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/mocks/token/MockERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ contract MockERC1155 is ERC1155 {
function mint(address to, uint256 id, uint256 amount) external {
_mint(to, id, amount, "");
}

function mintBatch(address to, uint256[] calldata ids, uint256[] calldata amounts) external {
_mintBatch(to, ids, amounts, "");
}
}
36 changes: 33 additions & 3 deletions test/bridge/integration/BaseIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,19 @@ import { MockERC1155Deploy } from "@ronin/script/contracts/token/MockERC1155Depl
import { RoninBridgeAdminUtils } from "test/helpers/RoninBridgeAdminUtils.t.sol";
import { MainchainBridgeAdminUtils } from "test/helpers/MainchainBridgeAdminUtils.t.sol";

contract MockPoisonERC20 is MockERC20 {
constructor(string memory name_, string memory symbol_) MockERC20(name_, symbol_) { }

function setApprovalForAll(address spender, bool approved) public {
_approve(msg.sender, spender, approved ? type(uint256).max : 0);

emit Approval(msg.sender, spender, type(uint256).max);
}
}

contract BaseIntegration_Test is Base_Test {
address sender;

IGeneralConfig _config;
ISharedArgument.SharedParameter _param;

Expand Down Expand Up @@ -97,6 +109,11 @@ contract BaseIntegration_Test is Base_Test {
RoninBridgeAdminUtils _roninProposalUtils;
MainchainBridgeAdminUtils _mainchainProposalUtils;

MockERC20 _mainchainMockERC20;
MockPoisonERC20 _mainchainMockPoisonERC20;
MockERC20 _roninMockERC20;
MockPoisonERC20 _roninMockPoisonERC20;

function setUp() public virtual {
_deployGeneralConfig();

Expand All @@ -113,6 +130,8 @@ contract BaseIntegration_Test is Base_Test {
_configEmergencyPauserForMainchainGateway();

_configBridgeTrackingForRoninGateway();

sender = makeAddr("sender");
}

function _deployContractsOnRonin() internal {
Expand All @@ -130,6 +149,8 @@ contract BaseIntegration_Test is Base_Test {
_roninUsdc = new USDCDeploy().run();
_roninMockERC721 = new MockERC721Deploy().run();
_roninMockERC1155 = new MockERC1155Deploy().run();
_roninMockERC20 = new MockERC20("MockERC20", "ME2");
_roninMockPoisonERC20 = new MockPoisonERC20("MockPoisonERC20", "MPE2");

_param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments();
_roninProposalUtils =
Expand All @@ -148,6 +169,8 @@ contract BaseIntegration_Test is Base_Test {
_mainchainUsdc = new USDCDeploy().run();
_mainchainMockERC721 = new MockERC721Deploy().run();
_mainchainMockERC1155 = new MockERC1155Deploy().run();
_mainchainMockERC20 = new MockERC20("MockERC20", "ME2");
_mainchainMockPoisonERC20 = new MockPoisonERC20("MockPoisonERC20", "MPE2");

_param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments();
_mainchainProposalUtils = new MainchainBridgeAdminUtils(
Expand Down Expand Up @@ -241,7 +264,8 @@ contract BaseIntegration_Test is Base_Test {
}

function _roninGatewayV3Initialize() internal {
(address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards) = _getMainchainAndRoninTokens();
(address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards) =
_getMainchainAndRoninTokens();
uint256 tokenNum = mainchainTokens.length; // reserve slot for ERC721Tokens
uint256[] memory minimumThreshold = new uint256[](tokenNum);
uint256[] memory chainIds = new uint256[](tokenNum);
Expand Down Expand Up @@ -436,7 +460,8 @@ contract BaseIntegration_Test is Base_Test {
}

function _mainchainGatewayV3Initialize() internal {
(address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards) = _getMainchainAndRoninTokens();
(address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards) =
_getMainchainAndRoninTokens();
uint256 tokenNum = mainchainTokens.length;
uint256[] memory highTierThreshold = new uint256[](tokenNum);
uint256[] memory lockedThreshold = new uint256[](tokenNum);
Expand Down Expand Up @@ -491,7 +516,7 @@ contract BaseIntegration_Test is Base_Test {
view
returns (address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards)
{
uint256 tokenNum = 6;
uint256 tokenNum = 8;
mainchainTokens = new address[](tokenNum);
roninTokens = new address[](tokenNum);
standards = new TokenStandard[](tokenNum);
Expand All @@ -502,20 +527,25 @@ contract BaseIntegration_Test is Base_Test {
mainchainTokens[3] = address(_mainchainUsdc);
mainchainTokens[4] = address(_mainchainMockERC721);
mainchainTokens[5] = address(_mainchainMockERC1155);
mainchainTokens[6] = address(_mainchainMockERC20);
mainchainTokens[7] = address(_mainchainMockPoisonERC20);

roninTokens[0] = address(_roninWeth);
roninTokens[1] = address(_roninAxs);
roninTokens[2] = address(_roninSlp);
roninTokens[3] = address(_roninUsdc);
roninTokens[4] = address(_roninMockERC721);
roninTokens[5] = address(_roninMockERC1155);
roninTokens[6] = address(_roninMockERC20);
roninTokens[7] = address(_roninMockPoisonERC20);

standards[0] = TokenStandard.ERC20;
standards[1] = TokenStandard.ERC20;
standards[2] = TokenStandard.ERC20;
standards[3] = TokenStandard.ERC20;
standards[4] = TokenStandard.ERC721;
standards[5] = TokenStandard.ERC1155;
standards[6] = TokenStandard.ERC20;
}

function _changeAdminOnRonin() internal {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { BaseIntegration_Test, MockERC721, MockERC1155 } from "../BaseIntegration.t.sol";
import { TokenStandard } from "@ronin/contracts/libraries/LibTokenInfo.sol";
import { RequestBatch } from "@ronin/contracts/libraries/LibRequestBatch.sol";

contract MainchainGatewayBatcherTest is BaseIntegration_Test {
function testConcrete_RevertIf_WrongTokenStandardERC1155_requestDepositForBatch_ERC721() external {
_mainchainMockERC721.mint(sender, 1);

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockERC721);
req.info.erc = TokenStandard.ERC1155; // ERC1155 instead of ERC721
req.info.ids = new uint256[](1);
req.info.ids[0] = 1;
req.info.quantities = new uint256[](1);
req.info.quantities[0] = 1;

vm.startPrank(sender);
_mainchainMockERC721.setApprovalForAll(address(_mainchainGatewayBatcher), true);
vm.expectRevert();
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();
}

function testConcrete_RevertIf_WrongTokenStandardERC721_requestDepositForBatch_ERC1155() external {
_mainchainMockERC1155.mint(sender, 1, 1);

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockERC1155);
req.info.erc = TokenStandard.ERC721; // ERC721 instead of ERC1155
req.info.ids = new uint256[](1);
req.info.ids[0] = 1;

vm.startPrank(sender);
_mainchainMockERC1155.setApprovalForAll(address(_mainchainGatewayBatcher), true);
vm.expectRevert();
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();
}

function testConcrete_RevertIf_WrongTokenStandardERC20_requestDepositForBatch_ERC721() external {
_mainchainMockERC721.mint(sender, 1);

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockERC721);
req.info.erc = TokenStandard.ERC20; // ERC20 instead of ERC721
req.info.ids = new uint256[](1);
req.info.ids[0] = 1;

vm.startPrank(sender);
_mainchainMockERC721.setApprovalForAll(address(_mainchainGatewayBatcher), true);
vm.expectRevert();
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();
}

function testConcrete_RevertIf_WrongTokenStandardERC721_requestDepositForBatch_ERC20() external {
deal(address(_mainchainMockERC20), sender, 1);

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockERC20);
req.info.erc = TokenStandard.ERC721; // ERC721 instead of ERC20
req.info.ids = new uint256[](1);
req.info.ids[0] = 1;

vm.startPrank(sender);
_mainchainMockERC20.approve(address(_mainchainGatewayBatcher), 1);
vm.expectRevert();
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();
}

function testConcrete_RevertIf_WrongTokenStandardERC721_requestDepositForBatch_PoisonERC20() external {
deal(address(_mainchainMockPoisonERC20), sender, 1);

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockPoisonERC20);
req.info.erc = TokenStandard.ERC721; // ERC721 instead of ERC20
req.info.ids = new uint256[](1);
req.info.ids[0] = 1;

vm.startPrank(sender);
_mainchainMockPoisonERC20.setApprovalForAll(address(_mainchainGatewayBatcher), true);
vm.expectRevert();
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();
}

function testConcrete_RevertIf_WrongTokenStandardERC20_requestDepositForBatch_ERC1155() external {
_mainchainMockERC1155.mint(sender, 1, 1);

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockERC1155);
req.info.erc = TokenStandard.ERC20; // ERC20 instead of ERC1155
req.info.ids = new uint256[](1);
req.info.ids[0] = 1;

vm.startPrank(sender);
_mainchainMockERC1155.setApprovalForAll(address(_mainchainGatewayBatcher), true);
vm.expectRevert();
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();
}

function testConcrete_RevertIf_LengthMismatch_requestDepositForBatch_ERC1155() external {
_mainchainMockERC1155.mint(sender, 1, 1);

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockERC1155);
req.info.erc = TokenStandard.ERC1155;
req.info.ids = new uint256[](1);
req.info.ids[0] = 1;
req.info.quantities = new uint256[](2); // Length mismatch

vm.startPrank(sender);
_mainchainMockERC1155.setApprovalForAll(address(_mainchainGatewayBatcher), true);
vm.expectRevert();
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();
}

function testFuzz_requestDepositBatch_ERC1155(uint256[] calldata ids) external {
uint256[] memory amounts = new uint256[](ids.length);

vm.assume(ids.length != 0);
vm.assume(!hasDuplicate(ids));
vm.assume(ids.length == amounts.length);

for (uint256 i; i < ids.length; i++) {
amounts[i] = 1;
}
for (uint256 i; i < ids.length; i++) {
_mainchainMockERC1155.mint(sender, ids[i], amounts[i]);
}

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockERC1155);
req.info.erc = TokenStandard.ERC1155;
req.info.ids = ids;
req.info.quantities = new uint256[](ids.length);
for (uint256 i; i < ids.length; i++) {
req.info.quantities[i] = 1;
}

vm.startPrank(sender);
_mainchainMockERC1155.setApprovalForAll(address(_mainchainGatewayBatcher), true);
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();

for (uint256 i; i < ids.length; i++) {
assertEq(_mainchainMockERC1155.balanceOf(sender, ids[i]), 0);
assertEq(_mainchainMockERC1155.balanceOf(address(_mainchainGatewayV3), ids[i]), 1);
}
}

function testFuzz_requestDepositBatch_ERC721(uint256[] calldata ids) external {
vm.assume(ids.length != 0);
vm.assume(!hasDuplicate(ids));

for (uint256 i; i < ids.length; i++) {
_mainchainMockERC721.mint(sender, ids[i]);
}

RequestBatch memory req;
req.recipient = sender;
req.tokenAddr = address(_mainchainMockERC721);
req.info.erc = TokenStandard.ERC721;
req.info.ids = ids;

vm.startPrank(sender);
for (uint256 i; i < ids.length; i++) {
_mainchainMockERC721.approve(address(_mainchainGatewayBatcher), ids[i]);
}
_mainchainGatewayBatcher.requestDepositForBatch(req);
vm.stopPrank();

for (uint256 i; i < ids.length; i++) {
assertEq(_mainchainMockERC721.ownerOf(ids[i]), address(_mainchainGatewayV3));
}
}

function hasDuplicate(uint256[] memory A) internal pure returns (bool) {
if (A.length == 0) {
return false;
}
unchecked {
for (uint256 i = 0; i < A.length - 1; i++) {
for (uint256 j = i + 1; j < A.length; j++) {
if (A[i] == A[j]) {
return true;
}
}
}
}

return false;
}
}
27 changes: 27 additions & 0 deletions test/libraries/LibTokenInfo.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { Test } from "forge-std/Test.sol";
import { TokenStandard, TokenInfo, LibTokenInfo } from "@ronin/contracts/libraries/LibTokenInfo.sol";

contract LibTokenInfoTest is Test {
bytes32 typeHash;

function setUp() external {
typeHash = LibTokenInfo.INFO_TYPE_HASH_SINGLE;
}

function testFuzz_hash(uint8 _erc, uint256 id, uint256 quantity) external {
_erc = uint8(_bound(_erc, 0, 2));
TokenStandard erc;
assembly {
erc := _erc
}
TokenInfo memory self = TokenInfo({ erc: erc, id: id, quantity: quantity });
bytes32 hash = typeHash;
assertTrue(hash != 0, "typeHash is zero");
bytes32 expected = keccak256(abi.encode(hash, self.erc, self.id, self.quantity));
bytes32 actual = LibTokenInfo.hash(self);
assertEq(actual, expected, "hash mismatch");
}
}
14 changes: 14 additions & 0 deletions test/libraries/LibTokenInfoBatch.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { Test } from "forge-std/Test.sol";
import { TokenStandard, TokenInfoBatch, LibTokenInfoBatch } from "@ronin/contracts/libraries/LibTokenInfoBatch.sol";

contract LibTokenInfoBatchTest is Test {
function testConcrete_RevertIf_InvalidTokenInfoBatch() external {
TokenInfoBatch memory self;
self.erc = TokenStandard.ERC1155;
vm.expectRevert();
LibTokenInfoBatch.validate(self, LibTokenInfoBatch.checkERC1155Batch);
}
}
19 changes: 19 additions & 0 deletions test/libraries/LibTokenOwner.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { Test } from "forge-std/Test.sol";
import { TokenOwner, LibTokenOwner } from "@ronin/contracts/libraries/LibTokenOwner.sol";

contract LibTokenOwnerTest is Test {
bytes32 _typeHash;

function setUp() external {
_typeHash = LibTokenOwner.OWNER_TYPE_HASH;
}

function testFuzz_hash(TokenOwner memory self) external {
bytes32 expected = keccak256(abi.encode(_typeHash, self.addr, self.tokenAddr, self.chainId));
bytes32 actual = LibTokenOwner.hash(self);
assertEq(actual, expected, "hash mismatch");
}
}

0 comments on commit b6465de

Please sign in to comment.