diff --git a/.gas-snapshot b/.gas-snapshot index 465efd32..fe79f769 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -44,38 +44,42 @@ TestICS04Handshake:testInvalidChanOpenAck() (gas: 2327618) TestICS04Handshake:testInvalidChanOpenConfirm() (gas: 2402634) TestICS04Handshake:testInvalidChanOpenInit() (gas: 1677184) TestICS04Handshake:testInvalidChanOpenTry() (gas: 1692266) -TestICS04Packet:testAcknowledgementPacket() (gas: 3133839) -TestICS04Packet:testInvalidSendPacket() (gas: 3317459) -TestICS04Packet:testRecvPacket() (gas: 9561916) -TestICS04Packet:testRecvPacketTimeoutHeight() (gas: 3083947) -TestICS04Packet:testRecvPacketTimeoutTimestamp() (gas: 3107997) -TestICS04Packet:testSendPacket() (gas: 4425319) -TestICS04Packet:testTimeoutOnClose() (gas: 3335905) -TestICS04Upgrade:testCrossingHelloInconsistentVersions() (gas: 9761065) -TestICS04Upgrade:testUpgradeAuthorityCancel() (gas: 45179742) -TestICS04Upgrade:testUpgradeCannotCancelWithOldErrorReceipt() (gas: 3309916) -TestICS04Upgrade:testUpgradeCannotRecvNextUpgradePacket() (gas: 5142516) -TestICS04Upgrade:testUpgradeCounterpartyAdvanceNextSequenceBeforeOpen() (gas: 5101888) -TestICS04Upgrade:testUpgradeCrossingHelloIncompatibleProposals() (gas: 4859793) -TestICS04Upgrade:testUpgradeFull() (gas: 55736320) -TestICS04Upgrade:testUpgradeInit() (gas: 2937759) -TestICS04Upgrade:testUpgradeNoChanges() (gas: 2354426) -TestICS04Upgrade:testUpgradeNotUpgradableModule() (gas: 3470809) -TestICS04Upgrade:testUpgradeOutOfSync() (gas: 3741133) -TestICS04Upgrade:testUpgradeRelaySuccessAtCounterpartyFlushComplete() (gas: 5115114) -TestICS04Upgrade:testUpgradeRelaySuccessAtFlushing() (gas: 5487347) -TestICS04Upgrade:testUpgradeSendPacketFailAtFlushingOrFlushComplete() (gas: 3920258) -TestICS04Upgrade:testUpgradeTimeoutAbortAck() (gas: 17345060) -TestICS04Upgrade:testUpgradeTimeoutAbortConfirm() (gas: 20945649) -TestICS04Upgrade:testUpgradeTimeoutUpgrade() (gas: 69105350) -TestICS04Upgrade:testUpgradeToOrdered() (gas: 53030759) -TestICS04Upgrade:testUpgradeToUnordered() (gas: 42323192) +TestICS04Packet:testAcknowledgementPacket() (gas: 3133817) +TestICS04Packet:testInvalidSendPacket() (gas: 3317437) +TestICS04Packet:testRecvPacket() (gas: 9561861) +TestICS04Packet:testRecvPacketTimeoutHeight() (gas: 3083925) +TestICS04Packet:testRecvPacketTimeoutTimestamp() (gas: 3107975) +TestICS04Packet:testSendPacket() (gas: 4425297) +TestICS04Packet:testTimeoutOnClose() (gas: 3335859) +TestICS04Upgrade:testCrossingHelloInconsistentVersions() (gas: 9761029) +TestICS04Upgrade:testUpgradeAuthorityCancel() (gas: 45179694) +TestICS04Upgrade:testUpgradeCannotCancelWithOldErrorReceipt() (gas: 3309912) +TestICS04Upgrade:testUpgradeCannotRecvNextUpgradePacket() (gas: 5142512) +TestICS04Upgrade:testUpgradeCounterpartyAdvanceNextSequenceBeforeOpen() (gas: 5101884) +TestICS04Upgrade:testUpgradeCrossingHelloIncompatibleProposals() (gas: 4859789) +TestICS04Upgrade:testUpgradeFull() (gas: 55736252) +TestICS04Upgrade:testUpgradeInit() (gas: 2937755) +TestICS04Upgrade:testUpgradeNoChanges() (gas: 2354422) +TestICS04Upgrade:testUpgradeNotUpgradableModule() (gas: 3470805) +TestICS04Upgrade:testUpgradeOutOfSync() (gas: 3741129) +TestICS04Upgrade:testUpgradeRelaySuccessAtCounterpartyFlushComplete() (gas: 5115110) +TestICS04Upgrade:testUpgradeRelaySuccessAtFlushing() (gas: 5487343) +TestICS04Upgrade:testUpgradeSendPacketFailAtFlushingOrFlushComplete() (gas: 3920254) +TestICS04Upgrade:testUpgradeTimeoutAbortAck() (gas: 17345056) +TestICS04Upgrade:testUpgradeTimeoutAbortConfirm() (gas: 20945645) +TestICS04Upgrade:testUpgradeTimeoutUpgrade() (gas: 69105286) +TestICS04Upgrade:testUpgradeToOrdered() (gas: 53030719) +TestICS04Upgrade:testUpgradeToUnordered() (gas: 42323160) TestICS04UpgradeApp:testUpgradeAuthorizationChanneNotFound() (gas: 62062) TestICS04UpgradeApp:testUpgradeAuthorizationRePropose() (gas: 2376902) TestICS04UpgradeApp:testUpgradeAuthorizationRemove() (gas: 2357348) -TestICS20:testAddressToHex(address) (runs: 256, μ: 26910, ~: 27088) -TestICS20:testHexToAddress(string) (runs: 256, μ: 4658, ~: 4617) -TestICS20:testIsEscapedString() (gas: 64753) -TestICS20:testMarshaling() (gas: 180017) -TestICS20:testParseAmount(uint256) (runs: 256, μ: 31599, ~: 27438) -TestICS20:testParseUint256String() (gas: 26745) \ No newline at end of file +TestICS20Lib:testAddressToHex(address) (runs: 256, μ: 26916, ~: 27088) +TestICS20Lib:testHexToAddress(string) (runs: 256, μ: 4658, ~: 4617) +TestICS20Lib:testIsEscapedString() (gas: 64753) +TestICS20Lib:testMarshaling() (gas: 180017) +TestICS20Lib:testParseAmount(uint256) (runs: 256, μ: 31619, ~: 27869) +TestICS20Lib:testParseUint256String() (gas: 26745) +TestICS20Transfer:testDeposit() (gas: 404927) +TestICS20Transfer:testDepositTransferWithdraw() (gas: 321969) +TestICS20Transfer:testRelay() (gas: 7588605) +TestICS20Transfer:testWithdraw() (gas: 416732) \ No newline at end of file diff --git a/Makefile b/Makefile index 3b964580..a5a98c1d 100644 --- a/Makefile +++ b/Makefile @@ -32,11 +32,11 @@ lint: .PHONY: test test: - TEST_UPGRADEABLE=$(TEST_UPGRADEABLE) $(FORGE) test -vvvv --gas-report --isolate --use solc:$(SOLC_VERSION) $(FORGE_SNAPSHOT_OPTION) + TEST_UPGRADEABLE=$(TEST_UPGRADEABLE) $(FORGE) test -vvvv --gas-report --isolate --use solc:$(SOLC_VERSION) .PHONY: snapshot snapshot: - $(FORGE) snapshot -vvvv --gas-report --isolate --use solc:$(SOLC_VERSION) $(FORGE_SNAPSHOT_OPTION) + $(FORGE) snapshot -vvvv --gas-report --isolate --use solc:$(SOLC_VERSION) .PHONY: coverage coverage: diff --git a/contracts/apps/20-transfer/ICS20Bank.sol b/contracts/apps/20-transfer/ICS20Bank.sol deleted file mode 100644 index 02557e52..00000000 --- a/contracts/apps/20-transfer/ICS20Bank.sol +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; -import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ICS20Lib} from "./ICS20Lib.sol"; -import {IICS20Bank} from "./IICS20Bank.sol"; -import {IICS20Errors} from "./IICS20Errors.sol"; - -contract ICS20Bank is Context, AccessControl, IICS20Bank, IICS20Errors { - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - - // Mapping from token ID to account balances - mapping(string => mapping(address => uint256)) internal _balances; - - constructor() { - _grantRole(ADMIN_ROLE, _msgSender()); - } - - function setOperator(address operator) public virtual { - if (!hasRole(ADMIN_ROLE, _msgSender())) { - revert ICS20BankNotAdminRole(_msgSender()); - } - _grantRole(OPERATOR_ROLE, operator); - } - - function balanceOf(address account, string calldata denom) public view virtual returns (uint256) { - return _balances[denom][account]; - } - - function transferFrom(address from, address to, string calldata denom, uint256 amount) public virtual override { - if (to == address(0)) { - revert ICS20InvalidReceiver(to); - } else if (from != _msgSender() && !hasRole(OPERATOR_ROLE, _msgSender())) { - revert ICS20InvalidSender(from); - } - uint256 fromBalance = _balances[denom][from]; - if (fromBalance < amount) { - revert ICS20InsufficientBalance(from, fromBalance, amount); - } - unchecked { - // SAFETY: balance is checked above - _balances[denom][from] = fromBalance - amount; - } - _balances[denom][to] += amount; - } - - function mint(address account, string calldata denom, uint256 amount) public virtual override { - if (!hasRole(OPERATOR_ROLE, _msgSender())) { - revert ICS20BankNotMintRole(_msgSender()); - } - _mint(account, denom, amount); - } - - function burn(address account, string calldata denom, uint256 amount) public virtual override { - if (!hasRole(OPERATOR_ROLE, _msgSender())) { - revert ICS20BankNotBurnRole(_msgSender()); - } - _burn(account, denom, amount); - } - - function deposit(address tokenContract, uint256 amount, address receiver) public virtual override { - if (tokenContract == address(0)) { - revert ICS20InvalidTokenContract(tokenContract); - } - if (!IERC20(tokenContract).transferFrom(_msgSender(), address(this), amount)) { - revert ICS20FailedERC20Transfer(tokenContract, _msgSender(), address(this), amount); - } - _mint(receiver, addressToDenom(tokenContract), amount); - } - - function withdraw(address tokenContract, uint256 amount, address receiver) public virtual override { - if (tokenContract == address(0)) { - revert ICS20InvalidTokenContract(tokenContract); - } - _burn(_msgSender(), addressToDenom(tokenContract), amount); - if (!IERC20(tokenContract).transfer(receiver, amount)) { - revert ICS20FailedERC20TransferFrom(tokenContract, _msgSender(), address(this), receiver, amount); - } - } - - function addressToDenom(address tokenContract) public pure virtual override returns (string memory) { - return ICS20Lib.addressToHexString(tokenContract); - } - - function _mint(address account, string memory denom, uint256 amount) internal { - _balances[denom][account] += amount; - } - - function _burn(address account, string memory denom, uint256 amount) internal { - uint256 accountBalance = _balances[denom][account]; - if (accountBalance < amount) { - revert ICS20InsufficientBalance(account, accountBalance, amount); - } - unchecked { - // SAFETY: balance is checked above - _balances[denom][account] = accountBalance - amount; - } - } -} diff --git a/contracts/apps/20-transfer/ICS20Lib.sol b/contracts/apps/20-transfer/ICS20Lib.sol index 4833e8af..c0215a95 100644 --- a/contracts/apps/20-transfer/ICS20Lib.sol +++ b/contracts/apps/20-transfer/ICS20Lib.sol @@ -2,20 +2,10 @@ pragma solidity ^0.8.20; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {Height} from "../../proto/Client.sol"; import {IICS20Errors} from "./IICS20Errors.sol"; library ICS20Lib { - /** - * @dev PacketData is defined in [ICS-20](https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer). - */ - struct PacketData { - string denom; - string sender; - string receiver; - uint256 amount; - string memo; - } - bytes internal constant SUCCESSFUL_ACKNOWLEDGEMENT_JSON = bytes('{"result":"AQ=="}'); bytes internal constant FAILED_ACKNOWLEDGEMENT_JSON = bytes('{"error":"failed"}'); bytes32 internal constant KECCAK256_SUCCESSFUL_ACKNOWLEDGEMENT_JSON = keccak256(SUCCESSFUL_ACKNOWLEDGEMENT_JSON); @@ -33,6 +23,25 @@ library ICS20Lib { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; + /** + * @dev PacketData is defined in [ICS-20](https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer). + */ + struct PacketData { + string denom; + string sender; + string receiver; + uint256 amount; + string memo; + } + + /** + * @dev Either `height` or `timestampNanos` must be set. + */ + struct Timeout { + Height.Data height; + uint64 timestampNanos; + } + /** * @dev marshalUnsafeJSON marshals PacketData into JSON bytes without escaping. * `memo` field is omitted if it is empty. @@ -147,6 +156,23 @@ library ICS20Lib { return pd; } + /** + * @dev timeout returns a Timeout struct with the given height. + */ + function timeout(uint64 revisionNumber, uint64 revisionHeight) internal pure returns (Timeout memory) { + return Timeout({ + height: Height.Data({revision_number: revisionNumber, revision_height: revisionHeight}), + timestampNanos: 0 + }); + } + + /** + * @dev timeout returns a Timeout struct with the given timestamp. + */ + function timeout(uint64 timestampNanos) internal pure returns (Timeout memory) { + return Timeout({height: Height.Data({revision_number: 0, revision_height: 0}), timestampNanos: timestampNanos}); + } + /** * @dev parseUint256String parses `bz` from a position `pos` to produce a uint256 value. * The parse will stop parsing when it encounters a non-digit character. @@ -372,4 +398,33 @@ library ICS20Lib { function equal(bytes memory a, bytes memory b) internal pure returns (bool) { return keccak256(a) == keccak256(b); } + + /** + * @dev denomPrefix returns the prefix of the denomination. + */ + function denomPrefix(string memory port, string memory channel) internal pure returns (bytes memory) { + return abi.encodePacked(port, "/", channel, "/"); + } + + /** + * @dev denom returns the denomination string. + */ + function denom(string memory port, string memory channel, address tokenContract) + internal + pure + returns (string memory) + { + return denom(port, channel, addressToHexString(tokenContract)); + } + + /** + * @dev denom returns the denomination string. + */ + function denom(string memory port, string memory channel, string memory baseDenom) + internal + pure + returns (string memory) + { + return string(abi.encodePacked(denomPrefix(port, channel), baseDenom)); + } } diff --git a/contracts/apps/20-transfer/ICS20Transfer.sol b/contracts/apps/20-transfer/ICS20Transfer.sol index 1ab048c2..9ae6b101 100644 --- a/contracts/apps/20-transfer/ICS20Transfer.sol +++ b/contracts/apps/20-transfer/ICS20Transfer.sol @@ -1,34 +1,208 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ShortString, ShortStrings} from "@openzeppelin/contracts/utils/ShortStrings.sol"; import {IBCAppBase} from "../commons/IBCAppBase.sol"; import {Packet} from "../../core/04-channel/IIBCChannel.sol"; import {IIBCModule} from "../../core/26-router/IIBCModule.sol"; import {Channel} from "../../proto/Channel.sol"; import {ICS20Lib} from "./ICS20Lib.sol"; import {IICS20Errors} from "./IICS20Errors.sol"; +import {IIBCHandler} from "../../core/25-handler/IIBCHandler.sol"; -abstract contract ICS20Transfer is IBCAppBase, IICS20Errors { +contract ICS20Transfer is IBCAppBase, IICS20Errors { + using ShortStrings for string; + using ShortStrings for ShortString; + + /// @dev ICS20 version string public constant ICS20_VERSION = "ics20-1"; - mapping(string => address) channelEscrowAddresses; + /// @dev IIBCHandler instance + IIBCHandler internal immutable ibcHandler; + /// @dev port identifier + ShortString internal immutable port; + + /// @dev balance mapping for the token + mapping(string denom => mapping(address account => uint256 balance)) internal _balances; + + /// @param ibcHandler_ IIBCHandler instance + /// @param port_ port identifier + constructor(IIBCHandler ibcHandler_, string memory port_) { + ibcHandler = ibcHandler_; + port = port_.toShortString(); + } + + // ------------------------------ Public Functions ------------------------------ // + + /** + * @dev sendTransfer sends a transfer packet to the destination chain. + * @param sourceChannel source channel of the packet + * @param denom denomination of the token. It can assume the denom string is escaped or not required to be escaped. + * @param amount amount of the token + * @param receiver receiver address on the destination chain. This must be a valid address format per destination chain. + */ + function sendTransfer( + string calldata sourceChannel, + string calldata denom, + uint256 amount, + string calldata receiver, + ICS20Lib.Timeout calldata timeout + ) external returns (uint64) { + if (!ICS20Lib.isEscapedJSONString(receiver)) { + revert ICS20InvalidReceiverAddress(receiver); + } + string memory sourcePort = port.toString(); + bytes memory denomPrefix = ICS20Lib.denomPrefix(sourcePort, sourceChannel); + bytes memory denomBytes = bytes(denom); + if ( + denomBytes.length < denomPrefix.length + || !ICS20Lib.equal(ICS20Lib.slice(denomBytes, 0, denomPrefix.length), denomPrefix) + ) { + // src chain is the source of the token + if (!_transferVoucherFrom(_msgSender(), getVoucherEscrow(sourceChannel), denom, amount)) { + revert ICS20InsufficientBalance(_msgSender(), _balances[denom][_msgSender()], amount); + } + } else { + // dst chain is the source of the token + _burnVoucher(_msgSender(), denom, amount); + } + bytes memory packetData = ICS20Lib.marshalJSON(denom, amount, encodeAddress(_msgSender()), receiver); + return ibcHandler.sendPacket(sourcePort, sourceChannel, timeout.height, timeout.timestampNanos, packetData); + } + + /** + * @dev depositSendTransfer sends a transfer packet to the destination chain after depositing the token. + * @param sourceChannel source channel of the packet + * @param tokenContract address of the token contract + * @param amount amount of the token + * @param receiver receiver address on the destination chain. This must be a valid address format per destination chain. + */ + function depositSendTransfer( + string calldata sourceChannel, + address tokenContract, + uint256 amount, + string calldata receiver, + ICS20Lib.Timeout calldata timeout + ) external returns (uint64) { + string memory sourcePort = port.toString(); + if (!ICS20Lib.isEscapedJSONString(receiver)) { + revert ICS20InvalidReceiverAddress(receiver); + } + if (tokenContract == address(0)) { + revert ICS20InvalidTokenContract(tokenContract); + } + address sender = _msgSender(); + if (!IERC20(tokenContract).transferFrom(sender, address(this), amount)) { + revert ICS20FailedERC20Transfer(tokenContract, sender, address(this), amount); + } + _mintVoucher(getVoucherEscrow(sourceChannel), tokenContract, amount); + bytes memory packetData = + ICS20Lib.marshalJSON(ICS20Lib.addressToHexString(tokenContract), amount, encodeAddress(sender), receiver); + return ibcHandler.sendPacket(sourcePort, sourceChannel, timeout.height, timeout.timestampNanos, packetData); + } + + /** + * @dev deposit deposits the ERC20 token to the contract. + * @param to address to deposit the token + * @param tokenContract address of the token contract + * @param amount amount of the token + */ + function deposit(address to, address tokenContract, uint256 amount) public { + if (tokenContract == address(0)) { + revert ICS20InvalidTokenContract(tokenContract); + } + address sender = _msgSender(); + if (!IERC20(tokenContract).transferFrom(sender, address(this), amount)) { + revert ICS20FailedERC20Transfer(tokenContract, sender, address(this), amount); + } + _mintVoucher(to, tokenContract, amount); + } + + /** + * @dev withdraw withdraws the ERC20 token from the contract. + * @param to address to withdraw the token + * @param tokenContract address of the token contract + * @param amount amount of the token + */ + function withdraw(address to, address tokenContract, uint256 amount) public { + if (tokenContract == address(0)) { + revert ICS20InvalidTokenContract(tokenContract); + } + address sender = _msgSender(); + _burnVoucher(sender, ICS20Lib.addressToHexString(tokenContract), amount); + if (!IERC20(tokenContract).transfer(to, amount)) { + revert ICS20FailedERC20TransferFrom(tokenContract, sender, address(this), to, amount); + } + } + + /** + * @dev transfer transfers the token to the given address. + * @param to address to transfer the token + * @param denom denomination of the token + * @param amount amount of the token + */ + function transfer(address to, string calldata denom, uint256 amount) public { + if (to == address(0)) { + revert ICS20InvalidReceiver(to); + } + address from = _msgSender(); + _burnVoucher(from, denom, amount); + _mintVoucher(to, denom, amount); + } + + /** + * @dev balanceOf returns the balance of the account for the given denomination. + * @param account account address + * @param denom denomination of the token + */ + function balanceOf(address account, string calldata denom) public view virtual returns (uint256) { + return _balances[denom][account]; + } + + /** + * @dev encodeAddress encodes an address to a hex string. + * The encoded address is used as `sender` field in the packet data. + */ + function encodeAddress(address sender) public pure virtual returns (string memory) { + return ICS20Lib.addressToHexString(sender); + } + /** + * @dev getVoucherEscrow returns the voucher escrow address for the given channel. + * @param channelId channel identifier + * @return voucher escrow address + */ + function getVoucherEscrow(string calldata channelId) public view virtual returns (address) { + return address(uint160(uint256(keccak256(abi.encode(address(this), channelId))))); + } + + /** + * @dev ibcAddress returns the address of the IBC handler. + */ + function ibcAddress() public view virtual override returns (address) { + return address(ibcHandler); + } + + // ------------------------------ IBC Module Callbacks ------------------------------ // + + /** + * @dev See {IIBCModule-onRecvPacket} + */ function onRecvPacket(Packet calldata packet, address) - external + public virtual override onlyIBC returns (bytes memory acknowledgement) { ICS20Lib.PacketData memory data = ICS20Lib.unmarshalJSON(packet.data); - bool success; - address receiver; - (receiver, success) = _decodeReceiver(data.receiver); + (address receiver, bool success) = _decodeReceiver(data.receiver); if (!success) { return ICS20Lib.FAILED_ACKNOWLEDGEMENT_JSON; } - bytes memory denomPrefix = _getDenomPrefix(packet.sourcePort, packet.sourceChannel); + bytes memory denomPrefix = ICS20Lib.denomPrefix(packet.sourcePort, packet.sourceChannel); bytes memory denom = bytes(data.denom); if ( denom.length >= denomPrefix.length @@ -36,32 +210,37 @@ abstract contract ICS20Transfer is IBCAppBase, IICS20Errors { ) { // sender chain is not the source, unescrow tokens bytes memory unprefixedDenom = ICS20Lib.slice(denom, denomPrefix.length, denom.length - denomPrefix.length); - success = _tryTransferFrom( - _getEscrowAddress(packet.destinationChannel), receiver, string(unprefixedDenom), data.amount - ); - } else { - // sender chain is the source, mint vouchers - - // ensure denom is not required to be escaped - if (ICS20Lib.isEscapeNeededString(denom)) { - success = false; + if ( + _transferVoucherFrom( + getVoucherEscrow(packet.destinationChannel), receiver, string(unprefixedDenom), data.amount + ) + ) { + return ICS20Lib.SUCCESSFUL_ACKNOWLEDGEMENT_JSON; } else { - success = _tryMint( - receiver, - string(abi.encodePacked(_getDenomPrefix(packet.destinationPort, packet.destinationChannel), denom)), - data.amount - ); + return ICS20Lib.FAILED_ACKNOWLEDGEMENT_JSON; } } - if (success) { - return ICS20Lib.SUCCESSFUL_ACKNOWLEDGEMENT_JSON; - } else { + + // sender chain is the source, mint vouchers + + // ensure denom is not required to be escaped + if (ICS20Lib.isEscapeNeededString(denom)) { return ICS20Lib.FAILED_ACKNOWLEDGEMENT_JSON; + } else { + _mintVoucher( + receiver, + string(abi.encodePacked(ICS20Lib.denomPrefix(packet.destinationPort, packet.destinationChannel), denom)), + data.amount + ); + return ICS20Lib.SUCCESSFUL_ACKNOWLEDGEMENT_JSON; } } + /** + * @dev See {IIBCModule-onAcknowledgementPacket} + */ function onAcknowledgementPacket(Packet calldata packet, bytes calldata acknowledgement, address) - external + public virtual override onlyIBC @@ -71,13 +250,26 @@ abstract contract ICS20Transfer is IBCAppBase, IICS20Errors { } } + /** + * @dev See {IIBCModule-onTimeoutPacket} + */ + function onTimeoutPacket(Packet calldata packet, address) public virtual override onlyIBC { + _refundTokens(ICS20Lib.unmarshalJSON(packet.data), packet.sourcePort, packet.sourceChannel); + } + + /** + * @dev See {IIBCModule-onChanOpenInit} + */ function onChanOpenInit(IIBCModule.MsgOnChanOpenInit calldata msg_) - external + public virtual override onlyIBC returns (address, string memory) { + if (!_equal(msg_.portId.toShortString(), port)) { + revert ICS20UnexpectedPort(msg_.portId, port.toString()); + } if (msg_.order != Channel.Order.ORDER_UNORDERED) { revert IBCModuleChannelOrderNotAllowed(msg_.portId, msg_.channelId, msg_.order); } @@ -85,114 +277,140 @@ abstract contract ICS20Transfer is IBCAppBase, IICS20Errors { if (versionBytes.length != 0 && keccak256(versionBytes) != keccak256(bytes(ICS20_VERSION))) { revert ICS20UnexpectedVersion(msg_.version); } - channelEscrowAddresses[msg_.channelId] = address(this); return (address(this), ICS20_VERSION); } + /** + * @dev See {IIBCModule-onChanOpenTry} + */ function onChanOpenTry(IIBCModule.MsgOnChanOpenTry calldata msg_) - external + public virtual override onlyIBC returns (address, string memory) { + if (!_equal(msg_.portId.toShortString(), port)) { + revert ICS20UnexpectedPort(msg_.portId, port.toString()); + } if (msg_.order != Channel.Order.ORDER_UNORDERED) { revert IBCModuleChannelOrderNotAllowed(msg_.portId, msg_.channelId, msg_.order); } if (keccak256(bytes(msg_.counterpartyVersion)) != keccak256(bytes(ICS20_VERSION))) { revert ICS20UnexpectedVersion(msg_.counterpartyVersion); } - channelEscrowAddresses[msg_.channelId] = address(this); return (address(this), ICS20_VERSION); } - function onChanOpenAck(IIBCModule.MsgOnChanOpenAck calldata msg_) external virtual override onlyIBC { + /** + * @dev See {IIBCModule-onChanOpenAck} + */ + function onChanOpenAck(IIBCModule.MsgOnChanOpenAck calldata msg_) public virtual override onlyIBC { if (keccak256(bytes(msg_.counterpartyVersion)) != keccak256(bytes(ICS20_VERSION))) { revert ICS20UnexpectedVersion(msg_.counterpartyVersion); } } - function onChanCloseInit(IIBCModule.MsgOnChanCloseInit calldata msg_) external virtual override onlyIBC { + /** + * @dev See {IIBCModule-onChanCloseInit} + */ + function onChanCloseInit(IIBCModule.MsgOnChanCloseInit calldata msg_) public virtual override onlyIBC { revert IBCModuleChannelCloseNotAllowed(msg_.portId, msg_.channelId); } - function onTimeoutPacket(Packet calldata packet, address) external virtual override onlyIBC { - _refundTokens(ICS20Lib.unmarshalJSON(packet.data), packet.sourcePort, packet.sourceChannel); + // ------------------------------ Internal Functions ------------------------------ // + + /** + * @dev _mintVoucher mints the token to the given address. + * @param to address to mint the token + * @param denom denomination of the token + * @param amount amount of the token + */ + function _mintVoucher(address to, string memory denom, uint256 amount) internal { + _balances[denom][to] += amount; } - function _getEscrowAddress(string memory sourceChannel) internal view virtual returns (address) { - address escrow = channelEscrowAddresses[sourceChannel]; - if (escrow == address(0)) { - revert ICS20EscrowAddressNotFound(sourceChannel); + /** + * @dev _mintVoucher mints the token to the given address. + * @param to address to mint the token + * @param tokenContract address of the token contract + * @param amount amount of the token + */ + function _mintVoucher(address to, address tokenContract, uint256 amount) internal { + _balances[ICS20Lib.addressToHexString(tokenContract)][to] += amount; + } + + /** + * @dev _burnVoucher burns the token from the given address. + * @param from address to burn the token + * @param denom denomination of the token + * @param amount amount of the token + */ + function _burnVoucher(address from, string memory denom, uint256 amount) internal { + uint256 accountBalance = _balances[denom][from]; + if (accountBalance < amount) { + revert ICS20InsufficientBalance(from, accountBalance, amount); + } + unchecked { + // SAFETY: balance is checked above + _balances[denom][from] = accountBalance - amount; + } + } + + /** + * @dev _transferVoucherFrom transfers the token from the sender to the receiver. + * @param from address to transfer the token from + * @param to address to transfer the token to + * @param denom denomination of the token + * @param amount amount of the token + * @return true if the transfer is successful, false otherwise + */ + function _transferVoucherFrom(address from, address to, string memory denom, uint256 amount) + internal + returns (bool) + { + if (from == address(0) || to == address(0)) { + return false; + } + uint256 fromBalance = _balances[denom][from]; + if (fromBalance < amount) { + return false; } - return escrow; + unchecked { + // SAFETY: balance is checked above + _balances[denom][from] = fromBalance - amount; + } + _balances[denom][to] += amount; + return true; } + /** + * @dev _refundTokens refunds the tokens to the sender. + * @param data packet data + * @param sourcePort source port of the packet + * @param sourceChannel source channel of the packet + */ function _refundTokens(ICS20Lib.PacketData memory data, string calldata sourcePort, string calldata sourceChannel) internal virtual { - bytes memory denomPrefix = _getDenomPrefix(sourcePort, sourceChannel); + bytes memory denomPrefix = ICS20Lib.denomPrefix(sourcePort, sourceChannel); bytes memory denom = bytes(data.denom); + address sender = _decodeSender(data.sender); if ( denom.length >= denomPrefix.length && ICS20Lib.equal(ICS20Lib.slice(denom, 0, denomPrefix.length), denomPrefix) ) { - _mint(_decodeSender(data.sender), data.denom, data.amount); + _mintVoucher(sender, data.denom, data.amount); } else { // sender was source chain - _transferFrom(_getEscrowAddress(sourceChannel), _decodeSender(data.sender), data.denom, data.amount); + address escrow = getVoucherEscrow(sourceChannel); + if (!_transferVoucherFrom(escrow, sender, data.denom, data.amount)) { + revert ICS20FailedRefund(escrow, sender, data.denom, data.amount); + } } } - function _getDenomPrefix(string calldata port, string calldata channel) internal pure returns (bytes memory) { - return abi.encodePacked(port, "/", channel, "/"); - } - - /** - * @dev _transferFrom transfers tokens from `sender` to `receiver` in the bank. - */ - function _transferFrom(address sender, address receiver, string memory denom, uint256 amount) internal virtual; - - /** - * @dev _burn burns tokens from `account` in the bank. - */ - function _burn(address account, string memory denom, uint256 amount) internal virtual; - - /** - * @dev _mint mints tokens to `account` in the bank. - */ - function _mint(address account, string memory denom, uint256 amount) internal virtual; - - /** - * @dev _tryTransferFrom transfers tokens from `sender` to `receiver` in the bank. - * If the transfer fails, it returns false and does not revert. - */ - function _tryTransferFrom(address sender, address receiver, string memory denom, uint256 amount) - internal - virtual - returns (bool); - - /** - * @dev _tryMint mints tokens to `account` in the bank. - * If the mint fails, it returns false and does not revert. - */ - function _tryMint(address account, string memory denom, uint256 amount) internal virtual returns (bool); - - /** - * @dev _tryBurn burns tokens from `account` in the bank. - * If the burn fails, it returns false and does not revert. - */ - function _tryBurn(address account, string memory denom, uint256 amount) internal virtual returns (bool); - - /** - * @dev _encodeSender encodes an address to a hex string. - * The encoded sender is used as `sender` field in the packet data. - */ - function _encodeSender(address sender) internal pure virtual returns (string memory) { - return ICS20Lib.addressToHexString(sender); - } - /** * @dev _decodeSender decodes a hex string to an address. * `sender` must be a valid address format. @@ -212,4 +430,11 @@ abstract contract ICS20Transfer is IBCAppBase, IICS20Errors { function _decodeReceiver(string memory receiver) internal pure virtual returns (address, bool) { return ICS20Lib.hexStringToAddress(receiver); } + + /** + * @dev _equal compares two ShortString values. + */ + function _equal(ShortString a, ShortString b) internal pure returns (bool) { + return ShortString.unwrap(a) == ShortString.unwrap(b); + } } diff --git a/contracts/apps/20-transfer/ICS20TransferBank.sol b/contracts/apps/20-transfer/ICS20TransferBank.sol deleted file mode 100644 index 7b625e8a..00000000 --- a/contracts/apps/20-transfer/ICS20TransferBank.sol +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -import {Height} from "../../proto/Client.sol"; -import {IIBCHandler} from "../../core/25-handler/IIBCHandler.sol"; -import {ICS20Transfer} from "./ICS20Transfer.sol"; -import {IICS20Bank} from "./IICS20Bank.sol"; -import {ICS20Lib} from "./ICS20Lib.sol"; - -contract ICS20TransferBank is ICS20Transfer { - IIBCHandler private immutable ibcHandler; - IICS20Bank private immutable bank; - - constructor(IIBCHandler ibcHandler_, IICS20Bank bank_) { - ibcHandler = ibcHandler_; - bank = bank_; - } - - /** - * @dev sendTransfer sends a transfer packet to the destination chain. - * @param denom denomination of the token. It can assume the denom string is escaped or not required to be escaped. - * @param amount amount of the token - * @param receiver receiver address on the destination chain - * @param sourcePort source port of the packet - * @param sourceChannel source channel of the packet - * @param timeoutHeight timeout height of the packet - */ - function sendTransfer( - string calldata denom, - uint256 amount, - string calldata receiver, - string calldata sourcePort, - string calldata sourceChannel, - uint64 timeoutHeight - ) external { - if (!ICS20Lib.isEscapedJSONString(receiver)) { - revert ICS20InvalidReceiverAddress(receiver); - } - bytes memory denomPrefix = _getDenomPrefix(sourcePort, sourceChannel); - bytes memory denomBytes = bytes(denom); - if ( - denomBytes.length < denomPrefix.length - || !ICS20Lib.equal(ICS20Lib.slice(denomBytes, 0, denomPrefix.length), denomPrefix) - ) { - // sender is source chain - _transferFrom(_msgSender(), _getEscrowAddress(sourceChannel), denom, amount); - } else { - _burn(_msgSender(), denom, amount); - } - bytes memory packetData = ICS20Lib.marshalJSON(denom, amount, _encodeSender(_msgSender()), receiver); - IIBCHandler(ibcAddress()).sendPacket( - sourcePort, sourceChannel, Height.Data({revision_number: 0, revision_height: timeoutHeight}), 0, packetData - ); - } - - function _transferFrom(address sender, address receiver, string memory denom, uint256 amount) internal override { - bank.transferFrom(sender, receiver, denom, amount); - } - - function _tryTransferFrom(address sender, address receiver, string memory denom, uint256 amount) - internal - override - returns (bool) - { - try bank.transferFrom(sender, receiver, denom, amount) { - return true; - } catch (bytes memory) { - return false; - } - } - - function _mint(address account, string memory denom, uint256 amount) internal override { - bank.mint(account, denom, amount); - } - - function _tryMint(address account, string memory denom, uint256 amount) internal override returns (bool) { - try bank.mint(account, denom, amount) { - return true; - } catch (bytes memory) { - return false; - } - } - - function _burn(address account, string memory denom, uint256 amount) internal override { - bank.burn(account, denom, amount); - } - - function _tryBurn(address account, string memory denom, uint256 amount) internal override returns (bool) { - try bank.burn(account, denom, amount) { - return true; - } catch (bytes memory) { - return false; - } - } - - function ibcAddress() public view virtual override returns (address) { - return address(ibcHandler); - } -} diff --git a/contracts/apps/20-transfer/IICS20Bank.sol b/contracts/apps/20-transfer/IICS20Bank.sol deleted file mode 100644 index fe2b354d..00000000 --- a/contracts/apps/20-transfer/IICS20Bank.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -interface IICS20Bank { - /** - * @dev balanceOf returns the balance of the account. - * @param account account address - * @param denom denom of the token - */ - function balanceOf(address account, string calldata denom) external view returns (uint256); - - /** - * @dev transferFrom transfers tokens from the sender to the receiver. - * @param from sender address - * @param to receiver address - * @param denom denom of the token - * @param amount amount of the token - */ - function transferFrom(address from, address to, string calldata denom, uint256 amount) external; - - /** - * @dev mint mints tokens to the account. - * @param account account address - * @param denom denom of the token - * @param amount amount of the token - */ - function mint(address account, string calldata denom, uint256 amount) external; - - /** - * @dev burn burns tokens from the account. - * @param account account address - * @param denom denom of the token - * @param amount amount of the token - */ - function burn(address account, string calldata denom, uint256 amount) external; - - /** - * @dev addressToDenom returns the denom of the token corresponding to the contract address. - * The denom must be a json escaped string. - */ - function addressToDenom(address tokenContract) external pure returns (string memory); - - /** - * @dev deposit deposits tokens to the bank. - * @param tokenContract token contract address - * @param amount amount of the token - * @param receiver receiver address on the bank - */ - function deposit(address tokenContract, uint256 amount, address receiver) external; - - /** - * @dev withdraw withdraws tokens from the bank. - * @param tokenContract token contract address - * @param amount amount of the token - * @param receiver receiver address on the bank - */ - function withdraw(address tokenContract, uint256 amount, address receiver) external; -} diff --git a/contracts/apps/20-transfer/IICS20Errors.sol b/contracts/apps/20-transfer/IICS20Errors.sol index 2ef576b6..139abdd1 100644 --- a/contracts/apps/20-transfer/IICS20Errors.sol +++ b/contracts/apps/20-transfer/IICS20Errors.sol @@ -2,16 +2,11 @@ pragma solidity ^0.8.20; interface IICS20Errors { - /// @param channelId Channel identifier - error ICS20EscrowAddressNotFound(string channelId); /// @param version Version string error ICS20UnexpectedVersion(string version); - /// @param sender Address of the sender - error ICS20BankNotAdminRole(address sender); - /// @param sender Address of the sender - error ICS20BankNotMintRole(address sender); - /// @param sender Address of the sender - error ICS20BankNotBurnRole(address sender); + /// @param actual port + /// @param expected port + error ICS20UnexpectedPort(string actual, string expected); /// @param tokenContract Address of the token contract error ICS20InvalidTokenContract(address tokenContract); /// @param tokenContract Address of the token contract @@ -29,8 +24,6 @@ interface IICS20Errors { /// @param balance Current balance for the interacting account /// @param needed Minimum amount required to perform a transfer error ICS20InsufficientBalance(address sender, uint256 balance, uint256 needed); - /// @param sender Address whose tokens are being transferred - error ICS20InvalidSender(address sender); /// @param receiver Address to which tokens are being transferred error ICS20InvalidReceiver(address receiver); /// @param sender Address of the sender @@ -59,4 +52,9 @@ interface IICS20Errors { /// @param start start index /// @param end end index error ICS20BytesSliceOutOfBounds(uint256 length, uint256 start, uint256 end); + /// @param escrow Address of the escrow contract + /// @param sender Address of the sender + /// @param denom Denomination of the tokens + /// @param amount Amount of tokens + error ICS20FailedRefund(address escrow, address sender, string denom, uint256 amount); } diff --git a/pkg/contract/ics20bank/ics20bank.go b/pkg/contract/ics20bank/ics20bank.go deleted file mode 100644 index 3487b912..00000000 --- a/pkg/contract/ics20bank/ics20bank.go +++ /dev/null @@ -1,1104 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package ics20bank - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// Ics20bankMetaData contains all meta data concerning the Ics20bank contract. -var Ics20bankMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"OPERATOR_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addressToDenom\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"denom\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"denom\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"denom\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setOperator\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"denom\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ICS20BankNotAdminRole\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20BankNotBurnRole\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20BankNotMintRole\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20BytesSliceOutOfBounds\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"start\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"end\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20BytesSliceOverflow\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20EscrowAddressNotFound\",\"inputs\":[{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ICS20FailedERC20Transfer\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20FailedERC20TransferFrom\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20InsufficientBalance\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidReceiver\",\"inputs\":[{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidReceiverAddress\",\"inputs\":[{\"name\":\"receiver\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidSender\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidSenderAddress\",\"inputs\":[{\"name\":\"sender\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidTokenContract\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONClosingBraceNotFound\",\"inputs\":[{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"bytes1\",\"internalType\":\"bytes1\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONInvalidEscape\",\"inputs\":[{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"bytes1\",\"internalType\":\"bytes1\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONStringClosingDoubleQuoteNotFound\",\"inputs\":[{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"bytes1\",\"internalType\":\"bytes1\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONStringUnclosed\",\"inputs\":[{\"name\":\"bz\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONUnexpectedBytes\",\"inputs\":[{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ICS20UnexpectedVersion\",\"inputs\":[{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}]}]", -} - -// Ics20bankABI is the input ABI used to generate the binding from. -// Deprecated: Use Ics20bankMetaData.ABI instead. -var Ics20bankABI = Ics20bankMetaData.ABI - -// Ics20bank is an auto generated Go binding around an Ethereum contract. -type Ics20bank struct { - Ics20bankCaller // Read-only binding to the contract - Ics20bankTransactor // Write-only binding to the contract - Ics20bankFilterer // Log filterer for contract events -} - -// Ics20bankCaller is an auto generated read-only Go binding around an Ethereum contract. -type Ics20bankCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// Ics20bankTransactor is an auto generated write-only Go binding around an Ethereum contract. -type Ics20bankTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// Ics20bankFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type Ics20bankFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// Ics20bankSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type Ics20bankSession struct { - Contract *Ics20bank // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// Ics20bankCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type Ics20bankCallerSession struct { - Contract *Ics20bankCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// Ics20bankTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type Ics20bankTransactorSession struct { - Contract *Ics20bankTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// Ics20bankRaw is an auto generated low-level Go binding around an Ethereum contract. -type Ics20bankRaw struct { - Contract *Ics20bank // Generic contract binding to access the raw methods on -} - -// Ics20bankCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type Ics20bankCallerRaw struct { - Contract *Ics20bankCaller // Generic read-only contract binding to access the raw methods on -} - -// Ics20bankTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type Ics20bankTransactorRaw struct { - Contract *Ics20bankTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewIcs20bank creates a new instance of Ics20bank, bound to a specific deployed contract. -func NewIcs20bank(address common.Address, backend bind.ContractBackend) (*Ics20bank, error) { - contract, err := bindIcs20bank(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Ics20bank{Ics20bankCaller: Ics20bankCaller{contract: contract}, Ics20bankTransactor: Ics20bankTransactor{contract: contract}, Ics20bankFilterer: Ics20bankFilterer{contract: contract}}, nil -} - -// NewIcs20bankCaller creates a new read-only instance of Ics20bank, bound to a specific deployed contract. -func NewIcs20bankCaller(address common.Address, caller bind.ContractCaller) (*Ics20bankCaller, error) { - contract, err := bindIcs20bank(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &Ics20bankCaller{contract: contract}, nil -} - -// NewIcs20bankTransactor creates a new write-only instance of Ics20bank, bound to a specific deployed contract. -func NewIcs20bankTransactor(address common.Address, transactor bind.ContractTransactor) (*Ics20bankTransactor, error) { - contract, err := bindIcs20bank(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &Ics20bankTransactor{contract: contract}, nil -} - -// NewIcs20bankFilterer creates a new log filterer instance of Ics20bank, bound to a specific deployed contract. -func NewIcs20bankFilterer(address common.Address, filterer bind.ContractFilterer) (*Ics20bankFilterer, error) { - contract, err := bindIcs20bank(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &Ics20bankFilterer{contract: contract}, nil -} - -// bindIcs20bank binds a generic wrapper to an already deployed contract. -func bindIcs20bank(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := Ics20bankMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Ics20bank *Ics20bankRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Ics20bank.Contract.Ics20bankCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Ics20bank *Ics20bankRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Ics20bank.Contract.Ics20bankTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Ics20bank *Ics20bankRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Ics20bank.Contract.Ics20bankTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Ics20bank *Ics20bankCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Ics20bank.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Ics20bank *Ics20bankTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Ics20bank.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Ics20bank *Ics20bankTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Ics20bank.Contract.contract.Transact(opts, method, params...) -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankCaller) ADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Ics20bank.contract.Call(opts, &out, "ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankSession) ADMINROLE() ([32]byte, error) { - return _Ics20bank.Contract.ADMINROLE(&_Ics20bank.CallOpts) -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankCallerSession) ADMINROLE() ([32]byte, error) { - return _Ics20bank.Contract.ADMINROLE(&_Ics20bank.CallOpts) -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Ics20bank.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankSession) DEFAULTADMINROLE() ([32]byte, error) { - return _Ics20bank.Contract.DEFAULTADMINROLE(&_Ics20bank.CallOpts) -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankCallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _Ics20bank.Contract.DEFAULTADMINROLE(&_Ics20bank.CallOpts) -} - -// OPERATORROLE is a free data retrieval call binding the contract method 0xf5b541a6. -// -// Solidity: function OPERATOR_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankCaller) OPERATORROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Ics20bank.contract.Call(opts, &out, "OPERATOR_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// OPERATORROLE is a free data retrieval call binding the contract method 0xf5b541a6. -// -// Solidity: function OPERATOR_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankSession) OPERATORROLE() ([32]byte, error) { - return _Ics20bank.Contract.OPERATORROLE(&_Ics20bank.CallOpts) -} - -// OPERATORROLE is a free data retrieval call binding the contract method 0xf5b541a6. -// -// Solidity: function OPERATOR_ROLE() view returns(bytes32) -func (_Ics20bank *Ics20bankCallerSession) OPERATORROLE() ([32]byte, error) { - return _Ics20bank.Contract.OPERATORROLE(&_Ics20bank.CallOpts) -} - -// AddressToDenom is a free data retrieval call binding the contract method 0x95469df8. -// -// Solidity: function addressToDenom(address tokenContract) pure returns(string) -func (_Ics20bank *Ics20bankCaller) AddressToDenom(opts *bind.CallOpts, tokenContract common.Address) (string, error) { - var out []interface{} - err := _Ics20bank.contract.Call(opts, &out, "addressToDenom", tokenContract) - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// AddressToDenom is a free data retrieval call binding the contract method 0x95469df8. -// -// Solidity: function addressToDenom(address tokenContract) pure returns(string) -func (_Ics20bank *Ics20bankSession) AddressToDenom(tokenContract common.Address) (string, error) { - return _Ics20bank.Contract.AddressToDenom(&_Ics20bank.CallOpts, tokenContract) -} - -// AddressToDenom is a free data retrieval call binding the contract method 0x95469df8. -// -// Solidity: function addressToDenom(address tokenContract) pure returns(string) -func (_Ics20bank *Ics20bankCallerSession) AddressToDenom(tokenContract common.Address) (string, error) { - return _Ics20bank.Contract.AddressToDenom(&_Ics20bank.CallOpts, tokenContract) -} - -// BalanceOf is a free data retrieval call binding the contract method 0xb9b092c8. -// -// Solidity: function balanceOf(address account, string denom) view returns(uint256) -func (_Ics20bank *Ics20bankCaller) BalanceOf(opts *bind.CallOpts, account common.Address, denom string) (*big.Int, error) { - var out []interface{} - err := _Ics20bank.contract.Call(opts, &out, "balanceOf", account, denom) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// BalanceOf is a free data retrieval call binding the contract method 0xb9b092c8. -// -// Solidity: function balanceOf(address account, string denom) view returns(uint256) -func (_Ics20bank *Ics20bankSession) BalanceOf(account common.Address, denom string) (*big.Int, error) { - return _Ics20bank.Contract.BalanceOf(&_Ics20bank.CallOpts, account, denom) -} - -// BalanceOf is a free data retrieval call binding the contract method 0xb9b092c8. -// -// Solidity: function balanceOf(address account, string denom) view returns(uint256) -func (_Ics20bank *Ics20bankCallerSession) BalanceOf(account common.Address, denom string) (*big.Int, error) { - return _Ics20bank.Contract.BalanceOf(&_Ics20bank.CallOpts, account, denom) -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Ics20bank *Ics20bankCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _Ics20bank.contract.Call(opts, &out, "getRoleAdmin", role) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Ics20bank *Ics20bankSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _Ics20bank.Contract.GetRoleAdmin(&_Ics20bank.CallOpts, role) -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Ics20bank *Ics20bankCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _Ics20bank.Contract.GetRoleAdmin(&_Ics20bank.CallOpts, role) -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Ics20bank *Ics20bankCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { - var out []interface{} - err := _Ics20bank.contract.Call(opts, &out, "hasRole", role, account) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Ics20bank *Ics20bankSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _Ics20bank.Contract.HasRole(&_Ics20bank.CallOpts, role, account) -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Ics20bank *Ics20bankCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _Ics20bank.Contract.HasRole(&_Ics20bank.CallOpts, role, account) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Ics20bank *Ics20bankCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _Ics20bank.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Ics20bank *Ics20bankSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Ics20bank.Contract.SupportsInterface(&_Ics20bank.CallOpts, interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Ics20bank *Ics20bankCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Ics20bank.Contract.SupportsInterface(&_Ics20bank.CallOpts, interfaceId) -} - -// Burn is a paid mutator transaction binding the contract method 0xc45b71de. -// -// Solidity: function burn(address account, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankTransactor) Burn(opts *bind.TransactOpts, account common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "burn", account, denom, amount) -} - -// Burn is a paid mutator transaction binding the contract method 0xc45b71de. -// -// Solidity: function burn(address account, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankSession) Burn(account common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.Contract.Burn(&_Ics20bank.TransactOpts, account, denom, amount) -} - -// Burn is a paid mutator transaction binding the contract method 0xc45b71de. -// -// Solidity: function burn(address account, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankTransactorSession) Burn(account common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.Contract.Burn(&_Ics20bank.TransactOpts, account, denom, amount) -} - -// Deposit is a paid mutator transaction binding the contract method 0xf45346dc. -// -// Solidity: function deposit(address tokenContract, uint256 amount, address receiver) returns() -func (_Ics20bank *Ics20bankTransactor) Deposit(opts *bind.TransactOpts, tokenContract common.Address, amount *big.Int, receiver common.Address) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "deposit", tokenContract, amount, receiver) -} - -// Deposit is a paid mutator transaction binding the contract method 0xf45346dc. -// -// Solidity: function deposit(address tokenContract, uint256 amount, address receiver) returns() -func (_Ics20bank *Ics20bankSession) Deposit(tokenContract common.Address, amount *big.Int, receiver common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.Deposit(&_Ics20bank.TransactOpts, tokenContract, amount, receiver) -} - -// Deposit is a paid mutator transaction binding the contract method 0xf45346dc. -// -// Solidity: function deposit(address tokenContract, uint256 amount, address receiver) returns() -func (_Ics20bank *Ics20bankTransactorSession) Deposit(tokenContract common.Address, amount *big.Int, receiver common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.Deposit(&_Ics20bank.TransactOpts, tokenContract, amount, receiver) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Ics20bank *Ics20bankTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "grantRole", role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Ics20bank *Ics20bankSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.GrantRole(&_Ics20bank.TransactOpts, role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Ics20bank *Ics20bankTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.GrantRole(&_Ics20bank.TransactOpts, role, account) -} - -// Mint is a paid mutator transaction binding the contract method 0xba7aef43. -// -// Solidity: function mint(address account, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankTransactor) Mint(opts *bind.TransactOpts, account common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "mint", account, denom, amount) -} - -// Mint is a paid mutator transaction binding the contract method 0xba7aef43. -// -// Solidity: function mint(address account, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankSession) Mint(account common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.Contract.Mint(&_Ics20bank.TransactOpts, account, denom, amount) -} - -// Mint is a paid mutator transaction binding the contract method 0xba7aef43. -// -// Solidity: function mint(address account, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankTransactorSession) Mint(account common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.Contract.Mint(&_Ics20bank.TransactOpts, account, denom, amount) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Ics20bank *Ics20bankTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "renounceRole", role, callerConfirmation) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Ics20bank *Ics20bankSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.RenounceRole(&_Ics20bank.TransactOpts, role, callerConfirmation) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Ics20bank *Ics20bankTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.RenounceRole(&_Ics20bank.TransactOpts, role, callerConfirmation) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Ics20bank *Ics20bankTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "revokeRole", role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Ics20bank *Ics20bankSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.RevokeRole(&_Ics20bank.TransactOpts, role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Ics20bank *Ics20bankTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.RevokeRole(&_Ics20bank.TransactOpts, role, account) -} - -// SetOperator is a paid mutator transaction binding the contract method 0xb3ab15fb. -// -// Solidity: function setOperator(address operator) returns() -func (_Ics20bank *Ics20bankTransactor) SetOperator(opts *bind.TransactOpts, operator common.Address) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "setOperator", operator) -} - -// SetOperator is a paid mutator transaction binding the contract method 0xb3ab15fb. -// -// Solidity: function setOperator(address operator) returns() -func (_Ics20bank *Ics20bankSession) SetOperator(operator common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.SetOperator(&_Ics20bank.TransactOpts, operator) -} - -// SetOperator is a paid mutator transaction binding the contract method 0xb3ab15fb. -// -// Solidity: function setOperator(address operator) returns() -func (_Ics20bank *Ics20bankTransactorSession) SetOperator(operator common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.SetOperator(&_Ics20bank.TransactOpts, operator) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0xf24dc1da. -// -// Solidity: function transferFrom(address from, address to, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankTransactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "transferFrom", from, to, denom, amount) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0xf24dc1da. -// -// Solidity: function transferFrom(address from, address to, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankSession) TransferFrom(from common.Address, to common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.Contract.TransferFrom(&_Ics20bank.TransactOpts, from, to, denom, amount) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0xf24dc1da. -// -// Solidity: function transferFrom(address from, address to, string denom, uint256 amount) returns() -func (_Ics20bank *Ics20bankTransactorSession) TransferFrom(from common.Address, to common.Address, denom string, amount *big.Int) (*types.Transaction, error) { - return _Ics20bank.Contract.TransferFrom(&_Ics20bank.TransactOpts, from, to, denom, amount) -} - -// Withdraw is a paid mutator transaction binding the contract method 0x69328dec. -// -// Solidity: function withdraw(address tokenContract, uint256 amount, address receiver) returns() -func (_Ics20bank *Ics20bankTransactor) Withdraw(opts *bind.TransactOpts, tokenContract common.Address, amount *big.Int, receiver common.Address) (*types.Transaction, error) { - return _Ics20bank.contract.Transact(opts, "withdraw", tokenContract, amount, receiver) -} - -// Withdraw is a paid mutator transaction binding the contract method 0x69328dec. -// -// Solidity: function withdraw(address tokenContract, uint256 amount, address receiver) returns() -func (_Ics20bank *Ics20bankSession) Withdraw(tokenContract common.Address, amount *big.Int, receiver common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.Withdraw(&_Ics20bank.TransactOpts, tokenContract, amount, receiver) -} - -// Withdraw is a paid mutator transaction binding the contract method 0x69328dec. -// -// Solidity: function withdraw(address tokenContract, uint256 amount, address receiver) returns() -func (_Ics20bank *Ics20bankTransactorSession) Withdraw(tokenContract common.Address, amount *big.Int, receiver common.Address) (*types.Transaction, error) { - return _Ics20bank.Contract.Withdraw(&_Ics20bank.TransactOpts, tokenContract, amount, receiver) -} - -// Ics20bankRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Ics20bank contract. -type Ics20bankRoleAdminChangedIterator struct { - Event *Ics20bankRoleAdminChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *Ics20bankRoleAdminChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(Ics20bankRoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(Ics20bankRoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *Ics20bankRoleAdminChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *Ics20bankRoleAdminChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// Ics20bankRoleAdminChanged represents a RoleAdminChanged event raised by the Ics20bank contract. -type Ics20bankRoleAdminChanged struct { - Role [32]byte - PreviousAdminRole [32]byte - NewAdminRole [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Ics20bank *Ics20bankFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*Ics20bankRoleAdminChangedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } - - logs, sub, err := _Ics20bank.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return &Ics20bankRoleAdminChangedIterator{contract: _Ics20bank.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil -} - -// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Ics20bank *Ics20bankFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *Ics20bankRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } - - logs, sub, err := _Ics20bank.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(Ics20bankRoleAdminChanged) - if err := _Ics20bank.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Ics20bank *Ics20bankFilterer) ParseRoleAdminChanged(log types.Log) (*Ics20bankRoleAdminChanged, error) { - event := new(Ics20bankRoleAdminChanged) - if err := _Ics20bank.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// Ics20bankRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Ics20bank contract. -type Ics20bankRoleGrantedIterator struct { - Event *Ics20bankRoleGranted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *Ics20bankRoleGrantedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(Ics20bankRoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(Ics20bankRoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *Ics20bankRoleGrantedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *Ics20bankRoleGrantedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// Ics20bankRoleGranted represents a RoleGranted event raised by the Ics20bank contract. -type Ics20bankRoleGranted struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Ics20bank *Ics20bankFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*Ics20bankRoleGrantedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _Ics20bank.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return &Ics20bankRoleGrantedIterator{contract: _Ics20bank.contract, event: "RoleGranted", logs: logs, sub: sub}, nil -} - -// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Ics20bank *Ics20bankFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *Ics20bankRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _Ics20bank.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(Ics20bankRoleGranted) - if err := _Ics20bank.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Ics20bank *Ics20bankFilterer) ParseRoleGranted(log types.Log) (*Ics20bankRoleGranted, error) { - event := new(Ics20bankRoleGranted) - if err := _Ics20bank.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// Ics20bankRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Ics20bank contract. -type Ics20bankRoleRevokedIterator struct { - Event *Ics20bankRoleRevoked // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *Ics20bankRoleRevokedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(Ics20bankRoleRevoked) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(Ics20bankRoleRevoked) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *Ics20bankRoleRevokedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *Ics20bankRoleRevokedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// Ics20bankRoleRevoked represents a RoleRevoked event raised by the Ics20bank contract. -type Ics20bankRoleRevoked struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Ics20bank *Ics20bankFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*Ics20bankRoleRevokedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _Ics20bank.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return &Ics20bankRoleRevokedIterator{contract: _Ics20bank.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil -} - -// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Ics20bank *Ics20bankFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *Ics20bankRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _Ics20bank.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(Ics20bankRoleRevoked) - if err := _Ics20bank.contract.UnpackLog(event, "RoleRevoked", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Ics20bank *Ics20bankFilterer) ParseRoleRevoked(log types.Log) (*Ics20bankRoleRevoked, error) { - event := new(Ics20bankRoleRevoked) - if err := _Ics20bank.contract.UnpackLog(event, "RoleRevoked", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/pkg/contract/ics20transfer/ics20transfer.go b/pkg/contract/ics20transfer/ics20transfer.go new file mode 100644 index 00000000..568cf6d6 --- /dev/null +++ b/pkg/contract/ics20transfer/ics20transfer.go @@ -0,0 +1,736 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ics20transfer + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// ChannelCounterpartyData is an auto generated low-level Go binding around an user-defined struct. +type ChannelCounterpartyData struct { + PortId string + ChannelId string +} + +// HeightData is an auto generated low-level Go binding around an user-defined struct. +type HeightData struct { + RevisionNumber uint64 + RevisionHeight uint64 +} + +// ICS20LibTimeout is an auto generated low-level Go binding around an user-defined struct. +type ICS20LibTimeout struct { + Height HeightData + TimestampNanos uint64 +} + +// IIBCModuleInitializerMsgOnChanOpenInit is an auto generated low-level Go binding around an user-defined struct. +type IIBCModuleInitializerMsgOnChanOpenInit struct { + Order uint8 + ConnectionHops []string + PortId string + ChannelId string + Counterparty ChannelCounterpartyData + Version string +} + +// IIBCModuleInitializerMsgOnChanOpenTry is an auto generated low-level Go binding around an user-defined struct. +type IIBCModuleInitializerMsgOnChanOpenTry struct { + Order uint8 + ConnectionHops []string + PortId string + ChannelId string + Counterparty ChannelCounterpartyData + CounterpartyVersion string +} + +// IIBCModuleMsgOnChanCloseConfirm is an auto generated low-level Go binding around an user-defined struct. +type IIBCModuleMsgOnChanCloseConfirm struct { + PortId string + ChannelId string +} + +// IIBCModuleMsgOnChanCloseInit is an auto generated low-level Go binding around an user-defined struct. +type IIBCModuleMsgOnChanCloseInit struct { + PortId string + ChannelId string +} + +// IIBCModuleMsgOnChanOpenAck is an auto generated low-level Go binding around an user-defined struct. +type IIBCModuleMsgOnChanOpenAck struct { + PortId string + ChannelId string + CounterpartyVersion string +} + +// IIBCModuleMsgOnChanOpenConfirm is an auto generated low-level Go binding around an user-defined struct. +type IIBCModuleMsgOnChanOpenConfirm struct { + PortId string + ChannelId string +} + +// Packet is an auto generated low-level Go binding around an user-defined struct. +type Packet struct { + Sequence uint64 + SourcePort string + SourceChannel string + DestinationPort string + DestinationChannel string + Data []byte + TimeoutHeight HeightData + TimeoutTimestamp uint64 +} + +// Ics20transferMetaData contains all meta data concerning the Ics20transfer contract. +var Ics20transferMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"ibcHandler_\",\"type\":\"address\",\"internalType\":\"contractIIBCHandler\"},{\"name\":\"port_\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ICS20_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"denom\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"depositSendTransfer\",\"inputs\":[{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"receiver\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeout\",\"type\":\"tuple\",\"internalType\":\"structICS20Lib.Timeout\",\"components\":[{\"name\":\"height\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timestampNanos\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"encodeAddress\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"getVoucherEscrow\",\"inputs\":[{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ibcAddress\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"onAcknowledgementPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanCloseConfirm\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanCloseConfirm\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanCloseInit\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanCloseInit\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenAck\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanOpenAck\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterpartyVersion\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenConfirm\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanOpenConfirm\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenInit\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIIBCModuleInitializer.MsgOnChanOpenInit\",\"components\":[{\"name\":\"order\",\"type\":\"uint8\",\"internalType\":\"enumChannel.Order\"},{\"name\":\"connectionHops\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterparty\",\"type\":\"tuple\",\"internalType\":\"structChannelCounterparty.Data\",\"components\":[{\"name\":\"port_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel_id\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenTry\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIIBCModuleInitializer.MsgOnChanOpenTry\",\"components\":[{\"name\":\"order\",\"type\":\"uint8\",\"internalType\":\"enumChannel.Order\"},{\"name\":\"connectionHops\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterparty\",\"type\":\"tuple\",\"internalType\":\"structChannelCounterparty.Data\",\"components\":[{\"name\":\"port_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel_id\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"counterpartyVersion\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onRecvPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onTimeoutPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendTransfer\",\"inputs\":[{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"denom\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"receiver\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeout\",\"type\":\"tuple\",\"internalType\":\"structICS20Lib.Timeout\",\"components\":[{\"name\":\"height\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timestampNanos\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"denom\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"error\",\"name\":\"IBCModuleChannelCloseNotAllowed\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCModuleChannelOrderNotAllowed\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"order\",\"type\":\"uint8\",\"internalType\":\"enumChannel.Order\"}]},{\"type\":\"error\",\"name\":\"IBCModuleInvalidSender\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20BytesSliceOutOfBounds\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"start\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"end\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20BytesSliceOverflow\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20FailedERC20Transfer\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20FailedERC20TransferFrom\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20FailedRefund\",\"inputs\":[{\"name\":\"escrow\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"denom\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20InsufficientBalance\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidReceiver\",\"inputs\":[{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidReceiverAddress\",\"inputs\":[{\"name\":\"receiver\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidSenderAddress\",\"inputs\":[{\"name\":\"sender\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ICS20InvalidTokenContract\",\"inputs\":[{\"name\":\"tokenContract\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONClosingBraceNotFound\",\"inputs\":[{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"bytes1\",\"internalType\":\"bytes1\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONInvalidEscape\",\"inputs\":[{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"bytes1\",\"internalType\":\"bytes1\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONStringClosingDoubleQuoteNotFound\",\"inputs\":[{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"bytes1\",\"internalType\":\"bytes1\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONStringUnclosed\",\"inputs\":[{\"name\":\"bz\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ICS20JSONUnexpectedBytes\",\"inputs\":[{\"name\":\"position\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ICS20UnexpectedPort\",\"inputs\":[{\"name\":\"actual\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"expected\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ICS20UnexpectedVersion\",\"inputs\":[{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"InvalidShortString\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StringTooLong\",\"inputs\":[{\"name\":\"str\",\"type\":\"string\",\"internalType\":\"string\"}]}]", +} + +// Ics20transferABI is the input ABI used to generate the binding from. +// Deprecated: Use Ics20transferMetaData.ABI instead. +var Ics20transferABI = Ics20transferMetaData.ABI + +// Ics20transfer is an auto generated Go binding around an Ethereum contract. +type Ics20transfer struct { + Ics20transferCaller // Read-only binding to the contract + Ics20transferTransactor // Write-only binding to the contract + Ics20transferFilterer // Log filterer for contract events +} + +// Ics20transferCaller is an auto generated read-only Go binding around an Ethereum contract. +type Ics20transferCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Ics20transferTransactor is an auto generated write-only Go binding around an Ethereum contract. +type Ics20transferTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Ics20transferFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Ics20transferFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Ics20transferSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Ics20transferSession struct { + Contract *Ics20transfer // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Ics20transferCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Ics20transferCallerSession struct { + Contract *Ics20transferCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Ics20transferTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Ics20transferTransactorSession struct { + Contract *Ics20transferTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Ics20transferRaw is an auto generated low-level Go binding around an Ethereum contract. +type Ics20transferRaw struct { + Contract *Ics20transfer // Generic contract binding to access the raw methods on +} + +// Ics20transferCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Ics20transferCallerRaw struct { + Contract *Ics20transferCaller // Generic read-only contract binding to access the raw methods on +} + +// Ics20transferTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Ics20transferTransactorRaw struct { + Contract *Ics20transferTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIcs20transfer creates a new instance of Ics20transfer, bound to a specific deployed contract. +func NewIcs20transfer(address common.Address, backend bind.ContractBackend) (*Ics20transfer, error) { + contract, err := bindIcs20transfer(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Ics20transfer{Ics20transferCaller: Ics20transferCaller{contract: contract}, Ics20transferTransactor: Ics20transferTransactor{contract: contract}, Ics20transferFilterer: Ics20transferFilterer{contract: contract}}, nil +} + +// NewIcs20transferCaller creates a new read-only instance of Ics20transfer, bound to a specific deployed contract. +func NewIcs20transferCaller(address common.Address, caller bind.ContractCaller) (*Ics20transferCaller, error) { + contract, err := bindIcs20transfer(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Ics20transferCaller{contract: contract}, nil +} + +// NewIcs20transferTransactor creates a new write-only instance of Ics20transfer, bound to a specific deployed contract. +func NewIcs20transferTransactor(address common.Address, transactor bind.ContractTransactor) (*Ics20transferTransactor, error) { + contract, err := bindIcs20transfer(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Ics20transferTransactor{contract: contract}, nil +} + +// NewIcs20transferFilterer creates a new log filterer instance of Ics20transfer, bound to a specific deployed contract. +func NewIcs20transferFilterer(address common.Address, filterer bind.ContractFilterer) (*Ics20transferFilterer, error) { + contract, err := bindIcs20transfer(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Ics20transferFilterer{contract: contract}, nil +} + +// bindIcs20transfer binds a generic wrapper to an already deployed contract. +func bindIcs20transfer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Ics20transferMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ics20transfer *Ics20transferRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ics20transfer.Contract.Ics20transferCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ics20transfer *Ics20transferRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ics20transfer.Contract.Ics20transferTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ics20transfer *Ics20transferRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ics20transfer.Contract.Ics20transferTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ics20transfer *Ics20transferCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ics20transfer.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ics20transfer *Ics20transferTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ics20transfer.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ics20transfer *Ics20transferTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ics20transfer.Contract.contract.Transact(opts, method, params...) +} + +// ICS20VERSION is a free data retrieval call binding the contract method 0x025183eb. +// +// Solidity: function ICS20_VERSION() view returns(string) +func (_Ics20transfer *Ics20transferCaller) ICS20VERSION(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Ics20transfer.contract.Call(opts, &out, "ICS20_VERSION") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// ICS20VERSION is a free data retrieval call binding the contract method 0x025183eb. +// +// Solidity: function ICS20_VERSION() view returns(string) +func (_Ics20transfer *Ics20transferSession) ICS20VERSION() (string, error) { + return _Ics20transfer.Contract.ICS20VERSION(&_Ics20transfer.CallOpts) +} + +// ICS20VERSION is a free data retrieval call binding the contract method 0x025183eb. +// +// Solidity: function ICS20_VERSION() view returns(string) +func (_Ics20transfer *Ics20transferCallerSession) ICS20VERSION() (string, error) { + return _Ics20transfer.Contract.ICS20VERSION(&_Ics20transfer.CallOpts) +} + +// BalanceOf is a free data retrieval call binding the contract method 0xb9b092c8. +// +// Solidity: function balanceOf(address account, string denom) view returns(uint256) +func (_Ics20transfer *Ics20transferCaller) BalanceOf(opts *bind.CallOpts, account common.Address, denom string) (*big.Int, error) { + var out []interface{} + err := _Ics20transfer.contract.Call(opts, &out, "balanceOf", account, denom) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0xb9b092c8. +// +// Solidity: function balanceOf(address account, string denom) view returns(uint256) +func (_Ics20transfer *Ics20transferSession) BalanceOf(account common.Address, denom string) (*big.Int, error) { + return _Ics20transfer.Contract.BalanceOf(&_Ics20transfer.CallOpts, account, denom) +} + +// BalanceOf is a free data retrieval call binding the contract method 0xb9b092c8. +// +// Solidity: function balanceOf(address account, string denom) view returns(uint256) +func (_Ics20transfer *Ics20transferCallerSession) BalanceOf(account common.Address, denom string) (*big.Int, error) { + return _Ics20transfer.Contract.BalanceOf(&_Ics20transfer.CallOpts, account, denom) +} + +// EncodeAddress is a free data retrieval call binding the contract method 0xd32b1bea. +// +// Solidity: function encodeAddress(address sender) pure returns(string) +func (_Ics20transfer *Ics20transferCaller) EncodeAddress(opts *bind.CallOpts, sender common.Address) (string, error) { + var out []interface{} + err := _Ics20transfer.contract.Call(opts, &out, "encodeAddress", sender) + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// EncodeAddress is a free data retrieval call binding the contract method 0xd32b1bea. +// +// Solidity: function encodeAddress(address sender) pure returns(string) +func (_Ics20transfer *Ics20transferSession) EncodeAddress(sender common.Address) (string, error) { + return _Ics20transfer.Contract.EncodeAddress(&_Ics20transfer.CallOpts, sender) +} + +// EncodeAddress is a free data retrieval call binding the contract method 0xd32b1bea. +// +// Solidity: function encodeAddress(address sender) pure returns(string) +func (_Ics20transfer *Ics20transferCallerSession) EncodeAddress(sender common.Address) (string, error) { + return _Ics20transfer.Contract.EncodeAddress(&_Ics20transfer.CallOpts, sender) +} + +// GetVoucherEscrow is a free data retrieval call binding the contract method 0x39c9c070. +// +// Solidity: function getVoucherEscrow(string channelId) view returns(address) +func (_Ics20transfer *Ics20transferCaller) GetVoucherEscrow(opts *bind.CallOpts, channelId string) (common.Address, error) { + var out []interface{} + err := _Ics20transfer.contract.Call(opts, &out, "getVoucherEscrow", channelId) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetVoucherEscrow is a free data retrieval call binding the contract method 0x39c9c070. +// +// Solidity: function getVoucherEscrow(string channelId) view returns(address) +func (_Ics20transfer *Ics20transferSession) GetVoucherEscrow(channelId string) (common.Address, error) { + return _Ics20transfer.Contract.GetVoucherEscrow(&_Ics20transfer.CallOpts, channelId) +} + +// GetVoucherEscrow is a free data retrieval call binding the contract method 0x39c9c070. +// +// Solidity: function getVoucherEscrow(string channelId) view returns(address) +func (_Ics20transfer *Ics20transferCallerSession) GetVoucherEscrow(channelId string) (common.Address, error) { + return _Ics20transfer.Contract.GetVoucherEscrow(&_Ics20transfer.CallOpts, channelId) +} + +// IbcAddress is a free data retrieval call binding the contract method 0x696a9bf4. +// +// Solidity: function ibcAddress() view returns(address) +func (_Ics20transfer *Ics20transferCaller) IbcAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Ics20transfer.contract.Call(opts, &out, "ibcAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// IbcAddress is a free data retrieval call binding the contract method 0x696a9bf4. +// +// Solidity: function ibcAddress() view returns(address) +func (_Ics20transfer *Ics20transferSession) IbcAddress() (common.Address, error) { + return _Ics20transfer.Contract.IbcAddress(&_Ics20transfer.CallOpts) +} + +// IbcAddress is a free data retrieval call binding the contract method 0x696a9bf4. +// +// Solidity: function ibcAddress() view returns(address) +func (_Ics20transfer *Ics20transferCallerSession) IbcAddress() (common.Address, error) { + return _Ics20transfer.Contract.IbcAddress(&_Ics20transfer.CallOpts) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Ics20transfer *Ics20transferCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Ics20transfer.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Ics20transfer *Ics20transferSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Ics20transfer.Contract.SupportsInterface(&_Ics20transfer.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Ics20transfer *Ics20transferCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Ics20transfer.Contract.SupportsInterface(&_Ics20transfer.CallOpts, interfaceId) +} + +// Deposit is a paid mutator transaction binding the contract method 0x8340f549. +// +// Solidity: function deposit(address to, address tokenContract, uint256 amount) returns() +func (_Ics20transfer *Ics20transferTransactor) Deposit(opts *bind.TransactOpts, to common.Address, tokenContract common.Address, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "deposit", to, tokenContract, amount) +} + +// Deposit is a paid mutator transaction binding the contract method 0x8340f549. +// +// Solidity: function deposit(address to, address tokenContract, uint256 amount) returns() +func (_Ics20transfer *Ics20transferSession) Deposit(to common.Address, tokenContract common.Address, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.Contract.Deposit(&_Ics20transfer.TransactOpts, to, tokenContract, amount) +} + +// Deposit is a paid mutator transaction binding the contract method 0x8340f549. +// +// Solidity: function deposit(address to, address tokenContract, uint256 amount) returns() +func (_Ics20transfer *Ics20transferTransactorSession) Deposit(to common.Address, tokenContract common.Address, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.Contract.Deposit(&_Ics20transfer.TransactOpts, to, tokenContract, amount) +} + +// DepositSendTransfer is a paid mutator transaction binding the contract method 0x8e8f8ca3. +// +// Solidity: function depositSendTransfer(string sourceChannel, address tokenContract, uint256 amount, string receiver, ((uint64,uint64),uint64) timeout) returns(uint64) +func (_Ics20transfer *Ics20transferTransactor) DepositSendTransfer(opts *bind.TransactOpts, sourceChannel string, tokenContract common.Address, amount *big.Int, receiver string, timeout ICS20LibTimeout) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "depositSendTransfer", sourceChannel, tokenContract, amount, receiver, timeout) +} + +// DepositSendTransfer is a paid mutator transaction binding the contract method 0x8e8f8ca3. +// +// Solidity: function depositSendTransfer(string sourceChannel, address tokenContract, uint256 amount, string receiver, ((uint64,uint64),uint64) timeout) returns(uint64) +func (_Ics20transfer *Ics20transferSession) DepositSendTransfer(sourceChannel string, tokenContract common.Address, amount *big.Int, receiver string, timeout ICS20LibTimeout) (*types.Transaction, error) { + return _Ics20transfer.Contract.DepositSendTransfer(&_Ics20transfer.TransactOpts, sourceChannel, tokenContract, amount, receiver, timeout) +} + +// DepositSendTransfer is a paid mutator transaction binding the contract method 0x8e8f8ca3. +// +// Solidity: function depositSendTransfer(string sourceChannel, address tokenContract, uint256 amount, string receiver, ((uint64,uint64),uint64) timeout) returns(uint64) +func (_Ics20transfer *Ics20transferTransactorSession) DepositSendTransfer(sourceChannel string, tokenContract common.Address, amount *big.Int, receiver string, timeout ICS20LibTimeout) (*types.Transaction, error) { + return _Ics20transfer.Contract.DepositSendTransfer(&_Ics20transfer.TransactOpts, sourceChannel, tokenContract, amount, receiver, timeout) +} + +// OnAcknowledgementPacket is a paid mutator transaction binding the contract method 0xfb8b532e. +// +// Solidity: function onAcknowledgementPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement, address ) returns() +func (_Ics20transfer *Ics20transferTransactor) OnAcknowledgementPacket(opts *bind.TransactOpts, packet Packet, acknowledgement []byte, arg2 common.Address) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onAcknowledgementPacket", packet, acknowledgement, arg2) +} + +// OnAcknowledgementPacket is a paid mutator transaction binding the contract method 0xfb8b532e. +// +// Solidity: function onAcknowledgementPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement, address ) returns() +func (_Ics20transfer *Ics20transferSession) OnAcknowledgementPacket(packet Packet, acknowledgement []byte, arg2 common.Address) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnAcknowledgementPacket(&_Ics20transfer.TransactOpts, packet, acknowledgement, arg2) +} + +// OnAcknowledgementPacket is a paid mutator transaction binding the contract method 0xfb8b532e. +// +// Solidity: function onAcknowledgementPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement, address ) returns() +func (_Ics20transfer *Ics20transferTransactorSession) OnAcknowledgementPacket(packet Packet, acknowledgement []byte, arg2 common.Address) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnAcknowledgementPacket(&_Ics20transfer.TransactOpts, packet, acknowledgement, arg2) +} + +// OnChanCloseConfirm is a paid mutator transaction binding the contract method 0x38c858bc. +// +// Solidity: function onChanCloseConfirm((string,string) ) returns() +func (_Ics20transfer *Ics20transferTransactor) OnChanCloseConfirm(opts *bind.TransactOpts, arg0 IIBCModuleMsgOnChanCloseConfirm) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onChanCloseConfirm", arg0) +} + +// OnChanCloseConfirm is a paid mutator transaction binding the contract method 0x38c858bc. +// +// Solidity: function onChanCloseConfirm((string,string) ) returns() +func (_Ics20transfer *Ics20transferSession) OnChanCloseConfirm(arg0 IIBCModuleMsgOnChanCloseConfirm) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanCloseConfirm(&_Ics20transfer.TransactOpts, arg0) +} + +// OnChanCloseConfirm is a paid mutator transaction binding the contract method 0x38c858bc. +// +// Solidity: function onChanCloseConfirm((string,string) ) returns() +func (_Ics20transfer *Ics20transferTransactorSession) OnChanCloseConfirm(arg0 IIBCModuleMsgOnChanCloseConfirm) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanCloseConfirm(&_Ics20transfer.TransactOpts, arg0) +} + +// OnChanCloseInit is a paid mutator transaction binding the contract method 0x3c7df3fb. +// +// Solidity: function onChanCloseInit((string,string) msg_) returns() +func (_Ics20transfer *Ics20transferTransactor) OnChanCloseInit(opts *bind.TransactOpts, msg_ IIBCModuleMsgOnChanCloseInit) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onChanCloseInit", msg_) +} + +// OnChanCloseInit is a paid mutator transaction binding the contract method 0x3c7df3fb. +// +// Solidity: function onChanCloseInit((string,string) msg_) returns() +func (_Ics20transfer *Ics20transferSession) OnChanCloseInit(msg_ IIBCModuleMsgOnChanCloseInit) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanCloseInit(&_Ics20transfer.TransactOpts, msg_) +} + +// OnChanCloseInit is a paid mutator transaction binding the contract method 0x3c7df3fb. +// +// Solidity: function onChanCloseInit((string,string) msg_) returns() +func (_Ics20transfer *Ics20transferTransactorSession) OnChanCloseInit(msg_ IIBCModuleMsgOnChanCloseInit) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanCloseInit(&_Ics20transfer.TransactOpts, msg_) +} + +// OnChanOpenAck is a paid mutator transaction binding the contract method 0x12f6ff6f. +// +// Solidity: function onChanOpenAck((string,string,string) msg_) returns() +func (_Ics20transfer *Ics20transferTransactor) OnChanOpenAck(opts *bind.TransactOpts, msg_ IIBCModuleMsgOnChanOpenAck) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onChanOpenAck", msg_) +} + +// OnChanOpenAck is a paid mutator transaction binding the contract method 0x12f6ff6f. +// +// Solidity: function onChanOpenAck((string,string,string) msg_) returns() +func (_Ics20transfer *Ics20transferSession) OnChanOpenAck(msg_ IIBCModuleMsgOnChanOpenAck) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanOpenAck(&_Ics20transfer.TransactOpts, msg_) +} + +// OnChanOpenAck is a paid mutator transaction binding the contract method 0x12f6ff6f. +// +// Solidity: function onChanOpenAck((string,string,string) msg_) returns() +func (_Ics20transfer *Ics20transferTransactorSession) OnChanOpenAck(msg_ IIBCModuleMsgOnChanOpenAck) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanOpenAck(&_Ics20transfer.TransactOpts, msg_) +} + +// OnChanOpenConfirm is a paid mutator transaction binding the contract method 0x81b174dc. +// +// Solidity: function onChanOpenConfirm((string,string) ) returns() +func (_Ics20transfer *Ics20transferTransactor) OnChanOpenConfirm(opts *bind.TransactOpts, arg0 IIBCModuleMsgOnChanOpenConfirm) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onChanOpenConfirm", arg0) +} + +// OnChanOpenConfirm is a paid mutator transaction binding the contract method 0x81b174dc. +// +// Solidity: function onChanOpenConfirm((string,string) ) returns() +func (_Ics20transfer *Ics20transferSession) OnChanOpenConfirm(arg0 IIBCModuleMsgOnChanOpenConfirm) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanOpenConfirm(&_Ics20transfer.TransactOpts, arg0) +} + +// OnChanOpenConfirm is a paid mutator transaction binding the contract method 0x81b174dc. +// +// Solidity: function onChanOpenConfirm((string,string) ) returns() +func (_Ics20transfer *Ics20transferTransactorSession) OnChanOpenConfirm(arg0 IIBCModuleMsgOnChanOpenConfirm) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanOpenConfirm(&_Ics20transfer.TransactOpts, arg0) +} + +// OnChanOpenInit is a paid mutator transaction binding the contract method 0x0b7b4ccb. +// +// Solidity: function onChanOpenInit((uint8,string[],string,string,(string,string),string) msg_) returns(address, string) +func (_Ics20transfer *Ics20transferTransactor) OnChanOpenInit(opts *bind.TransactOpts, msg_ IIBCModuleInitializerMsgOnChanOpenInit) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onChanOpenInit", msg_) +} + +// OnChanOpenInit is a paid mutator transaction binding the contract method 0x0b7b4ccb. +// +// Solidity: function onChanOpenInit((uint8,string[],string,string,(string,string),string) msg_) returns(address, string) +func (_Ics20transfer *Ics20transferSession) OnChanOpenInit(msg_ IIBCModuleInitializerMsgOnChanOpenInit) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanOpenInit(&_Ics20transfer.TransactOpts, msg_) +} + +// OnChanOpenInit is a paid mutator transaction binding the contract method 0x0b7b4ccb. +// +// Solidity: function onChanOpenInit((uint8,string[],string,string,(string,string),string) msg_) returns(address, string) +func (_Ics20transfer *Ics20transferTransactorSession) OnChanOpenInit(msg_ IIBCModuleInitializerMsgOnChanOpenInit) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanOpenInit(&_Ics20transfer.TransactOpts, msg_) +} + +// OnChanOpenTry is a paid mutator transaction binding the contract method 0xa7a61e66. +// +// Solidity: function onChanOpenTry((uint8,string[],string,string,(string,string),string) msg_) returns(address, string) +func (_Ics20transfer *Ics20transferTransactor) OnChanOpenTry(opts *bind.TransactOpts, msg_ IIBCModuleInitializerMsgOnChanOpenTry) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onChanOpenTry", msg_) +} + +// OnChanOpenTry is a paid mutator transaction binding the contract method 0xa7a61e66. +// +// Solidity: function onChanOpenTry((uint8,string[],string,string,(string,string),string) msg_) returns(address, string) +func (_Ics20transfer *Ics20transferSession) OnChanOpenTry(msg_ IIBCModuleInitializerMsgOnChanOpenTry) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanOpenTry(&_Ics20transfer.TransactOpts, msg_) +} + +// OnChanOpenTry is a paid mutator transaction binding the contract method 0xa7a61e66. +// +// Solidity: function onChanOpenTry((uint8,string[],string,string,(string,string),string) msg_) returns(address, string) +func (_Ics20transfer *Ics20transferTransactorSession) OnChanOpenTry(msg_ IIBCModuleInitializerMsgOnChanOpenTry) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnChanOpenTry(&_Ics20transfer.TransactOpts, msg_) +} + +// OnRecvPacket is a paid mutator transaction binding the contract method 0x2301c6f5. +// +// Solidity: function onRecvPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns(bytes acknowledgement) +func (_Ics20transfer *Ics20transferTransactor) OnRecvPacket(opts *bind.TransactOpts, packet Packet, arg1 common.Address) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onRecvPacket", packet, arg1) +} + +// OnRecvPacket is a paid mutator transaction binding the contract method 0x2301c6f5. +// +// Solidity: function onRecvPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns(bytes acknowledgement) +func (_Ics20transfer *Ics20transferSession) OnRecvPacket(packet Packet, arg1 common.Address) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnRecvPacket(&_Ics20transfer.TransactOpts, packet, arg1) +} + +// OnRecvPacket is a paid mutator transaction binding the contract method 0x2301c6f5. +// +// Solidity: function onRecvPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns(bytes acknowledgement) +func (_Ics20transfer *Ics20transferTransactorSession) OnRecvPacket(packet Packet, arg1 common.Address) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnRecvPacket(&_Ics20transfer.TransactOpts, packet, arg1) +} + +// OnTimeoutPacket is a paid mutator transaction binding the contract method 0x52c7157d. +// +// Solidity: function onTimeoutPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns() +func (_Ics20transfer *Ics20transferTransactor) OnTimeoutPacket(opts *bind.TransactOpts, packet Packet, arg1 common.Address) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "onTimeoutPacket", packet, arg1) +} + +// OnTimeoutPacket is a paid mutator transaction binding the contract method 0x52c7157d. +// +// Solidity: function onTimeoutPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns() +func (_Ics20transfer *Ics20transferSession) OnTimeoutPacket(packet Packet, arg1 common.Address) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnTimeoutPacket(&_Ics20transfer.TransactOpts, packet, arg1) +} + +// OnTimeoutPacket is a paid mutator transaction binding the contract method 0x52c7157d. +// +// Solidity: function onTimeoutPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns() +func (_Ics20transfer *Ics20transferTransactorSession) OnTimeoutPacket(packet Packet, arg1 common.Address) (*types.Transaction, error) { + return _Ics20transfer.Contract.OnTimeoutPacket(&_Ics20transfer.TransactOpts, packet, arg1) +} + +// SendTransfer is a paid mutator transaction binding the contract method 0xb3d1f4a3. +// +// Solidity: function sendTransfer(string sourceChannel, string denom, uint256 amount, string receiver, ((uint64,uint64),uint64) timeout) returns(uint64) +func (_Ics20transfer *Ics20transferTransactor) SendTransfer(opts *bind.TransactOpts, sourceChannel string, denom string, amount *big.Int, receiver string, timeout ICS20LibTimeout) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "sendTransfer", sourceChannel, denom, amount, receiver, timeout) +} + +// SendTransfer is a paid mutator transaction binding the contract method 0xb3d1f4a3. +// +// Solidity: function sendTransfer(string sourceChannel, string denom, uint256 amount, string receiver, ((uint64,uint64),uint64) timeout) returns(uint64) +func (_Ics20transfer *Ics20transferSession) SendTransfer(sourceChannel string, denom string, amount *big.Int, receiver string, timeout ICS20LibTimeout) (*types.Transaction, error) { + return _Ics20transfer.Contract.SendTransfer(&_Ics20transfer.TransactOpts, sourceChannel, denom, amount, receiver, timeout) +} + +// SendTransfer is a paid mutator transaction binding the contract method 0xb3d1f4a3. +// +// Solidity: function sendTransfer(string sourceChannel, string denom, uint256 amount, string receiver, ((uint64,uint64),uint64) timeout) returns(uint64) +func (_Ics20transfer *Ics20transferTransactorSession) SendTransfer(sourceChannel string, denom string, amount *big.Int, receiver string, timeout ICS20LibTimeout) (*types.Transaction, error) { + return _Ics20transfer.Contract.SendTransfer(&_Ics20transfer.TransactOpts, sourceChannel, denom, amount, receiver, timeout) +} + +// Transfer is a paid mutator transaction binding the contract method 0xfff3a01b. +// +// Solidity: function transfer(address to, string denom, uint256 amount) returns() +func (_Ics20transfer *Ics20transferTransactor) Transfer(opts *bind.TransactOpts, to common.Address, denom string, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "transfer", to, denom, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xfff3a01b. +// +// Solidity: function transfer(address to, string denom, uint256 amount) returns() +func (_Ics20transfer *Ics20transferSession) Transfer(to common.Address, denom string, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.Contract.Transfer(&_Ics20transfer.TransactOpts, to, denom, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xfff3a01b. +// +// Solidity: function transfer(address to, string denom, uint256 amount) returns() +func (_Ics20transfer *Ics20transferTransactorSession) Transfer(to common.Address, denom string, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.Contract.Transfer(&_Ics20transfer.TransactOpts, to, denom, amount) +} + +// Withdraw is a paid mutator transaction binding the contract method 0xd9caed12. +// +// Solidity: function withdraw(address to, address tokenContract, uint256 amount) returns() +func (_Ics20transfer *Ics20transferTransactor) Withdraw(opts *bind.TransactOpts, to common.Address, tokenContract common.Address, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.contract.Transact(opts, "withdraw", to, tokenContract, amount) +} + +// Withdraw is a paid mutator transaction binding the contract method 0xd9caed12. +// +// Solidity: function withdraw(address to, address tokenContract, uint256 amount) returns() +func (_Ics20transfer *Ics20transferSession) Withdraw(to common.Address, tokenContract common.Address, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.Contract.Withdraw(&_Ics20transfer.TransactOpts, to, tokenContract, amount) +} + +// Withdraw is a paid mutator transaction binding the contract method 0xd9caed12. +// +// Solidity: function withdraw(address to, address tokenContract, uint256 amount) returns() +func (_Ics20transfer *Ics20transferTransactorSession) Withdraw(to common.Address, tokenContract common.Address, amount *big.Int) (*types.Transaction, error) { + return _Ics20transfer.Contract.Withdraw(&_Ics20transfer.TransactOpts, to, tokenContract, amount) +} diff --git a/pkg/testing/app.go b/pkg/testing/app.go index 81c58d39..b9681111 100644 --- a/pkg/testing/app.go +++ b/pkg/testing/app.go @@ -2,66 +2,16 @@ package testing import ( "context" - "fmt" "math/big" - "strings" ) -func (c *Coordinator) ApproveAndDepositToken( +func (c *Coordinator) Approve( ctx context.Context, chain *Chain, senderIndex uint32, amount uint64, - receiverIndex uint32, ) error { - berforeBalance, err := chain.ERC20.BalanceOf(chain.CallOpts(ctx, senderIndex), chain.CallOpts(ctx, senderIndex).From) - if err != nil { - return err - } - beforeBankBalance, err := chain.ICS20Bank.BalanceOf( - chain.CallOpts(ctx, receiverIndex), - chain.CallOpts(ctx, receiverIndex).From, - strings.ToLower(chain.ContractConfig.ERC20TokenAddress.String())) - if err != nil { - return err - } - - err = chain.WaitIfNoError(ctx, "ERC20::Approve")( - chain.ERC20.Approve(chain.TxOpts(ctx, senderIndex), chain.ContractConfig.ICS20BankAddress, big.NewInt(int64(amount))), + return chain.WaitIfNoError(ctx, "ERC20::Approve")( + chain.ERC20.Approve(chain.TxOpts(ctx, senderIndex), chain.ContractConfig.ICS20TransferAddress, big.NewInt(int64(amount))), ) - if err != nil { - return err - } - err = chain.WaitIfNoError(ctx, "ERC20::Deposit")(chain.ICS20Bank.Deposit( - chain.TxOpts(ctx, senderIndex), - chain.ContractConfig.ERC20TokenAddress, - big.NewInt(int64(amount)), - chain.CallOpts(ctx, receiverIndex).From, - )) - if err != nil { - return err - } - - // ensure that the balance is reduced - afterBalance, err := chain.ERC20.BalanceOf(chain.CallOpts(ctx, senderIndex), chain.CallOpts(ctx, senderIndex).From) - if err != nil { - return err - } - if berforeBalance.Int64()-int64(amount) != afterBalance.Int64() { - return fmt.Errorf("balance is not reduced") - } - - // ensure that the bank balance is increased - afterBankBalance, err := chain.ICS20Bank.BalanceOf( - chain.CallOpts(ctx, receiverIndex), - chain.CallOpts(ctx, receiverIndex).From, - strings.ToLower(chain.ContractConfig.ERC20TokenAddress.String())) - if err != nil { - return err - } - if beforeBankBalance.Int64()+int64(amount) != afterBankBalance.Int64() { - return fmt.Errorf("bank balance is not increased") - } - - return nil } diff --git a/pkg/testing/chains.go b/pkg/testing/chains.go index 81d9103a..3df2dbe8 100644 --- a/pkg/testing/chains.go +++ b/pkg/testing/chains.go @@ -28,8 +28,7 @@ import ( "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/erc20" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ibchandler" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ibcmockapp" - "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ics20bank" - "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ics20transferbank" + "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ics20transfer" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/qbftclient" qbftclienttypes "github.com/hyperledger-labs/yui-ibc-solidity/pkg/ibc/clients/qbft" channeltypes "github.com/hyperledger-labs/yui-ibc-solidity/pkg/ibc/core/channel" @@ -84,11 +83,7 @@ func init() { abiGeneratedConnectionIdentifier = abiIBCHandler.Events["GeneratedConnectionIdentifier"] abiGeneratedChannelIdentifier = abiIBCHandler.Events["GeneratedChannelIdentifier"] - abiICS20Bank, err := abi.JSON(strings.NewReader(ics20bank.Ics20bankABI)) - if err != nil { - panic(err) - } - abiICS20TransferBank, err := abi.JSON(strings.NewReader(ics20transferbank.Ics20transferbankABI)) + abiICS20Transfer, err := abi.JSON(strings.NewReader(ics20transfer.Ics20transferABI)) if err != nil { panic(err) } @@ -98,8 +93,7 @@ func init() { } IBCErrorsRepository = client.NewErrorsRepository() addErrorsToRepository(abiIBCHandler.Errors, IBCErrorsRepository) - addErrorsToRepository(abiICS20Bank.Errors, IBCErrorsRepository) - addErrorsToRepository(abiICS20TransferBank.Errors, IBCErrorsRepository) + addErrorsToRepository(abiICS20Transfer.Errors, IBCErrorsRepository) addErrorsToRepository(abiQBFTClient.Errors, IBCErrorsRepository) } @@ -130,8 +124,7 @@ type Chain struct { // App Modules ERC20 erc20.Erc20 - ICS20Transfer ics20transferbank.Ics20transferbank - ICS20Bank ics20bank.Ics20bank + ICS20Transfer ics20transfer.Ics20transfer IBCMockApp ibcmockapp.Ibcmockapp // Input data for light client @@ -177,11 +170,7 @@ func NewChain(t *testing.T, client *client.ETHClient, lc *LightClient, isAutoMin if err != nil { t.Fatal(err) } - ics20transfer, err := ics20transferbank.NewIcs20transferbank(config.ICS20TransferBankAddress, client) - if err != nil { - t.Fatal(err) - } - ics20bank, err := ics20bank.NewIcs20bank(config.ICS20BankAddress, client) + ics20transfer, err := ics20transfer.NewIcs20transfer(config.ICS20TransferAddress, client) if err != nil { t.Fatal(err) } @@ -207,7 +196,6 @@ func NewChain(t *testing.T, client *client.ETHClient, lc *LightClient, isAutoMin ERC20: *erc20_, ICS20Transfer: *ics20transfer, - ICS20Bank: *ics20bank, IBCMockApp: *ibcMockApp, } @@ -250,6 +238,10 @@ func (chain *Chain) CallOpts(ctx context.Context, index uint32) *bind.CallOpts { } } +func (chain *Chain) Address(index uint32) common.Address { + return gethcrypto.PubkeyToAddress(chain.prvKey(index).PublicKey) +} + func (chain *Chain) prvKey(index uint32) *ecdsa.PrivateKey { key, ok := chain.keys[index] if ok { @@ -1076,7 +1068,7 @@ func (chain *Chain) AdvanceBlockNumber( } else { // execute a meaningless transaction to increase the block height err := chain.WaitIfNoError(ctx, "ERC20::Approve")( - chain.ERC20.Approve(chain.TxOpts(ctx, RelayerKeyIndex), chain.ContractConfig.ICS20BankAddress, big.NewInt(0)), + chain.ERC20.Approve(chain.TxOpts(ctx, RelayerKeyIndex), chain.ContractConfig.ICS20TransferAddress, big.NewInt(0)), ) if err != nil { return err diff --git a/pkg/testing/config.go b/pkg/testing/config.go index fc10b576..ffab25e7 100644 --- a/pkg/testing/config.go +++ b/pkg/testing/config.go @@ -9,12 +9,11 @@ import ( ) type ContractConfig struct { - ibcHandlerAddress common.Address - erc1967ProxyAddress common.Address - ICS20TransferBankAddress common.Address - ICS20BankAddress common.Address - ERC20TokenAddress common.Address - IBCMockAppAddress common.Address + ibcHandlerAddress common.Address + erc1967ProxyAddress common.Address + ICS20TransferAddress common.Address + ERC20TokenAddress common.Address + IBCMockAppAddress common.Address } func (cc *ContractConfig) Validate() error { @@ -25,10 +24,8 @@ func (cc *ContractConfig) Validate() error { } else { return errors.New("IBCHandlerAddress is empty") } - } else if cc.ICS20TransferBankAddress == zero { - return errors.New("ICS20TransferBankAddress is empty") - } else if cc.ICS20BankAddress == zero { - return errors.New("ICS20BankAddress is empty") + } else if cc.ICS20TransferAddress == zero { + return errors.New("ICS20Transfer is empty") } else if cc.ERC20TokenAddress == zero { return errors.New("ERC20TokenAddress is empty") } else if cc.IBCMockAppAddress == zero { @@ -79,10 +76,8 @@ func buildContractConfigFromBroadcastLog(path string) (*ContractConfig, error) { cc.ibcHandlerAddress = tx.ContractAddress case "ERC1967Proxy": cc.erc1967ProxyAddress = tx.ContractAddress - case "ICS20TransferBank": - cc.ICS20TransferBankAddress = tx.ContractAddress - case "ICS20Bank": - cc.ICS20BankAddress = tx.ContractAddress + case "ICS20Transfer": + cc.ICS20TransferAddress = tx.ContractAddress case "ERC20Token": cc.ERC20TokenAddress = tx.ContractAddress case "IBCMockApp": diff --git a/scripts/abigen.sh b/scripts/abigen.sh index 350e5459..eae58f99 100755 --- a/scripts/abigen.sh +++ b/scripts/abigen.sh @@ -23,8 +23,7 @@ function main() { local srcs=( "IBCHandler" "ERC20" - "ICS20TransferBank" - "ICS20Bank" + "ICS20Transfer" "QBFTClient" "MockClient" "IBCMockApp" diff --git a/tests/e2e/chains_test.go b/tests/e2e/chains_test.go index c0dfddc4..45e0fece 100644 --- a/tests/e2e/chains_test.go +++ b/tests/e2e/chains_test.go @@ -14,6 +14,7 @@ import ( "github.com/hyperledger-labs/yui-ibc-solidity/pkg/chains" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/client" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ibcmockapp" + "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ics20transfer" channeltypes "github.com/hyperledger-labs/yui-ibc-solidity/pkg/ibc/core/channel" ibctesting "github.com/hyperledger-labs/yui-ibc-solidity/pkg/testing" "github.com/stretchr/testify/suite" @@ -67,29 +68,28 @@ func (suite *ChainTestSuite) TestICS20() { /// Tests for Transfer module /// - beforeBalanceA, err := chainA.ERC20.BalanceOf(chainA.CallOpts(ctx, relayer), chainA.CallOpts(ctx, deployerA).From) + suite.Require().NoError(chainA.WaitIfNoError(ctx, "ERC20::Transfer")( + chainA.ERC20.Transfer(chainA.TxOpts(ctx, deployerA), chainA.Address(aliceA), big.NewInt(100)), + )) + beforeBalanceA, err := chainA.ERC20.BalanceOf(chainA.CallOpts(ctx, relayer), chainA.Address(aliceA)) suite.Require().NoError(err) suite.Require().NoError( - coordinator.ApproveAndDepositToken(ctx, chainA, deployerA, 100, aliceA), + coordinator.Approve(ctx, chainA, aliceA, 100), ) baseDenom := strings.ToLower(chainA.ContractConfig.ERC20TokenAddress.String()) // try to transfer the token to chainB - suite.Require().NoError(chainA.WaitIfNoError(ctx, "ICS20::SendTransfer")( - chainA.ICS20Transfer.SendTransfer( + suite.Require().NoError(chainA.WaitIfNoError(ctx, "ICS20Transfer::DepositSendTransfer")( + chainA.ICS20Transfer.DepositSendTransfer( chainA.TxOpts(ctx, aliceA), - baseDenom, + chanA.ID, + chainA.ContractConfig.ERC20TokenAddress, big.NewInt(100), addressToHexString(chainB.CallOpts(ctx, bobB).From), - chanA.PortID, chanA.ID, - uint64(chainB.LastHeader().Number.Int64())+1000, + packetTimeout(uint64(chainB.LastHeader().Number.Int64())+1000), ), )) - // ensure that escrow has correct balance - escrowBalance, err := chainA.ICS20Bank.BalanceOf(chainA.CallOpts(ctx, relayer), chainA.ContractConfig.ICS20TransferBankAddress, baseDenom) - suite.Require().NoError(err) - suite.Require().GreaterOrEqual(escrowBalance.Int64(), int64(100)) suite.Require().NoError(coordinator.UpdateClient(ctx, chainB, chainA, clientB, false)) @@ -114,20 +114,19 @@ func (suite *ChainTestSuite) TestICS20() { // ensure that chainB has correct balance expectedDenom := fmt.Sprintf("%v/%v/%v", chanB.PortID, chanB.ID, baseDenom) - balance, err := chainB.ICS20Bank.BalanceOf(chainB.CallOpts(ctx, relayer), chainB.CallOpts(ctx, bobB).From, expectedDenom) + balance, err := chainB.ICS20Transfer.BalanceOf(chainB.CallOpts(ctx, relayer), chainB.CallOpts(ctx, bobB).From, expectedDenom) suite.Require().NoError(err) suite.Require().Equal(int64(100), balance.Int64()) // try to transfer the token to chainA - suite.Require().NoError(chainB.WaitIfNoError(ctx, "ICS20::SendTransfer")( + suite.Require().NoError(chainB.WaitIfNoError(ctx, "ICS20Transfer::SendTransfer")( chainB.ICS20Transfer.SendTransfer( chainB.TxOpts(ctx, bobB), + chanB.ID, expectedDenom, big.NewInt(100), addressToHexString(chainA.CallOpts(ctx, aliceA).From), - chanB.PortID, - chanB.ID, - uint64(chainA.LastHeader().Number.Int64())+1000, + packetTimeout(uint64(chainA.LastHeader().Number.Int64())+1000), ), )) suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA, false)) @@ -152,14 +151,14 @@ func (suite *ChainTestSuite) TestICS20() { }) { - suite.Require().NoError(chainA.WaitIfNoError(ctx, "ICS20::SendTransfer")( + suite.Require().NoError(chainA.WaitIfNoError(ctx, "ICS20Transfer::SendTransfer")( chainA.ICS20Transfer.SendTransfer( chainA.TxOpts(ctx, aliceA), + chanA.ID, baseDenom, big.NewInt(50), addressToHexString(chainB.CallOpts(ctx, bobB).From), - chanA.PortID, chanA.ID, - uint64(chainB.LastHeader().Number.Int64())+1, + packetTimeout(uint64(chainB.LastHeader().Number.Int64())+1), ), )) transferPacket, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) @@ -178,16 +177,16 @@ func (suite *ChainTestSuite) TestICS20() { } // withdraw tokens from the bank - suite.Require().NoError(chainA.WaitIfNoError(ctx, "ICS20::Withdraw")( - chainA.ICS20Bank.Withdraw( + suite.Require().NoError(chainA.WaitIfNoError(ctx, "ICS20Transfer::Withdraw")( + chainA.ICS20Transfer.Withdraw( chainA.TxOpts(ctx, aliceA), + chainA.Address(aliceA), chainA.ContractConfig.ERC20TokenAddress, big.NewInt(100), - chainA.CallOpts(ctx, deployerA).From, ))) // ensure that token balance equals original value - afterBalanceA, err := chainA.ERC20.BalanceOf(chainA.CallOpts(ctx, relayer), chainA.CallOpts(ctx, deployerA).From) + afterBalanceA, err := chainA.ERC20.BalanceOf(chainA.CallOpts(ctx, relayer), chainA.Address(aliceA)) suite.Require().NoError(err) suite.Require().Equal(beforeBalanceA.Int64(), afterBalanceA.Int64()) } @@ -322,8 +321,11 @@ func (suite *ChainTestSuite) TestPacketRelayWithDelay() { /// Tests for Transfer module /// + suite.Require().NoError(chainA.WaitIfNoError(ctx, "ERC20::Transfer")( + chainA.ERC20.Transfer(chainA.TxOpts(ctx, deployerA), chainA.Address(aliceA), big.NewInt(100)), + )) suite.Require().NoError( - coordinator.ApproveAndDepositToken(ctx, chainA, deployerA, 100, aliceA), + coordinator.Approve(ctx, chainA, aliceA, 100), ) baseDenom := strings.ToLower(chainA.ContractConfig.ERC20TokenAddress.String()) @@ -334,30 +336,25 @@ func (suite *ChainTestSuite) TestPacketRelayWithDelay() { suite.Require().NoError(chainB.SetExpectedTimePerBlock(ctx, deployerB, 0)) // try to transfer the token to chainB - suite.Require().NoError(chainA.WaitIfNoError(ctx, "ICS20::SendTransfer")( - chainA.ICS20Transfer.SendTransfer( + suite.Require().NoError(chainA.WaitIfNoError(ctx, "ICS20Transfer::SendTransfer")( + chainA.ICS20Transfer.DepositSendTransfer( chainA.TxOpts(ctx, aliceA), - baseDenom, + chanA.ID, + chainA.ContractConfig.ERC20TokenAddress, big.NewInt(100), addressToHexString(chainB.CallOpts(ctx, bobB).From), - chanA.PortID, chanA.ID, - uint64(chainB.LastHeader().Number.Int64())+1000, + packetTimeout(uint64(chainB.LastHeader().Number.Int64())+1000), ), )) delayStartTimeForRecv := time.Now() suite.Require().NoError(coordinator.UpdateClient(ctx, chainB, chainA, clientB, false)) - // ensure that escrow has correct balance - escrowBalance, err := chainA.ICS20Bank.BalanceOf(chainA.CallOpts(ctx, relayer), chainA.ContractConfig.ICS20TransferBankAddress, baseDenom) - suite.Require().NoError(err) - suite.Require().GreaterOrEqual(escrowBalance.Int64(), int64(100)) - // relay the packet coordinator.RelayLastSentPacketWithDelay(ctx, chainA, chainB, chanA, chanB, 1, 1, delayStartTimeForRecv) // ensure that chainB has correct balance expectedDenom := fmt.Sprintf("%v/%v/%v", chanB.PortID, chanB.ID, baseDenom) - balance, err := chainB.ICS20Bank.BalanceOf(chainB.CallOpts(ctx, relayer), chainB.CallOpts(ctx, bobB).From, expectedDenom) + balance, err := chainB.ICS20Transfer.BalanceOf(chainB.CallOpts(ctx, relayer), chainB.CallOpts(ctx, bobB).From, expectedDenom) suite.Require().NoError(err) suite.Require().Equal(int64(100), balance.Int64()) @@ -375,12 +372,11 @@ func (suite *ChainTestSuite) TestPacketRelayWithDelay() { suite.Require().NoError(chainB.WaitIfNoError(ctx, "ICS20::SendTransfer")( chainB.ICS20Transfer.SendTransfer( chainB.TxOpts(ctx, bobB), + chanB.ID, expectedDenom, big.NewInt(100), addressToHexString(chainA.CallOpts(ctx, aliceA).From), - chanB.PortID, - chanB.ID, - uint64(chainA.LastHeader().Number.Int64())+1000, + packetTimeout(uint64(chainA.LastHeader().Number.Int64())+1000), ), )) delayStartTimeForRecv = time.Now() @@ -395,6 +391,15 @@ func addressToHexString(addr common.Address) string { return strings.ToLower(addr.String()) } +func packetTimeout(height uint64) ics20transfer.ICS20LibTimeout { + return ics20transfer.ICS20LibTimeout{ + Height: ics20transfer.HeightData{ + RevisionNumber: 0, + RevisionHeight: height, + }, + } +} + func TestChainTestSuite(t *testing.T) { suite.Run(t, new(ChainTestSuite)) } diff --git a/tests/foundry/src/Deploy.s.sol b/tests/foundry/src/Deploy.s.sol index a6e9e73d..c3a09214 100644 --- a/tests/foundry/src/Deploy.s.sol +++ b/tests/foundry/src/Deploy.s.sol @@ -19,14 +19,15 @@ import {IIBCHandler} from "../../../contracts/core/25-handler/IIBCHandler.sol"; import {OwnableIBCHandler} from "../../../contracts/core/25-handler/OwnableIBCHandler.sol"; import {MockClient} from "../../../contracts/clients/mock/MockClient.sol"; import {QBFTClient} from "../../../contracts/clients/qbft/QBFTClient.sol"; -import {ICS20Bank} from "../../../contracts/apps/20-transfer/ICS20Bank.sol"; -import {ICS20TransferBank} from "../../../contracts/apps/20-transfer/ICS20TransferBank.sol"; +import {ICS20Transfer} from "../../../contracts/apps/20-transfer/ICS20Transfer.sol"; import {ERC20Token} from "../../../contracts/apps/20-transfer/ERC20Token.sol"; import {IBCMockApp} from "../../../contracts/apps/mock/IBCMockApp.sol"; contract DeployScript is Script { string private constant MOCK_CLIENT_TYPE = "mock-client"; string private constant QBFT_CLIENT_TYPE = "hb-qbft"; + string private constant ICS20_TRANSFER_PORT = "transfer"; + string private constant MOCK_PORT = "mock"; function run() external { uint256 privateKey = @@ -66,14 +67,12 @@ contract DeployScript is Script { } // deploy ics20 contract - ICS20Bank bank = new ICS20Bank(); - ICS20TransferBank transferBank = new ICS20TransferBank(handler, bank); - bank.setOperator(address(transferBank)); - handler.bindPort("transfer", transferBank); + ICS20Transfer transfer = new ICS20Transfer(handler, ICS20_TRANSFER_PORT); + handler.bindPort(ICS20_TRANSFER_PORT, transfer); // deploy mock app contract IBCMockApp mockApp = new IBCMockApp(handler); - handler.bindPort("mock", mockApp); + handler.bindPort(MOCK_PORT, mockApp); // deploy client contracts MockClient mockClient = new MockClient(address(handler)); diff --git a/tests/foundry/src/ICS20.t.sol b/tests/foundry/src/ICS20Lib.t.sol similarity index 97% rename from tests/foundry/src/ICS20.t.sol rename to tests/foundry/src/ICS20Lib.t.sol index 1b5cb6ce..19494997 100644 --- a/tests/foundry/src/ICS20.t.sol +++ b/tests/foundry/src/ICS20Lib.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; -import "forge-std/Test.sol"; -import "../../../contracts/apps/20-transfer/ICS20Lib.sol"; +import {Test} from "forge-std/Test.sol"; +import {ICS20Lib} from "../../../contracts/apps/20-transfer/ICS20Lib.sol"; -contract TestICS20 is Test { +contract TestICS20Lib is Test { function setUp() public {} function testMarshaling() public { diff --git a/tests/foundry/src/ICS20Transfer.t.sol b/tests/foundry/src/ICS20Transfer.t.sol new file mode 100644 index 00000000..f70a68c2 --- /dev/null +++ b/tests/foundry/src/ICS20Transfer.t.sol @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import "./helpers/IBCTestHelper.t.sol"; +import "forge-std/Test.sol"; +import {ICS20Transfer} from "../../../contracts/apps/20-transfer/ICS20Transfer.sol"; +import {ICS20Lib} from "../../../contracts/apps/20-transfer/ICS20Lib.sol"; +import {ERC20Token} from "../../../contracts/apps/20-transfer/ERC20Token.sol"; +import {LocalhostClientLib} from "../../../contracts/clients/09-localhost/LocalhostClient.sol"; +import {LocalhostHelper} from "../../../contracts/clients/09-localhost/LocalhostHelper.sol"; +import {ICS04PacketEventTestHelper} from "./helpers/ICS04PacketTestHelper.t.sol"; +import {IIBCChannelRecvPacket, IIBCChannelAcknowledgePacket} from "../../../contracts/core/04-channel/IIBCChannel.sol"; + +contract TestICS20Transfer is IBCTestHelper, ICS04PacketEventTestHelper { + using LocalhostHelper for TestableIBCHandler; + + string internal constant ICS20_APP_PORT = "transfer"; + string internal constant ICS20_APP_VERSION = "ics20-1"; + + address immutable alice = address(0x01); + address immutable bob = address(0x02); + address immutable charlie = address(0x03); + + TestableIBCHandler ibcHandler; + ICS20Transfer transferApp; + ERC20Token token; + + struct ChannelInfo { + string connectionId; + string portId; + string channelId; + } + + function setUp() public { + token = new ERC20Token("test", "test", 1000000); + + ibcHandler = defaultIBCHandler(); + transferApp = new ICS20Transfer(ibcHandler, ICS20_APP_PORT); + ibcHandler.bindPort(ICS20_APP_PORT, transferApp); + ibcHandler.registerLocalhostClient(); + ibcHandler.createLocalhostClient(); + } + + function testRelay() public { + vm.recordLogs(); + (ChannelInfo memory channel0, ChannelInfo memory channel1) = createTransferChannel(); + (ChannelInfo memory channel2, ChannelInfo memory channel3) = createTransferChannel(); + + string memory denom0 = ICS20Lib.addressToHexString(address(token)); + string memory denom1 = ICS20Lib.denom(channel1.portId, channel1.channelId, address(token)); + string memory denom2 = ICS20Lib.denom(channel3.portId, channel3.channelId, denom1); + + token.transfer(alice, 1000); + { + vm.startPrank(alice); + assertTrue(token.approve(address(transferApp), 1000)); + transferApp.depositSendTransfer( + channel0.channelId, + address(token), + 1000, + ICS20Lib.addressToHexString(bob), + ICS20Lib.timeout(0, 2) + ); + vm.stopPrank(); + assertEq(token.balanceOf(address(transferApp)), 1000); + assertEq(transferApp.balanceOf(alice, denom0), 0); + assertEq(transferApp.balanceOf(bob, denom1), 0); + Packet memory packet = relayLastSentPacket(channel0.portId, channel0.channelId); + relayLastWrittenAcknowledgement(packet); + assertEq(transferApp.balanceOf(bob, denom1), 1000); + } + { + vm.prank(bob); + transferApp.sendTransfer( + channel1.channelId, + denom1, + 700, + ICS20Lib.addressToHexString(alice), + ICS20Lib.timeout(0, 2) + ); + assertEq(transferApp.balanceOf(bob, denom1), 300); + Packet memory packet = relayLastSentPacket(channel1.portId, channel1.channelId); + assertEq(token.balanceOf(address(transferApp)), 1000); + relayLastWrittenAcknowledgement(packet); + assertEq(transferApp.balanceOf(alice, denom0), 700); + vm.prank(alice); + transferApp.withdraw(alice, address(token), 200); + assertEq(transferApp.balanceOf(alice, denom0), 500); + assertEq(token.balanceOf(alice), 200); + assertEq(token.balanceOf(address(transferApp)), 800); + } + { + vm.prank(bob); + transferApp.sendTransfer( + channel2.channelId, + denom1, + 200, + ICS20Lib.addressToHexString(charlie), + ICS20Lib.timeout(0, 2) + ); + assertEq(transferApp.balanceOf(bob, denom1), 100); + Packet memory packet = relayLastSentPacket(channel2.portId, channel2.channelId); + assertEq(token.balanceOf(address(transferApp)), 800); + relayLastWrittenAcknowledgement(packet); + assertEq(transferApp.balanceOf(charlie, denom2), 200); + } + { + vm.prank(charlie); + transferApp.sendTransfer( + channel3.channelId, + denom2, + 100, + ICS20Lib.addressToHexString(bob), + ICS20Lib.timeout(0, 2) + ); + assertEq(transferApp.balanceOf(charlie, denom2), 100); + relayLastWrittenAcknowledgement(relayLastSentPacket(channel3.portId, channel3.channelId)); + assertEq(transferApp.balanceOf(bob, denom1), 200); + + vm.prank(charlie); + transferApp.sendTransfer( + channel1.channelId, + denom2, + 100, + ICS20Lib.addressToHexString(alice), + ICS20Lib.timeout(0, 2) + ); + assertEq(transferApp.balanceOf(charlie, denom2), 0); + relayLastWrittenAcknowledgement(relayLastSentPacket(channel1.portId, channel1.channelId)); + assertEq(transferApp.balanceOf(alice, ICS20Lib.denom(channel0.portId, channel0.channelId, denom2)), 100); + assertEq(transferApp.balanceOf(alice, denom0), 500); + } + // bob transfer 100 to alice + { + vm.prank(bob); + transferApp.sendTransfer( + channel1.channelId, + denom1, + 100, + ICS20Lib.addressToHexString(alice), + ICS20Lib.timeout(0, 2) + ); + assertEq(transferApp.balanceOf(bob, denom1), 100); + Packet memory packet = relayLastSentPacket(channel1.portId, channel1.channelId); + assertEq(token.balanceOf(address(transferApp)), 800); + relayLastWrittenAcknowledgement(packet); + assertEq(transferApp.balanceOf(alice, denom0), 600); + } + } + + function testDepositTransferWithdraw() public { + token.transfer(alice, 1000); + string memory denom0 = ICS20Lib.addressToHexString(address(token)); + vm.startPrank(alice); + token.approve(address(transferApp), 1000); + transferApp.deposit(alice, address(token), 1000); + transferApp.transfer(bob, denom0, 300); + vm.stopPrank(); + assertEq(transferApp.balanceOf(alice, denom0), 700); + assertEq(transferApp.balanceOf(bob, denom0), 300); + vm.prank(bob); + transferApp.withdraw(bob, address(token), 200); + assertEq(token.balanceOf(bob), 200); + assertEq(transferApp.balanceOf(bob, denom0), 100); + } + + function testDeposit() public { + token.transfer(alice, 1000); + + vm.startPrank(alice); + vm.expectRevert(); + transferApp.deposit(alice, address(token), 1000); + + token.approve(address(transferApp), 100); + vm.expectRevert(); + transferApp.deposit(alice, address(token), 101); + + token.approve(address(transferApp), 500); + transferApp.deposit(bob, address(token), 500); + transferApp.balanceOf(bob, ICS20Lib.addressToHexString(address(token))); + + token.approve(address(transferApp), 500); + transferApp.deposit(alice, address(token), 500); + transferApp.balanceOf(alice, ICS20Lib.addressToHexString(address(token))); + } + + function testWithdraw() public { + token.transfer(alice, 1000); + vm.startPrank(alice); + token.approve(address(transferApp), 1000); + transferApp.deposit(alice, address(token), 1000); + assertEq(token.balanceOf(alice), 0); + + vm.expectRevert(); + transferApp.withdraw(alice, address(token), 1001); + + vm.expectRevert(); + transferApp.withdraw(alice, address(0x01), 1000); + + transferApp.withdraw(alice, address(token), 200); + assertEq(token.balanceOf(alice), 200); + + vm.expectRevert(); + transferApp.withdraw(alice, address(token), 900); + + transferApp.withdraw(bob, address(token), 800); + assertEq(token.balanceOf(bob), 800); + + string memory denom = ICS20Lib.addressToHexString(address(token)); + assertEq(transferApp.balanceOf(alice, denom), 0); + } + + function createTransferChannel() internal returns (ChannelInfo memory, ChannelInfo memory) { + (string memory connectionId0, string memory connectionId1) = ibcHandler.createLocalhostConnection(); + (string memory channelId0, string memory channelId1) = ibcHandler.createLocalhostChannel( + LocalhostHelper.MsgCreateChannel({ + connectionId0: connectionId0, + connectionId1: connectionId1, + portId0: ICS20_APP_PORT, + portId1: ICS20_APP_PORT, + ordering: Channel.Order.ORDER_UNORDERED, + version: ICS20_APP_VERSION + }) + ); + return ( + ChannelInfo({connectionId: connectionId0, portId: ICS20_APP_PORT, channelId: channelId0}), + ChannelInfo({connectionId: connectionId1, portId: ICS20_APP_PORT, channelId: channelId1}) + ); + } + + function relayLastSentPacket(string memory portId, string memory channelId) internal returns (Packet memory) { + Packet memory packet = getLastSentPacket(ibcHandler, portId, channelId, vm.getRecordedLogs()); + ibcHandler.recvPacket( + IIBCChannelRecvPacket.MsgPacketRecv({ + packet: packet, + proof: LocalhostClientLib.sentinelProof(), + proofHeight: Height.nil() + }) + ); + return packet; + } + + function relayLastWrittenAcknowledgement(Packet memory packet) internal returns (WriteAcknolwedgement memory) { + WriteAcknolwedgement memory ack = getLastWrittenAcknowledgement(ibcHandler, vm.getRecordedLogs()); + assertEq(ack.acknowledgement, ICS20Lib.SUCCESSFUL_ACKNOWLEDGEMENT_JSON); + ibcHandler.acknowledgePacket( + IIBCChannelAcknowledgePacket.MsgPacketAcknowledgement({ + packet: packet, + acknowledgement: ack.acknowledgement, + proof: LocalhostClientLib.sentinelProof(), + proofHeight: Height.nil() + }) + ); + return ack; + } +} \ No newline at end of file