diff --git a/contracts/test/Gateway.t.sol b/contracts/test/Gateway.t.sol index e66b1d3d16..d52d9b574f 100644 --- a/contracts/test/Gateway.t.sol +++ b/contracts/test/Gateway.t.sol @@ -54,12 +54,12 @@ contract GatewayTest is Test { // Emitted when token minted event TokenMinted(bytes32 indexed tokenID, address token, address recipient, uint256 amount); - ParaID public bridgeHubParaID = ParaID.wrap(1001); - bytes32 public bridgeHubAgentID = keccak256("1001"); + ParaID public bridgeHubParaID = ParaID.wrap(1013); + bytes32 public bridgeHubAgentID = 0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314; address public bridgeHubAgent; - ParaID public assetHubParaID = ParaID.wrap(1002); - bytes32 public assetHubAgentID = keccak256("1002"); + ParaID public assetHubParaID = ParaID.wrap(1000); + bytes32 public assetHubAgentID = 0x81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79; address public assetHubAgent; address public relayer; @@ -966,4 +966,29 @@ contract GatewayTest is Test { address(info.token), destPara, recipientAddress32, 1, 1 ); } + + function testParseAgentExecuteCall() public { + bytes memory data = + hex"000000000000000000000000000000000000000000000000000000000000002081c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001008080778c30c20fa2ebc0ed18d2cbca1f30b027625c7d9d97f5d589721c91aeb6000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000003646f7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003646f740000000000000000000000000000000000000000000000000000000000"; + + AgentExecuteParams memory params = abi.decode(data, (AgentExecuteParams)); + + (AgentExecuteCommand command, bytes memory payload) = abi.decode(params.payload, (AgentExecuteCommand, bytes)); + + //Register foreign token + assertEq(uint256(command), uint256(1)); + + (bytes32 tokenID, string memory name, string memory symbol, uint8 decimals) = + abi.decode(payload, (bytes32, string, string, uint8)); + assertEq(tokenID, 0x8080778c30c20fa2ebc0ed18d2cbca1f30b027625c7d9d97f5d589721c91aeb6); + + console.log("name:%s", name); + console.log("symbol:%s", symbol); + console.log("decimals:%s", decimals); + + vm.expectEmit(true, true, false, false); + emit IGateway.ForeignTokenRegistered(tokenID, assetHubAgentID, address(0)); + + GatewayMock(address(gateway)).agentExecutePublic(abi.encode(params)); + } } diff --git a/relayer/contracts/gateway.go b/relayer/contracts/gateway.go index 814a6a5017..59acd84dcc 100644 --- a/relayer/contracts/gateway.go +++ b/relayer/contracts/gateway.go @@ -47,6 +47,15 @@ type MultiAddress struct { Data []byte } +// TokenInfo is an auto generated low-level Go binding around an user-defined struct. +type TokenInfo struct { + IsRegistered bool + IsForeign bool + TokenID [32]byte + AgentID [32]byte + Token common.Address +} + // VerificationDigestItem is an auto generated low-level Go binding around an user-defined struct. type VerificationDigestItem struct { Kind *big.Int @@ -91,7 +100,7 @@ type VerificationProof struct { // GatewayMetaData contains all meta data concerning the Gateway contract. var GatewayMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"agentOf\",\"inputs\":[{\"name\":\"agentID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"channelNoncesOf\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"internalType\":\"ChannelID\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"channelOperatingModeOf\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"internalType\":\"ChannelID\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumOperatingMode\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"implementation\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isTokenRegistered\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"operatingMode\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumOperatingMode\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"pricingParameters\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"UD60x18\"},{\"name\":\"\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"quoteRegisterTokenFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"quoteSendTokenFee\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationChain\",\"type\":\"uint32\",\"internalType\":\"ParaID\"},{\"name\":\"destinationFee\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"registerToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"sendToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationChain\",\"type\":\"uint32\",\"internalType\":\"ParaID\"},{\"name\":\"destinationAddress\",\"type\":\"tuple\",\"internalType\":\"structMultiAddress\",\"components\":[{\"name\":\"kind\",\"type\":\"uint8\",\"internalType\":\"enumKind\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"destinationFee\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"submitV1\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structInboundMessage\",\"components\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"internalType\":\"ChannelID\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"command\",\"type\":\"uint8\",\"internalType\":\"enumCommand\"},{\"name\":\"params\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"maxDispatchGas\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxFeePerGas\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"reward\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"id\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"headerProof\",\"type\":\"tuple\",\"internalType\":\"structVerification.Proof\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structVerification.ParachainHeader\",\"components\":[{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"number\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"extrinsicsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"digestItems\",\"type\":\"tuple[]\",\"internalType\":\"structVerification.DigestItem[]\",\"components\":[{\"name\":\"kind\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"consensusEngineID\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"headProof\",\"type\":\"tuple\",\"internalType\":\"structVerification.HeadProof\",\"components\":[{\"name\":\"pos\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"width\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leafPartial\",\"type\":\"tuple\",\"internalType\":\"structVerification.MMRLeafPartial\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AgentCreated\",\"inputs\":[{\"name\":\"agentID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"agent\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AgentFundsWithdrawn\",\"inputs\":[{\"name\":\"agentID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChannelCreated\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"ChannelID\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChannelUpdated\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"ChannelID\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InboundMessageDispatched\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"ChannelID\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"success\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OperatingModeChanged\",\"inputs\":[{\"name\":\"mode\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"enumOperatingMode\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OutboundMessageAccepted\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"ChannelID\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"payload\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PricingParametersChanged\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenRegistrationSent\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenSent\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"destinationChain\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"ParaID\"},{\"name\":\"destinationAddress\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structMultiAddress\",\"components\":[{\"name\":\"kind\",\"type\":\"uint8\",\"internalType\":\"enumKind\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"amount\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenTransferFeesChanged\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false}]", + ABI: "[{\"type\":\"function\",\"name\":\"agentOf\",\"inputs\":[{\"name\":\"agentID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"channelNoncesOf\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"internalType\":\"ChannelID\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"channelOperatingModeOf\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"internalType\":\"ChannelID\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumOperatingMode\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenInfo\",\"inputs\":[{\"name\":\"tokenID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structTokenInfo\",\"components\":[{\"name\":\"isRegistered\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"isForeign\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"tokenID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"agentID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"implementation\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isTokenRegistered\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"operatingMode\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumOperatingMode\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"pricingParameters\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"UD60x18\"},{\"name\":\"\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"quoteRegisterTokenFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"quoteSendTokenFee\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationChain\",\"type\":\"uint32\",\"internalType\":\"ParaID\"},{\"name\":\"destinationFee\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"registerToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"sendToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationChain\",\"type\":\"uint32\",\"internalType\":\"ParaID\"},{\"name\":\"destinationAddress\",\"type\":\"tuple\",\"internalType\":\"structMultiAddress\",\"components\":[{\"name\":\"kind\",\"type\":\"uint8\",\"internalType\":\"enumKind\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"destinationFee\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"submitV1\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structInboundMessage\",\"components\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"internalType\":\"ChannelID\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"command\",\"type\":\"uint8\",\"internalType\":\"enumCommand\"},{\"name\":\"params\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"maxDispatchGas\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maxFeePerGas\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"reward\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"id\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"headerProof\",\"type\":\"tuple\",\"internalType\":\"structVerification.Proof\",\"components\":[{\"name\":\"header\",\"type\":\"tuple\",\"internalType\":\"structVerification.ParachainHeader\",\"components\":[{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"number\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"extrinsicsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"digestItems\",\"type\":\"tuple[]\",\"internalType\":\"structVerification.DigestItem[]\",\"components\":[{\"name\":\"kind\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"consensusEngineID\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"headProof\",\"type\":\"tuple\",\"internalType\":\"structVerification.HeadProof\",\"components\":[{\"name\":\"pos\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"width\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leafPartial\",\"type\":\"tuple\",\"internalType\":\"structVerification.MMRLeafPartial\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationChain\",\"type\":\"uint32\",\"internalType\":\"ParaID\"},{\"name\":\"destinationAddress\",\"type\":\"tuple\",\"internalType\":\"structMultiAddress\",\"components\":[{\"name\":\"kind\",\"type\":\"uint8\",\"internalType\":\"enumKind\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"destinationFee\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"AgentCreated\",\"inputs\":[{\"name\":\"agentID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"agent\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AgentFundsWithdrawn\",\"inputs\":[{\"name\":\"agentID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChannelCreated\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"ChannelID\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChannelUpdated\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"ChannelID\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ForeignTokenRegistered\",\"inputs\":[{\"name\":\"tokenID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"agentID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"token\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InboundMessageDispatched\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"ChannelID\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"success\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OperatingModeChanged\",\"inputs\":[{\"name\":\"mode\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"enumOperatingMode\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OutboundMessageAccepted\",\"inputs\":[{\"name\":\"channelID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"ChannelID\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"payload\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PricingParametersChanged\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenRegistrationSent\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenSent\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"destinationChain\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"ParaID\"},{\"name\":\"destinationAddress\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structMultiAddress\",\"components\":[{\"name\":\"kind\",\"type\":\"uint8\",\"internalType\":\"enumKind\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"amount\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenTransferFeesChanged\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenTransfered\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"destinationChain\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"ParaID\"},{\"name\":\"destinationAddress\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structMultiAddress\",\"components\":[{\"name\":\"kind\",\"type\":\"uint8\",\"internalType\":\"enumKind\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"amount\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false}]", } // GatewayABI is the input ABI used to generate the binding from. @@ -334,6 +343,37 @@ func (_Gateway *GatewayCallerSession) ChannelOperatingModeOf(channelID [32]byte) return _Gateway.Contract.ChannelOperatingModeOf(&_Gateway.CallOpts, channelID) } +// GetTokenInfo is a free data retrieval call binding the contract method 0x2d8b70a1. +// +// Solidity: function getTokenInfo(bytes32 tokenID) view returns((bool,bool,bytes32,bytes32,address)) +func (_Gateway *GatewayCaller) GetTokenInfo(opts *bind.CallOpts, tokenID [32]byte) (TokenInfo, error) { + var out []interface{} + err := _Gateway.contract.Call(opts, &out, "getTokenInfo", tokenID) + + if err != nil { + return *new(TokenInfo), err + } + + out0 := *abi.ConvertType(out[0], new(TokenInfo)).(*TokenInfo) + + return out0, err + +} + +// GetTokenInfo is a free data retrieval call binding the contract method 0x2d8b70a1. +// +// Solidity: function getTokenInfo(bytes32 tokenID) view returns((bool,bool,bytes32,bytes32,address)) +func (_Gateway *GatewaySession) GetTokenInfo(tokenID [32]byte) (TokenInfo, error) { + return _Gateway.Contract.GetTokenInfo(&_Gateway.CallOpts, tokenID) +} + +// GetTokenInfo is a free data retrieval call binding the contract method 0x2d8b70a1. +// +// Solidity: function getTokenInfo(bytes32 tokenID) view returns((bool,bool,bytes32,bytes32,address)) +func (_Gateway *GatewayCallerSession) GetTokenInfo(tokenID [32]byte) (TokenInfo, error) { + return _Gateway.Contract.GetTokenInfo(&_Gateway.CallOpts, tokenID) +} + // Implementation is a free data retrieval call binding the contract method 0x5c60da1b. // // Solidity: function implementation() view returns(address) @@ -584,6 +624,27 @@ func (_Gateway *GatewayTransactorSession) SubmitV1(message InboundMessage, leafP return _Gateway.Contract.SubmitV1(&_Gateway.TransactOpts, message, leafProof, headerProof) } +// TransferToken is a paid mutator transaction binding the contract method 0x1382f5eb. +// +// Solidity: function transferToken(address token, uint32 destinationChain, (uint8,bytes) destinationAddress, uint128 destinationFee, uint128 amount) payable returns() +func (_Gateway *GatewayTransactor) TransferToken(opts *bind.TransactOpts, token common.Address, destinationChain uint32, destinationAddress MultiAddress, destinationFee *big.Int, amount *big.Int) (*types.Transaction, error) { + return _Gateway.contract.Transact(opts, "transferToken", token, destinationChain, destinationAddress, destinationFee, amount) +} + +// TransferToken is a paid mutator transaction binding the contract method 0x1382f5eb. +// +// Solidity: function transferToken(address token, uint32 destinationChain, (uint8,bytes) destinationAddress, uint128 destinationFee, uint128 amount) payable returns() +func (_Gateway *GatewaySession) TransferToken(token common.Address, destinationChain uint32, destinationAddress MultiAddress, destinationFee *big.Int, amount *big.Int) (*types.Transaction, error) { + return _Gateway.Contract.TransferToken(&_Gateway.TransactOpts, token, destinationChain, destinationAddress, destinationFee, amount) +} + +// TransferToken is a paid mutator transaction binding the contract method 0x1382f5eb. +// +// Solidity: function transferToken(address token, uint32 destinationChain, (uint8,bytes) destinationAddress, uint128 destinationFee, uint128 amount) payable returns() +func (_Gateway *GatewayTransactorSession) TransferToken(token common.Address, destinationChain uint32, destinationAddress MultiAddress, destinationFee *big.Int, amount *big.Int) (*types.Transaction, error) { + return _Gateway.Contract.TransferToken(&_Gateway.TransactOpts, token, destinationChain, destinationAddress, destinationFee, amount) +} + // GatewayAgentCreatedIterator is returned from FilterAgentCreated and is used to iterate over the raw logs and unpacked data for AgentCreated events raised by the Gateway contract. type GatewayAgentCreatedIterator struct { Event *GatewayAgentCreated // Event containing the contract specifics and raw log @@ -1161,6 +1222,152 @@ func (_Gateway *GatewayFilterer) ParseChannelUpdated(log types.Log) (*GatewayCha return event, nil } +// GatewayForeignTokenRegisteredIterator is returned from FilterForeignTokenRegistered and is used to iterate over the raw logs and unpacked data for ForeignTokenRegistered events raised by the Gateway contract. +type GatewayForeignTokenRegisteredIterator struct { + Event *GatewayForeignTokenRegistered // 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 *GatewayForeignTokenRegisteredIterator) 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(GatewayForeignTokenRegistered) + 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(GatewayForeignTokenRegistered) + 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 *GatewayForeignTokenRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayForeignTokenRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayForeignTokenRegistered represents a ForeignTokenRegistered event raised by the Gateway contract. +type GatewayForeignTokenRegistered struct { + TokenID [32]byte + AgentID [32]byte + Token common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterForeignTokenRegistered is a free log retrieval operation binding the contract event 0xc4a9ffa44bcfe101c1450dc2e08360693767d951c4a5c726e36cde0371dc4ddb. +// +// Solidity: event ForeignTokenRegistered(bytes32 indexed tokenID, bytes32 agentID, address token) +func (_Gateway *GatewayFilterer) FilterForeignTokenRegistered(opts *bind.FilterOpts, tokenID [][32]byte) (*GatewayForeignTokenRegisteredIterator, error) { + + var tokenIDRule []interface{} + for _, tokenIDItem := range tokenID { + tokenIDRule = append(tokenIDRule, tokenIDItem) + } + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "ForeignTokenRegistered", tokenIDRule) + if err != nil { + return nil, err + } + return &GatewayForeignTokenRegisteredIterator{contract: _Gateway.contract, event: "ForeignTokenRegistered", logs: logs, sub: sub}, nil +} + +// WatchForeignTokenRegistered is a free log subscription operation binding the contract event 0xc4a9ffa44bcfe101c1450dc2e08360693767d951c4a5c726e36cde0371dc4ddb. +// +// Solidity: event ForeignTokenRegistered(bytes32 indexed tokenID, bytes32 agentID, address token) +func (_Gateway *GatewayFilterer) WatchForeignTokenRegistered(opts *bind.WatchOpts, sink chan<- *GatewayForeignTokenRegistered, tokenID [][32]byte) (event.Subscription, error) { + + var tokenIDRule []interface{} + for _, tokenIDItem := range tokenID { + tokenIDRule = append(tokenIDRule, tokenIDItem) + } + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "ForeignTokenRegistered", tokenIDRule) + 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(GatewayForeignTokenRegistered) + if err := _Gateway.contract.UnpackLog(event, "ForeignTokenRegistered", 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 +} + +// ParseForeignTokenRegistered is a log parse operation binding the contract event 0xc4a9ffa44bcfe101c1450dc2e08360693767d951c4a5c726e36cde0371dc4ddb. +// +// Solidity: event ForeignTokenRegistered(bytes32 indexed tokenID, bytes32 agentID, address token) +func (_Gateway *GatewayFilterer) ParseForeignTokenRegistered(log types.Log) (*GatewayForeignTokenRegistered, error) { + event := new(GatewayForeignTokenRegistered) + if err := _Gateway.contract.UnpackLog(event, "ForeignTokenRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + // GatewayInboundMessageDispatchedIterator is returned from FilterInboundMessageDispatched and is used to iterate over the raw logs and unpacked data for InboundMessageDispatched events raised by the Gateway contract. type GatewayInboundMessageDispatchedIterator struct { Event *GatewayInboundMessageDispatched // Event containing the contract specifics and raw log @@ -2173,6 +2380,170 @@ func (_Gateway *GatewayFilterer) ParseTokenTransferFeesChanged(log types.Log) (* return event, nil } +// GatewayTokenTransferedIterator is returned from FilterTokenTransfered and is used to iterate over the raw logs and unpacked data for TokenTransfered events raised by the Gateway contract. +type GatewayTokenTransferedIterator struct { + Event *GatewayTokenTransfered // 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 *GatewayTokenTransferedIterator) 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(GatewayTokenTransfered) + 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(GatewayTokenTransfered) + 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 *GatewayTokenTransferedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayTokenTransferedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayTokenTransfered represents a TokenTransfered event raised by the Gateway contract. +type GatewayTokenTransfered struct { + Token common.Address + Sender common.Address + DestinationChain uint32 + DestinationAddress MultiAddress + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTokenTransfered is a free log retrieval operation binding the contract event 0x83c992bcd5b2b18b0cb4ceb131a37c34e5b795f5e00e7058b99a33e9bcf1ee47. +// +// Solidity: event TokenTransfered(address indexed token, address indexed sender, uint32 indexed destinationChain, (uint8,bytes) destinationAddress, uint128 amount) +func (_Gateway *GatewayFilterer) FilterTokenTransfered(opts *bind.FilterOpts, token []common.Address, sender []common.Address, destinationChain []uint32) (*GatewayTokenTransferedIterator, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var destinationChainRule []interface{} + for _, destinationChainItem := range destinationChain { + destinationChainRule = append(destinationChainRule, destinationChainItem) + } + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "TokenTransfered", tokenRule, senderRule, destinationChainRule) + if err != nil { + return nil, err + } + return &GatewayTokenTransferedIterator{contract: _Gateway.contract, event: "TokenTransfered", logs: logs, sub: sub}, nil +} + +// WatchTokenTransfered is a free log subscription operation binding the contract event 0x83c992bcd5b2b18b0cb4ceb131a37c34e5b795f5e00e7058b99a33e9bcf1ee47. +// +// Solidity: event TokenTransfered(address indexed token, address indexed sender, uint32 indexed destinationChain, (uint8,bytes) destinationAddress, uint128 amount) +func (_Gateway *GatewayFilterer) WatchTokenTransfered(opts *bind.WatchOpts, sink chan<- *GatewayTokenTransfered, token []common.Address, sender []common.Address, destinationChain []uint32) (event.Subscription, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var destinationChainRule []interface{} + for _, destinationChainItem := range destinationChain { + destinationChainRule = append(destinationChainRule, destinationChainItem) + } + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "TokenTransfered", tokenRule, senderRule, destinationChainRule) + 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(GatewayTokenTransfered) + if err := _Gateway.contract.UnpackLog(event, "TokenTransfered", 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 +} + +// ParseTokenTransfered is a log parse operation binding the contract event 0x83c992bcd5b2b18b0cb4ceb131a37c34e5b795f5e00e7058b99a33e9bcf1ee47. +// +// Solidity: event TokenTransfered(address indexed token, address indexed sender, uint32 indexed destinationChain, (uint8,bytes) destinationAddress, uint128 amount) +func (_Gateway *GatewayFilterer) ParseTokenTransfered(log types.Log) (*GatewayTokenTransfered, error) { + event := new(GatewayTokenTransfered) + if err := _Gateway.contract.UnpackLog(event, "TokenTransfered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + // GatewayUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the Gateway contract. type GatewayUpgradedIterator struct { Event *GatewayUpgraded // Event containing the contract specifics and raw log diff --git a/smoketest/src/helper.rs b/smoketest/src/helper.rs index 26c0b54f13..e470245f45 100644 --- a/smoketest/src/helper.rs +++ b/smoketest/src/helper.rs @@ -2,9 +2,20 @@ use crate::{ constants::*, contracts::i_gateway, parachains::{ - bridgehub::{self, api::runtime_types::snowbridge_core::outbound::v1::OperatingMode}, + bridgehub::{ + self, + api::{ + runtime_types, + runtime_types::{ + snowbridge_core::outbound::v1::OperatingMode, xcm::VersionedLocation, + }, + }, + }, penpal::{ - api::{runtime_types as penpalTypes, runtime_types::xcm::VersionedLocation}, + api::{ + runtime_types as penpalTypes, + runtime_types::xcm::VersionedLocation as penpalVersionLocation, + }, {self}, }, relaychain, @@ -185,7 +196,7 @@ pub async fn send_sudo_xcm_transact( penpal_client: &Box>, message: Box, ) -> Result, Box> { - let dest = Box::new(VersionedLocation::V3(MultiLocation { + let dest = Box::new(penpalVersionLocation::V3(MultiLocation { parents: 1, interior: Junctions::X1(Junction::Parachain(BRIDGE_HUB_PARA_ID)), })); @@ -353,3 +364,28 @@ pub fn print_event_log_for_unit_tests(log: &Log) { println!("}}") } + +pub async fn construct_register_relay_token_call( + bridge_hub_client: &Box>, +) -> Result, Box> { + type Junctions = runtime_types::staging_xcm::v4::junctions::Junctions; + type Junction = runtime_types::staging_xcm::v4::junction::Junction; + let location = VersionedLocation::V4(runtime_types::staging_xcm::v4::location::Location { + parents: 1, + interior: Junctions::X1([Junction::Parachain(ASSET_HUB_PARA_ID)]), + }); + let asset = VersionedLocation::V4(runtime_types::staging_xcm::v4::location::Location { + parents: 1, + interior: Junctions::Here, + }); + let metadata = runtime_types::snowbridge_core::AssetRegistrarMetadata { + name: "dot".as_bytes().to_vec(), + symbol: "dot".as_bytes().to_vec(), + decimals: 10, + }; + let call = bridgehub::api::ethereum_system::calls::TransactionApi + .force_register_token(location, asset, metadata) + .encode_call_data(&bridge_hub_client.metadata())?; + + Ok(call) +} diff --git a/smoketest/tests/register_polkadot_token.rs b/smoketest/tests/register_polkadot_token.rs new file mode 100644 index 0000000000..6ba466c672 --- /dev/null +++ b/smoketest/tests/register_polkadot_token.rs @@ -0,0 +1,22 @@ +use snowbridge_smoketest::{ + contracts::i_gateway::ForeignTokenRegisteredFilter, helper::*, + parachains::bridgehub::api::ethereum_system::events::RegisterToken, +}; + +#[tokio::test] +async fn register_polkadot_token() { + let test_clients = initial_clients().await.expect("initialize clients"); + + let encoded_call = construct_register_relay_token_call(&test_clients.bridge_hub_client) + .await + .expect("construct inner call."); + + governance_bridgehub_call_from_relay_chain(encoded_call) + .await + .expect("set token fees"); + + wait_for_bridgehub_event::(&test_clients.bridge_hub_client).await; + + wait_for_ethereum_event::(&test_clients.ethereum_client).await; + +}