From 60d942989a5cad4753325ed8249a4ccaa4fe6330 Mon Sep 17 00:00:00 2001 From: Ignacio Mazzara Date: Sun, 2 May 2021 20:38:46 -0300 Subject: [PATCH] feat: withdrawFor --- artifacts/ChildERC1155.json | 2 +- artifacts/ChildERC20.json | 2 +- artifacts/ChildERC721.json | 2 +- artifacts/ChildMintableERC1155.json | 2 +- artifacts/ChildMintableERC20.json | 2 +- artifacts/ChildMintableERC721.json | 2 +- artifacts/MaticWETH.json | 2 +- contracts/child/ChildToken/ChildERC1155.sol | 30 + contracts/child/ChildToken/ChildERC20.sol | 11 + contracts/child/ChildToken/ChildERC721.sol | 60 +- .../child/ChildToken/ChildMintableERC1155.sol | 30 + .../child/ChildToken/ChildMintableERC20.sol | 11 + .../child/ChildToken/ChildMintableERC721.sol | 61 + .../UpgradeableChildERC20/UChildERC20.sol | 11 + flat/ChildERC1155.sol | 30 + flat/ChildERC20.sol | 11 + flat/ChildERC721.sol | 60 +- flat/ChildMintableERC1155.sol | 30 + flat/ChildMintableERC20.sol | 11 + flat/ChildMintableERC721.sol | 61 + flat/MaticWETH.sol | 11 + flat/UChildERC20.sol | 11 + test/child/ChildERC1155.test.js | 277 +++ test/child/ChildERC20.test.js | 90 + test/child/ChildERC721.test.js | 221 ++ test/root/Withdraw.test.js | 1841 ++++++++++++++--- 26 files changed, 2564 insertions(+), 318 deletions(-) diff --git a/artifacts/ChildERC1155.json b/artifacts/ChildERC1155.json index ffbea381..768f3f45 100644 --- a/artifacts/ChildERC1155.json +++ b/artifacts/ChildERC1155.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"string","name":"uri_","type":"string"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawBatch","outputs":[],"stateMutability":"nonpayable","type":"function"}]} +{"abi":[{"inputs":[{"internalType":"string","name":"uri_","type":"string"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawForSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawForBatch","outputs":[],"stateMutability":"nonpayable","type":"function"}]} diff --git a/artifacts/ChildERC20.json b/artifacts/ChildERC20.json index 9219c13e..4b6c48c6 100644 --- a/artifacts/ChildERC20.json +++ b/artifacts/ChildERC20.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]} +{"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFor","outputs":[],"stateMutability":"nonpayable","type":"function"}]} diff --git a/artifacts/ChildERC721.json b/artifacts/ChildERC721.json index 5ed68076..f46a5307 100644 --- a/artifacts/ChildERC721.json +++ b/artifacts/ChildERC721.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"metaData","type":"bytes"}],"name":"TransferWithMetadata","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"WithdrawnBatch","type":"event"},{"inputs":[],"name":"BATCH_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdrawBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawWithMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"encodeTokenMetadata","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]} +{"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"metaData","type":"bytes"}],"name":"TransferWithMetadata","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"WithdrawnBatch","type":"event"},{"inputs":[],"name":"BATCH_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdrawBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawWithMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdrawForBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawForWithMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"encodeTokenMetadata","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]} diff --git a/artifacts/ChildMintableERC1155.json b/artifacts/ChildMintableERC1155.json index f1c60d11..bf718afa 100644 --- a/artifacts/ChildMintableERC1155.json +++ b/artifacts/ChildMintableERC1155.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"string","name":"uri_","type":"string"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"}]} +{"abi":[{"inputs":[{"internalType":"string","name":"uri_","type":"string"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawForSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawForBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"}]} diff --git a/artifacts/ChildMintableERC20.json b/artifacts/ChildMintableERC20.json index dc05e9b8..ff7ecbd3 100644 --- a/artifacts/ChildMintableERC20.json +++ b/artifacts/ChildMintableERC20.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"}]} +{"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"}]} diff --git a/artifacts/ChildMintableERC721.json b/artifacts/ChildMintableERC721.json index 122eb1f2..4a8343b9 100644 --- a/artifacts/ChildMintableERC721.json +++ b/artifacts/ChildMintableERC721.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"metaData","type":"bytes"}],"name":"TransferWithMetadata","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"WithdrawnBatch","type":"event"},{"inputs":[],"name":"BATCH_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawnTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdrawBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawWithMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"encodeTokenMetadata","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"}]} +{"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"metaData","type":"bytes"}],"name":"TransferWithMetadata","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"WithdrawnBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address[]","name":"recipients","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"WithdrawnForBatch","type":"event"},{"inputs":[],"name":"BATCH_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawnTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdrawBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawWithMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdrawForBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawForWithMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"encodeTokenMetadata","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"}]} diff --git a/artifacts/MaticWETH.json b/artifacts/MaticWETH.json index 609ecfb5..e227edfa 100644 --- a/artifacts/MaticWETH.json +++ b/artifacts/MaticWETH.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]} +{"abi":[{"inputs":[{"internalType":"address","name":"childChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSITOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFor","outputs":[],"stateMutability":"nonpayable","type":"function"}]} diff --git a/contracts/child/ChildToken/ChildERC1155.sol b/contracts/child/ChildToken/ChildERC1155.sol index ef77ca3c..9b3d1f43 100644 --- a/contracts/child/ChildToken/ChildERC1155.sol +++ b/contracts/child/ChildToken/ChildERC1155.sol @@ -79,4 +79,34 @@ contract ChildERC1155 is { _burnBatch(_msgSender(), ids, amounts); } + + /** + * @notice called when user wants to withdraw single token back to root chain + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param id id to withdraw + * @param amount amount to withdraw + */ + function withdrawForSingle(address recipient, uint256 id, uint256 amount) external { + address sender = _msgSender(); + + safeTransferFrom(sender, recipient, id, amount, bytes("")); + _burn(recipient, id, amount); + } + + /** + * @notice called when user wants to batch withdraw tokens back to root chain + * @dev Should transfer burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param ids ids to withdraw + * @param amounts amounts to withdraw + */ + function withdrawForBatch(address recipient, uint256[] calldata ids, uint256[] calldata amounts) + external + { + address sender = _msgSender(); + + safeBatchTransferFrom(sender, recipient, ids, amounts, bytes("")); + _burnBatch(recipient, ids, amounts); + } } diff --git a/contracts/child/ChildToken/ChildERC20.sol b/contracts/child/ChildToken/ChildERC20.sol index 234d9c07..ce2a446e 100644 --- a/contracts/child/ChildToken/ChildERC20.sol +++ b/contracts/child/ChildToken/ChildERC20.sol @@ -65,4 +65,15 @@ contract ChildERC20 is function withdraw(uint256 amount) external { _burn(_msgSender(), amount); } + + /** + * @notice called when user wants to withdraw tokens back to root chain for another user + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive tokens on the root chain + * @param amount amount of tokens to withdraw + */ + function withdrawFor(address recipient, uint256 amount) external { + _transfer(_msgSender(), recipient, amount); + _burn(recipient, amount); + } } diff --git a/contracts/child/ChildToken/ChildERC721.sol b/contracts/child/ChildToken/ChildERC721.sol index 1312d3f6..921063d3 100644 --- a/contracts/child/ChildToken/ChildERC721.sol +++ b/contracts/child/ChildToken/ChildERC721.sol @@ -100,7 +100,7 @@ contract ChildERC721 is /** * @notice called when user wants to withdraw token back to root chain with arbitrary metadata * @dev Should handle withraw by burning user's token. - * + * * This transaction will be verified when exiting on root chain * * @param tokenId tokenId to withdraw @@ -116,6 +116,64 @@ contract ChildERC721 is } + /** + * @notice called when user wants to withdraw token back to root chain + * @dev Should transfer and burn user's token. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param tokenId tokenId to withdraw + */ + function withdrawFor(address recipient, uint256 tokenId) external { + address sender = _msgSender(); + + require(sender == ownerOf(tokenId), "ChildERC721: INVALID_TOKEN_OWNER"); + + _transfer(sender, recipient, tokenId); + _burn(tokenId); + } + + /** + * @notice called when user wants to withdraw multiple tokens back to root chain + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param tokenIds tokenId list to withdraw + */ + function withdrawForBatch(address recipient, uint256[] calldata tokenIds) external { + address sender = _msgSender(); + uint256 length = tokenIds.length; + + require(length <= BATCH_LIMIT, "ChildERC721: EXCEEDS_BATCH_LIMIT"); + + for (uint256 i; i < length; i++) { + uint256 tokenId = tokenIds[i]; + require(sender == ownerOf(tokenId), string(abi.encodePacked("ChildERC721: INVALID_TOKEN_OWNER ", tokenId))); + _transfer(sender, recipient, tokenId); + _burn(tokenId); + } + emit WithdrawnBatch(recipient, tokenIds); + } + + /** + * @notice called when user wants to withdraw token back to root chain with arbitrary metadata + * @dev Should handle transfer and withraw by burning user's token. + * + * This transaction will be verified when exiting on root chain + * + * @param recipient address that will receive the token on the root chain + * @param tokenId tokenId to withdraw + */ + function withdrawForWithMetadata(address recipient, uint256 tokenId) external { + address sender = _msgSender(); + + require(sender == ownerOf(tokenId), "ChildERC721: INVALID_TOKEN_OWNER"); + + _transfer(sender, recipient, tokenId); + + // Encoding metadata associated with tokenId & emitting event + emit TransferWithMetadata(sender, recipient, tokenId, this.encodeTokenMetadata(tokenId)); + + _burn(tokenId); + } + /** * @notice This method is supposed to be called by client when withdrawing token with metadata * and pass return value of this function as second paramter of `withdrawWithMetadata` method diff --git a/contracts/child/ChildToken/ChildMintableERC1155.sol b/contracts/child/ChildToken/ChildMintableERC1155.sol index ac0d052d..5e4865cc 100644 --- a/contracts/child/ChildToken/ChildMintableERC1155.sol +++ b/contracts/child/ChildToken/ChildMintableERC1155.sol @@ -85,6 +85,36 @@ contract ChildMintableERC1155 is _burnBatch(_msgSender(), ids, amounts); } + /** + * @notice called when user wants to withdraw single token back to root chain + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param id id to withdraw + * @param amount amount to withdraw + */ + function withdrawForSingle(address recipient, uint256 id, uint256 amount) external { + address sender = _msgSender(); + + safeTransferFrom(sender, recipient, id, amount, bytes("")); + _burn(recipient, id, amount); + } + + /** + * @notice called when user wants to batch withdraw tokens back to root chain + * @dev Should transfer burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param ids ids to withdraw + * @param amounts amounts to withdraw + */ + function withdrawForBatch(address recipient, uint256[] calldata ids, uint256[] calldata amounts) + external + { + address sender = _msgSender(); + + safeBatchTransferFrom(sender, recipient, ids, amounts, bytes("")); + _burnBatch(recipient, ids, amounts); + } + /** * @notice See definition of `_mint` in ERC1155 contract * @dev This implementation only allows admins to mint tokens diff --git a/contracts/child/ChildToken/ChildMintableERC20.sol b/contracts/child/ChildToken/ChildMintableERC20.sol index b0f280ea..72b80808 100644 --- a/contracts/child/ChildToken/ChildMintableERC20.sol +++ b/contracts/child/ChildToken/ChildMintableERC20.sol @@ -66,6 +66,17 @@ contract ChildMintableERC20 is _burn(_msgSender(), amount); } + /** + * @notice called when user wants to withdraw tokens back to root chain for another user + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive tokens on the root chain + * @param amount amount of tokens to withdraw + */ + function withdrawFor(address recipient, uint256 amount) external { + _transfer(_msgSender(), recipient, amount); + _burn(recipient, amount); + } + /** * @notice Example function to handle minting tokens on matic chain * @dev Minting can be done as per requirement, diff --git a/contracts/child/ChildToken/ChildMintableERC721.sol b/contracts/child/ChildToken/ChildMintableERC721.sol index 2a10191a..7101a697 100644 --- a/contracts/child/ChildToken/ChildMintableERC721.sol +++ b/contracts/child/ChildToken/ChildMintableERC721.sol @@ -21,6 +21,7 @@ contract ChildMintableERC721 is uint256 public constant BATCH_LIMIT = 20; event WithdrawnBatch(address indexed user, uint256[] tokenIds); + event WithdrawnForBatch(address indexed user, address[] recipients, uint256[] tokenIds); event TransferWithMetadata(address indexed from, address indexed to, uint256 indexed tokenId, bytes metaData); constructor( @@ -140,6 +141,66 @@ contract ChildMintableERC721 is } + /** + * @notice called when user wants to withdraw token back to root chain + * @dev Should transfer and burn user's token. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param tokenId tokenId to withdraw + */ + function withdrawFor(address recipient, uint256 tokenId) external { + address sender = _msgSender(); + + require(sender == ownerOf(tokenId), "ChildERC721: INVALID_TOKEN_OWNER"); + + _transfer(sender, recipient, tokenId); + + withdrawnTokens[tokenId] = true; + _burn(tokenId); + } + + /** + * @notice called when user wants to withdraw multiple tokens back to root chain + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param tokenIds tokenId list to withdraw + */ + function withdrawForBatch(address recipient, uint256[] calldata tokenIds) external { + address sender = _msgSender(); + uint256 length = tokenIds.length; + require(length <= BATCH_LIMIT, "ChildERC721: EXCEEDS_BATCH_LIMIT"); + for (uint256 i; i < length; i++) { + uint256 tokenId = tokenIds[i]; + require(sender == ownerOf(tokenId), string(abi.encodePacked("ChildERC721: INVALID_TOKEN_OWNER ", tokenId))); + _transfer(sender, recipient, tokenId); + withdrawnTokens[tokenId] = true; + _burn(tokenId); + } + emit WithdrawnBatch(recipient, tokenIds); + } + + /** + * @notice called when user wants to withdraw token back to root chain with arbitrary metadata + * @dev Should handle transfer and withraw by burning user's token. + * + * This transaction will be verified when exiting on root chain + * + * @param recipient address that will receive the token on the root chain + * @param tokenId tokenId to withdraw + */ + function withdrawForWithMetadata(address recipient, uint256 tokenId) external { + address sender = _msgSender(); + + require(sender == ownerOf(tokenId), "ChildERC721: INVALID_TOKEN_OWNER"); + + _transfer(sender, recipient, tokenId); + withdrawnTokens[tokenId] = true; + + // Encoding metadata associated with tokenId & emitting event + emit TransferWithMetadata(sender, recipient, tokenId, this.encodeTokenMetadata(tokenId)); + + _burn(tokenId); + } + /** * @notice This method is supposed to be called by client when withdrawing token with metadata * and pass return value of this function as second paramter of `withdrawWithMetadata` method diff --git a/contracts/child/ChildToken/UpgradeableChildERC20/UChildERC20.sol b/contracts/child/ChildToken/UpgradeableChildERC20/UChildERC20.sol index a2bfae64..0371c525 100644 --- a/contracts/child/ChildToken/UpgradeableChildERC20/UChildERC20.sol +++ b/contracts/child/ChildToken/UpgradeableChildERC20/UChildERC20.sol @@ -81,4 +81,15 @@ contract UChildERC20 is function withdraw(uint256 amount) external { _burn(_msgSender(), amount); } + + /** + * @notice called when user wants to withdraw tokens back to root chain for another user + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive tokens on the root chain + * @param amount amount of tokens to withdraw + */ + function withdrawFor(address recipient, uint256 amount) external { + _transfer(_msgSender(), recipient, amount); + _burn(recipient, amount); + } } diff --git a/flat/ChildERC1155.sol b/flat/ChildERC1155.sol index 504c76a9..b79a5aec 100644 --- a/flat/ChildERC1155.sol +++ b/flat/ChildERC1155.sol @@ -1816,4 +1816,34 @@ contract ChildERC1155 is { _burnBatch(_msgSender(), ids, amounts); } + + /** + * @notice called when user wants to withdraw single token back to root chain + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param id id to withdraw + * @param amount amount to withdraw + */ + function withdrawForSingle(address recipient, uint256 id, uint256 amount) external { + address sender = _msgSender(); + + safeTransferFrom(sender, recipient, id, amount, bytes("")); + _burn(recipient, id, amount); + } + + /** + * @notice called when user wants to batch withdraw tokens back to root chain + * @dev Should transfer burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param ids ids to withdraw + * @param amounts amounts to withdraw + */ + function withdrawForBatch(address recipient, uint256[] calldata ids, uint256[] calldata amounts) + external + { + address sender = _msgSender(); + + safeBatchTransferFrom(sender, recipient, ids, amounts, bytes("")); + _burnBatch(recipient, ids, amounts); + } } diff --git a/flat/ChildERC20.sol b/flat/ChildERC20.sol index dc53d143..7c62fd61 100644 --- a/flat/ChildERC20.sol +++ b/flat/ChildERC20.sol @@ -1506,4 +1506,15 @@ contract ChildERC20 is function withdraw(uint256 amount) external { _burn(_msgSender(), amount); } + + /** + * @notice called when user wants to withdraw tokens back to root chain for another user + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive tokens on the root chain + * @param amount amount of tokens to withdraw + */ + function withdrawFor(address recipient, uint256 amount) external { + _transfer(_msgSender(), recipient, amount); + _burn(recipient, amount); + } } diff --git a/flat/ChildERC721.sol b/flat/ChildERC721.sol index 83b571eb..a7029e90 100644 --- a/flat/ChildERC721.sol +++ b/flat/ChildERC721.sol @@ -2203,7 +2203,7 @@ contract ChildERC721 is /** * @notice called when user wants to withdraw token back to root chain with arbitrary metadata * @dev Should handle withraw by burning user's token. - * + * * This transaction will be verified when exiting on root chain * * @param tokenId tokenId to withdraw @@ -2219,6 +2219,64 @@ contract ChildERC721 is } + /** + * @notice called when user wants to withdraw token back to root chain + * @dev Should transfer and burn user's token. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param tokenId tokenId to withdraw + */ + function withdrawFor(address recipient, uint256 tokenId) external { + address sender = _msgSender(); + + require(sender == ownerOf(tokenId), "ChildERC721: INVALID_TOKEN_OWNER"); + + _transfer(sender, recipient, tokenId); + _burn(tokenId); + } + + /** + * @notice called when user wants to withdraw multiple tokens back to root chain + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param tokenIds tokenId list to withdraw + */ + function withdrawForBatch(address recipient, uint256[] calldata tokenIds) external { + address sender = _msgSender(); + uint256 length = tokenIds.length; + + require(length <= BATCH_LIMIT, "ChildERC721: EXCEEDS_BATCH_LIMIT"); + + for (uint256 i; i < length; i++) { + uint256 tokenId = tokenIds[i]; + require(sender == ownerOf(tokenId), string(abi.encodePacked("ChildERC721: INVALID_TOKEN_OWNER ", tokenId))); + _transfer(sender, recipient, tokenId); + _burn(tokenId); + } + emit WithdrawnBatch(recipient, tokenIds); + } + + /** + * @notice called when user wants to withdraw token back to root chain with arbitrary metadata + * @dev Should handle transfer and withraw by burning user's token. + * + * This transaction will be verified when exiting on root chain + * + * @param recipient address that will receive the token on the root chain + * @param tokenId tokenId to withdraw + */ + function withdrawForWithMetadata(address recipient, uint256 tokenId) external { + address sender = _msgSender(); + + require(sender == ownerOf(tokenId), "ChildERC721: INVALID_TOKEN_OWNER"); + + _transfer(sender, recipient, tokenId); + + // Encoding metadata associated with tokenId & emitting event + emit TransferWithMetadata(sender, recipient, tokenId, this.encodeTokenMetadata(tokenId)); + + _burn(tokenId); + } + /** * @notice This method is supposed to be called by client when withdrawing token with metadata * and pass return value of this function as second paramter of `withdrawWithMetadata` method diff --git a/flat/ChildMintableERC1155.sol b/flat/ChildMintableERC1155.sol index 4a841241..98c9dc62 100644 --- a/flat/ChildMintableERC1155.sol +++ b/flat/ChildMintableERC1155.sol @@ -1822,6 +1822,36 @@ contract ChildMintableERC1155 is _burnBatch(_msgSender(), ids, amounts); } + /** + * @notice called when user wants to withdraw single token back to root chain + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param id id to withdraw + * @param amount amount to withdraw + */ + function withdrawForSingle(address recipient, uint256 id, uint256 amount) external { + address sender = _msgSender(); + + safeTransferFrom(sender, recipient, id, amount, bytes("")); + _burn(recipient, id, amount); + } + + /** + * @notice called when user wants to batch withdraw tokens back to root chain + * @dev Should transfer burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param ids ids to withdraw + * @param amounts amounts to withdraw + */ + function withdrawForBatch(address recipient, uint256[] calldata ids, uint256[] calldata amounts) + external + { + address sender = _msgSender(); + + safeBatchTransferFrom(sender, recipient, ids, amounts, bytes("")); + _burnBatch(recipient, ids, amounts); + } + /** * @notice See definition of `_mint` in ERC1155 contract * @dev This implementation only allows admins to mint tokens diff --git a/flat/ChildMintableERC20.sol b/flat/ChildMintableERC20.sol index e92a4055..0b1712ca 100644 --- a/flat/ChildMintableERC20.sol +++ b/flat/ChildMintableERC20.sol @@ -1507,6 +1507,17 @@ contract ChildMintableERC20 is _burn(_msgSender(), amount); } + /** + * @notice called when user wants to withdraw tokens back to root chain for another user + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive tokens on the root chain + * @param amount amount of tokens to withdraw + */ + function withdrawFor(address recipient, uint256 amount) external { + _transfer(_msgSender(), recipient, amount); + _burn(recipient, amount); + } + /** * @notice Example function to handle minting tokens on matic chain * @dev Minting can be done as per requirement, diff --git a/flat/ChildMintableERC721.sol b/flat/ChildMintableERC721.sol index 5618fcf6..9b87ae0e 100644 --- a/flat/ChildMintableERC721.sol +++ b/flat/ChildMintableERC721.sol @@ -2124,6 +2124,7 @@ contract ChildMintableERC721 is uint256 public constant BATCH_LIMIT = 20; event WithdrawnBatch(address indexed user, uint256[] tokenIds); + event WithdrawnForBatch(address indexed user, address[] recipients, uint256[] tokenIds); event TransferWithMetadata(address indexed from, address indexed to, uint256 indexed tokenId, bytes metaData); constructor( @@ -2243,6 +2244,66 @@ contract ChildMintableERC721 is } + /** + * @notice called when user wants to withdraw token back to root chain + * @dev Should transfer and burn user's token. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param tokenId tokenId to withdraw + */ + function withdrawFor(address recipient, uint256 tokenId) external { + address sender = _msgSender(); + + require(sender == ownerOf(tokenId), "ChildERC721: INVALID_TOKEN_OWNER"); + + _transfer(sender, recipient, tokenId); + + withdrawnTokens[tokenId] = true; + _burn(tokenId); + } + + /** + * @notice called when user wants to withdraw multiple tokens back to root chain + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive the token on the root chain + * @param tokenIds tokenId list to withdraw + */ + function withdrawForBatch(address recipient, uint256[] calldata tokenIds) external { + address sender = _msgSender(); + uint256 length = tokenIds.length; + require(length <= BATCH_LIMIT, "ChildERC721: EXCEEDS_BATCH_LIMIT"); + for (uint256 i; i < length; i++) { + uint256 tokenId = tokenIds[i]; + require(sender == ownerOf(tokenId), string(abi.encodePacked("ChildERC721: INVALID_TOKEN_OWNER ", tokenId))); + _transfer(sender, recipient, tokenId); + withdrawnTokens[tokenId] = true; + _burn(tokenId); + } + emit WithdrawnBatch(recipient, tokenIds); + } + + /** + * @notice called when user wants to withdraw token back to root chain with arbitrary metadata + * @dev Should handle transfer and withraw by burning user's token. + * + * This transaction will be verified when exiting on root chain + * + * @param recipient address that will receive the token on the root chain + * @param tokenId tokenId to withdraw + */ + function withdrawForWithMetadata(address recipient, uint256 tokenId) external { + address sender = _msgSender(); + + require(sender == ownerOf(tokenId), "ChildERC721: INVALID_TOKEN_OWNER"); + + _transfer(sender, recipient, tokenId); + withdrawnTokens[tokenId] = true; + + // Encoding metadata associated with tokenId & emitting event + emit TransferWithMetadata(sender, recipient, tokenId, this.encodeTokenMetadata(tokenId)); + + _burn(tokenId); + } + /** * @notice This method is supposed to be called by client when withdrawing token with metadata * and pass return value of this function as second paramter of `withdrawWithMetadata` method diff --git a/flat/MaticWETH.sol b/flat/MaticWETH.sol index 85352df1..d7fbde6a 100644 --- a/flat/MaticWETH.sol +++ b/flat/MaticWETH.sol @@ -1506,6 +1506,17 @@ contract ChildERC20 is function withdraw(uint256 amount) external { _burn(_msgSender(), amount); } + + /** + * @notice called when user wants to withdraw tokens back to root chain for another user + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive tokens on the root chain + * @param amount amount of tokens to withdraw + */ + function withdrawFor(address recipient, uint256 amount) external { + _transfer(_msgSender(), recipient, amount); + _burn(recipient, amount); + } } // File: contracts/child/ChildToken/MaticWETH.sol diff --git a/flat/UChildERC20.sol b/flat/UChildERC20.sol index 213e61bf..0bfff972 100644 --- a/flat/UChildERC20.sol +++ b/flat/UChildERC20.sol @@ -1542,4 +1542,15 @@ contract UChildERC20 is function withdraw(uint256 amount) external { _burn(_msgSender(), amount); } + + /** + * @notice called when user wants to withdraw tokens back to root chain for another user + * @dev Should transfer and burn user's tokens. This transaction will be verified when exiting on root chain + * @param recipient address that will receive tokens on the root chain + * @param amount amount of tokens to withdraw + */ + function withdrawFor(address recipient, uint256 amount) external { + _transfer(_msgSender(), recipient, amount); + _burn(recipient, amount); + } } diff --git a/test/child/ChildERC1155.test.js b/test/child/ChildERC1155.test.js index 11491f5f..364affa8 100644 --- a/test/child/ChildERC1155.test.js +++ b/test/child/ChildERC1155.test.js @@ -172,6 +172,109 @@ contract('ChildERC1155', (accounts) => { }) }) + describe('Should burn tokens on withdrawForSingle', () => { + const withdrawAmount = mockValues.amounts[9] + const depositAmount = withdrawAmount.add(mockValues.amounts[3]) + const tokenId = mockValues.numbers[4] + const user = accounts[0] + const recipient = accounts[1] + let contracts + let oldAccountBalance + let withdrawTx + let transferSingleBurnLog + let transferSingleTransferLog + + before(async() => { + contracts = await deployer.deployFreshChildContracts(accounts) + const depositData = constructERC1155DepositData([tokenId], [depositAmount]) + const DEPOSITOR_ROLE = await contracts.dummyERC1155.DEPOSITOR_ROLE() + await contracts.dummyERC1155.grantRole(DEPOSITOR_ROLE, accounts[0]) + await contracts.dummyERC1155.deposit(user, depositData) + oldAccountBalance = await contracts.dummyERC1155.balanceOf(user, tokenId) + }) + + it('Can receive withdraw tx', async() => { + withdrawTx = await contracts.dummyERC1155.withdrawForSingle(recipient, tokenId, withdrawAmount) + should.exist(withdrawTx) + }) + + it('Should emit TransferSingle log', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + const transferSingleLogs = logs.filter(l => l && l.event === 'TransferSingle') + + transferSingleLogs.length.should.equal(2) + transferSingleBurnLog = transferSingleLogs.pop() + transferSingleTransferLog = transferSingleLogs.pop() + }) + + describe('Correct values should be emitted in Transfer\'s TransferSingle log', () => { + it('Event should be emitted by correct contract', () => { + transferSingleTransferLog.address.should.equal( + contracts.dummyERC1155.address.toLowerCase() + ) + }) + + it('Should emit proper operator', () => { + transferSingleTransferLog.args.operator.should.equal(user) + }) + + it('Should emit proper From', () => { + transferSingleTransferLog.args.from.should.equal(user) + }) + + it('Should emit proper To', () => { + transferSingleTransferLog.args.to.should.equal(recipient) + }) + + it('Should emit correct amount', () => { + const transferLogAmount = new BN(transferSingleTransferLog.args.value.toString()) + transferLogAmount.should.be.bignumber.that.equals(withdrawAmount) + }) + + it('Should emit correct tokenId', () => { + const transferLogTokenId = transferSingleTransferLog.args.id + transferLogTokenId.toNumber().should.equal(tokenId) + }) + }) + + describe('Correct values should be emitted in Burn\'s TransferBatch log', () => { + it('Event should be emitted by correct contract', () => { + transferSingleBurnLog.address.should.equal( + contracts.dummyERC1155.address.toLowerCase() + ) + }) + + it('Should emit proper operator', () => { + transferSingleBurnLog.args.operator.should.equal(user) + }) + + it('Should emit proper From', () => { + transferSingleBurnLog.args.from.should.equal(recipient) + }) + + it('Should emit proper To', () => { + transferSingleBurnLog.args.to.should.equal(mockValues.zeroAddress) + }) + + it('Should emit correct amount', () => { + const transferLogAmount = new BN(transferSingleBurnLog.args.value.toString()) + transferLogAmount.should.be.bignumber.that.equals(withdrawAmount) + }) + + it('Should emit correct tokenId', () => { + const transferLogTokenId = transferSingleBurnLog.args.id + transferLogTokenId.toNumber().should.equal(tokenId) + }) + }) + + it('Withdraw amount should be deducted from user', async() => { + const newAccountBalance = await contracts.dummyERC1155.balanceOf(user, tokenId) + newAccountBalance.should.be.a.bignumber.that.equals( + oldAccountBalance.sub(withdrawAmount) + ) + }) + }) + describe('Should mint tokens on deposit batch', () => { const tokenIdA = mockValues.numbers[8] const tokenIdB = mockValues.numbers[6] @@ -400,4 +503,178 @@ contract('ChildERC1155', (accounts) => { ) }) }) + + describe('Should burn tokens on withdrawBatchFor', () => { + const withdrawAmountA = mockValues.amounts[2] + const withdrawAmountB = mockValues.amounts[2] + const withdrawAmountC = mockValues.amounts[1] + const depositAmountA = withdrawAmountA.add(mockValues.amounts[0]) + const depositAmountB = withdrawAmountA.add(mockValues.amounts[9]) + const depositAmountC = withdrawAmountA.add(mockValues.amounts[6]) + const tokenIdA = mockValues.numbers[4] + const tokenIdB = mockValues.numbers[5] + const tokenIdC = mockValues.numbers[8] + const user = accounts[0] + const recipient = accounts[1] + let contracts + let oldAccountBalanceA + let oldAccountBalanceB + let oldAccountBalanceC + let withdrawTx + let transferBatchTransferLog + let transferBatchBurnLog + + before(async() => { + contracts = await deployer.deployFreshChildContracts(accounts) + const depositData = constructERC1155DepositData( + [tokenIdA, tokenIdB, tokenIdC], + [depositAmountA, depositAmountB, depositAmountC] + ) + const DEPOSITOR_ROLE = await contracts.dummyERC1155.DEPOSITOR_ROLE() + await contracts.dummyERC1155.grantRole(DEPOSITOR_ROLE, accounts[0]) + await contracts.dummyERC1155.deposit(user, depositData) + oldAccountBalanceA = await contracts.dummyERC1155.balanceOf(user, tokenIdA) + oldAccountBalanceB = await contracts.dummyERC1155.balanceOf(user, tokenIdB) + oldAccountBalanceC = await contracts.dummyERC1155.balanceOf(user, tokenIdC) + }) + + it('Can receive withdraw for tx', async() => { + withdrawTx = await contracts.dummyERC1155.withdrawForBatch( + recipient, + [tokenIdA, tokenIdB, tokenIdC], + [withdrawAmountA, withdrawAmountB, withdrawAmountC] + ) + should.exist(withdrawTx) + }) + + it('Should emit TransferBatch log', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + const transferBatchLogs = logs.filter(l => l && l.event === 'TransferBatch') + + transferBatchLogs.length.should.equal(2) + transferBatchBurnLog = transferBatchLogs.pop() + transferBatchTransferLog = transferBatchLogs.pop() + }) + + describe('Correct values should be emitted in Transfer\'s TransferBatch log', () => { + it('Event should be emitted by correct contract', () => { + transferBatchTransferLog.address.should.equal( + contracts.dummyERC1155.address.toLowerCase() + ) + }) + + it('Should emit proper operator', () => { + transferBatchTransferLog.args.operator.should.equal(user) + }) + + it('Should emit proper From', () => { + transferBatchTransferLog.args.from.should.equal(user) + }) + + it('Should emit proper To', () => { + transferBatchTransferLog.args.to.should.equal(recipient) + }) + + it('Should emit correct amount for A', () => { + const transferLogAmount = new BN(transferBatchTransferLog.args.values[0].toString()) + transferLogAmount.should.be.bignumber.that.equals(withdrawAmountA) + }) + + it('Should emit correct amount for B', () => { + const transferLogAmount = new BN(transferBatchTransferLog.args.values[1].toString()) + transferLogAmount.should.be.bignumber.that.equals(withdrawAmountB) + }) + + it('Should emit correct amount for C', () => { + const transferLogAmount = new BN(transferBatchTransferLog.args.values[2].toString()) + transferLogAmount.should.be.bignumber.that.equals(withdrawAmountC) + }) + + it('Should emit correct tokenId for A', () => { + const transferLogTokenId = transferBatchTransferLog.args.ids[0] + transferLogTokenId.toNumber().should.equal(tokenIdA) + }) + + it('Should emit correct tokenId for B', () => { + const transferLogTokenId = transferBatchTransferLog.args.ids[1] + transferLogTokenId.toNumber().should.equal(tokenIdB) + }) + + it('Should emit correct tokenId for C', () => { + const transferLogTokenId = transferBatchTransferLog.args.ids[2] + transferLogTokenId.toNumber().should.equal(tokenIdC) + }) + }) + + describe('Correct values should be emitted in Burn\'s TransferBatch log', () => { + it('Event should be emitted by correct contract', () => { + transferBatchBurnLog.address.should.equal( + contracts.dummyERC1155.address.toLowerCase() + ) + }) + + it('Should emit proper operator', () => { + transferBatchBurnLog.args.operator.should.equal(user) + }) + + it('Should emit proper From', () => { + transferBatchBurnLog.args.from.should.equal(recipient) + }) + + it('Should emit proper To', () => { + transferBatchBurnLog.args.to.should.equal(mockValues.zeroAddress) + }) + + it('Should emit correct amount for A', () => { + const transferLogAmount = new BN(transferBatchBurnLog.args.values[0].toString()) + transferLogAmount.should.be.bignumber.that.equals(withdrawAmountA) + }) + + it('Should emit correct amount for B', () => { + const transferLogAmount = new BN(transferBatchBurnLog.args.values[1].toString()) + transferLogAmount.should.be.bignumber.that.equals(withdrawAmountB) + }) + + it('Should emit correct amount for C', () => { + const transferLogAmount = new BN(transferBatchBurnLog.args.values[2].toString()) + transferLogAmount.should.be.bignumber.that.equals(withdrawAmountC) + }) + + it('Should emit correct tokenId for A', () => { + const transferLogTokenId = transferBatchBurnLog.args.ids[0] + transferLogTokenId.toNumber().should.equal(tokenIdA) + }) + + it('Should emit correct tokenId for B', () => { + const transferLogTokenId = transferBatchBurnLog.args.ids[1] + transferLogTokenId.toNumber().should.equal(tokenIdB) + }) + + it('Should emit correct tokenId for C', () => { + const transferLogTokenId = transferBatchBurnLog.args.ids[2] + transferLogTokenId.toNumber().should.equal(tokenIdC) + }) + }) + + it('Withdraw amount should be deducted from user for A', async() => { + const newAccountBalance = await contracts.dummyERC1155.balanceOf(user, tokenIdA) + newAccountBalance.should.be.a.bignumber.that.equals( + oldAccountBalanceA.sub(withdrawAmountA) + ) + }) + + it('Withdraw amount should be deducted from user for B', async() => { + const newAccountBalance = await contracts.dummyERC1155.balanceOf(user, tokenIdB) + newAccountBalance.should.be.a.bignumber.that.equals( + oldAccountBalanceB.sub(withdrawAmountB) + ) + }) + + it('Withdraw amount should be deducted from user for C', async() => { + const newAccountBalance = await contracts.dummyERC1155.balanceOf(user, tokenIdC) + newAccountBalance.should.be.a.bignumber.that.equals( + oldAccountBalanceC.sub(withdrawAmountC) + ) + }) + }) }) diff --git a/test/child/ChildERC20.test.js b/test/child/ChildERC20.test.js index 365d432e..f57b9d55 100644 --- a/test/child/ChildERC20.test.js +++ b/test/child/ChildERC20.test.js @@ -149,4 +149,94 @@ contract('ChildERC20', (accounts) => { ) }) }) + + describe('Should burn tokens on withdrawFor', () => { + const withdrawAmount = mockValues.amounts[2] + const depositAmount = withdrawAmount.add(mockValues.amounts[3]) + const user = accounts[0] + const withdrawer = accounts[1] + let contracts + let oldAccountBalance + let withdrawTx + let transferLogs + let transferTransferLog + let burnTransferLog + + before(async() => { + contracts = await deployer.deployFreshChildContracts(accounts) + const DEPOSITOR_ROLE = await contracts.dummyERC20.DEPOSITOR_ROLE() + await contracts.dummyERC20.grantRole(DEPOSITOR_ROLE, accounts[0]) + const depositData = abi.encode(['uint256'], [depositAmount.toString()]) + await contracts.dummyERC20.deposit(user, depositData) + oldAccountBalance = await contracts.dummyERC20.balanceOf(user) + }) + + it('Can receive withdraw tx', async() => { + withdrawTx = await contracts.dummyERC20.withdrawFor(withdrawer, withdrawAmount) + should.exist(withdrawTx) + }) + + it('Should emit Transfer log', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + transferLogs = logs.filter(l => l && l.event === 'Transfer') + transferLogs.length.should.equal(2) + + burnTransferLog = transferLogs.pop() + transferTransferLog = transferLogs.pop() + }) + + describe('Correct values should be emitted in transfer\s Transfer log', () => { + it('Event should be emitted by correct contract', () => { + transferTransferLog.address.should.equal( + contracts.dummyERC20.address.toLowerCase() + ) + }) + + it('Should emit proper From', () => { + transferTransferLog.args.from.should.equal(user) + }) + + it('Should emit proper To', () => { + transferTransferLog.args.to.should.equal(withdrawer) + }) + + it('Should emit correct amount', () => { + const transferTransferLogAmount = new BN(transferTransferLog.args.value.toString()) + transferTransferLogAmount.should.be.bignumber.that.equals(withdrawAmount) + }) + }) + + describe('Correct values should be emitted in burn\'s Transfer log', () => { + it('Event should be emitted by correct contract', () => { + burnTransferLog.address.should.equal( + contracts.dummyERC20.address.toLowerCase() + ) + }) + + it('Should emit proper From', () => { + burnTransferLog.args.from.should.equal(withdrawer) + }) + + it('Should emit proper To', () => { + burnTransferLog.args.to.should.equal(mockValues.zeroAddress) + }) + + it('Should emit correct amount', () => { + const burnTransferLogAmount = new BN(burnTransferLog.args.value.toString()) + burnTransferLogAmount.should.be.bignumber.that.equals(withdrawAmount) + }) + }) + + it('Withdraw amount should be deducted from user', async() => { + const newWithdrawerAccountBalance = await contracts.dummyERC20.balanceOf(withdrawer) + newWithdrawerAccountBalance.should.be.a.bignumber.that.equals( + new BN('0'), + ) + + const newDepositAccountBalance = await contracts.dummyERC20.balanceOf(user) + newDepositAccountBalance.should.be.a.bignumber.that.equals( + oldAccountBalance.sub(withdrawAmount) + ) + }) + }) }) diff --git a/test/child/ChildERC721.test.js b/test/child/ChildERC721.test.js index 0fe127aa..e5813562 100644 --- a/test/child/ChildERC721.test.js +++ b/test/child/ChildERC721.test.js @@ -240,4 +240,225 @@ contract('ChildERC721', (accounts) => { await expectRevert(contracts.dummyERC721.ownerOf(tokenId), 'ERC721: owner query for nonexistent token') }) }) + + describe('Should burn token on withdrawFor', () => { + const tokenId = mockValues.numbers[6] + const user = accounts[0] + const withdrawer = accounts[1] + let contracts + let withdrawTx + let transferLogs + let transferTransferLog + let burnTransferLog + + before(async() => { + contracts = await deployer.deployFreshChildContracts(accounts) + const depositData = abi.encode(['uint256'], [tokenId]) + const DEPOSITOR_ROLE = await contracts.dummyERC721.DEPOSITOR_ROLE() + await contracts.dummyERC721.grantRole(DEPOSITOR_ROLE, accounts[0]) + await contracts.dummyERC721.deposit(user, depositData) + }) + + it('User should own token', async() => { + const owner = await contracts.dummyERC721.ownerOf(tokenId) + owner.should.equal(user) + }) + + it('Can receive withdraw tx', async() => { + withdrawTx = await contracts.dummyERC721.withdrawFor(withdrawer, tokenId) + should.exist(withdrawTx) + }) + + it('Should emit Transfer log', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + transferLogs = logs.filter(l => l && l.event === 'Transfer') + transferLogs.length.should.equal(2) + + burnTransferLog = transferLogs.pop() + transferTransferLog = transferLogs.pop() + }) + + describe('Correct values should be emitted in transfer\'s Transfer log', () => { + it('Event should be emitted by correct contract', () => { + transferTransferLog.address.should.equal( + contracts.dummyERC721.address.toLowerCase() + ) + }) + + it('Should emit proper From', () => { + transferTransferLog.args.from.should.equal(user) + }) + + it('Should emit proper To', () => { + transferTransferLog.args.to.should.equal(withdrawer) + }) + + it('Should emit correct tokenId', () => { + const transferTransferLogTokenId = transferTransferLog.args.tokenId.toNumber() + transferTransferLogTokenId.should.equal(tokenId) + }) + }) + + describe('Correct values should be emitted in burn\'s Transfer log', () => { + it('Event should be emitted by correct contract', () => { + burnTransferLog.address.should.equal( + contracts.dummyERC721.address.toLowerCase() + ) + }) + + it('Should emit proper From', () => { + burnTransferLog.args.from.should.equal(withdrawer) + }) + + it('Should emit proper To', () => { + burnTransferLog.args.to.should.equal(mockValues.zeroAddress) + }) + + it('Should emit correct tokenId', () => { + const burnTransferLogTokenId = burnTransferLog.args.tokenId.toNumber() + burnTransferLogTokenId.should.equal(tokenId) + }) + }) + + it('Token should not exist after burning', async() => { + await expectRevert(contracts.dummyERC721.ownerOf(tokenId), 'ERC721: owner query for nonexistent token') + }) + }) + + describe('Should burn token on withdrawForBatch', () => { + const tokenId = mockValues.numbers[6] + const tokenId1 = mockValues.numbers[7] + const user = accounts[0] + const withdrawer = accounts[1] + let contracts + let withdrawTx + let transferLogs + let burnTransferLogTokenId + let transferTransferLogTokenId + let burnTransferLogTokenId1 + let transferTransferLogTokenId1 + + before(async() => { + contracts = await deployer.deployFreshChildContracts(accounts) + const DEPOSITOR_ROLE = await contracts.dummyERC721.DEPOSITOR_ROLE() + let depositData = abi.encode(['uint256'], [tokenId]) + await contracts.dummyERC721.grantRole(DEPOSITOR_ROLE, accounts[0]) + await contracts.dummyERC721.deposit(user, depositData) + + depositData = abi.encode(['uint256'], [tokenId1]) + await contracts.dummyERC721.grantRole(DEPOSITOR_ROLE, accounts[0]) + await contracts.dummyERC721.deposit(user, depositData) + }) + + it('User should own token', async() => { + const owner = await contracts.dummyERC721.ownerOf(tokenId) + owner.should.equal(user) + }) + + it('Can receive withdraw tx', async() => { + withdrawTx = await contracts.dummyERC721.withdrawForBatch(withdrawer, [tokenId, tokenId1]) + should.exist(withdrawTx) + }) + + it('Should emit Transfer log', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + transferLogs = logs.filter(l => l && l.event === 'Transfer') + transferLogs.length.should.equal(4) + + burnTransferLogTokenId1 = transferLogs.pop() + transferTransferLogTokenId1 = transferLogs.pop() + burnTransferLogTokenId = transferLogs.pop() + transferTransferLogTokenId = transferLogs.pop() + }) + + describe('Correct values should be emitted in transfer\'s Transfer log for tokenId', () => { + it('Event should be emitted by correct contract', () => { + transferTransferLogTokenId1.address.should.equal( + contracts.dummyERC721.address.toLowerCase() + ) + }) + + it('Should emit proper From', () => { + transferTransferLogTokenId1.args.from.should.equal(user) + }) + + it('Should emit proper To', () => { + transferTransferLogTokenId1.args.to.should.equal(withdrawer) + }) + + it('Should emit correct tokenId', () => { + const transferTransferLogTokenId1TokenId = transferTransferLogTokenId1.args.tokenId.toNumber() + transferTransferLogTokenId1TokenId.should.equal(tokenId1) + }) + }) + + describe('Correct values should be emitted in burn\'s Transfer log for tokenId1', () => { + it('Event should be emitted by correct contract', () => { + burnTransferLogTokenId1.address.should.equal( + contracts.dummyERC721.address.toLowerCase() + ) + }) + + it('Should emit proper From', () => { + burnTransferLogTokenId1.args.from.should.equal(withdrawer) + }) + + it('Should emit proper To', () => { + burnTransferLogTokenId1.args.to.should.equal(mockValues.zeroAddress) + }) + + it('Should emit correct tokenId', () => { + const burnTransferLogTokenId1TokenId = burnTransferLogTokenId1.args.tokenId.toNumber() + burnTransferLogTokenId1TokenId.should.equal(tokenId1) + }) + }) + + describe('Correct values should be emitted in transfer\'s Transfer log for tokenId', () => { + it('Event should be emitted by correct contract', () => { + transferTransferLogTokenId.address.should.equal( + contracts.dummyERC721.address.toLowerCase() + ) + }) + + it('Should emit proper From', () => { + transferTransferLogTokenId.args.from.should.equal(user) + }) + + it('Should emit proper To', () => { + transferTransferLogTokenId.args.to.should.equal(withdrawer) + }) + + it('Should emit correct tokenId', () => { + const transferTransferLogTokenIdTokenId = transferTransferLogTokenId.args.tokenId.toNumber() + transferTransferLogTokenIdTokenId.should.equal(tokenId) + }) + }) + + describe('Correct values should be emitted in burn\'s Transfer log for tokenId', () => { + it('Event should be emitted by correct contract', () => { + burnTransferLogTokenId.address.should.equal( + contracts.dummyERC721.address.toLowerCase() + ) + }) + + it('Should emit proper From', () => { + burnTransferLogTokenId.args.from.should.equal(withdrawer) + }) + + it('Should emit proper To', () => { + burnTransferLogTokenId.args.to.should.equal(mockValues.zeroAddress) + }) + + it('Should emit correct tokenId', () => { + const burnTransferLogTokenIdTokenId = burnTransferLogTokenId.args.tokenId.toNumber() + burnTransferLogTokenIdTokenId.should.equal(tokenId) + }) + }) + + + it('Token should not exist after burning', async() => { + await expectRevert(contracts.dummyERC721.ownerOf(tokenId), 'ERC721: owner query for nonexistent token') + await expectRevert(contracts.dummyERC721.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') + }) + }) }) diff --git a/test/root/Withdraw.test.js b/test/root/Withdraw.test.js index 850de908..368be354 100644 --- a/test/root/Withdraw.test.js +++ b/test/root/Withdraw.test.js @@ -331,12 +331,12 @@ contract('RootChainManager', async(accounts) => { }) }) - describe('Withdraw ERC20 :: non-deposit account', async() => { + describe('Withdraw ERC20 :: withdraw for another account', async() => { const depositAmount = mockValues.amounts[1] let totalDepositedAmount = new BN('0') const withdrawAmount = mockValues.amounts[1] const depositReceiver = accounts[0] - const nonDepositAccount = accounts[1] + const withdrawReceiver = accounts[1] const depositData = abi.encode(['uint256'], [depositAmount.toString()]) let contracts let dummyERC20 @@ -397,13 +397,13 @@ contract('RootChainManager', async(accounts) => { }) it('Can receive withdraw tx', async() => { - withdrawTx = await contracts.child.dummyERC20.withdraw(withdrawAmount, { from: depositReceiver }) + withdrawTx = await contracts.child.dummyERC20.withdrawFor(withdrawReceiver, withdrawAmount, { from: depositReceiver }) should.exist(withdrawTx) }) it('Should emit Transfer log in withdraw tx', () => { const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) - transferLog = logs.find(l => l.event === 'Transfer') + transferLog = logs.filter(l => l && l.event === 'Transfer').pop() should.exist(transferLog) }) @@ -429,7 +429,7 @@ contract('RootChainManager', async(accounts) => { it('Should fail: exit with a random data receipt', async() => { const receipt = await childWeb3.eth.getTransactionReceipt(withdrawTx.receipt.transactionHash) const dummyReceipt = getFakeReceiptBytes(receipt, '') - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -446,14 +446,14 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'RootChainManager: INVALID_PROOF') + { from: depositReceiver }), 'RootChainManager: INVALID_PROOF') }) it('Should fail: exit with a fake amount data in receipt', async() => { const receipt = await childWeb3.eth.getTransactionReceipt( withdrawTx.receipt.transactionHash) const dummyReceipt = getFakeReceiptBytes(receipt, mockValues.bytes32[4]) - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -470,11 +470,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'revert') + { from: depositReceiver }), 'revert') }) it('Should fail to start exit (changed the block number to future block)', async() => { - const logIndex = 0 + const logIndex = 1 const fakeBlockNumber = checkpointData.number + 1 const data = bufferToHex( rlp.encode([ @@ -492,11 +492,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'Leaf index is too big') + { from: depositReceiver }), 'Leaf index is too big') }) it('Should fail to start exit (changed the block number with different encoding)', async() => { - const logIndex = 0 + const logIndex = 1 const fakeBlockNumber = pad(checkpointData.number, 64) const data = bufferToHex( rlp.encode([ @@ -514,12 +514,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert.unspecified(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount })) + { from: depositReceiver })) }) - // call exit from some account other than depositReceiver it('Should start exit', async() => { - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -534,9 +533,8 @@ contract('RootChainManager', async(accounts) => { logIndex ]) ) - // start exit - exitTx = await contracts.root.rootChainManager.exit(data, { from: nonDepositAccount }) + exitTx = await contracts.root.rootChainManager.exit(data, { from: depositReceiver }) should.exist(exitTx) }) @@ -544,7 +542,7 @@ contract('RootChainManager', async(accounts) => { const receipt = await childWeb3.eth.getTransactionReceipt( withdrawTx.receipt.transactionHash) const dummyReceipt = getDiffEncodedReceipt(receipt, mockValues.bytes32[4]) - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -561,11 +559,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') }) it('Should fail: start exit again', async() => { - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -582,11 +580,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') }) it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { - const logIndex = toHex(Array(64).fill(0).join('')) + const logIndex = toHex(Array(63).fill(0).join('')) + '1' const data = bufferToHex( rlp.encode([ headerNumber, @@ -603,7 +601,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') }) it('Should emit Transfer log in exit tx', () => { @@ -613,9 +611,14 @@ contract('RootChainManager', async(accounts) => { }) it('Should have more amount in withdrawer account after withdraw', async() => { - const newAccountBalance = await dummyERC20.balanceOf(depositReceiver) - newAccountBalance.should.be.a.bignumber.that.equals( - accountBalance.add(depositAmount) + const newWithdrawAccountBalance = await dummyERC20.balanceOf(withdrawReceiver) + newWithdrawAccountBalance.should.be.a.bignumber.that.equals( + depositAmount + ) + + const newDepositAccountBalance = await dummyERC20.balanceOf(depositReceiver) + newDepositAccountBalance.should.be.a.bignumber.that.equals( + accountBalance ) }) @@ -627,14 +630,15 @@ contract('RootChainManager', async(accounts) => { }) }) - describe('Withdraw ERC721', async() => { - const depositTokenId = mockValues.numbers[4] - const depositAmount = new BN('1') - const withdrawAmount = new BN('1') + describe('Withdraw ERC20 :: non-deposit account', async() => { + const depositAmount = mockValues.amounts[1] + let totalDepositedAmount = new BN('0') + const withdrawAmount = mockValues.amounts[1] const depositReceiver = accounts[0] - const depositData = abi.encode(['uint256'], [depositTokenId.toString()]) + const nonDepositAccount = accounts[1] + const depositData = abi.encode(['uint256'], [depositAmount.toString()]) let contracts - let dummyERC721 + let dummyERC20 let rootChainManager let accountBalance let contractBalance @@ -646,35 +650,45 @@ contract('RootChainManager', async(accounts) => { before(async() => { contracts = await deployer.deployInitializedContracts(accounts) - dummyERC721 = contracts.root.dummyERC721 + dummyERC20 = contracts.root.dummyERC20 rootChainManager = contracts.root.rootChainManager - await dummyERC721.mint(depositTokenId) - accountBalance = await dummyERC721.balanceOf(accounts[0]) - contractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) + accountBalance = await dummyERC20.balanceOf(accounts[0]) + contractBalance = await dummyERC20.balanceOf(contracts.root.erc20Predicate.address) }) it('Depositor should be able to approve and deposit', async() => { - await dummyERC721.approve(contracts.root.erc721Predicate.address, depositTokenId) - const depositTx = await rootChainManager.depositFor(depositReceiver, dummyERC721.address, depositData) + await dummyERC20.approve(contracts.root.erc20Predicate.address, depositAmount) + const depositTx = await rootChainManager.depositFor(depositReceiver, dummyERC20.address, depositData) + should.exist(depositTx) + totalDepositedAmount = totalDepositedAmount.add(depositAmount) + const syncTx = await syncState({ tx: depositTx }) + should.exist(syncTx) + }) + + it('Second depositor should be able to approve and deposit', async() => { + await dummyERC20.mint(depositAmount) + await dummyERC20.transfer(accounts[2], depositAmount) + await dummyERC20.approve(contracts.root.erc20Predicate.address, mockValues.amounts[2], { from: accounts[2] }) + const depositTx = await rootChainManager.depositFor(accounts[2], dummyERC20.address, depositData, { from: accounts[2] }) should.exist(depositTx) + totalDepositedAmount = totalDepositedAmount.add(depositAmount) const syncTx = await syncState({ tx: depositTx }) should.exist(syncTx) }) it('Deposit amount should be deducted from depositor account', async() => { - const newAccountBalance = await dummyERC721.balanceOf(accounts[0]) + const newAccountBalance = await dummyERC20.balanceOf(accounts[0]) newAccountBalance.should.be.a.bignumber.that.equals( accountBalance.sub(depositAmount) ) - // update account balance accountBalance = newAccountBalance }) it('Deposit amount should be credited to correct contract', async() => { - const newContractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) + const newContractBalance = await dummyERC20.balanceOf(contracts.root.erc20Predicate.address) newContractBalance.should.be.a.bignumber.that.equals( - contractBalance.add(depositAmount) + contractBalance.add(totalDepositedAmount) ) // update balance @@ -682,7 +696,7 @@ contract('RootChainManager', async(accounts) => { }) it('Can receive withdraw tx', async() => { - withdrawTx = await contracts.child.dummyERC721.withdraw(depositTokenId, { from: depositReceiver }) + withdrawTx = await contracts.child.dummyERC20.withdraw(withdrawAmount, { from: depositReceiver }) should.exist(withdrawTx) }) @@ -712,10 +726,9 @@ contract('RootChainManager', async(accounts) => { }) it('Should fail: exit with a random data receipt', async() => { - const receipt = await childWeb3.eth.getTransactionReceipt( - withdrawTx.receipt.transactionHash) + const receipt = await childWeb3.eth.getTransactionReceipt(withdrawTx.receipt.transactionHash) const dummyReceipt = getFakeReceiptBytes(receipt, '') - const logIndex = 1 + const logIndex = 0 const data = bufferToHex( rlp.encode([ headerNumber, @@ -732,14 +745,14 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'revert') + { from: nonDepositAccount }), 'RootChainManager: INVALID_PROOF') }) it('Should fail: exit with a fake amount data in receipt', async() => { const receipt = await childWeb3.eth.getTransactionReceipt( withdrawTx.receipt.transactionHash) const dummyReceipt = getFakeReceiptBytes(receipt, mockValues.bytes32[4]) - const logIndex = 1 + const logIndex = 0 const data = bufferToHex( rlp.encode([ headerNumber, @@ -756,11 +769,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'revert') + { from: nonDepositAccount }), 'revert') }) - it('Should fail to start exit (changed the block number)', async() => { - const logIndex = 1 + it('Should fail to start exit (changed the block number to future block)', async() => { + const logIndex = 0 const fakeBlockNumber = checkpointData.number + 1 const data = bufferToHex( rlp.encode([ @@ -778,11 +791,34 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'Leaf index is too big') + { from: nonDepositAccount }), 'Leaf index is too big') + }) + + it('Should fail to start exit (changed the block number with different encoding)', async() => { + const logIndex = 0 + const fakeBlockNumber = pad(checkpointData.number, 64) + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + fakeBlockNumber, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert.unspecified(contracts.root.rootChainManager.exit(data, + { from: nonDepositAccount })) }) + // call exit from some account other than depositReceiver it('Should start exit', async() => { - const logIndex = 1 + const logIndex = 0 const data = bufferToHex( rlp.encode([ headerNumber, @@ -797,13 +833,38 @@ contract('RootChainManager', async(accounts) => { logIndex ]) ) + // start exit - exitTx = await contracts.root.rootChainManager.exit(data, { from: depositReceiver }) + exitTx = await contracts.root.rootChainManager.exit(data, { from: nonDepositAccount }) should.exist(exitTx) }) + it('Should fail: exit with a differently encoded amount data in receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt( + withdrawTx.receipt.transactionHash) + const dummyReceipt = getDiffEncodedReceipt(receipt, mockValues.bytes32[4]) + const logIndex = 0 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + }) + it('Should fail: start exit again', async() => { - const logIndex = 1 + const logIndex = 0 const data = bufferToHex( rlp.encode([ headerNumber, @@ -820,11 +881,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') + { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') }) it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { - const logIndex = toHex(Array(63).fill(0).join('') + '1') + const logIndex = toHex(Array(64).fill(0).join('')) const data = bufferToHex( rlp.encode([ headerNumber, @@ -841,7 +902,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') + { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') }) it('Should emit Transfer log in exit tx', () => { @@ -851,37 +912,32 @@ contract('RootChainManager', async(accounts) => { }) it('Should have more amount in withdrawer account after withdraw', async() => { - const newAccountBalance = await dummyERC721.balanceOf(depositReceiver) + const newAccountBalance = await dummyERC20.balanceOf(depositReceiver) newAccountBalance.should.be.a.bignumber.that.equals( accountBalance.add(depositAmount) ) }) it('Should have less amount in predicate contract after withdraw', async() => { - const newContractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) + const newContractBalance = await dummyERC20.balanceOf(contracts.root.erc20Predicate.address) newContractBalance.should.be.a.bignumber.that.equals( contractBalance.sub(withdrawAmount) ) }) }) - describe('Withdraw batch ERC721', async() => { - const tokenId1 = mockValues.numbers[4] - const tokenId2 = mockValues.numbers[5] - const tokenId3 = mockValues.numbers[8] - const user = accounts[0] - const depositData = abi.encode( - ['uint256[]'], - [ - [tokenId1.toString(), tokenId2.toString(), tokenId3.toString()] - ] - ) + describe('Withdraw ERC721', async() => { + const depositTokenId = mockValues.numbers[4] + const depositAmount = new BN('1') + const withdrawAmount = new BN('1') + const depositReceiver = accounts[0] + const depositData = abi.encode(['uint256'], [depositTokenId.toString()]) let contracts - let rootToken - let childToken + let dummyERC721 let rootChainManager - let checkpointManager - let erc721Predicate + let accountBalance + let contractBalance + let transferLog let withdrawTx let checkpointData let headerNumber @@ -889,83 +945,55 @@ contract('RootChainManager', async(accounts) => { before(async() => { contracts = await deployer.deployInitializedContracts(accounts) - rootToken = contracts.root.dummyERC721 - childToken = contracts.child.dummyERC721 + dummyERC721 = contracts.root.dummyERC721 rootChainManager = contracts.root.rootChainManager - checkpointManager = contracts.root.checkpointManager - erc721Predicate = contracts.root.erc721Predicate - await rootToken.mint(tokenId1) - await rootToken.mint(tokenId2) - await rootToken.mint(tokenId3) - }) - - it('User should own tokens on root chain', async() => { - { - const owner = await rootToken.ownerOf(tokenId1) - owner.should.equal(user) - } - { - const owner = await rootToken.ownerOf(tokenId2) - owner.should.equal(user) - } - { - const owner = await rootToken.ownerOf(tokenId3) - owner.should.equal(user) - } - }) - - it('Tokens should not exist on child chain', async() => { - await expectRevert(childToken.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') - await expectRevert(childToken.ownerOf(tokenId2), 'ERC721: owner query for nonexistent token') - await expectRevert(childToken.ownerOf(tokenId3), 'ERC721: owner query for nonexistent token') + await dummyERC721.mint(depositTokenId) + accountBalance = await dummyERC721.balanceOf(accounts[0]) + contractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) }) - it('User should be able to approve and deposit', async() => { - await rootToken.setApprovalForAll(erc721Predicate.address, true) - const depositTx = await rootChainManager.depositFor(user, rootToken.address, depositData) + it('Depositor should be able to approve and deposit', async() => { + await dummyERC721.approve(contracts.root.erc721Predicate.address, depositTokenId) + const depositTx = await rootChainManager.depositFor(depositReceiver, dummyERC721.address, depositData) should.exist(depositTx) const syncTx = await syncState({ tx: depositTx }) should.exist(syncTx) }) - it('Predicate should own tokens on root chain', async() => { - { - const owner = await rootToken.ownerOf(tokenId1) - owner.should.equal(erc721Predicate.address) - } - { - const owner = await rootToken.ownerOf(tokenId2) - owner.should.equal(erc721Predicate.address) - } - { - const owner = await rootToken.ownerOf(tokenId3) - owner.should.equal(erc721Predicate.address) - } + it('Deposit amount should be deducted from depositor account', async() => { + const newAccountBalance = await dummyERC721.balanceOf(accounts[0]) + newAccountBalance.should.be.a.bignumber.that.equals( + accountBalance.sub(depositAmount) + ) + + // update account balance + accountBalance = newAccountBalance }) - it('User should own tokens on child chain', async() => { - { - const owner = await childToken.ownerOf(tokenId1) - owner.should.equal(user) - } - { - const owner = await childToken.ownerOf(tokenId2) - owner.should.equal(user) - } - { - const owner = await childToken.ownerOf(tokenId3) - owner.should.equal(user) - } + it('Deposit amount should be credited to correct contract', async() => { + const newContractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) + newContractBalance.should.be.a.bignumber.that.equals( + contractBalance.add(depositAmount) + ) + + // update balance + contractBalance = newContractBalance }) - it('User should be able to start withdraw', async() => { - withdrawTx = await childToken.withdrawBatch([tokenId1, tokenId2, tokenId3]) + it('Can receive withdraw tx', async() => { + withdrawTx = await contracts.child.dummyERC721.withdraw(depositTokenId, { from: depositReceiver }) should.exist(withdrawTx) }) + it('Should emit Transfer log in withdraw tx', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + transferLog = logs.find(l => l.event === 'Transfer') + should.exist(transferLog) + }) + it('Should submit checkpoint', async() => { // submit checkpoint including burn (withdraw) tx - checkpointData = await submitCheckpoint(checkpointManager, withdrawTx.receipt) + checkpointData = await submitCheckpoint(contracts.root.checkpointManager, withdrawTx.receipt) should.exist(checkpointData) }) @@ -974,17 +1002,43 @@ contract('RootChainManager', async(accounts) => { should.exist(root) // fetch latest header number - headerNumber = await checkpointManager.currentCheckpointNumber() + headerNumber = await contracts.root.checkpointManager.currentCheckpointNumber() headerNumber.should.be.bignumber.gt('0') // fetch header block details and validate - const headerData = await checkpointManager.headerBlocks(headerNumber) + const headerData = await contracts.root.checkpointManager.headerBlocks(headerNumber) root.should.equal(headerData.root) }) - it('User should be able to exit', async() => { - const logIndex = withdrawTx.receipt.rawLogs - .findIndex(log => log.topics[0].toLowerCase() === ERC721_WITHDRAW_BATCH_EVENT_SIG.toLowerCase()) + it('Should fail: exit with a random data receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt( + withdrawTx.receipt.transactionHash) + const dummyReceipt = getFakeReceiptBytes(receipt, '') + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'revert') + }) + + it('Should fail: exit with a fake amount data in receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt( + withdrawTx.receipt.transactionHash) + const dummyReceipt = getFakeReceiptBytes(receipt, mockValues.bytes32[4]) + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -993,6 +1047,28 @@ contract('RootChainManager', async(accounts) => { checkpointData.timestamp, bufferToHex(checkpointData.transactionsRoot), bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'revert') + }) + + it('Should fail to start exit (changed the block number)', async() => { + const logIndex = 1 + const fakeBlockNumber = checkpointData.number + 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + fakeBlockNumber, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), bufferToHex(checkpointData.receipt), bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), bufferToHex(checkpointData.path), // branch mask, @@ -1000,38 +1076,100 @@ contract('RootChainManager', async(accounts) => { ]) ) // start exit - exitTx = await contracts.root.rootChainManager.exit(data, { from: user }) + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'Leaf index is too big') + }) + + it('Should start exit', async() => { + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + exitTx = await contracts.root.rootChainManager.exit(data, { from: depositReceiver }) should.exist(exitTx) }) - it('User should own tokens on root chain', async() => { - { - const owner = await rootToken.ownerOf(tokenId1) - owner.should.equal(user) - } - { - const owner = await rootToken.ownerOf(tokenId2) - owner.should.equal(user) - } - { - const owner = await rootToken.ownerOf(tokenId3) - owner.should.equal(user) - } + it('Should fail: start exit again', async() => { + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') }) - it('Tokens should not exist on child chain', async() => { - await expectRevert(childToken.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') - await expectRevert(childToken.ownerOf(tokenId2), 'ERC721: owner query for nonexistent token') - await expectRevert(childToken.ownerOf(tokenId3), 'ERC721: owner query for nonexistent token') + it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { + const logIndex = toHex(Array(63).fill(0).join('') + '1') + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') + }) + + it('Should emit Transfer log in exit tx', () => { + const logs = logDecoder.decodeLogs(exitTx.receipt.rawLogs) + const exitTransferLog = logs.find(l => l.event === 'Transfer') + should.exist(exitTransferLog) + }) + + it('Should have more amount in withdrawer account after withdraw', async() => { + const newAccountBalance = await dummyERC721.balanceOf(depositReceiver) + newAccountBalance.should.be.a.bignumber.that.equals( + accountBalance.add(depositAmount) + ) + }) + + it('Should have less amount in predicate contract after withdraw', async() => { + const newContractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) + newContractBalance.should.be.a.bignumber.that.equals( + contractBalance.sub(withdrawAmount) + ) }) }) - describe('Withdraw ERC721 :: non-deposit account', async() => { + describe('Withdraw ERC721 :: withdraw for another account', async() => { const depositTokenId = mockValues.numbers[4] const depositAmount = new BN('1') const withdrawAmount = new BN('1') const depositReceiver = accounts[0] - const nonDepositAccount = accounts[1] + const withdrawReceiver = accounts[1] const depositData = abi.encode(['uint256'], [depositTokenId.toString()]) let contracts let dummyERC721 @@ -1082,13 +1220,13 @@ contract('RootChainManager', async(accounts) => { }) it('Can receive withdraw tx', async() => { - withdrawTx = await contracts.child.dummyERC721.withdraw(depositTokenId, { from: depositReceiver }) + withdrawTx = await contracts.child.dummyERC721.withdrawFor(withdrawReceiver, depositTokenId, { from: depositReceiver }) should.exist(withdrawTx) }) it('Should emit Transfer log in withdraw tx', () => { const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) - transferLog = logs.find(l => l.event === 'Transfer') + transferLog = logs.filter(l => l && l.event === 'Transfer').pop() should.exist(transferLog) }) @@ -1115,7 +1253,7 @@ contract('RootChainManager', async(accounts) => { const receipt = await childWeb3.eth.getTransactionReceipt( withdrawTx.receipt.transactionHash) const dummyReceipt = getFakeReceiptBytes(receipt, '') - const logIndex = 1 + const logIndex = 3 const data = bufferToHex( rlp.encode([ headerNumber, @@ -1132,14 +1270,14 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'revert') + { from: depositReceiver }), 'revert') }) it('Should fail: exit with a fake amount data in receipt', async() => { const receipt = await childWeb3.eth.getTransactionReceipt( withdrawTx.receipt.transactionHash) const dummyReceipt = getFakeReceiptBytes(receipt, mockValues.bytes32[4]) - const logIndex = 1 + const logIndex = 3 const data = bufferToHex( rlp.encode([ headerNumber, @@ -1156,11 +1294,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'revert') + { from: depositReceiver }), 'revert') }) it('Should fail to start exit (changed the block number)', async() => { - const logIndex = 1 + const logIndex = 3 const fakeBlockNumber = checkpointData.number + 1 const data = bufferToHex( rlp.encode([ @@ -1178,11 +1316,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'Leaf index is too big') + { from: depositReceiver }), 'Leaf index is too big') }) it('Should start exit', async() => { - const logIndex = 1 + const logIndex = 3 const data = bufferToHex( rlp.encode([ headerNumber, @@ -1197,13 +1335,13 @@ contract('RootChainManager', async(accounts) => { logIndex ]) ) - // start exit from non deposit receiver - exitTx = await contracts.root.rootChainManager.exit(data, { from: nonDepositAccount }) + // start exit + exitTx = await contracts.root.rootChainManager.exit(data, { from: depositReceiver }) should.exist(exitTx) }) it('Should fail: start exit again', async() => { - const logIndex = 1 + const logIndex = 3 const data = bufferToHex( rlp.encode([ headerNumber, @@ -1220,11 +1358,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') }) it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { - const logIndex = toHex(Array(63).fill(0).join('') + '1') + const logIndex = toHex(Array(63).fill(0).join('') + '3') const data = bufferToHex( rlp.encode([ headerNumber, @@ -1241,7 +1379,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') }) it('Should emit Transfer log in exit tx', () => { @@ -1251,10 +1389,18 @@ contract('RootChainManager', async(accounts) => { }) it('Should have more amount in withdrawer account after withdraw', async() => { - const newAccountBalance = await dummyERC721.balanceOf(depositReceiver) - newAccountBalance.should.be.a.bignumber.that.equals( - accountBalance.add(depositAmount) + const newWithdrawAccountBalance = await dummyERC721.balanceOf(withdrawReceiver) + newWithdrawAccountBalance.should.be.a.bignumber.that.equals( + depositAmount ) + + const newDepositAccountBalance = await dummyERC721.balanceOf(depositReceiver) + newDepositAccountBalance.should.be.a.bignumber.that.equals( + accountBalance + ) + + const owner = await dummyERC721.ownerOf(depositTokenId) + owner.should.equal(withdrawReceiver) }) it('Should have less amount in predicate contract after withdraw', async() => { @@ -1400,37 +1546,1106 @@ contract('RootChainManager', async(accounts) => { ]) ) // start exit - exitTx = await contracts.root.rootChainManager.exit(data, { from: user }) - should.exist(exitTx) + exitTx = await contracts.root.rootChainManager.exit(data, { from: user }) + should.exist(exitTx) + }) + + it('User should own tokens on root chain', async() => { + { + const owner = await rootToken.ownerOf(tokenId1) + owner.should.equal(user) + } + { + const owner = await rootToken.ownerOf(tokenId2) + owner.should.equal(user) + } + { + const owner = await rootToken.ownerOf(tokenId3) + owner.should.equal(user) + } + }) + + it('Tokens should not exist on child chain', async() => { + await expectRevert(childToken.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId2), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId3), 'ERC721: owner query for nonexistent token') + }) + }) + + describe('Withdraw batch ERC721 :: withdraw for another account', async() => { + const tokenId1 = mockValues.numbers[4] + const tokenId2 = mockValues.numbers[5] + const tokenId3 = mockValues.numbers[8] + const user = accounts[0] + const beneficiary = accounts[1] + const depositData = abi.encode( + ['uint256[]'], + [ + [tokenId1.toString(), tokenId2.toString(), tokenId3.toString()] + ] + ) + let contracts + let rootToken + let childToken + let rootChainManager + let checkpointManager + let erc721Predicate + let withdrawTx + let checkpointData + let headerNumber + let exitTx + + before(async() => { + contracts = await deployer.deployInitializedContracts(accounts) + rootToken = contracts.root.dummyERC721 + childToken = contracts.child.dummyERC721 + rootChainManager = contracts.root.rootChainManager + checkpointManager = contracts.root.checkpointManager + erc721Predicate = contracts.root.erc721Predicate + await rootToken.mint(tokenId1) + await rootToken.mint(tokenId2) + await rootToken.mint(tokenId3) + }) + + it('User should own tokens on root chain', async() => { + { + const owner = await rootToken.ownerOf(tokenId1) + owner.should.equal(user) + } + { + const owner = await rootToken.ownerOf(tokenId2) + owner.should.equal(user) + } + { + const owner = await rootToken.ownerOf(tokenId3) + owner.should.equal(user) + } + }) + + it('Tokens should not exist on child chain', async() => { + await expectRevert(childToken.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId2), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId3), 'ERC721: owner query for nonexistent token') + }) + + it('User should be able to approve and deposit', async() => { + await rootToken.setApprovalForAll(erc721Predicate.address, true) + const depositTx = await rootChainManager.depositFor(user, rootToken.address, depositData) + should.exist(depositTx) + const syncTx = await syncState({ tx: depositTx }) + should.exist(syncTx) + }) + + it('Predicate should own tokens on root chain', async() => { + { + const owner = await rootToken.ownerOf(tokenId1) + owner.should.equal(erc721Predicate.address) + } + { + const owner = await rootToken.ownerOf(tokenId2) + owner.should.equal(erc721Predicate.address) + } + { + const owner = await rootToken.ownerOf(tokenId3) + owner.should.equal(erc721Predicate.address) + } + }) + + it('User should own tokens on child chain', async() => { + { + const owner = await childToken.ownerOf(tokenId1) + owner.should.equal(user) + } + { + const owner = await childToken.ownerOf(tokenId2) + owner.should.equal(user) + } + { + const owner = await childToken.ownerOf(tokenId3) + owner.should.equal(user) + } + }) + + it('User should be able to start withdraw', async() => { + withdrawTx = await childToken.withdrawForBatch(beneficiary, [tokenId1, tokenId2, tokenId3]) + should.exist(withdrawTx) + }) + + it('Should submit checkpoint', async() => { + // submit checkpoint including burn (withdraw) tx + checkpointData = await submitCheckpoint(checkpointManager, withdrawTx.receipt) + should.exist(checkpointData) + }) + + it('Should match checkpoint details', async() => { + const root = bufferToHex(checkpointData.header.root) + should.exist(root) + + // fetch latest header number + headerNumber = await checkpointManager.currentCheckpointNumber() + headerNumber.should.be.bignumber.gt('0') + + // fetch header block details and validate + const headerData = await checkpointManager.headerBlocks(headerNumber) + root.should.equal(headerData.root) + }) + + it('User should be able to exit', async() => { + const logIndex = withdrawTx.receipt.rawLogs + .findIndex(log => log.topics[0].toLowerCase() === ERC721_WITHDRAW_BATCH_EVENT_SIG.toLowerCase()) + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + exitTx = await contracts.root.rootChainManager.exit(data, { from: user }) + should.exist(exitTx) + }) + + it('User should own tokens on root chain', async() => { + { + const owner = await rootToken.ownerOf(tokenId1) + owner.should.equal(beneficiary) + } + { + const owner = await rootToken.ownerOf(tokenId2) + owner.should.equal(beneficiary) + } + { + const owner = await rootToken.ownerOf(tokenId3) + owner.should.equal(beneficiary) + } + }) + + it('Tokens should not exist on child chain', async() => { + await expectRevert(childToken.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId2), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId3), 'ERC721: owner query for nonexistent token') + }) + }) + + describe('Withdraw ERC721 :: non-deposit account', async() => { + const depositTokenId = mockValues.numbers[4] + const depositAmount = new BN('1') + const withdrawAmount = new BN('1') + const depositReceiver = accounts[0] + const nonDepositAccount = accounts[1] + const depositData = abi.encode(['uint256'], [depositTokenId.toString()]) + let contracts + let dummyERC721 + let rootChainManager + let accountBalance + let contractBalance + let transferLog + let withdrawTx + let checkpointData + let headerNumber + let exitTx + + before(async() => { + contracts = await deployer.deployInitializedContracts(accounts) + dummyERC721 = contracts.root.dummyERC721 + rootChainManager = contracts.root.rootChainManager + await dummyERC721.mint(depositTokenId) + accountBalance = await dummyERC721.balanceOf(accounts[0]) + contractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) + }) + + it('Depositor should be able to approve and deposit', async() => { + await dummyERC721.approve(contracts.root.erc721Predicate.address, depositTokenId) + const depositTx = await rootChainManager.depositFor(depositReceiver, dummyERC721.address, depositData) + should.exist(depositTx) + const syncTx = await syncState({ tx: depositTx }) + should.exist(syncTx) + }) + + it('Deposit amount should be deducted from depositor account', async() => { + const newAccountBalance = await dummyERC721.balanceOf(accounts[0]) + newAccountBalance.should.be.a.bignumber.that.equals( + accountBalance.sub(depositAmount) + ) + + // update account balance + accountBalance = newAccountBalance + }) + + it('Deposit amount should be credited to correct contract', async() => { + const newContractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) + newContractBalance.should.be.a.bignumber.that.equals( + contractBalance.add(depositAmount) + ) + + // update balance + contractBalance = newContractBalance + }) + + it('Can receive withdraw tx', async() => { + withdrawTx = await contracts.child.dummyERC721.withdraw(depositTokenId, { from: depositReceiver }) + should.exist(withdrawTx) + }) + + it('Should emit Transfer log in withdraw tx', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + transferLog = logs.find(l => l.event === 'Transfer') + should.exist(transferLog) + }) + + it('Should submit checkpoint', async() => { + // submit checkpoint including burn (withdraw) tx + checkpointData = await submitCheckpoint(contracts.root.checkpointManager, withdrawTx.receipt) + should.exist(checkpointData) + }) + + it('Should match checkpoint details', async() => { + const root = bufferToHex(checkpointData.header.root) + should.exist(root) + + // fetch latest header number + headerNumber = await contracts.root.checkpointManager.currentCheckpointNumber() + headerNumber.should.be.bignumber.gt('0') + + // fetch header block details and validate + const headerData = await contracts.root.checkpointManager.headerBlocks(headerNumber) + root.should.equal(headerData.root) + }) + + it('Should fail: exit with a random data receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt( + withdrawTx.receipt.transactionHash) + const dummyReceipt = getFakeReceiptBytes(receipt, '') + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: nonDepositAccount }), 'revert') + }) + + it('Should fail: exit with a fake amount data in receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt( + withdrawTx.receipt.transactionHash) + const dummyReceipt = getFakeReceiptBytes(receipt, mockValues.bytes32[4]) + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: nonDepositAccount }), 'revert') + }) + + it('Should fail to start exit (changed the block number)', async() => { + const logIndex = 1 + const fakeBlockNumber = checkpointData.number + 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + fakeBlockNumber, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: nonDepositAccount }), 'Leaf index is too big') + }) + + it('Should start exit', async() => { + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit from non deposit receiver + exitTx = await contracts.root.rootChainManager.exit(data, { from: nonDepositAccount }) + should.exist(exitTx) + }) + + it('Should fail: start exit again', async() => { + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + }) + + it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { + const logIndex = toHex(Array(63).fill(0).join('') + '1') + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + }) + + it('Should emit Transfer log in exit tx', () => { + const logs = logDecoder.decodeLogs(exitTx.receipt.rawLogs) + const exitTransferLog = logs.find(l => l.event === 'Transfer') + should.exist(exitTransferLog) + }) + + it('Should have more amount in withdrawer account after withdraw', async() => { + const newAccountBalance = await dummyERC721.balanceOf(depositReceiver) + newAccountBalance.should.be.a.bignumber.that.equals( + accountBalance.add(depositAmount) + ) + }) + + it('Should have less amount in predicate contract after withdraw', async() => { + const newContractBalance = await dummyERC721.balanceOf(contracts.root.erc721Predicate.address) + newContractBalance.should.be.a.bignumber.that.equals( + contractBalance.sub(withdrawAmount) + ) + }) + }) + + describe('Withdraw batch ERC721', async() => { + const tokenId1 = mockValues.numbers[4] + const tokenId2 = mockValues.numbers[5] + const tokenId3 = mockValues.numbers[8] + const user = accounts[0] + const depositData = abi.encode( + ['uint256[]'], + [ + [tokenId1.toString(), tokenId2.toString(), tokenId3.toString()] + ] + ) + let contracts + let rootToken + let childToken + let rootChainManager + let checkpointManager + let erc721Predicate + let withdrawTx + let checkpointData + let headerNumber + let exitTx + + before(async() => { + contracts = await deployer.deployInitializedContracts(accounts) + rootToken = contracts.root.dummyERC721 + childToken = contracts.child.dummyERC721 + rootChainManager = contracts.root.rootChainManager + checkpointManager = contracts.root.checkpointManager + erc721Predicate = contracts.root.erc721Predicate + await rootToken.mint(tokenId1) + await rootToken.mint(tokenId2) + await rootToken.mint(tokenId3) + }) + + it('User should own tokens on root chain', async() => { + { + const owner = await rootToken.ownerOf(tokenId1) + owner.should.equal(user) + } + { + const owner = await rootToken.ownerOf(tokenId2) + owner.should.equal(user) + } + { + const owner = await rootToken.ownerOf(tokenId3) + owner.should.equal(user) + } + }) + + it('Tokens should not exist on child chain', async() => { + await expectRevert(childToken.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId2), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId3), 'ERC721: owner query for nonexistent token') + }) + + it('User should be able to approve and deposit', async() => { + await rootToken.setApprovalForAll(erc721Predicate.address, true) + const depositTx = await rootChainManager.depositFor(user, rootToken.address, depositData) + should.exist(depositTx) + const syncTx = await syncState({ tx: depositTx }) + should.exist(syncTx) + }) + + it('Predicate should own tokens on root chain', async() => { + { + const owner = await rootToken.ownerOf(tokenId1) + owner.should.equal(erc721Predicate.address) + } + { + const owner = await rootToken.ownerOf(tokenId2) + owner.should.equal(erc721Predicate.address) + } + { + const owner = await rootToken.ownerOf(tokenId3) + owner.should.equal(erc721Predicate.address) + } + }) + + it('User should own tokens on child chain', async() => { + { + const owner = await childToken.ownerOf(tokenId1) + owner.should.equal(user) + } + { + const owner = await childToken.ownerOf(tokenId2) + owner.should.equal(user) + } + { + const owner = await childToken.ownerOf(tokenId3) + owner.should.equal(user) + } + }) + + it('User should be able to start withdraw', async() => { + withdrawTx = await childToken.withdrawBatch([tokenId1, tokenId2, tokenId3]) + should.exist(withdrawTx) + }) + + it('Should submit checkpoint', async() => { + // submit checkpoint including burn (withdraw) tx + checkpointData = await submitCheckpoint(checkpointManager, withdrawTx.receipt) + should.exist(checkpointData) + }) + + it('Should match checkpoint details', async() => { + const root = bufferToHex(checkpointData.header.root) + should.exist(root) + + // fetch latest header number + headerNumber = await checkpointManager.currentCheckpointNumber() + headerNumber.should.be.bignumber.gt('0') + + // fetch header block details and validate + const headerData = await checkpointManager.headerBlocks(headerNumber) + root.should.equal(headerData.root) + }) + + it('User should be able to exit', async() => { + const logIndex = withdrawTx.receipt.rawLogs + .findIndex(log => log.topics[0].toLowerCase() === ERC721_WITHDRAW_BATCH_EVENT_SIG.toLowerCase()) + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + exitTx = await contracts.root.rootChainManager.exit(data, { from: user }) + should.exist(exitTx) + }) + + it('User should own tokens on root chain', async() => { + { + const owner = await rootToken.ownerOf(tokenId1) + owner.should.equal(user) + } + { + const owner = await rootToken.ownerOf(tokenId2) + owner.should.equal(user) + } + { + const owner = await rootToken.ownerOf(tokenId3) + owner.should.equal(user) + } + }) + + it('Tokens should not exist on child chain', async() => { + await expectRevert(childToken.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId2), 'ERC721: owner query for nonexistent token') + await expectRevert(childToken.ownerOf(tokenId3), 'ERC721: owner query for nonexistent token') + }) + }) + + describe('Withdraw single ERC1155', async() => { + const tokenId = mockValues.numbers[8] + const depositAmount = mockValues.amounts[1] + const withdrawAmount = mockValues.amounts[1] + const depositReceiver = accounts[0] + const depositData = abi.encode( + [ + 'uint256[]', + 'uint256[]', + 'bytes' + ], + [ + [tokenId.toString()], + [depositAmount.toString()], + ['0x0'] + ] + ) + let contracts + let dummyERC1155 + let rootChainManager + let accountBalance + let contractBalance + let transferLog + let withdrawTx + let checkpointData + let headerNumber + let exitTx + + before(async() => { + contracts = await deployer.deployInitializedContracts(accounts) + dummyERC1155 = contracts.root.dummyERC1155 + rootChainManager = contracts.root.rootChainManager + const mintAmount = depositAmount.add(mockValues.amounts[2]) + await dummyERC1155.mint(accounts[0], tokenId, mintAmount) + accountBalance = await dummyERC1155.balanceOf(accounts[0], tokenId) + contractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) + }) + + it('Depositor should be able to approve and deposit', async() => { + await dummyERC1155.setApprovalForAll(contracts.root.erc1155Predicate.address, true) + const depositTx = await rootChainManager.depositFor(depositReceiver, dummyERC1155.address, depositData) + should.exist(depositTx) + const syncTx = await syncState({ tx: depositTx }) + should.exist(syncTx) + }) + + it('Deposit amount should be deducted from depositor account', async() => { + const newAccountBalance = await dummyERC1155.balanceOf(accounts[0], tokenId) + newAccountBalance.should.be.a.bignumber.that.equals( + accountBalance.sub(depositAmount) + ) + + // update account balance + accountBalance = newAccountBalance + }) + + it('Deposit amount should be credited to correct contract', async() => { + const newContractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) + newContractBalance.should.be.a.bignumber.that.equals( + contractBalance.add(depositAmount) + ) + + // update balance + contractBalance = newContractBalance + }) + + it('Can receive withdraw tx', async() => { + withdrawTx = await contracts.child.dummyERC1155.withdrawSingle(tokenId, withdrawAmount, { from: depositReceiver }) + should.exist(withdrawTx) + }) + + it('Should emit Transfer log in withdraw tx', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + transferLog = logs.find(l => l.event === 'TransferSingle') + should.exist(transferLog) + }) + + it('Should submit checkpoint', async() => { + // submit checkpoint including burn (withdraw) tx + checkpointData = await submitCheckpoint(contracts.root.checkpointManager, withdrawTx.receipt) + should.exist(checkpointData) + }) + + it('Should match checkpoint details', async() => { + const root = bufferToHex(checkpointData.header.root) + should.exist(root) + + // fetch latest header number + headerNumber = await contracts.root.checkpointManager.currentCheckpointNumber() + headerNumber.should.be.bignumber.gt('0') + + // fetch header block details and validate + const headerData = await contracts.root.checkpointManager.headerBlocks(headerNumber) + root.should.equal(headerData.root) + }) + + it('Should fail: exit with a random data receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt(withdrawTx.receipt.transactionHash) + const dummyReceipt = getFakeReceiptBytes(receipt, '') + const logIndex = 0 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'RootChainManager: INVALID_PROOF') + }) + + it('Should fail: exit with a fake amount data in receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt( + withdrawTx.receipt.transactionHash) + const dummyReceipt = getFakeReceiptBytes(receipt, mockValues.bytes32[4]) + const logIndex = 0 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'revert') + }) + + it('Should fail to start exit (changed the block number)', async() => { + const logIndex = 0 + const fakeBlockNumber = checkpointData.number + 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + fakeBlockNumber, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'Leaf index is too big') + }) + + it('Should start exit', async() => { + const logIndex = 0 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + exitTx = await contracts.root.rootChainManager.exit(data, + { from: depositReceiver }) + should.exist(exitTx) + }) + + it('Should fail: start exit again', async() => { + const logIndex = 0 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') + }) + + it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { + const logIndex = toHex(Array(64).fill(0).join('')) + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') + }) + + it('Should emit Transfer log in exit tx', () => { + const logs = logDecoder.decodeLogs(exitTx.receipt.rawLogs) + const exitTransferLog = logs.find(l => l.event === 'TransferSingle') + should.exist(exitTransferLog) + }) + + it('Should have more amount in withdrawer account after withdraw', async() => { + const newAccountBalance = await dummyERC1155.balanceOf(depositReceiver, tokenId) + newAccountBalance.should.be.a.bignumber.that.equals( + accountBalance.add(depositAmount) + ) + }) + + it('Should have less amount in predicate contract after withdraw', async() => { + const newContractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) + newContractBalance.should.be.a.bignumber.that.equals( + contractBalance.sub(withdrawAmount) + ) + }) + }) + + describe('Withdraw single ERC1155 :: withdraw for another account', async() => { + const tokenId = mockValues.numbers[8] + const depositAmount = mockValues.amounts[1] + const withdrawAmount = mockValues.amounts[1] + const depositReceiver = accounts[0] + const withdrawReceiver = accounts[1] + const depositData = abi.encode( + [ + 'uint256[]', + 'uint256[]', + 'bytes' + ], + [ + [tokenId.toString()], + [depositAmount.toString()], + ['0x0'] + ] + ) + let contracts + let dummyERC1155 + let rootChainManager + let accountBalance + let contractBalance + let transferLog + let withdrawTx + let checkpointData + let headerNumber + let exitTx + + before(async() => { + contracts = await deployer.deployInitializedContracts(accounts) + dummyERC1155 = contracts.root.dummyERC1155 + rootChainManager = contracts.root.rootChainManager + const mintAmount = depositAmount.add(mockValues.amounts[2]) + await dummyERC1155.mint(accounts[0], tokenId, mintAmount) + accountBalance = await dummyERC1155.balanceOf(accounts[0], tokenId) + contractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) + }) + + it('Depositor should be able to approve and deposit', async() => { + await dummyERC1155.setApprovalForAll(contracts.root.erc1155Predicate.address, true) + const depositTx = await rootChainManager.depositFor(depositReceiver, dummyERC1155.address, depositData) + should.exist(depositTx) + const syncTx = await syncState({ tx: depositTx }) + should.exist(syncTx) + }) + + it('Deposit amount should be deducted from depositor account', async() => { + const newAccountBalance = await dummyERC1155.balanceOf(accounts[0], tokenId) + newAccountBalance.should.be.a.bignumber.that.equals( + accountBalance.sub(depositAmount) + ) + + // update account balance + accountBalance = newAccountBalance + }) + + it('Deposit amount should be credited to correct contract', async() => { + const newContractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) + newContractBalance.should.be.a.bignumber.that.equals( + contractBalance.add(depositAmount) + ) + + // update balance + contractBalance = newContractBalance + }) + + it('Can receive withdraw tx', async() => { + withdrawTx = await contracts.child.dummyERC1155.withdrawForSingle(withdrawReceiver, tokenId, withdrawAmount, { from: depositReceiver }) + should.exist(withdrawTx) + }) + + it('Should emit Transfer log in withdraw tx', () => { + const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + transferLog = logs.filter(l => l && l.event === 'TransferSingle').pop() + should.exist(transferLog) + }) + + it('Should submit checkpoint', async() => { + // submit checkpoint including burn (withdraw) tx + checkpointData = await submitCheckpoint(contracts.root.checkpointManager, withdrawTx.receipt) + should.exist(checkpointData) + }) + + it('Should match checkpoint details', async() => { + const root = bufferToHex(checkpointData.header.root) + should.exist(root) + + // fetch latest header number + headerNumber = await contracts.root.checkpointManager.currentCheckpointNumber() + headerNumber.should.be.bignumber.gt('0') + + // fetch header block details and validate + const headerData = await contracts.root.checkpointManager.headerBlocks(headerNumber) + root.should.equal(headerData.root) + }) + + it('Should fail: exit with a random data receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt(withdrawTx.receipt.transactionHash) + const dummyReceipt = getFakeReceiptBytes(receipt, '') + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'RootChainManager: INVALID_PROOF') + }) + + it('Should fail: exit with a fake amount data in receipt', async() => { + const receipt = await childWeb3.eth.getTransactionReceipt( + withdrawTx.receipt.transactionHash) + const dummyReceipt = getFakeReceiptBytes(receipt, mockValues.bytes32[4]) + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(dummyReceipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'revert') + }) + + it('Should fail to start exit (changed the block number)', async() => { + const logIndex = 1 + const fakeBlockNumber = checkpointData.number + 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + fakeBlockNumber, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'Leaf index is too big') + }) + + it('Should start exit', async() => { + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + exitTx = await contracts.root.rootChainManager.exit(data, + { from: depositReceiver }) + should.exist(exitTx) + }) + + it('Should fail: start exit again', async() => { + const logIndex = 1 + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') + }) + + it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { + const logIndex = toHex(Array(63).fill(0).join('')) + '1' + const data = bufferToHex( + rlp.encode([ + headerNumber, + bufferToHex(Buffer.concat(checkpointData.proof)), + checkpointData.number, + checkpointData.timestamp, + bufferToHex(checkpointData.transactionsRoot), + bufferToHex(checkpointData.receiptsRoot), + bufferToHex(checkpointData.receipt), + bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), + bufferToHex(checkpointData.path), // branch mask, + logIndex + ]) + ) + // start exit + await expectRevert(contracts.root.rootChainManager.exit(data, + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') }) - it('User should own tokens on root chain', async() => { - { - const owner = await rootToken.ownerOf(tokenId1) - owner.should.equal(user) - } - { - const owner = await rootToken.ownerOf(tokenId2) - owner.should.equal(user) - } - { - const owner = await rootToken.ownerOf(tokenId3) - owner.should.equal(user) - } + it('Should emit Transfer log in exit tx', () => { + const logs = logDecoder.decodeLogs(exitTx.receipt.rawLogs) + const exitTransferLog = logs.find(l => l.event === 'TransferSingle') + should.exist(exitTransferLog) }) - it('Tokens should not exist on child chain', async() => { - await expectRevert(childToken.ownerOf(tokenId1), 'ERC721: owner query for nonexistent token') - await expectRevert(childToken.ownerOf(tokenId2), 'ERC721: owner query for nonexistent token') - await expectRevert(childToken.ownerOf(tokenId3), 'ERC721: owner query for nonexistent token') + it('Should have more amount in withdrawer account after withdraw', async() => { + const newWithdrawAccountBalance = await dummyERC1155.balanceOf(withdrawReceiver, tokenId) + newWithdrawAccountBalance.should.be.a.bignumber.that.equals( + depositAmount + ) + + const newDepositAccountBalance = await dummyERC1155.balanceOf(depositReceiver, tokenId) + newDepositAccountBalance.should.be.a.bignumber.that.equals( + accountBalance + ) + }) + + it('Should have less amount in predicate contract after withdraw', async() => { + const newContractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) + newContractBalance.should.be.a.bignumber.that.equals( + contractBalance.sub(withdrawAmount) + ) }) }) - describe('Withdraw single ERC1155', async() => { + describe('Withdraw single ERC1155 :: non-deposit account', async() => { const tokenId = mockValues.numbers[8] const depositAmount = mockValues.amounts[1] const withdrawAmount = mockValues.amounts[1] const depositReceiver = accounts[0] + const nonDepositAccount = accounts[1] const depositData = abi.encode( [ 'uint256[]', @@ -1542,7 +2757,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'RootChainManager: INVALID_PROOF') + { from: nonDepositAccount }), 'RootChainManager: INVALID_PROOF') }) it('Should fail: exit with a fake amount data in receipt', async() => { @@ -1566,7 +2781,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'revert') + { from: nonDepositAccount }), 'revert') }) it('Should fail to start exit (changed the block number)', async() => { @@ -1588,7 +2803,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'Leaf index is too big') + { from: nonDepositAccount }), 'Leaf index is too big') }) it('Should start exit', async() => { @@ -1609,7 +2824,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit exitTx = await contracts.root.rootChainManager.exit(data, - { from: depositReceiver }) + { from: nonDepositAccount }) should.exist(exitTx) }) @@ -1631,7 +2846,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') + { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') }) it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { @@ -1652,7 +2867,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') + { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') }) it('Should emit Transfer log in exit tx', () => { @@ -1676,43 +2891,52 @@ contract('RootChainManager', async(accounts) => { }) }) - describe('Withdraw single ERC1155 :: non-deposit account', async() => { - const tokenId = mockValues.numbers[8] - const depositAmount = mockValues.amounts[1] - const withdrawAmount = mockValues.amounts[1] + describe('Withdraw batch ERC1155', async() => { + let erc1155PredicateAddress + const withdrawAmountA = mockValues.amounts[2] + const withdrawAmountB = mockValues.amounts[2] + const withdrawAmountC = mockValues.amounts[1] + const depositAmountA = withdrawAmountA.add(mockValues.amounts[0]) + const depositAmountB = withdrawAmountA.add(mockValues.amounts[9]) + const depositAmountC = withdrawAmountA.add(mockValues.amounts[6]) + const tokenIdA = mockValues.numbers[4] + const tokenIdB = mockValues.numbers[5] + const tokenIdC = mockValues.numbers[8] const depositReceiver = accounts[0] - const nonDepositAccount = accounts[1] - const depositData = abi.encode( - [ - 'uint256[]', - 'uint256[]', - 'bytes' - ], - [ - [tokenId.toString()], - [depositAmount.toString()], - ['0x0'] - ] + const depositData = constructERC1155DepositData( + [tokenIdA, tokenIdB, tokenIdC], + [depositAmountA, depositAmountB, depositAmountC] ) let contracts let dummyERC1155 let rootChainManager - let accountBalance - let contractBalance - let transferLog + let accountBalanceA + let accountBalanceB + let accountBalanceC + let contractBalanceA + let contractBalanceB + let contractBalanceC + let transferBatchLog let withdrawTx let checkpointData let headerNumber let exitTx + let logs before(async() => { contracts = await deployer.deployInitializedContracts(accounts) dummyERC1155 = contracts.root.dummyERC1155 rootChainManager = contracts.root.rootChainManager - const mintAmount = depositAmount.add(mockValues.amounts[2]) - await dummyERC1155.mint(accounts[0], tokenId, mintAmount) - accountBalance = await dummyERC1155.balanceOf(accounts[0], tokenId) - contractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) + await dummyERC1155.mint(accounts[0], tokenIdA, depositAmountA) + await dummyERC1155.mint(accounts[0], tokenIdB, depositAmountB) + await dummyERC1155.mint(accounts[0], tokenIdC, depositAmountC) + accountBalanceA = await dummyERC1155.balanceOf(accounts[0], tokenIdA) + erc1155PredicateAddress = contracts.root.erc1155Predicate.address + contractBalanceA = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdA) + accountBalanceB = await dummyERC1155.balanceOf(accounts[0], tokenIdB) + contractBalanceB = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdB) + accountBalanceC = await dummyERC1155.balanceOf(accounts[0], tokenIdC) + contractBalanceC = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdC) }) it('Depositor should be able to approve and deposit', async() => { @@ -1724,34 +2948,55 @@ contract('RootChainManager', async(accounts) => { }) it('Deposit amount should be deducted from depositor account', async() => { - const newAccountBalance = await dummyERC1155.balanceOf(accounts[0], tokenId) - newAccountBalance.should.be.a.bignumber.that.equals( - accountBalance.sub(depositAmount) + const newAccountBalanceA = await dummyERC1155.balanceOf(accounts[0], tokenIdA) + newAccountBalanceA.should.be.a.bignumber.that.equals( + accountBalanceA.sub(depositAmountA) + ) + const newAccountBalanceB = await dummyERC1155.balanceOf(accounts[0], tokenIdB) + newAccountBalanceB.should.be.a.bignumber.that.equals( + accountBalanceB.sub(depositAmountB) + ) + const newAccountBalanceC = await dummyERC1155.balanceOf(accounts[0], tokenIdC) + newAccountBalanceC.should.be.a.bignumber.that.equals( + accountBalanceC.sub(depositAmountC) ) - // update account balance - accountBalance = newAccountBalance + accountBalanceA = newAccountBalanceA + accountBalanceB = newAccountBalanceB + accountBalanceC = newAccountBalanceC }) it('Deposit amount should be credited to correct contract', async() => { - const newContractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) - newContractBalance.should.be.a.bignumber.that.equals( - contractBalance.add(depositAmount) + const newContractBalanceA = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdA) + newContractBalanceA.should.be.a.bignumber.that.equals( + contractBalanceA.add(depositAmountA) + ) + const newContractBalanceB = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdB) + newContractBalanceB.should.be.a.bignumber.that.equals( + contractBalanceB.add(depositAmountB) + ) + const newContractBalanceC = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdC) + newContractBalanceC.should.be.a.bignumber.that.equals( + contractBalanceC.add(depositAmountC) ) - // update balance - contractBalance = newContractBalance + contractBalanceA = newContractBalanceA + contractBalanceB = newContractBalanceB + contractBalanceC = newContractBalanceC }) it('Can receive withdraw tx', async() => { - withdrawTx = await contracts.child.dummyERC1155.withdrawSingle(tokenId, withdrawAmount, { from: depositReceiver }) + withdrawTx = await contracts.child.dummyERC1155.withdrawBatch( + [tokenIdA, tokenIdB, tokenIdC], + [withdrawAmountA, withdrawAmountB, withdrawAmountC], + { from: depositReceiver }) should.exist(withdrawTx) }) it('Should emit Transfer log in withdraw tx', () => { - const logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) - transferLog = logs.find(l => l.event === 'TransferSingle') - should.exist(transferLog) + logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) + transferBatchLog = logs.find(l => l.event === 'TransferBatch') + should.exist(transferBatchLog) }) it('Should submit checkpoint', async() => { @@ -1793,7 +3038,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'RootChainManager: INVALID_PROOF') + { from: depositReceiver }), 'RootChainManager: INVALID_PROOF') }) it('Should fail: exit with a fake amount data in receipt', async() => { @@ -1817,29 +3062,7 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'revert') - }) - - it('Should fail to start exit (changed the block number)', async() => { - const logIndex = 0 - const fakeBlockNumber = checkpointData.number + 1 - const data = bufferToHex( - rlp.encode([ - headerNumber, - bufferToHex(Buffer.concat(checkpointData.proof)), - fakeBlockNumber, - checkpointData.timestamp, - bufferToHex(checkpointData.transactionsRoot), - bufferToHex(checkpointData.receiptsRoot), - bufferToHex(checkpointData.receipt), - bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), - bufferToHex(checkpointData.path), // branch mask, - logIndex - ]) - ) - // start exit - await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'Leaf index is too big') + { from: depositReceiver }), 'revert') }) it('Should start exit', async() => { @@ -1860,11 +3083,11 @@ contract('RootChainManager', async(accounts) => { ) // start exit exitTx = await contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }) + { from: depositReceiver }) should.exist(exitTx) }) - it('Should fail: start exit again', async() => { + it('start exit again', async() => { const logIndex = 0 const data = bufferToHex( rlp.encode([ @@ -1882,52 +3105,41 @@ contract('RootChainManager', async(accounts) => { ) // start exit await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') - }) - - it('Should fail to start exit again (change the log index to generate same exit hash)', async() => { - const logIndex = toHex(Array(64).fill(0).join('')) - const data = bufferToHex( - rlp.encode([ - headerNumber, - bufferToHex(Buffer.concat(checkpointData.proof)), - checkpointData.number, - checkpointData.timestamp, - bufferToHex(checkpointData.transactionsRoot), - bufferToHex(checkpointData.receiptsRoot), - bufferToHex(checkpointData.receipt), - bufferToHex(rlp.encode(checkpointData.receiptParentNodes)), - bufferToHex(checkpointData.path), // branch mask, - logIndex - ]) - ) - // start exit - await expectRevert(contracts.root.rootChainManager.exit(data, - { from: nonDepositAccount }), 'EXIT_ALREADY_PROCESSED') + { from: depositReceiver }), 'EXIT_ALREADY_PROCESSED') }) it('Should emit Transfer log in exit tx', () => { const logs = logDecoder.decodeLogs(exitTx.receipt.rawLogs) - const exitTransferLog = logs.find(l => l.event === 'TransferSingle') + const exitTransferLog = logs.find(l => l.event === 'TransferBatch') should.exist(exitTransferLog) }) it('Should have more amount in withdrawer account after withdraw', async() => { - const newAccountBalance = await dummyERC1155.balanceOf(depositReceiver, tokenId) - newAccountBalance.should.be.a.bignumber.that.equals( - accountBalance.add(depositAmount) - ) + const newAccountBalanceA = await dummyERC1155.balanceOf(depositReceiver, tokenIdA) + newAccountBalanceA.should.be.a.bignumber.that.equals(accountBalanceA.add(withdrawAmountA)) + const newAccountBalanceB = await dummyERC1155.balanceOf(depositReceiver, tokenIdB) + newAccountBalanceB.should.be.a.bignumber.that.equals(accountBalanceB.add(withdrawAmountB)) + const newAccountBalanceC = await dummyERC1155.balanceOf(depositReceiver, tokenIdC) + newAccountBalanceC.should.be.a.bignumber.that.equals(accountBalanceC.add(withdrawAmountC)) }) it('Should have less amount in predicate contract after withdraw', async() => { - const newContractBalance = await dummyERC1155.balanceOf(contracts.root.erc1155Predicate.address, tokenId) - newContractBalance.should.be.a.bignumber.that.equals( - contractBalance.sub(withdrawAmount) + const newContractBalanceA = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdA) + newContractBalanceA.should.be.a.bignumber.that.equals( + contractBalanceA.sub(withdrawAmountA) + ) + const newContractBalanceB = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdB) + newContractBalanceB.should.be.a.bignumber.that.equals( + contractBalanceB.sub(withdrawAmountB) + ) + const newContractBalanceC = await dummyERC1155.balanceOf(erc1155PredicateAddress, tokenIdC) + newContractBalanceC.should.be.a.bignumber.that.equals( + contractBalanceC.sub(withdrawAmountC) ) }) }) - describe('Withdraw batch ERC1155', async() => { + describe('Withdraw batch ERC1155 :: withdraw for another account', async() => { let erc1155PredicateAddress const withdrawAmountA = mockValues.amounts[2] const withdrawAmountB = mockValues.amounts[2] @@ -1939,6 +3151,7 @@ contract('RootChainManager', async(accounts) => { const tokenIdB = mockValues.numbers[5] const tokenIdC = mockValues.numbers[8] const depositReceiver = accounts[0] + const withdrawReceiver = accounts[1] const depositData = constructERC1155DepositData( [tokenIdA, tokenIdB, tokenIdC], [depositAmountA, depositAmountB, depositAmountC] @@ -2022,7 +3235,8 @@ contract('RootChainManager', async(accounts) => { }) it('Can receive withdraw tx', async() => { - withdrawTx = await contracts.child.dummyERC1155.withdrawBatch( + withdrawTx = await contracts.child.dummyERC1155.withdrawForBatch( + withdrawReceiver, [tokenIdA, tokenIdB, tokenIdC], [withdrawAmountA, withdrawAmountB, withdrawAmountC], { from: depositReceiver }) @@ -2031,7 +3245,7 @@ contract('RootChainManager', async(accounts) => { it('Should emit Transfer log in withdraw tx', () => { logs = logDecoder.decodeLogs(withdrawTx.receipt.rawLogs) - transferBatchLog = logs.find(l => l.event === 'TransferBatch') + transferBatchLog = logs.filter(l => l && l.event === 'TransferBatch').pop() should.exist(transferBatchLog) }) @@ -2057,7 +3271,7 @@ contract('RootChainManager', async(accounts) => { it('Should fail: exit with a random data receipt', async() => { const receipt = await childWeb3.eth.getTransactionReceipt(withdrawTx.receipt.transactionHash) const dummyReceipt = getFakeReceiptBytes(receipt, '') - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -2081,7 +3295,7 @@ contract('RootChainManager', async(accounts) => { const receipt = await childWeb3.eth.getTransactionReceipt( withdrawTx.receipt.transactionHash) const dummyReceipt = getFakeReceiptBytes(receipt, mockValues.bytes32[4]) - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -2102,7 +3316,7 @@ contract('RootChainManager', async(accounts) => { }) it('Should start exit', async() => { - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -2124,7 +3338,7 @@ contract('RootChainManager', async(accounts) => { }) it('start exit again', async() => { - const logIndex = 0 + const logIndex = 1 const data = bufferToHex( rlp.encode([ headerNumber, @@ -2151,12 +3365,21 @@ contract('RootChainManager', async(accounts) => { }) it('Should have more amount in withdrawer account after withdraw', async() => { - const newAccountBalanceA = await dummyERC1155.balanceOf(depositReceiver, tokenIdA) - newAccountBalanceA.should.be.a.bignumber.that.equals(accountBalanceA.add(withdrawAmountA)) - const newAccountBalanceB = await dummyERC1155.balanceOf(depositReceiver, tokenIdB) - newAccountBalanceB.should.be.a.bignumber.that.equals(accountBalanceB.add(withdrawAmountB)) - const newAccountBalanceC = await dummyERC1155.balanceOf(depositReceiver, tokenIdC) - newAccountBalanceC.should.be.a.bignumber.that.equals(accountBalanceC.add(withdrawAmountC)) + const newWithdrawAccountBalanceA = await dummyERC1155.balanceOf(withdrawReceiver, tokenIdA) + newWithdrawAccountBalanceA.should.be.a.bignumber.that.equals(withdrawAmountA) + const newWithdrawAccountBalanceB = await dummyERC1155.balanceOf(withdrawReceiver, tokenIdB) + newWithdrawAccountBalanceB.should.be.a.bignumber.that.equals(withdrawAmountB) + const newWithdrawAccountBalanceC = await dummyERC1155.balanceOf(withdrawReceiver, tokenIdC) + newWithdrawAccountBalanceC.should.be.a.bignumber.that.equals(withdrawAmountC) + + const newDepositAccountBalanceA = await dummyERC1155.balanceOf(depositReceiver, tokenIdA) + newDepositAccountBalanceA.should.be.a.bignumber.that.equals(accountBalanceA) + + const newDepositAccountBalanceB = await dummyERC1155.balanceOf(depositReceiver, tokenIdB) + newDepositAccountBalanceB.should.be.a.bignumber.that.equals(accountBalanceB) + + const newDepositAccountBalanceC = await dummyERC1155.balanceOf(depositReceiver, tokenIdC) + newDepositAccountBalanceC.should.be.a.bignumber.that.equals(accountBalanceC) }) it('Should have less amount in predicate contract after withdraw', async() => {