diff --git a/cli/src/index.ts b/cli/src/index.ts index cd7a735f2..153d5fcae 100755 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -2843,7 +2843,7 @@ async function upgradeSui( // Helper function to perform complete package upgrade in a single PTB async function performPackageUpgradeInPTB< N extends Network, - C extends SuiChains + C extends SuiChains, >( ctx: ChainContext, packagePath: string, @@ -4230,9 +4230,8 @@ async function missingConfigs( missing.standardRelaying.push([toChain, desiredStandardRelaying]); } } else if (toIsSolana) { - const specialRelaying = await whTransceiver.isSpecialRelayingEnabled( - toChain - ); + const specialRelaying = + await whTransceiver.isSpecialRelayingEnabled(toChain); const desiredSpecialRelaying = !( from.config.local?.transceivers.wormhole.executor ?? false ); diff --git a/cli/src/signSendWait.ts b/cli/src/signSendWait.ts index a7edd77c3..0f5a6a214 100644 --- a/cli/src/signSendWait.ts +++ b/cli/src/signSendWait.ts @@ -62,7 +62,7 @@ export const signSendWaitEvmSpecialOwner = async ( export const signSendWaitWithOverride = async < N extends Network, - C extends Chain + C extends Chain, >( chain: ChainContext, xfer: AsyncGenerator>, diff --git a/evm/ts/__tests__/calculateLocalTokenAddress.test.ts b/evm/ts/__tests__/calculateLocalTokenAddress.test.ts new file mode 100644 index 000000000..e6a4725b9 --- /dev/null +++ b/evm/ts/__tests__/calculateLocalTokenAddress.test.ts @@ -0,0 +1,48 @@ +import { MultiTokenNtt } from "@wormhole-foundation/sdk-definitions-ntt"; +import { EvmMultiTokenNtt } from "../src/multiTokenNtt.js"; +import { toUniversal } from "@wormhole-foundation/sdk-definitions"; + +describe("calculateLocalTokenAddress", () => { + it("should calculate the correct local token address", async () => { + const tokenImplementation = "0xbd7312fA1d9433ab2616FBE7aC615A58D81D2c8E"; + const creationCode = + "0x604060808152610416908138038061001681610218565b93843982019181818403126102135780516001600160a01b038116808203610213576020838101516001600160401b0394919391858211610213570186601f820112156102135780519061007161006c83610253565b610218565b918083528583019886828401011161021357888661008f930161026e565b813b156101b9577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916841790556000927fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a28051158015906101b2575b61010b575b855160d190816103458239f35b855194606086019081118682101761019e578697849283926101889952602788527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c87890152660819985a5b195960ca1b8a8901525190845af4913d15610194573d9061017a61006c83610253565b91825281943d92013e610291565b508038808080806100fe565b5060609250610291565b634e487b7160e01b84526041600452602484fd5b50826100f9565b855162461bcd60e51b815260048101859052602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b600080fd5b6040519190601f01601f191682016001600160401b0381118382101761023d57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161023d57601f01601f191660200190565b60005b8381106102815750506000910152565b8181015183820152602001610271565b919290156102f357508151156102a5575090565b3b156102ae5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156103065750805190602001fd5b6044604051809262461bcd60e51b825260206004830152610336815180928160248601526020868601910161026e565b601f01601f19168101030190fdfe608060405236156054577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54600090819081906001600160a01b0316368280378136915af43d82803e156050573d90f35b3d90fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54600090819081906001600160a01b0316368280378136915af43d82803e156050573d90f3fea26469706673582212206554f4df1904914343564cd467a416ab7dfbd4626b3eb40104613d037cd433f264736f6c63430008130033"; + const expectedAddress = "0xCaf00B2fB2fa0EAE51ecAfef7e45f13fF1BB448a"; + + const originalToken: MultiTokenNtt.OriginalTokenId = { + chain: "Sepolia", + // @ts-ignore + address: toUniversal( + "Sepolia", + "0x738141EFf659625F2eAD4feECDfCD94155C67f18" + ), + }; + + const tokenMeta = { + name: "W Token", + symbol: "Ws", + decimals: 18, + }; + + const mockMultiTokenNtt = { + tokenImplementation: jest.fn().mockResolvedValue(tokenImplementation), + tokenProxyCreationCode: jest.fn().mockResolvedValue(creationCode), + }; + + // Minimal implementation of MultiTokenNtt for testing + const multiTokenNtt = { + multiTokenNtt: mockMultiTokenNtt, + managerAddress: "0x600D3C45Cd002E7359D12597Bb8058a0C32A20Df", + chain: "Monad", + calculateLocalTokenAddress: + EvmMultiTokenNtt.prototype.calculateLocalTokenAddress, + }; + + const result = await multiTokenNtt.calculateLocalTokenAddress( + originalToken, + tokenMeta + ); + + expect(result.toString()).toBe(expectedAddress); + }); +}); diff --git a/evm/ts/src/ethers-contracts/1_1_0/GmpManager.ts b/evm/ts/src/ethers-contracts/1_1_0/GmpManager.ts new file mode 100644 index 000000000..f6be640f7 --- /dev/null +++ b/evm/ts/src/ethers-contracts/1_1_0/GmpManager.ts @@ -0,0 +1,1586 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { + BaseContract, + BigNumberish, + BytesLike, + FunctionFragment, + Result, + Interface, + EventFragment, + AddressLike, + ContractRunner, + ContractMethod, + Listener, +} from "ethers"; +import type { + TypedContractEvent, + TypedDeferredTopicFilter, + TypedEventLog, + TypedLogDescription, + TypedListener, + TypedContractMethod, +} from "./common.js"; + +export declare namespace TransceiverStructs { + export type NttManagerMessageStruct = { + id: BytesLike; + sender: BytesLike; + payload: BytesLike; + }; + + export type NttManagerMessageStructOutput = [ + id: string, + sender: string, + payload: string + ] & { id: string; sender: string; payload: string }; +} + +export declare namespace GmpManager { + export type GmpPeerStruct = { peerAddress: BytesLike }; + + export type GmpPeerStructOutput = [peerAddress: string] & { + peerAddress: string; + }; +} + +export declare namespace TransceiverRegistry { + export type TransceiverWithIndexStruct = { + transceiver: AddressLike; + index: BigNumberish; + }; + + export type TransceiverWithIndexStructOutput = [ + transceiver: string, + index: bigint + ] & { transceiver: string; index: bigint }; + + export type TransceiverInfoStruct = { + registered: boolean; + enabled: boolean; + index: BigNumberish; + }; + + export type TransceiverInfoStructOutput = [ + registered: boolean, + enabled: boolean, + index: bigint + ] & { registered: boolean; enabled: boolean; index: bigint }; +} + +export interface GmpManagerInterface extends Interface { + getFunction( + nameOrSignature: + | "GMP_MANAGER_VERSION" + | "attestationReceived" + | "chainId" + | "executeMsg" + | "getKnownChains" + | "getMigratesImmutables" + | "getPeer" + | "getReceiveTransceiversForChain" + | "getReceiveTransceiversWithIndicesForChain" + | "getSendTransceiversForChain" + | "getSendTransceiversWithIndicesForChain" + | "getThreshold" + | "getTransceiverInfo" + | "getTransceivers" + | "initialize" + | "isMessageApprovedForChain" + | "isMessageExecuted" + | "isPaused" + | "messageAttestations" + | "messageAttestationsForChain" + | "migrate" + | "nextMessageSequence" + | "owner" + | "pause" + | "pauser" + | "quoteDeliveryPrice" + | "registerKnownChain" + | "removeReceiveTransceiverForChain" + | "removeSendTransceiverForChain" + | "removeTransceiver" + | "reserveMessageSequence" + | "sendMessage" + | "setPeer" + | "setReceiveTransceiverForChain" + | "setSendTransceiverForChain" + | "setThreshold" + | "setTransceiver" + | "transceiverAttestedToMessage" + | "transferOwnership" + | "transferPauserCapability" + | "unpause" + | "upgrade" + ): FunctionFragment; + + getEvent( + nameOrSignatureOrTopic: + | "AdminChanged" + | "BeaconUpgraded" + | "Initialized" + | "MessageAlreadyExecuted" + | "MessageAttestedTo" + | "MessageExecuted" + | "MessageSent" + | "NotPaused" + | "OwnershipTransferred" + | "Paused" + | "PauserTransferred" + | "PeerUpdated" + | "ReceiveTransceiverUpdatedForChain" + | "SendTransceiverUpdatedForChain" + | "ThresholdChanged" + | "ThresholdUpdatedForChain" + | "TransceiverAdded" + | "TransceiverRemoved" + | "Upgraded" + ): EventFragment; + + encodeFunctionData( + functionFragment: "GMP_MANAGER_VERSION", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "attestationReceived", + values: [ + BigNumberish, + BytesLike, + TransceiverStructs.NttManagerMessageStruct + ] + ): string; + encodeFunctionData(functionFragment: "chainId", values?: undefined): string; + encodeFunctionData( + functionFragment: "executeMsg", + values: [ + BigNumberish, + BytesLike, + TransceiverStructs.NttManagerMessageStruct + ] + ): string; + encodeFunctionData( + functionFragment: "getKnownChains", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "getMigratesImmutables", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "getPeer", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getReceiveTransceiversForChain", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getReceiveTransceiversWithIndicesForChain", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getSendTransceiversForChain", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getSendTransceiversWithIndicesForChain", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getThreshold", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getTransceiverInfo", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "getTransceivers", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "initialize", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "isMessageApprovedForChain", + values: [BigNumberish, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "isMessageExecuted", + values: [BytesLike] + ): string; + encodeFunctionData(functionFragment: "isPaused", values?: undefined): string; + encodeFunctionData( + functionFragment: "messageAttestations", + values: [BytesLike] + ): string; + encodeFunctionData( + functionFragment: "messageAttestationsForChain", + values: [BigNumberish, BytesLike] + ): string; + encodeFunctionData(functionFragment: "migrate", values?: undefined): string; + encodeFunctionData( + functionFragment: "nextMessageSequence", + values?: undefined + ): string; + encodeFunctionData(functionFragment: "owner", values?: undefined): string; + encodeFunctionData(functionFragment: "pause", values?: undefined): string; + encodeFunctionData(functionFragment: "pauser", values?: undefined): string; + encodeFunctionData( + functionFragment: "quoteDeliveryPrice", + values: [BigNumberish, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "registerKnownChain", + values: [BigNumberish, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "removeReceiveTransceiverForChain", + values: [BigNumberish, AddressLike] + ): string; + encodeFunctionData( + functionFragment: "removeSendTransceiverForChain", + values: [BigNumberish, AddressLike] + ): string; + encodeFunctionData( + functionFragment: "removeTransceiver", + values: [AddressLike] + ): string; + encodeFunctionData( + functionFragment: "reserveMessageSequence", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "sendMessage", + values: [ + BigNumberish, + BytesLike, + BytesLike, + BigNumberish, + BytesLike, + BytesLike + ] + ): string; + encodeFunctionData( + functionFragment: "setPeer", + values: [BigNumberish, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "setReceiveTransceiverForChain", + values: [BigNumberish, AddressLike] + ): string; + encodeFunctionData( + functionFragment: "setSendTransceiverForChain", + values: [BigNumberish, AddressLike] + ): string; + encodeFunctionData( + functionFragment: "setThreshold", + values: [BigNumberish, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "setTransceiver", + values: [AddressLike] + ): string; + encodeFunctionData( + functionFragment: "transceiverAttestedToMessage", + values: [BytesLike, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "transferOwnership", + values: [AddressLike] + ): string; + encodeFunctionData( + functionFragment: "transferPauserCapability", + values: [AddressLike] + ): string; + encodeFunctionData(functionFragment: "unpause", values?: undefined): string; + encodeFunctionData( + functionFragment: "upgrade", + values: [AddressLike] + ): string; + + decodeFunctionResult( + functionFragment: "GMP_MANAGER_VERSION", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "attestationReceived", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "chainId", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "executeMsg", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "getKnownChains", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getMigratesImmutables", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "getPeer", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "getReceiveTransceiversForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getReceiveTransceiversWithIndicesForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getSendTransceiversForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getSendTransceiversWithIndicesForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getThreshold", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getTransceiverInfo", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getTransceivers", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "initialize", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "isMessageApprovedForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "isMessageExecuted", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "isPaused", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "messageAttestations", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "messageAttestationsForChain", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "migrate", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "nextMessageSequence", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "owner", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "pause", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "pauser", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "quoteDeliveryPrice", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "registerKnownChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "removeReceiveTransceiverForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "removeSendTransceiverForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "removeTransceiver", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "reserveMessageSequence", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "sendMessage", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "setPeer", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "setReceiveTransceiverForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "setSendTransceiverForChain", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "setThreshold", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "setTransceiver", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "transceiverAttestedToMessage", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "transferOwnership", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "transferPauserCapability", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "unpause", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "upgrade", data: BytesLike): Result; +} + +export namespace AdminChangedEvent { + export type InputTuple = [previousAdmin: AddressLike, newAdmin: AddressLike]; + export type OutputTuple = [previousAdmin: string, newAdmin: string]; + export interface OutputObject { + previousAdmin: string; + newAdmin: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace BeaconUpgradedEvent { + export type InputTuple = [beacon: AddressLike]; + export type OutputTuple = [beacon: string]; + export interface OutputObject { + beacon: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace InitializedEvent { + export type InputTuple = [version: BigNumberish]; + export type OutputTuple = [version: bigint]; + export interface OutputObject { + version: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace MessageAlreadyExecutedEvent { + export type InputTuple = [sourceNttManager: BytesLike, msgHash: BytesLike]; + export type OutputTuple = [sourceNttManager: string, msgHash: string]; + export interface OutputObject { + sourceNttManager: string; + msgHash: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace MessageAttestedToEvent { + export type InputTuple = [ + digest: BytesLike, + transceiver: AddressLike, + index: BigNumberish + ]; + export type OutputTuple = [ + digest: string, + transceiver: string, + index: bigint + ]; + export interface OutputObject { + digest: string; + transceiver: string; + index: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace MessageExecutedEvent { + export type InputTuple = [ + messageHash: BytesLike, + sourceChain: BigNumberish, + sender: AddressLike, + callee: AddressLike, + data: BytesLike + ]; + export type OutputTuple = [ + messageHash: string, + sourceChain: bigint, + sender: string, + callee: string, + data: string + ]; + export interface OutputObject { + messageHash: string; + sourceChain: bigint; + sender: string; + callee: string; + data: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace MessageSentEvent { + export type InputTuple = [ + sequence: BigNumberish, + sender: AddressLike, + targetChain: BigNumberish, + callee: BytesLike, + data: BytesLike, + fee: BigNumberish + ]; + export type OutputTuple = [ + sequence: bigint, + sender: string, + targetChain: bigint, + callee: string, + data: string, + fee: bigint + ]; + export interface OutputObject { + sequence: bigint; + sender: string; + targetChain: bigint; + callee: string; + data: string; + fee: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace NotPausedEvent { + export type InputTuple = [notPaused: boolean]; + export type OutputTuple = [notPaused: boolean]; + export interface OutputObject { + notPaused: boolean; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace OwnershipTransferredEvent { + export type InputTuple = [previousOwner: AddressLike, newOwner: AddressLike]; + export type OutputTuple = [previousOwner: string, newOwner: string]; + export interface OutputObject { + previousOwner: string; + newOwner: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace PausedEvent { + export type InputTuple = [paused: boolean]; + export type OutputTuple = [paused: boolean]; + export interface OutputObject { + paused: boolean; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace PauserTransferredEvent { + export type InputTuple = [oldPauser: AddressLike, newPauser: AddressLike]; + export type OutputTuple = [oldPauser: string, newPauser: string]; + export interface OutputObject { + oldPauser: string; + newPauser: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace PeerUpdatedEvent { + export type InputTuple = [ + chainId: BigNumberish, + oldPeerAddress: BytesLike, + newPeerAddress: BytesLike + ]; + export type OutputTuple = [ + chainId: bigint, + oldPeerAddress: string, + newPeerAddress: string + ]; + export interface OutputObject { + chainId: bigint; + oldPeerAddress: string; + newPeerAddress: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace ReceiveTransceiverUpdatedForChainEvent { + export type InputTuple = [ + sourceChain: BigNumberish, + transceiver: AddressLike, + enabled: boolean + ]; + export type OutputTuple = [ + sourceChain: bigint, + transceiver: string, + enabled: boolean + ]; + export interface OutputObject { + sourceChain: bigint; + transceiver: string; + enabled: boolean; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace SendTransceiverUpdatedForChainEvent { + export type InputTuple = [ + targetChain: BigNumberish, + transceiver: AddressLike, + enabled: boolean + ]; + export type OutputTuple = [ + targetChain: bigint, + transceiver: string, + enabled: boolean + ]; + export interface OutputObject { + targetChain: bigint; + transceiver: string; + enabled: boolean; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace ThresholdChangedEvent { + export type InputTuple = [ + oldThreshold: BigNumberish, + threshold: BigNumberish + ]; + export type OutputTuple = [oldThreshold: bigint, threshold: bigint]; + export interface OutputObject { + oldThreshold: bigint; + threshold: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace ThresholdUpdatedForChainEvent { + export type InputTuple = [sourceChain: BigNumberish, threshold: BigNumberish]; + export type OutputTuple = [sourceChain: bigint, threshold: bigint]; + export interface OutputObject { + sourceChain: bigint; + threshold: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace TransceiverAddedEvent { + export type InputTuple = [ + transceiver: AddressLike, + transceiversNum: BigNumberish, + threshold: BigNumberish + ]; + export type OutputTuple = [ + transceiver: string, + transceiversNum: bigint, + threshold: bigint + ]; + export interface OutputObject { + transceiver: string; + transceiversNum: bigint; + threshold: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace TransceiverRemovedEvent { + export type InputTuple = [transceiver: AddressLike, threshold: BigNumberish]; + export type OutputTuple = [transceiver: string, threshold: bigint]; + export interface OutputObject { + transceiver: string; + threshold: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace UpgradedEvent { + export type InputTuple = [implementation: AddressLike]; + export type OutputTuple = [implementation: string]; + export interface OutputObject { + implementation: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export interface GmpManager extends BaseContract { + connect(runner?: ContractRunner | null): GmpManager; + waitForDeployment(): Promise; + + interface: GmpManagerInterface; + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on( + event: TCEvent, + listener: TypedListener + ): Promise; + on( + filter: TypedDeferredTopicFilter, + listener: TypedListener + ): Promise; + + once( + event: TCEvent, + listener: TypedListener + ): Promise; + once( + filter: TypedDeferredTopicFilter, + listener: TypedListener + ): Promise; + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise>; + removeAllListeners( + event?: TCEvent + ): Promise; + + GMP_MANAGER_VERSION: TypedContractMethod<[], [string], "view">; + + attestationReceived: TypedContractMethod< + [ + sourceChainId: BigNumberish, + sourceNttManagerAddress: BytesLike, + payload: TransceiverStructs.NttManagerMessageStruct + ], + [void], + "nonpayable" + >; + + chainId: TypedContractMethod<[], [bigint], "view">; + + executeMsg: TypedContractMethod< + [ + sourceChainId: BigNumberish, + sourceGmpManagerAddress: BytesLike, + message: TransceiverStructs.NttManagerMessageStruct + ], + [void], + "nonpayable" + >; + + getKnownChains: TypedContractMethod<[], [bigint[]], "view">; + + getMigratesImmutables: TypedContractMethod<[], [boolean], "view">; + + getPeer: TypedContractMethod< + [chainId_: BigNumberish], + [GmpManager.GmpPeerStructOutput], + "view" + >; + + getReceiveTransceiversForChain: TypedContractMethod< + [sourceChain: BigNumberish], + [[string[], bigint] & { transceivers: string[]; threshold: bigint }], + "view" + >; + + getReceiveTransceiversWithIndicesForChain: TypedContractMethod< + [sourceChain: BigNumberish], + [TransceiverRegistry.TransceiverWithIndexStructOutput[]], + "view" + >; + + getSendTransceiversForChain: TypedContractMethod< + [targetChain: BigNumberish], + [string[]], + "view" + >; + + getSendTransceiversWithIndicesForChain: TypedContractMethod< + [targetChain: BigNumberish], + [TransceiverRegistry.TransceiverWithIndexStructOutput[]], + "view" + >; + + getThreshold: TypedContractMethod< + [sourceChain: BigNumberish], + [bigint], + "view" + >; + + getTransceiverInfo: TypedContractMethod< + [], + [TransceiverRegistry.TransceiverInfoStructOutput[]], + "view" + >; + + getTransceivers: TypedContractMethod<[], [string[]], "view">; + + initialize: TypedContractMethod<[], [void], "payable">; + + isMessageApprovedForChain: TypedContractMethod< + [sourceChain: BigNumberish, digest: BytesLike], + [boolean], + "view" + >; + + isMessageExecuted: TypedContractMethod< + [digest: BytesLike], + [boolean], + "view" + >; + + isPaused: TypedContractMethod<[], [boolean], "view">; + + messageAttestations: TypedContractMethod< + [digest: BytesLike], + [bigint], + "view" + >; + + messageAttestationsForChain: TypedContractMethod< + [sourceChain: BigNumberish, digest: BytesLike], + [bigint], + "view" + >; + + migrate: TypedContractMethod<[], [void], "nonpayable">; + + nextMessageSequence: TypedContractMethod<[], [bigint], "view">; + + owner: TypedContractMethod<[], [string], "view">; + + pause: TypedContractMethod<[], [void], "nonpayable">; + + pauser: TypedContractMethod<[], [string], "view">; + + quoteDeliveryPrice: TypedContractMethod< + [recipientChain: BigNumberish, transceiverInstructions: BytesLike], + [[bigint[], bigint]], + "view" + >; + + registerKnownChain: TypedContractMethod< + [peerChainId: BigNumberish, peerAddress: BytesLike], + [void], + "nonpayable" + >; + + removeReceiveTransceiverForChain: TypedContractMethod< + [sourceChain: BigNumberish, transceiver: AddressLike], + [void], + "nonpayable" + >; + + removeSendTransceiverForChain: TypedContractMethod< + [targetChain: BigNumberish, transceiver: AddressLike], + [void], + "nonpayable" + >; + + removeTransceiver: TypedContractMethod< + [transceiver: AddressLike], + [void], + "nonpayable" + >; + + reserveMessageSequence: TypedContractMethod<[], [bigint], "nonpayable">; + + sendMessage: TypedContractMethod< + [ + targetChain: BigNumberish, + callee: BytesLike, + refundAddress: BytesLike, + reservedSequence: BigNumberish, + data: BytesLike, + transceiverInstructions: BytesLike + ], + [bigint], + "payable" + >; + + setPeer: TypedContractMethod< + [peerChainId: BigNumberish, peerAddress: BytesLike], + [void], + "nonpayable" + >; + + setReceiveTransceiverForChain: TypedContractMethod< + [sourceChain: BigNumberish, transceiver: AddressLike], + [void], + "nonpayable" + >; + + setSendTransceiverForChain: TypedContractMethod< + [targetChain: BigNumberish, transceiver: AddressLike], + [void], + "nonpayable" + >; + + setThreshold: TypedContractMethod< + [sourceChain: BigNumberish, threshold: BigNumberish], + [void], + "nonpayable" + >; + + setTransceiver: TypedContractMethod< + [transceiver: AddressLike], + [void], + "nonpayable" + >; + + transceiverAttestedToMessage: TypedContractMethod< + [digest: BytesLike, index: BigNumberish], + [boolean], + "view" + >; + + transferOwnership: TypedContractMethod< + [newOwner: AddressLike], + [void], + "nonpayable" + >; + + transferPauserCapability: TypedContractMethod< + [newPauser: AddressLike], + [void], + "nonpayable" + >; + + unpause: TypedContractMethod<[], [void], "nonpayable">; + + upgrade: TypedContractMethod< + [newImplementation: AddressLike], + [void], + "nonpayable" + >; + + getFunction( + key: string | FunctionFragment + ): T; + + getFunction( + nameOrSignature: "GMP_MANAGER_VERSION" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "attestationReceived" + ): TypedContractMethod< + [ + sourceChainId: BigNumberish, + sourceNttManagerAddress: BytesLike, + payload: TransceiverStructs.NttManagerMessageStruct + ], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "chainId" + ): TypedContractMethod<[], [bigint], "view">; + getFunction( + nameOrSignature: "executeMsg" + ): TypedContractMethod< + [ + sourceChainId: BigNumberish, + sourceGmpManagerAddress: BytesLike, + message: TransceiverStructs.NttManagerMessageStruct + ], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "getKnownChains" + ): TypedContractMethod<[], [bigint[]], "view">; + getFunction( + nameOrSignature: "getMigratesImmutables" + ): TypedContractMethod<[], [boolean], "view">; + getFunction( + nameOrSignature: "getPeer" + ): TypedContractMethod< + [chainId_: BigNumberish], + [GmpManager.GmpPeerStructOutput], + "view" + >; + getFunction( + nameOrSignature: "getReceiveTransceiversForChain" + ): TypedContractMethod< + [sourceChain: BigNumberish], + [[string[], bigint] & { transceivers: string[]; threshold: bigint }], + "view" + >; + getFunction( + nameOrSignature: "getReceiveTransceiversWithIndicesForChain" + ): TypedContractMethod< + [sourceChain: BigNumberish], + [TransceiverRegistry.TransceiverWithIndexStructOutput[]], + "view" + >; + getFunction( + nameOrSignature: "getSendTransceiversForChain" + ): TypedContractMethod<[targetChain: BigNumberish], [string[]], "view">; + getFunction( + nameOrSignature: "getSendTransceiversWithIndicesForChain" + ): TypedContractMethod< + [targetChain: BigNumberish], + [TransceiverRegistry.TransceiverWithIndexStructOutput[]], + "view" + >; + getFunction( + nameOrSignature: "getThreshold" + ): TypedContractMethod<[sourceChain: BigNumberish], [bigint], "view">; + getFunction( + nameOrSignature: "getTransceiverInfo" + ): TypedContractMethod< + [], + [TransceiverRegistry.TransceiverInfoStructOutput[]], + "view" + >; + getFunction( + nameOrSignature: "getTransceivers" + ): TypedContractMethod<[], [string[]], "view">; + getFunction( + nameOrSignature: "initialize" + ): TypedContractMethod<[], [void], "payable">; + getFunction( + nameOrSignature: "isMessageApprovedForChain" + ): TypedContractMethod< + [sourceChain: BigNumberish, digest: BytesLike], + [boolean], + "view" + >; + getFunction( + nameOrSignature: "isMessageExecuted" + ): TypedContractMethod<[digest: BytesLike], [boolean], "view">; + getFunction( + nameOrSignature: "isPaused" + ): TypedContractMethod<[], [boolean], "view">; + getFunction( + nameOrSignature: "messageAttestations" + ): TypedContractMethod<[digest: BytesLike], [bigint], "view">; + getFunction( + nameOrSignature: "messageAttestationsForChain" + ): TypedContractMethod< + [sourceChain: BigNumberish, digest: BytesLike], + [bigint], + "view" + >; + getFunction( + nameOrSignature: "migrate" + ): TypedContractMethod<[], [void], "nonpayable">; + getFunction( + nameOrSignature: "nextMessageSequence" + ): TypedContractMethod<[], [bigint], "view">; + getFunction( + nameOrSignature: "owner" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "pause" + ): TypedContractMethod<[], [void], "nonpayable">; + getFunction( + nameOrSignature: "pauser" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "quoteDeliveryPrice" + ): TypedContractMethod< + [recipientChain: BigNumberish, transceiverInstructions: BytesLike], + [[bigint[], bigint]], + "view" + >; + getFunction( + nameOrSignature: "registerKnownChain" + ): TypedContractMethod< + [peerChainId: BigNumberish, peerAddress: BytesLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "removeReceiveTransceiverForChain" + ): TypedContractMethod< + [sourceChain: BigNumberish, transceiver: AddressLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "removeSendTransceiverForChain" + ): TypedContractMethod< + [targetChain: BigNumberish, transceiver: AddressLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "removeTransceiver" + ): TypedContractMethod<[transceiver: AddressLike], [void], "nonpayable">; + getFunction( + nameOrSignature: "reserveMessageSequence" + ): TypedContractMethod<[], [bigint], "nonpayable">; + getFunction( + nameOrSignature: "sendMessage" + ): TypedContractMethod< + [ + targetChain: BigNumberish, + callee: BytesLike, + refundAddress: BytesLike, + reservedSequence: BigNumberish, + data: BytesLike, + transceiverInstructions: BytesLike + ], + [bigint], + "payable" + >; + getFunction( + nameOrSignature: "setPeer" + ): TypedContractMethod< + [peerChainId: BigNumberish, peerAddress: BytesLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "setReceiveTransceiverForChain" + ): TypedContractMethod< + [sourceChain: BigNumberish, transceiver: AddressLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "setSendTransceiverForChain" + ): TypedContractMethod< + [targetChain: BigNumberish, transceiver: AddressLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "setThreshold" + ): TypedContractMethod< + [sourceChain: BigNumberish, threshold: BigNumberish], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "setTransceiver" + ): TypedContractMethod<[transceiver: AddressLike], [void], "nonpayable">; + getFunction( + nameOrSignature: "transceiverAttestedToMessage" + ): TypedContractMethod< + [digest: BytesLike, index: BigNumberish], + [boolean], + "view" + >; + getFunction( + nameOrSignature: "transferOwnership" + ): TypedContractMethod<[newOwner: AddressLike], [void], "nonpayable">; + getFunction( + nameOrSignature: "transferPauserCapability" + ): TypedContractMethod<[newPauser: AddressLike], [void], "nonpayable">; + getFunction( + nameOrSignature: "unpause" + ): TypedContractMethod<[], [void], "nonpayable">; + getFunction( + nameOrSignature: "upgrade" + ): TypedContractMethod< + [newImplementation: AddressLike], + [void], + "nonpayable" + >; + + getEvent( + key: "AdminChanged" + ): TypedContractEvent< + AdminChangedEvent.InputTuple, + AdminChangedEvent.OutputTuple, + AdminChangedEvent.OutputObject + >; + getEvent( + key: "BeaconUpgraded" + ): TypedContractEvent< + BeaconUpgradedEvent.InputTuple, + BeaconUpgradedEvent.OutputTuple, + BeaconUpgradedEvent.OutputObject + >; + getEvent( + key: "Initialized" + ): TypedContractEvent< + InitializedEvent.InputTuple, + InitializedEvent.OutputTuple, + InitializedEvent.OutputObject + >; + getEvent( + key: "MessageAlreadyExecuted" + ): TypedContractEvent< + MessageAlreadyExecutedEvent.InputTuple, + MessageAlreadyExecutedEvent.OutputTuple, + MessageAlreadyExecutedEvent.OutputObject + >; + getEvent( + key: "MessageAttestedTo" + ): TypedContractEvent< + MessageAttestedToEvent.InputTuple, + MessageAttestedToEvent.OutputTuple, + MessageAttestedToEvent.OutputObject + >; + getEvent( + key: "MessageExecuted" + ): TypedContractEvent< + MessageExecutedEvent.InputTuple, + MessageExecutedEvent.OutputTuple, + MessageExecutedEvent.OutputObject + >; + getEvent( + key: "MessageSent" + ): TypedContractEvent< + MessageSentEvent.InputTuple, + MessageSentEvent.OutputTuple, + MessageSentEvent.OutputObject + >; + getEvent( + key: "NotPaused" + ): TypedContractEvent< + NotPausedEvent.InputTuple, + NotPausedEvent.OutputTuple, + NotPausedEvent.OutputObject + >; + getEvent( + key: "OwnershipTransferred" + ): TypedContractEvent< + OwnershipTransferredEvent.InputTuple, + OwnershipTransferredEvent.OutputTuple, + OwnershipTransferredEvent.OutputObject + >; + getEvent( + key: "Paused" + ): TypedContractEvent< + PausedEvent.InputTuple, + PausedEvent.OutputTuple, + PausedEvent.OutputObject + >; + getEvent( + key: "PauserTransferred" + ): TypedContractEvent< + PauserTransferredEvent.InputTuple, + PauserTransferredEvent.OutputTuple, + PauserTransferredEvent.OutputObject + >; + getEvent( + key: "PeerUpdated" + ): TypedContractEvent< + PeerUpdatedEvent.InputTuple, + PeerUpdatedEvent.OutputTuple, + PeerUpdatedEvent.OutputObject + >; + getEvent( + key: "ReceiveTransceiverUpdatedForChain" + ): TypedContractEvent< + ReceiveTransceiverUpdatedForChainEvent.InputTuple, + ReceiveTransceiverUpdatedForChainEvent.OutputTuple, + ReceiveTransceiverUpdatedForChainEvent.OutputObject + >; + getEvent( + key: "SendTransceiverUpdatedForChain" + ): TypedContractEvent< + SendTransceiverUpdatedForChainEvent.InputTuple, + SendTransceiverUpdatedForChainEvent.OutputTuple, + SendTransceiverUpdatedForChainEvent.OutputObject + >; + getEvent( + key: "ThresholdChanged" + ): TypedContractEvent< + ThresholdChangedEvent.InputTuple, + ThresholdChangedEvent.OutputTuple, + ThresholdChangedEvent.OutputObject + >; + getEvent( + key: "ThresholdUpdatedForChain" + ): TypedContractEvent< + ThresholdUpdatedForChainEvent.InputTuple, + ThresholdUpdatedForChainEvent.OutputTuple, + ThresholdUpdatedForChainEvent.OutputObject + >; + getEvent( + key: "TransceiverAdded" + ): TypedContractEvent< + TransceiverAddedEvent.InputTuple, + TransceiverAddedEvent.OutputTuple, + TransceiverAddedEvent.OutputObject + >; + getEvent( + key: "TransceiverRemoved" + ): TypedContractEvent< + TransceiverRemovedEvent.InputTuple, + TransceiverRemovedEvent.OutputTuple, + TransceiverRemovedEvent.OutputObject + >; + getEvent( + key: "Upgraded" + ): TypedContractEvent< + UpgradedEvent.InputTuple, + UpgradedEvent.OutputTuple, + UpgradedEvent.OutputObject + >; + + filters: { + "AdminChanged(address,address)": TypedContractEvent< + AdminChangedEvent.InputTuple, + AdminChangedEvent.OutputTuple, + AdminChangedEvent.OutputObject + >; + AdminChanged: TypedContractEvent< + AdminChangedEvent.InputTuple, + AdminChangedEvent.OutputTuple, + AdminChangedEvent.OutputObject + >; + + "BeaconUpgraded(address)": TypedContractEvent< + BeaconUpgradedEvent.InputTuple, + BeaconUpgradedEvent.OutputTuple, + BeaconUpgradedEvent.OutputObject + >; + BeaconUpgraded: TypedContractEvent< + BeaconUpgradedEvent.InputTuple, + BeaconUpgradedEvent.OutputTuple, + BeaconUpgradedEvent.OutputObject + >; + + "Initialized(uint64)": TypedContractEvent< + InitializedEvent.InputTuple, + InitializedEvent.OutputTuple, + InitializedEvent.OutputObject + >; + Initialized: TypedContractEvent< + InitializedEvent.InputTuple, + InitializedEvent.OutputTuple, + InitializedEvent.OutputObject + >; + + "MessageAlreadyExecuted(bytes32,bytes32)": TypedContractEvent< + MessageAlreadyExecutedEvent.InputTuple, + MessageAlreadyExecutedEvent.OutputTuple, + MessageAlreadyExecutedEvent.OutputObject + >; + MessageAlreadyExecuted: TypedContractEvent< + MessageAlreadyExecutedEvent.InputTuple, + MessageAlreadyExecutedEvent.OutputTuple, + MessageAlreadyExecutedEvent.OutputObject + >; + + "MessageAttestedTo(bytes32,address,uint8)": TypedContractEvent< + MessageAttestedToEvent.InputTuple, + MessageAttestedToEvent.OutputTuple, + MessageAttestedToEvent.OutputObject + >; + MessageAttestedTo: TypedContractEvent< + MessageAttestedToEvent.InputTuple, + MessageAttestedToEvent.OutputTuple, + MessageAttestedToEvent.OutputObject + >; + + "MessageExecuted(bytes32,uint16,address,address,bytes)": TypedContractEvent< + MessageExecutedEvent.InputTuple, + MessageExecutedEvent.OutputTuple, + MessageExecutedEvent.OutputObject + >; + MessageExecuted: TypedContractEvent< + MessageExecutedEvent.InputTuple, + MessageExecutedEvent.OutputTuple, + MessageExecutedEvent.OutputObject + >; + + "MessageSent(uint64,address,uint16,bytes32,bytes,uint256)": TypedContractEvent< + MessageSentEvent.InputTuple, + MessageSentEvent.OutputTuple, + MessageSentEvent.OutputObject + >; + MessageSent: TypedContractEvent< + MessageSentEvent.InputTuple, + MessageSentEvent.OutputTuple, + MessageSentEvent.OutputObject + >; + + "NotPaused(bool)": TypedContractEvent< + NotPausedEvent.InputTuple, + NotPausedEvent.OutputTuple, + NotPausedEvent.OutputObject + >; + NotPaused: TypedContractEvent< + NotPausedEvent.InputTuple, + NotPausedEvent.OutputTuple, + NotPausedEvent.OutputObject + >; + + "OwnershipTransferred(address,address)": TypedContractEvent< + OwnershipTransferredEvent.InputTuple, + OwnershipTransferredEvent.OutputTuple, + OwnershipTransferredEvent.OutputObject + >; + OwnershipTransferred: TypedContractEvent< + OwnershipTransferredEvent.InputTuple, + OwnershipTransferredEvent.OutputTuple, + OwnershipTransferredEvent.OutputObject + >; + + "Paused(bool)": TypedContractEvent< + PausedEvent.InputTuple, + PausedEvent.OutputTuple, + PausedEvent.OutputObject + >; + Paused: TypedContractEvent< + PausedEvent.InputTuple, + PausedEvent.OutputTuple, + PausedEvent.OutputObject + >; + + "PauserTransferred(address,address)": TypedContractEvent< + PauserTransferredEvent.InputTuple, + PauserTransferredEvent.OutputTuple, + PauserTransferredEvent.OutputObject + >; + PauserTransferred: TypedContractEvent< + PauserTransferredEvent.InputTuple, + PauserTransferredEvent.OutputTuple, + PauserTransferredEvent.OutputObject + >; + + "PeerUpdated(uint16,bytes32,bytes32)": TypedContractEvent< + PeerUpdatedEvent.InputTuple, + PeerUpdatedEvent.OutputTuple, + PeerUpdatedEvent.OutputObject + >; + PeerUpdated: TypedContractEvent< + PeerUpdatedEvent.InputTuple, + PeerUpdatedEvent.OutputTuple, + PeerUpdatedEvent.OutputObject + >; + + "ReceiveTransceiverUpdatedForChain(uint16,address,bool)": TypedContractEvent< + ReceiveTransceiverUpdatedForChainEvent.InputTuple, + ReceiveTransceiverUpdatedForChainEvent.OutputTuple, + ReceiveTransceiverUpdatedForChainEvent.OutputObject + >; + ReceiveTransceiverUpdatedForChain: TypedContractEvent< + ReceiveTransceiverUpdatedForChainEvent.InputTuple, + ReceiveTransceiverUpdatedForChainEvent.OutputTuple, + ReceiveTransceiverUpdatedForChainEvent.OutputObject + >; + + "SendTransceiverUpdatedForChain(uint16,address,bool)": TypedContractEvent< + SendTransceiverUpdatedForChainEvent.InputTuple, + SendTransceiverUpdatedForChainEvent.OutputTuple, + SendTransceiverUpdatedForChainEvent.OutputObject + >; + SendTransceiverUpdatedForChain: TypedContractEvent< + SendTransceiverUpdatedForChainEvent.InputTuple, + SendTransceiverUpdatedForChainEvent.OutputTuple, + SendTransceiverUpdatedForChainEvent.OutputObject + >; + + "ThresholdChanged(uint8,uint8)": TypedContractEvent< + ThresholdChangedEvent.InputTuple, + ThresholdChangedEvent.OutputTuple, + ThresholdChangedEvent.OutputObject + >; + ThresholdChanged: TypedContractEvent< + ThresholdChangedEvent.InputTuple, + ThresholdChangedEvent.OutputTuple, + ThresholdChangedEvent.OutputObject + >; + + "ThresholdUpdatedForChain(uint16,uint8)": TypedContractEvent< + ThresholdUpdatedForChainEvent.InputTuple, + ThresholdUpdatedForChainEvent.OutputTuple, + ThresholdUpdatedForChainEvent.OutputObject + >; + ThresholdUpdatedForChain: TypedContractEvent< + ThresholdUpdatedForChainEvent.InputTuple, + ThresholdUpdatedForChainEvent.OutputTuple, + ThresholdUpdatedForChainEvent.OutputObject + >; + + "TransceiverAdded(address,uint256,uint8)": TypedContractEvent< + TransceiverAddedEvent.InputTuple, + TransceiverAddedEvent.OutputTuple, + TransceiverAddedEvent.OutputObject + >; + TransceiverAdded: TypedContractEvent< + TransceiverAddedEvent.InputTuple, + TransceiverAddedEvent.OutputTuple, + TransceiverAddedEvent.OutputObject + >; + + "TransceiverRemoved(address,uint8)": TypedContractEvent< + TransceiverRemovedEvent.InputTuple, + TransceiverRemovedEvent.OutputTuple, + TransceiverRemovedEvent.OutputObject + >; + TransceiverRemoved: TypedContractEvent< + TransceiverRemovedEvent.InputTuple, + TransceiverRemovedEvent.OutputTuple, + TransceiverRemovedEvent.OutputObject + >; + + "Upgraded(address)": TypedContractEvent< + UpgradedEvent.InputTuple, + UpgradedEvent.OutputTuple, + UpgradedEvent.OutputObject + >; + Upgraded: TypedContractEvent< + UpgradedEvent.InputTuple, + UpgradedEvent.OutputTuple, + UpgradedEvent.OutputObject + >; + }; +} diff --git a/evm/ts/src/ethers-contracts/1_1_0/MultiTokenNtt.ts b/evm/ts/src/ethers-contracts/1_1_0/MultiTokenNtt.ts new file mode 100644 index 000000000..5d09e88b4 --- /dev/null +++ b/evm/ts/src/ethers-contracts/1_1_0/MultiTokenNtt.ts @@ -0,0 +1,1467 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { + BaseContract, + BigNumberish, + BytesLike, + FunctionFragment, + Result, + Interface, + EventFragment, + AddressLike, + ContractRunner, + ContractMethod, + Listener, +} from "ethers"; +import type { + TypedContractEvent, + TypedDeferredTopicFilter, + TypedEventLog, + TypedLogDescription, + TypedListener, + TypedContractMethod, +} from "./common.js"; + +export type TokenMetaStruct = { + name: BytesLike; + symbol: BytesLike; + decimals: BigNumberish; +}; + +export type TokenMetaStructOutput = [ + name: string, + symbol: string, + decimals: bigint +] & { name: string; symbol: string; decimals: bigint }; + +export type TokenIdStruct = { chainId: BigNumberish; tokenAddress: BytesLike }; + +export type TokenIdStructOutput = [chainId: bigint, tokenAddress: string] & { + chainId: bigint; + tokenAddress: string; +}; + +export type TokenInfoStruct = { meta: TokenMetaStruct; token: TokenIdStruct }; + +export type TokenInfoStructOutput = [ + meta: TokenMetaStructOutput, + token: TokenIdStructOutput +] & { meta: TokenMetaStructOutput; token: TokenIdStructOutput }; + +export declare namespace NativeTokenTransferCodec { + export type NativeTokenTransferStruct = { + amount: BigNumberish; + token: TokenInfoStruct; + sender: BytesLike; + to: BytesLike; + additionalPayload: BytesLike; + }; + + export type NativeTokenTransferStructOutput = [ + amount: bigint, + token: TokenInfoStructOutput, + sender: string, + to: string, + additionalPayload: string + ] & { + amount: bigint; + token: TokenInfoStructOutput; + sender: string; + to: string; + additionalPayload: string; + }; +} + +export declare namespace RateLimitLib { + export type RateLimitParamsStruct = { + limit: BigNumberish; + currentCapacity: BigNumberish; + lastTxTimestamp: BigNumberish; + }; + + export type RateLimitParamsStructOutput = [ + limit: bigint, + currentCapacity: bigint, + lastTxTimestamp: bigint + ] & { limit: bigint; currentCapacity: bigint; lastTxTimestamp: bigint }; +} + +export declare namespace IMultiTokenRateLimiter { + export type InboundQueuedTransferStruct = { + txTimestamp: BigNumberish; + sourceChainId: BigNumberish; + transferDigest: BytesLike; + }; + + export type InboundQueuedTransferStructOutput = [ + txTimestamp: bigint, + sourceChainId: bigint, + transferDigest: string + ] & { txTimestamp: bigint; sourceChainId: bigint; transferDigest: string }; + + export type OutboundQueuedTransferStruct = { + recipient: BytesLike; + refundAddress: BytesLike; + sender: AddressLike; + amount: BigNumberish; + recipientChain: BigNumberish; + txTimestamp: BigNumberish; + token: AddressLike; + transceiverInstructions: BytesLike; + }; + + export type OutboundQueuedTransferStructOutput = [ + recipient: string, + refundAddress: string, + sender: string, + amount: bigint, + recipientChain: bigint, + txTimestamp: bigint, + token: string, + transceiverInstructions: string + ] & { + recipient: string; + refundAddress: string; + sender: string; + amount: bigint; + recipientChain: bigint; + txTimestamp: bigint; + token: string; + transceiverInstructions: string; + }; +} + +export declare namespace Peers { + export type PeerStruct = { peerAddress: BytesLike }; + + export type PeerStructOutput = [peerAddress: string] & { + peerAddress: string; + }; +} + +export declare namespace MultiTokenNtt { + export type TransferArgsStruct = { + token: AddressLike; + amount: BigNumberish; + recipientChain: BigNumberish; + recipient: BytesLike; + refundAddress: BytesLike; + shouldQueue: boolean; + transceiverInstructions: BytesLike; + additionalPayload: BytesLike; + }; + + export type TransferArgsStructOutput = [ + token: string, + amount: bigint, + recipientChain: bigint, + recipient: string, + refundAddress: string, + shouldQueue: boolean, + transceiverInstructions: string, + additionalPayload: string + ] & { + token: string; + amount: bigint; + recipientChain: bigint; + recipient: string; + refundAddress: string; + shouldQueue: boolean; + transceiverInstructions: string; + additionalPayload: string; + }; + + export type GasTokenTransferArgsStruct = { + amount: BigNumberish; + recipientChain: BigNumberish; + recipient: BytesLike; + refundAddress: BytesLike; + shouldQueue: boolean; + transceiverInstructions: BytesLike; + additionalPayload: BytesLike; + }; + + export type GasTokenTransferArgsStructOutput = [ + amount: bigint, + recipientChain: bigint, + recipient: string, + refundAddress: string, + shouldQueue: boolean, + transceiverInstructions: string, + additionalPayload: string + ] & { + amount: bigint; + recipientChain: bigint; + recipient: string; + refundAddress: string; + shouldQueue: boolean; + transceiverInstructions: string; + additionalPayload: string; + }; +} + +export interface MultiTokenNttInterface extends Interface { + getFunction( + nameOrSignature: + | "NTT_MANAGER_VERSION" + | "WETH" + | "cancelOutboundQueuedTransfer" + | "completeInboundQueuedTransfer" + | "completeOutboundQueuedTransfer" + | "getCurrentInboundCapacity" + | "getCurrentOutboundCapacity" + | "getInboundLimitParams" + | "getInboundQueuedTransfer" + | "getMigratesImmutables" + | "getOutboundLimitParams" + | "getOutboundQueuedTransfer" + | "getPeer" + | "getToken" + | "getTokenId" + | "gmpManager" + | "initialize" + | "isPaused" + | "migrate" + | "overrideLocalAsset" + | "owner" + | "pause" + | "pauser" + | "rateLimitDuration" + | "receiveMessage" + | "setInboundLimit" + | "setOutboundLimit" + | "setPeer" + | "tokenImplementation" + | "tokenProxyCreationCode" + | "transfer" + | "transferOwnership" + | "transferPauserCapability" + | "unpause" + | "upgrade" + | "wrapAndTransferGasToken" + ): FunctionFragment; + + getEvent( + nameOrSignatureOrTopic: + | "AdminChanged" + | "BeaconUpgraded" + | "InboundTransferLimitUpdated" + | "InboundTransferQueued" + | "Initialized" + | "NotPaused" + | "OutboundTransferCancelled" + | "OutboundTransferLimitUpdated" + | "OutboundTransferQueued" + | "OutboundTransferRateLimited" + | "OwnershipTransferred" + | "Paused" + | "PauserTransferred" + | "PeerUpdated" + | "TransferRedeemed" + | "TransferSent" + | "Upgraded" + ): EventFragment; + + encodeFunctionData( + functionFragment: "NTT_MANAGER_VERSION", + values?: undefined + ): string; + encodeFunctionData(functionFragment: "WETH", values?: undefined): string; + encodeFunctionData( + functionFragment: "cancelOutboundQueuedTransfer", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "completeInboundQueuedTransfer", + values: [BytesLike, NativeTokenTransferCodec.NativeTokenTransferStruct] + ): string; + encodeFunctionData( + functionFragment: "completeOutboundQueuedTransfer", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getCurrentInboundCapacity", + values: [TokenIdStruct, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getCurrentOutboundCapacity", + values: [TokenIdStruct] + ): string; + encodeFunctionData( + functionFragment: "getInboundLimitParams", + values: [TokenIdStruct, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getInboundQueuedTransfer", + values: [BytesLike] + ): string; + encodeFunctionData( + functionFragment: "getMigratesImmutables", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "getOutboundLimitParams", + values: [TokenIdStruct] + ): string; + encodeFunctionData( + functionFragment: "getOutboundQueuedTransfer", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getPeer", + values: [BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "getToken", + values: [TokenIdStruct] + ): string; + encodeFunctionData( + functionFragment: "getTokenId", + values: [AddressLike] + ): string; + encodeFunctionData( + functionFragment: "gmpManager", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "initialize", + values?: undefined + ): string; + encodeFunctionData(functionFragment: "isPaused", values?: undefined): string; + encodeFunctionData(functionFragment: "migrate", values?: undefined): string; + encodeFunctionData( + functionFragment: "overrideLocalAsset", + values: [TokenIdStruct, AddressLike] + ): string; + encodeFunctionData(functionFragment: "owner", values?: undefined): string; + encodeFunctionData(functionFragment: "pause", values?: undefined): string; + encodeFunctionData(functionFragment: "pauser", values?: undefined): string; + encodeFunctionData( + functionFragment: "rateLimitDuration", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "receiveMessage", + values: [BytesLike, BigNumberish, BytesLike, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "setInboundLimit", + values: [TokenIdStruct, BigNumberish, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "setOutboundLimit", + values: [TokenIdStruct, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "setPeer", + values: [BigNumberish, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "tokenImplementation", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "tokenProxyCreationCode", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "transfer", + values: [MultiTokenNtt.TransferArgsStruct] + ): string; + encodeFunctionData( + functionFragment: "transferOwnership", + values: [AddressLike] + ): string; + encodeFunctionData( + functionFragment: "transferPauserCapability", + values: [AddressLike] + ): string; + encodeFunctionData(functionFragment: "unpause", values?: undefined): string; + encodeFunctionData( + functionFragment: "upgrade", + values: [AddressLike] + ): string; + encodeFunctionData( + functionFragment: "wrapAndTransferGasToken", + values: [MultiTokenNtt.GasTokenTransferArgsStruct] + ): string; + + decodeFunctionResult( + functionFragment: "NTT_MANAGER_VERSION", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "WETH", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "cancelOutboundQueuedTransfer", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "completeInboundQueuedTransfer", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "completeOutboundQueuedTransfer", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getCurrentInboundCapacity", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getCurrentOutboundCapacity", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getInboundLimitParams", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getInboundQueuedTransfer", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getMigratesImmutables", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getOutboundLimitParams", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "getOutboundQueuedTransfer", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "getPeer", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "getToken", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "getTokenId", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "gmpManager", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "initialize", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "isPaused", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "migrate", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "overrideLocalAsset", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "owner", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "pause", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "pauser", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "rateLimitDuration", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "receiveMessage", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "setInboundLimit", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "setOutboundLimit", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "setPeer", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "tokenImplementation", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "tokenProxyCreationCode", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "transfer", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "transferOwnership", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "transferPauserCapability", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "unpause", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "upgrade", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "wrapAndTransferGasToken", + data: BytesLike + ): Result; +} + +export namespace AdminChangedEvent { + export type InputTuple = [previousAdmin: AddressLike, newAdmin: AddressLike]; + export type OutputTuple = [previousAdmin: string, newAdmin: string]; + export interface OutputObject { + previousAdmin: string; + newAdmin: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace BeaconUpgradedEvent { + export type InputTuple = [beacon: AddressLike]; + export type OutputTuple = [beacon: string]; + export interface OutputObject { + beacon: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace InboundTransferLimitUpdatedEvent { + export type InputTuple = [ + chainId: BigNumberish, + oldLimit: BigNumberish, + newLimit: BigNumberish + ]; + export type OutputTuple = [ + chainId: bigint, + oldLimit: bigint, + newLimit: bigint + ]; + export interface OutputObject { + chainId: bigint; + oldLimit: bigint; + newLimit: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace InboundTransferQueuedEvent { + export type InputTuple = [digest: BytesLike]; + export type OutputTuple = [digest: string]; + export interface OutputObject { + digest: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace InitializedEvent { + export type InputTuple = [version: BigNumberish]; + export type OutputTuple = [version: bigint]; + export interface OutputObject { + version: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace NotPausedEvent { + export type InputTuple = [notPaused: boolean]; + export type OutputTuple = [notPaused: boolean]; + export interface OutputObject { + notPaused: boolean; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace OutboundTransferCancelledEvent { + export type InputTuple = [ + sequence: BigNumberish, + recipient: AddressLike, + amount: BigNumberish + ]; + export type OutputTuple = [ + sequence: bigint, + recipient: string, + amount: bigint + ]; + export interface OutputObject { + sequence: bigint; + recipient: string; + amount: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace OutboundTransferLimitUpdatedEvent { + export type InputTuple = [oldLimit: BigNumberish, newLimit: BigNumberish]; + export type OutputTuple = [oldLimit: bigint, newLimit: bigint]; + export interface OutputObject { + oldLimit: bigint; + newLimit: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace OutboundTransferQueuedEvent { + export type InputTuple = [queueSequence: BigNumberish]; + export type OutputTuple = [queueSequence: bigint]; + export interface OutputObject { + queueSequence: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace OutboundTransferRateLimitedEvent { + export type InputTuple = [ + sender: AddressLike, + sequence: BigNumberish, + amount: BigNumberish, + currentCapacity: BigNumberish + ]; + export type OutputTuple = [ + sender: string, + sequence: bigint, + amount: bigint, + currentCapacity: bigint + ]; + export interface OutputObject { + sender: string; + sequence: bigint; + amount: bigint; + currentCapacity: bigint; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace OwnershipTransferredEvent { + export type InputTuple = [previousOwner: AddressLike, newOwner: AddressLike]; + export type OutputTuple = [previousOwner: string, newOwner: string]; + export interface OutputObject { + previousOwner: string; + newOwner: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace PausedEvent { + export type InputTuple = [paused: boolean]; + export type OutputTuple = [paused: boolean]; + export interface OutputObject { + paused: boolean; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace PauserTransferredEvent { + export type InputTuple = [oldPauser: AddressLike, newPauser: AddressLike]; + export type OutputTuple = [oldPauser: string, newPauser: string]; + export interface OutputObject { + oldPauser: string; + newPauser: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace PeerUpdatedEvent { + export type InputTuple = [ + chainId: BigNumberish, + oldPeerAddress: BytesLike, + newPeerAddress: BytesLike + ]; + export type OutputTuple = [ + chainId: bigint, + oldPeerAddress: string, + newPeerAddress: string + ]; + export interface OutputObject { + chainId: bigint; + oldPeerAddress: string; + newPeerAddress: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace TransferRedeemedEvent { + export type InputTuple = [digest: BytesLike]; + export type OutputTuple = [digest: string]; + export interface OutputObject { + digest: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace TransferSentEvent { + export type InputTuple = [ + sequence: BigNumberish, + tokenChain: BigNumberish, + token: BytesLike, + recipient: BytesLike, + refundAddress: BytesLike, + amount: BigNumberish, + toChain: BigNumberish, + sender: AddressLike + ]; + export type OutputTuple = [ + sequence: bigint, + tokenChain: bigint, + token: string, + recipient: string, + refundAddress: string, + amount: bigint, + toChain: bigint, + sender: string + ]; + export interface OutputObject { + sequence: bigint; + tokenChain: bigint; + token: string; + recipient: string; + refundAddress: string; + amount: bigint; + toChain: bigint; + sender: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export namespace UpgradedEvent { + export type InputTuple = [implementation: AddressLike]; + export type OutputTuple = [implementation: string]; + export interface OutputObject { + implementation: string; + } + export type Event = TypedContractEvent; + export type Filter = TypedDeferredTopicFilter; + export type Log = TypedEventLog; + export type LogDescription = TypedLogDescription; +} + +export interface MultiTokenNtt extends BaseContract { + connect(runner?: ContractRunner | null): MultiTokenNtt; + waitForDeployment(): Promise; + + interface: MultiTokenNttInterface; + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on( + event: TCEvent, + listener: TypedListener + ): Promise; + on( + filter: TypedDeferredTopicFilter, + listener: TypedListener + ): Promise; + + once( + event: TCEvent, + listener: TypedListener + ): Promise; + once( + filter: TypedDeferredTopicFilter, + listener: TypedListener + ): Promise; + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise>; + removeAllListeners( + event?: TCEvent + ): Promise; + + NTT_MANAGER_VERSION: TypedContractMethod<[], [string], "view">; + + WETH: TypedContractMethod<[], [string], "view">; + + cancelOutboundQueuedTransfer: TypedContractMethod< + [messageSequence: BigNumberish], + [void], + "nonpayable" + >; + + completeInboundQueuedTransfer: TypedContractMethod< + [ + digest: BytesLike, + nativeTokenTransfer: NativeTokenTransferCodec.NativeTokenTransferStruct + ], + [void], + "nonpayable" + >; + + completeOutboundQueuedTransfer: TypedContractMethod< + [messageSequence: BigNumberish], + [bigint], + "payable" + >; + + getCurrentInboundCapacity: TypedContractMethod< + [tokenId: TokenIdStruct, chainId_: BigNumberish], + [bigint], + "view" + >; + + getCurrentOutboundCapacity: TypedContractMethod< + [tokenId: TokenIdStruct], + [bigint], + "view" + >; + + getInboundLimitParams: TypedContractMethod< + [tokenId: TokenIdStruct, chainId_: BigNumberish], + [RateLimitLib.RateLimitParamsStructOutput], + "view" + >; + + getInboundQueuedTransfer: TypedContractMethod< + [digest: BytesLike], + [IMultiTokenRateLimiter.InboundQueuedTransferStructOutput], + "view" + >; + + getMigratesImmutables: TypedContractMethod<[], [boolean], "view">; + + getOutboundLimitParams: TypedContractMethod< + [tokenId: TokenIdStruct], + [RateLimitLib.RateLimitParamsStructOutput], + "view" + >; + + getOutboundQueuedTransfer: TypedContractMethod< + [queueSequence: BigNumberish], + [IMultiTokenRateLimiter.OutboundQueuedTransferStructOutput], + "view" + >; + + getPeer: TypedContractMethod< + [chainId_: BigNumberish], + [Peers.PeerStructOutput], + "view" + >; + + getToken: TypedContractMethod<[tokenId: TokenIdStruct], [string], "view">; + + getTokenId: TypedContractMethod< + [token: AddressLike], + [[TokenIdStructOutput, bigint]], + "view" + >; + + gmpManager: TypedContractMethod<[], [string], "view">; + + initialize: TypedContractMethod<[], [void], "payable">; + + isPaused: TypedContractMethod<[], [boolean], "view">; + + migrate: TypedContractMethod<[], [void], "nonpayable">; + + overrideLocalAsset: TypedContractMethod< + [token: TokenIdStruct, localToken: AddressLike], + [void], + "nonpayable" + >; + + owner: TypedContractMethod<[], [string], "view">; + + pause: TypedContractMethod<[], [void], "nonpayable">; + + pauser: TypedContractMethod<[], [string], "view">; + + rateLimitDuration: TypedContractMethod<[], [bigint], "view">; + + receiveMessage: TypedContractMethod< + [ + digest: BytesLike, + sourceChainId: BigNumberish, + sender: BytesLike, + data: BytesLike + ], + [void], + "nonpayable" + >; + + setInboundLimit: TypedContractMethod< + [token: TokenIdStruct, limit: BigNumberish, chainId_: BigNumberish], + [void], + "nonpayable" + >; + + setOutboundLimit: TypedContractMethod< + [token: TokenIdStruct, limit: BigNumberish], + [void], + "nonpayable" + >; + + setPeer: TypedContractMethod< + [_chainId: BigNumberish, peerAddress: BytesLike], + [void], + "nonpayable" + >; + + tokenImplementation: TypedContractMethod<[], [string], "view">; + + tokenProxyCreationCode: TypedContractMethod<[], [string], "view">; + + transfer: TypedContractMethod< + [args: MultiTokenNtt.TransferArgsStruct], + [bigint], + "payable" + >; + + transferOwnership: TypedContractMethod< + [newOwner: AddressLike], + [void], + "nonpayable" + >; + + transferPauserCapability: TypedContractMethod< + [newPauser: AddressLike], + [void], + "nonpayable" + >; + + unpause: TypedContractMethod<[], [void], "nonpayable">; + + upgrade: TypedContractMethod< + [newImplementation: AddressLike], + [void], + "nonpayable" + >; + + wrapAndTransferGasToken: TypedContractMethod< + [args: MultiTokenNtt.GasTokenTransferArgsStruct], + [bigint], + "payable" + >; + + getFunction( + key: string | FunctionFragment + ): T; + + getFunction( + nameOrSignature: "NTT_MANAGER_VERSION" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "WETH" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "cancelOutboundQueuedTransfer" + ): TypedContractMethod<[messageSequence: BigNumberish], [void], "nonpayable">; + getFunction( + nameOrSignature: "completeInboundQueuedTransfer" + ): TypedContractMethod< + [ + digest: BytesLike, + nativeTokenTransfer: NativeTokenTransferCodec.NativeTokenTransferStruct + ], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "completeOutboundQueuedTransfer" + ): TypedContractMethod<[messageSequence: BigNumberish], [bigint], "payable">; + getFunction( + nameOrSignature: "getCurrentInboundCapacity" + ): TypedContractMethod< + [tokenId: TokenIdStruct, chainId_: BigNumberish], + [bigint], + "view" + >; + getFunction( + nameOrSignature: "getCurrentOutboundCapacity" + ): TypedContractMethod<[tokenId: TokenIdStruct], [bigint], "view">; + getFunction( + nameOrSignature: "getInboundLimitParams" + ): TypedContractMethod< + [tokenId: TokenIdStruct, chainId_: BigNumberish], + [RateLimitLib.RateLimitParamsStructOutput], + "view" + >; + getFunction( + nameOrSignature: "getInboundQueuedTransfer" + ): TypedContractMethod< + [digest: BytesLike], + [IMultiTokenRateLimiter.InboundQueuedTransferStructOutput], + "view" + >; + getFunction( + nameOrSignature: "getMigratesImmutables" + ): TypedContractMethod<[], [boolean], "view">; + getFunction( + nameOrSignature: "getOutboundLimitParams" + ): TypedContractMethod< + [tokenId: TokenIdStruct], + [RateLimitLib.RateLimitParamsStructOutput], + "view" + >; + getFunction( + nameOrSignature: "getOutboundQueuedTransfer" + ): TypedContractMethod< + [queueSequence: BigNumberish], + [IMultiTokenRateLimiter.OutboundQueuedTransferStructOutput], + "view" + >; + getFunction( + nameOrSignature: "getPeer" + ): TypedContractMethod< + [chainId_: BigNumberish], + [Peers.PeerStructOutput], + "view" + >; + getFunction( + nameOrSignature: "getToken" + ): TypedContractMethod<[tokenId: TokenIdStruct], [string], "view">; + getFunction( + nameOrSignature: "getTokenId" + ): TypedContractMethod< + [token: AddressLike], + [[TokenIdStructOutput, bigint]], + "view" + >; + getFunction( + nameOrSignature: "gmpManager" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "initialize" + ): TypedContractMethod<[], [void], "payable">; + getFunction( + nameOrSignature: "isPaused" + ): TypedContractMethod<[], [boolean], "view">; + getFunction( + nameOrSignature: "migrate" + ): TypedContractMethod<[], [void], "nonpayable">; + getFunction( + nameOrSignature: "overrideLocalAsset" + ): TypedContractMethod< + [token: TokenIdStruct, localToken: AddressLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "owner" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "pause" + ): TypedContractMethod<[], [void], "nonpayable">; + getFunction( + nameOrSignature: "pauser" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "rateLimitDuration" + ): TypedContractMethod<[], [bigint], "view">; + getFunction( + nameOrSignature: "receiveMessage" + ): TypedContractMethod< + [ + digest: BytesLike, + sourceChainId: BigNumberish, + sender: BytesLike, + data: BytesLike + ], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "setInboundLimit" + ): TypedContractMethod< + [token: TokenIdStruct, limit: BigNumberish, chainId_: BigNumberish], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "setOutboundLimit" + ): TypedContractMethod< + [token: TokenIdStruct, limit: BigNumberish], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "setPeer" + ): TypedContractMethod< + [_chainId: BigNumberish, peerAddress: BytesLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "tokenImplementation" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "tokenProxyCreationCode" + ): TypedContractMethod<[], [string], "view">; + getFunction( + nameOrSignature: "transfer" + ): TypedContractMethod< + [args: MultiTokenNtt.TransferArgsStruct], + [bigint], + "payable" + >; + getFunction( + nameOrSignature: "transferOwnership" + ): TypedContractMethod<[newOwner: AddressLike], [void], "nonpayable">; + getFunction( + nameOrSignature: "transferPauserCapability" + ): TypedContractMethod<[newPauser: AddressLike], [void], "nonpayable">; + getFunction( + nameOrSignature: "unpause" + ): TypedContractMethod<[], [void], "nonpayable">; + getFunction( + nameOrSignature: "upgrade" + ): TypedContractMethod< + [newImplementation: AddressLike], + [void], + "nonpayable" + >; + getFunction( + nameOrSignature: "wrapAndTransferGasToken" + ): TypedContractMethod< + [args: MultiTokenNtt.GasTokenTransferArgsStruct], + [bigint], + "payable" + >; + + getEvent( + key: "AdminChanged" + ): TypedContractEvent< + AdminChangedEvent.InputTuple, + AdminChangedEvent.OutputTuple, + AdminChangedEvent.OutputObject + >; + getEvent( + key: "BeaconUpgraded" + ): TypedContractEvent< + BeaconUpgradedEvent.InputTuple, + BeaconUpgradedEvent.OutputTuple, + BeaconUpgradedEvent.OutputObject + >; + getEvent( + key: "InboundTransferLimitUpdated" + ): TypedContractEvent< + InboundTransferLimitUpdatedEvent.InputTuple, + InboundTransferLimitUpdatedEvent.OutputTuple, + InboundTransferLimitUpdatedEvent.OutputObject + >; + getEvent( + key: "InboundTransferQueued" + ): TypedContractEvent< + InboundTransferQueuedEvent.InputTuple, + InboundTransferQueuedEvent.OutputTuple, + InboundTransferQueuedEvent.OutputObject + >; + getEvent( + key: "Initialized" + ): TypedContractEvent< + InitializedEvent.InputTuple, + InitializedEvent.OutputTuple, + InitializedEvent.OutputObject + >; + getEvent( + key: "NotPaused" + ): TypedContractEvent< + NotPausedEvent.InputTuple, + NotPausedEvent.OutputTuple, + NotPausedEvent.OutputObject + >; + getEvent( + key: "OutboundTransferCancelled" + ): TypedContractEvent< + OutboundTransferCancelledEvent.InputTuple, + OutboundTransferCancelledEvent.OutputTuple, + OutboundTransferCancelledEvent.OutputObject + >; + getEvent( + key: "OutboundTransferLimitUpdated" + ): TypedContractEvent< + OutboundTransferLimitUpdatedEvent.InputTuple, + OutboundTransferLimitUpdatedEvent.OutputTuple, + OutboundTransferLimitUpdatedEvent.OutputObject + >; + getEvent( + key: "OutboundTransferQueued" + ): TypedContractEvent< + OutboundTransferQueuedEvent.InputTuple, + OutboundTransferQueuedEvent.OutputTuple, + OutboundTransferQueuedEvent.OutputObject + >; + getEvent( + key: "OutboundTransferRateLimited" + ): TypedContractEvent< + OutboundTransferRateLimitedEvent.InputTuple, + OutboundTransferRateLimitedEvent.OutputTuple, + OutboundTransferRateLimitedEvent.OutputObject + >; + getEvent( + key: "OwnershipTransferred" + ): TypedContractEvent< + OwnershipTransferredEvent.InputTuple, + OwnershipTransferredEvent.OutputTuple, + OwnershipTransferredEvent.OutputObject + >; + getEvent( + key: "Paused" + ): TypedContractEvent< + PausedEvent.InputTuple, + PausedEvent.OutputTuple, + PausedEvent.OutputObject + >; + getEvent( + key: "PauserTransferred" + ): TypedContractEvent< + PauserTransferredEvent.InputTuple, + PauserTransferredEvent.OutputTuple, + PauserTransferredEvent.OutputObject + >; + getEvent( + key: "PeerUpdated" + ): TypedContractEvent< + PeerUpdatedEvent.InputTuple, + PeerUpdatedEvent.OutputTuple, + PeerUpdatedEvent.OutputObject + >; + getEvent( + key: "TransferRedeemed" + ): TypedContractEvent< + TransferRedeemedEvent.InputTuple, + TransferRedeemedEvent.OutputTuple, + TransferRedeemedEvent.OutputObject + >; + getEvent( + key: "TransferSent" + ): TypedContractEvent< + TransferSentEvent.InputTuple, + TransferSentEvent.OutputTuple, + TransferSentEvent.OutputObject + >; + getEvent( + key: "Upgraded" + ): TypedContractEvent< + UpgradedEvent.InputTuple, + UpgradedEvent.OutputTuple, + UpgradedEvent.OutputObject + >; + + filters: { + "AdminChanged(address,address)": TypedContractEvent< + AdminChangedEvent.InputTuple, + AdminChangedEvent.OutputTuple, + AdminChangedEvent.OutputObject + >; + AdminChanged: TypedContractEvent< + AdminChangedEvent.InputTuple, + AdminChangedEvent.OutputTuple, + AdminChangedEvent.OutputObject + >; + + "BeaconUpgraded(address)": TypedContractEvent< + BeaconUpgradedEvent.InputTuple, + BeaconUpgradedEvent.OutputTuple, + BeaconUpgradedEvent.OutputObject + >; + BeaconUpgraded: TypedContractEvent< + BeaconUpgradedEvent.InputTuple, + BeaconUpgradedEvent.OutputTuple, + BeaconUpgradedEvent.OutputObject + >; + + "InboundTransferLimitUpdated(uint16,uint256,uint256)": TypedContractEvent< + InboundTransferLimitUpdatedEvent.InputTuple, + InboundTransferLimitUpdatedEvent.OutputTuple, + InboundTransferLimitUpdatedEvent.OutputObject + >; + InboundTransferLimitUpdated: TypedContractEvent< + InboundTransferLimitUpdatedEvent.InputTuple, + InboundTransferLimitUpdatedEvent.OutputTuple, + InboundTransferLimitUpdatedEvent.OutputObject + >; + + "InboundTransferQueued(bytes32)": TypedContractEvent< + InboundTransferQueuedEvent.InputTuple, + InboundTransferQueuedEvent.OutputTuple, + InboundTransferQueuedEvent.OutputObject + >; + InboundTransferQueued: TypedContractEvent< + InboundTransferQueuedEvent.InputTuple, + InboundTransferQueuedEvent.OutputTuple, + InboundTransferQueuedEvent.OutputObject + >; + + "Initialized(uint64)": TypedContractEvent< + InitializedEvent.InputTuple, + InitializedEvent.OutputTuple, + InitializedEvent.OutputObject + >; + Initialized: TypedContractEvent< + InitializedEvent.InputTuple, + InitializedEvent.OutputTuple, + InitializedEvent.OutputObject + >; + + "NotPaused(bool)": TypedContractEvent< + NotPausedEvent.InputTuple, + NotPausedEvent.OutputTuple, + NotPausedEvent.OutputObject + >; + NotPaused: TypedContractEvent< + NotPausedEvent.InputTuple, + NotPausedEvent.OutputTuple, + NotPausedEvent.OutputObject + >; + + "OutboundTransferCancelled(uint256,address,uint256)": TypedContractEvent< + OutboundTransferCancelledEvent.InputTuple, + OutboundTransferCancelledEvent.OutputTuple, + OutboundTransferCancelledEvent.OutputObject + >; + OutboundTransferCancelled: TypedContractEvent< + OutboundTransferCancelledEvent.InputTuple, + OutboundTransferCancelledEvent.OutputTuple, + OutboundTransferCancelledEvent.OutputObject + >; + + "OutboundTransferLimitUpdated(uint256,uint256)": TypedContractEvent< + OutboundTransferLimitUpdatedEvent.InputTuple, + OutboundTransferLimitUpdatedEvent.OutputTuple, + OutboundTransferLimitUpdatedEvent.OutputObject + >; + OutboundTransferLimitUpdated: TypedContractEvent< + OutboundTransferLimitUpdatedEvent.InputTuple, + OutboundTransferLimitUpdatedEvent.OutputTuple, + OutboundTransferLimitUpdatedEvent.OutputObject + >; + + "OutboundTransferQueued(uint64)": TypedContractEvent< + OutboundTransferQueuedEvent.InputTuple, + OutboundTransferQueuedEvent.OutputTuple, + OutboundTransferQueuedEvent.OutputObject + >; + OutboundTransferQueued: TypedContractEvent< + OutboundTransferQueuedEvent.InputTuple, + OutboundTransferQueuedEvent.OutputTuple, + OutboundTransferQueuedEvent.OutputObject + >; + + "OutboundTransferRateLimited(address,uint64,uint256,uint256)": TypedContractEvent< + OutboundTransferRateLimitedEvent.InputTuple, + OutboundTransferRateLimitedEvent.OutputTuple, + OutboundTransferRateLimitedEvent.OutputObject + >; + OutboundTransferRateLimited: TypedContractEvent< + OutboundTransferRateLimitedEvent.InputTuple, + OutboundTransferRateLimitedEvent.OutputTuple, + OutboundTransferRateLimitedEvent.OutputObject + >; + + "OwnershipTransferred(address,address)": TypedContractEvent< + OwnershipTransferredEvent.InputTuple, + OwnershipTransferredEvent.OutputTuple, + OwnershipTransferredEvent.OutputObject + >; + OwnershipTransferred: TypedContractEvent< + OwnershipTransferredEvent.InputTuple, + OwnershipTransferredEvent.OutputTuple, + OwnershipTransferredEvent.OutputObject + >; + + "Paused(bool)": TypedContractEvent< + PausedEvent.InputTuple, + PausedEvent.OutputTuple, + PausedEvent.OutputObject + >; + Paused: TypedContractEvent< + PausedEvent.InputTuple, + PausedEvent.OutputTuple, + PausedEvent.OutputObject + >; + + "PauserTransferred(address,address)": TypedContractEvent< + PauserTransferredEvent.InputTuple, + PauserTransferredEvent.OutputTuple, + PauserTransferredEvent.OutputObject + >; + PauserTransferred: TypedContractEvent< + PauserTransferredEvent.InputTuple, + PauserTransferredEvent.OutputTuple, + PauserTransferredEvent.OutputObject + >; + + "PeerUpdated(uint16,bytes32,bytes32)": TypedContractEvent< + PeerUpdatedEvent.InputTuple, + PeerUpdatedEvent.OutputTuple, + PeerUpdatedEvent.OutputObject + >; + PeerUpdated: TypedContractEvent< + PeerUpdatedEvent.InputTuple, + PeerUpdatedEvent.OutputTuple, + PeerUpdatedEvent.OutputObject + >; + + "TransferRedeemed(bytes32)": TypedContractEvent< + TransferRedeemedEvent.InputTuple, + TransferRedeemedEvent.OutputTuple, + TransferRedeemedEvent.OutputObject + >; + TransferRedeemed: TypedContractEvent< + TransferRedeemedEvent.InputTuple, + TransferRedeemedEvent.OutputTuple, + TransferRedeemedEvent.OutputObject + >; + + "TransferSent(uint64,uint16,bytes32,bytes32,bytes32,uint256,uint16,address)": TypedContractEvent< + TransferSentEvent.InputTuple, + TransferSentEvent.OutputTuple, + TransferSentEvent.OutputObject + >; + TransferSent: TypedContractEvent< + TransferSentEvent.InputTuple, + TransferSentEvent.OutputTuple, + TransferSentEvent.OutputObject + >; + + "Upgraded(address)": TypedContractEvent< + UpgradedEvent.InputTuple, + UpgradedEvent.OutputTuple, + UpgradedEvent.OutputObject + >; + Upgraded: TypedContractEvent< + UpgradedEvent.InputTuple, + UpgradedEvent.OutputTuple, + UpgradedEvent.OutputObject + >; + }; +} diff --git a/evm/ts/src/ethers-contracts/1_1_0/factories/GmpManager__factory.ts b/evm/ts/src/ethers-contracts/1_1_0/factories/GmpManager__factory.ts new file mode 100644 index 000000000..f956ab40c --- /dev/null +++ b/evm/ts/src/ethers-contracts/1_1_0/factories/GmpManager__factory.ts @@ -0,0 +1,1734 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { + Contract, + ContractFactory, + ContractTransactionResponse, + Interface, +} from "ethers"; +import type { + Signer, + BigNumberish, + ContractDeployTransaction, + ContractRunner, +} from "ethers"; +import type { NonPayableOverrides } from "../common.js"; +import type { GmpManager, GmpManagerInterface } from "../GmpManager.js"; + +const _abi = [ + { + type: "constructor", + inputs: [ + { + name: "_chainId", + type: "uint16", + internalType: "uint16", + }, + ], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "GMP_MANAGER_VERSION", + inputs: [], + outputs: [ + { + name: "", + type: "string", + internalType: "string", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "attestationReceived", + inputs: [ + { + name: "sourceChainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "sourceNttManagerAddress", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "payload", + type: "tuple", + internalType: "struct TransceiverStructs.NttManagerMessage", + components: [ + { + name: "id", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "sender", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "payload", + type: "bytes", + internalType: "bytes", + }, + ], + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "chainId", + inputs: [], + outputs: [ + { + name: "", + type: "uint16", + internalType: "uint16", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "executeMsg", + inputs: [ + { + name: "sourceChainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "sourceGmpManagerAddress", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "message", + type: "tuple", + internalType: "struct TransceiverStructs.NttManagerMessage", + components: [ + { + name: "id", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "sender", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "payload", + type: "bytes", + internalType: "bytes", + }, + ], + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "getKnownChains", + inputs: [], + outputs: [ + { + name: "", + type: "uint16[]", + internalType: "uint16[]", + }, + ], + stateMutability: "pure", + }, + { + type: "function", + name: "getMigratesImmutables", + inputs: [], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getPeer", + inputs: [ + { + name: "chainId_", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "", + type: "tuple", + internalType: "struct GmpManager.GmpPeer", + components: [ + { + name: "peerAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getReceiveTransceiversForChain", + inputs: [ + { + name: "sourceChain", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "transceivers", + type: "address[]", + internalType: "address[]", + }, + { + name: "threshold", + type: "uint8", + internalType: "uint8", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getReceiveTransceiversWithIndicesForChain", + inputs: [ + { + name: "sourceChain", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "transceivers", + type: "tuple[]", + internalType: "struct TransceiverRegistry.TransceiverWithIndex[]", + components: [ + { + name: "transceiver", + type: "address", + internalType: "address", + }, + { + name: "index", + type: "uint8", + internalType: "uint8", + }, + ], + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getSendTransceiversForChain", + inputs: [ + { + name: "targetChain", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "transceivers", + type: "address[]", + internalType: "address[]", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getSendTransceiversWithIndicesForChain", + inputs: [ + { + name: "targetChain", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "transceivers", + type: "tuple[]", + internalType: "struct TransceiverRegistry.TransceiverWithIndex[]", + components: [ + { + name: "transceiver", + type: "address", + internalType: "address", + }, + { + name: "index", + type: "uint8", + internalType: "uint8", + }, + ], + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getThreshold", + inputs: [ + { + name: "sourceChain", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "", + type: "uint8", + internalType: "uint8", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getTransceiverInfo", + inputs: [], + outputs: [ + { + name: "", + type: "tuple[]", + internalType: "struct TransceiverRegistry.TransceiverInfo[]", + components: [ + { + name: "registered", + type: "bool", + internalType: "bool", + }, + { + name: "enabled", + type: "bool", + internalType: "bool", + }, + { + name: "index", + type: "uint8", + internalType: "uint8", + }, + ], + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getTransceivers", + inputs: [], + outputs: [ + { + name: "result", + type: "address[]", + internalType: "address[]", + }, + ], + stateMutability: "pure", + }, + { + type: "function", + name: "initialize", + inputs: [], + outputs: [], + stateMutability: "payable", + }, + { + type: "function", + name: "isMessageApprovedForChain", + inputs: [ + { + name: "sourceChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + ], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "isMessageExecuted", + inputs: [ + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + ], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "isPaused", + inputs: [], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "messageAttestations", + inputs: [ + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + ], + outputs: [ + { + name: "count", + type: "uint8", + internalType: "uint8", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "messageAttestationsForChain", + inputs: [ + { + name: "sourceChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + ], + outputs: [ + { + name: "count", + type: "uint8", + internalType: "uint8", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "migrate", + inputs: [], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "nextMessageSequence", + inputs: [], + outputs: [ + { + name: "", + type: "uint64", + internalType: "uint64", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "owner", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "address", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "pause", + inputs: [], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "pauser", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "address", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "quoteDeliveryPrice", + inputs: [ + { + name: "recipientChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "transceiverInstructions", + type: "bytes", + internalType: "bytes", + }, + ], + outputs: [ + { + name: "", + type: "uint256[]", + internalType: "uint256[]", + }, + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "registerKnownChain", + inputs: [ + { + name: "peerChainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "peerAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "removeReceiveTransceiverForChain", + inputs: [ + { + name: "sourceChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "removeSendTransceiverForChain", + inputs: [ + { + name: "targetChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "removeTransceiver", + inputs: [ + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "reserveMessageSequence", + inputs: [], + outputs: [ + { + name: "sequence", + type: "uint64", + internalType: "uint64", + }, + ], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "sendMessage", + inputs: [ + { + name: "targetChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "callee", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "refundAddress", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "reservedSequence", + type: "uint64", + internalType: "uint64", + }, + { + name: "data", + type: "bytes", + internalType: "bytes", + }, + { + name: "transceiverInstructions", + type: "bytes", + internalType: "bytes", + }, + ], + outputs: [ + { + name: "actualSequence", + type: "uint64", + internalType: "uint64", + }, + ], + stateMutability: "payable", + }, + { + type: "function", + name: "setPeer", + inputs: [ + { + name: "peerChainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "peerAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setReceiveTransceiverForChain", + inputs: [ + { + name: "sourceChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setSendTransceiverForChain", + inputs: [ + { + name: "targetChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setThreshold", + inputs: [ + { + name: "sourceChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "threshold", + type: "uint8", + internalType: "uint8", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setTransceiver", + inputs: [ + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "transceiverAttestedToMessage", + inputs: [ + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "index", + type: "uint8", + internalType: "uint8", + }, + ], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "transferOwnership", + inputs: [ + { + name: "newOwner", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "transferPauserCapability", + inputs: [ + { + name: "newPauser", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "unpause", + inputs: [], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "upgrade", + inputs: [ + { + name: "newImplementation", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "event", + name: "AdminChanged", + inputs: [ + { + name: "previousAdmin", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "newAdmin", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "BeaconUpgraded", + inputs: [ + { + name: "beacon", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Initialized", + inputs: [ + { + name: "version", + type: "uint64", + indexed: false, + internalType: "uint64", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "MessageAlreadyExecuted", + inputs: [ + { + name: "sourceNttManager", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "msgHash", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "MessageAttestedTo", + inputs: [ + { + name: "digest", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + { + name: "transceiver", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "index", + type: "uint8", + indexed: false, + internalType: "uint8", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "MessageExecuted", + inputs: [ + { + name: "messageHash", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "sourceChain", + type: "uint16", + indexed: true, + internalType: "uint16", + }, + { + name: "sender", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "callee", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "data", + type: "bytes", + indexed: false, + internalType: "bytes", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "MessageSent", + inputs: [ + { + name: "sequence", + type: "uint64", + indexed: true, + internalType: "uint64", + }, + { + name: "sender", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "targetChain", + type: "uint16", + indexed: false, + internalType: "uint16", + }, + { + name: "callee", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + { + name: "data", + type: "bytes", + indexed: false, + internalType: "bytes", + }, + { + name: "fee", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NotPaused", + inputs: [ + { + name: "notPaused", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "OwnershipTransferred", + inputs: [ + { + name: "previousOwner", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "newOwner", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Paused", + inputs: [ + { + name: "paused", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "PauserTransferred", + inputs: [ + { + name: "oldPauser", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "newPauser", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "PeerUpdated", + inputs: [ + { + name: "chainId", + type: "uint16", + indexed: true, + internalType: "uint16", + }, + { + name: "oldPeerAddress", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + { + name: "newPeerAddress", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "ReceiveTransceiverUpdatedForChain", + inputs: [ + { + name: "sourceChain", + type: "uint16", + indexed: false, + internalType: "uint16", + }, + { + name: "transceiver", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "enabled", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "SendTransceiverUpdatedForChain", + inputs: [ + { + name: "targetChain", + type: "uint16", + indexed: false, + internalType: "uint16", + }, + { + name: "transceiver", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "enabled", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "ThresholdChanged", + inputs: [ + { + name: "oldThreshold", + type: "uint8", + indexed: false, + internalType: "uint8", + }, + { + name: "threshold", + type: "uint8", + indexed: false, + internalType: "uint8", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "ThresholdUpdatedForChain", + inputs: [ + { + name: "sourceChain", + type: "uint16", + indexed: false, + internalType: "uint16", + }, + { + name: "threshold", + type: "uint8", + indexed: false, + internalType: "uint8", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "TransceiverAdded", + inputs: [ + { + name: "transceiver", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "transceiversNum", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "threshold", + type: "uint8", + indexed: false, + internalType: "uint8", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "TransceiverRemoved", + inputs: [ + { + name: "transceiver", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "threshold", + type: "uint8", + indexed: false, + internalType: "uint8", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Upgraded", + inputs: [ + { + name: "implementation", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "error", + name: "CallFailed", + inputs: [ + { + name: "returnData", + type: "bytes", + internalType: "bytes", + }, + ], + }, + { + type: "error", + name: "CallerNotTransceiver", + inputs: [ + { + name: "caller", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "DeliveryPaymentTooLow", + inputs: [ + { + name: "requiredPayment", + type: "uint256", + internalType: "uint256", + }, + { + name: "providedPayment", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "DisabledTransceiver", + inputs: [ + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "InvalidCallee", + inputs: [], + }, + { + type: "error", + name: "InvalidChainId", + inputs: [], + }, + { + type: "error", + name: "InvalidEvmAddress", + inputs: [], + }, + { + type: "error", + name: "InvalidInitialization", + inputs: [], + }, + { + type: "error", + name: "InvalidInstructionIndex", + inputs: [ + { + name: "providedIndex", + type: "uint256", + internalType: "uint256", + }, + { + name: "numTransceivers", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "InvalidPauser", + inputs: [ + { + name: "account", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "InvalidPeer", + inputs: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "peerAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + type: "error", + name: "InvalidPeerChainIdZero", + inputs: [], + }, + { + type: "error", + name: "InvalidPeerSameChainId", + inputs: [], + }, + { + type: "error", + name: "InvalidPeerZeroAddress", + inputs: [], + }, + { + type: "error", + name: "InvalidPrefix", + inputs: [], + }, + { + type: "error", + name: "InvalidRefundAddress", + inputs: [], + }, + { + type: "error", + name: "InvalidTargetChain", + inputs: [ + { + name: "targetChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + ], + }, + { + type: "error", + name: "InvalidTransceiverZeroAddress", + inputs: [], + }, + { + type: "error", + name: "LengthMismatch", + inputs: [ + { + name: "encodedLength", + type: "uint256", + internalType: "uint256", + }, + { + name: "expectedLength", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "MessageNotApproved", + inputs: [ + { + name: "msgHash", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + type: "error", + name: "NoEnabledTransceivers", + inputs: [], + }, + { + type: "error", + name: "NoThresholdConfiguredForChain", + inputs: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + ], + }, + { + type: "error", + name: "NoTransceiversConfiguredForChain", + inputs: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + ], + }, + { + type: "error", + name: "NonRegisteredTransceiver", + inputs: [ + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "NotAnEvmAddress", + inputs: [ + { + name: "", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + type: "error", + name: "NotInitializing", + inputs: [], + }, + { + type: "error", + name: "NotMigrating", + inputs: [], + }, + { + type: "error", + name: "OnlyDelegateCall", + inputs: [], + }, + { + type: "error", + name: "OwnableInvalidOwner", + inputs: [ + { + name: "owner", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "OwnableUnauthorizedAccount", + inputs: [ + { + name: "account", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "PayloadTooLong", + inputs: [ + { + name: "length", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "PayloadTooLong", + inputs: [ + { + name: "size", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "PeerNotRegistered", + inputs: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + ], + }, + { + type: "error", + name: "ReentrancyGuardReentrantCall", + inputs: [], + }, + { + type: "error", + name: "RefundFailed", + inputs: [ + { + name: "refundAmount", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "RequireContractIsNotPaused", + inputs: [], + }, + { + type: "error", + name: "RequireContractIsPaused", + inputs: [], + }, + { + type: "error", + name: "RetrievedIncorrectRegisteredTransceivers", + inputs: [ + { + name: "retrieved", + type: "uint256", + internalType: "uint256", + }, + { + name: "registered", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "SequenceNotReserved", + inputs: [ + { + name: "sequence", + type: "uint64", + internalType: "uint64", + }, + ], + }, + { + type: "error", + name: "SequenceNotReservedBySender", + inputs: [ + { + name: "sequence", + type: "uint64", + internalType: "uint64", + }, + { + name: "sender", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "ThresholdTooHigh", + inputs: [ + { + name: "threshold", + type: "uint256", + internalType: "uint256", + }, + { + name: "transceivers", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "TooManyTransceivers", + inputs: [], + }, + { + type: "error", + name: "TransceiverAlreadyAttestedToMessage", + inputs: [ + { + name: "nttManagerMessageHash", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + type: "error", + name: "TransceiverAlreadyEnabled", + inputs: [ + { + name: "transceiver", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "UnexpectedDeployer", + inputs: [ + { + name: "expectedOwner", + type: "address", + internalType: "address", + }, + { + name: "owner", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "UnexpectedMsgValue", + inputs: [], + }, + { + type: "error", + name: "UnorderedInstructions", + inputs: [ + { + name: "lastIndex", + type: "uint256", + internalType: "uint256", + }, + { + name: "instructionIndex", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "ZeroThreshold", + inputs: [], + }, +] as const; + +const _bytecode = + "0x6101006040523480156200001257600080fd5b5060405162004f9a38038062004f9a83398101604081905262000035916200010e565b80620000406200005a565b3060805261ffff1660c052504660e0523360a0526200013b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000ab5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146200010b5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6000602082840312156200012157600080fd5b815161ffff811681146200013457600080fd5b9392505050565b60805160a05160c05160e051614e056200019560003960005050600081816105c6015281816109a601528181611567015281816115b4015261329301526000818161369d01526136d9015260006121a20152614e056000f3fe6080604052600436106102515760003560e01c80638da5cb5b11610139578063b13c82ea116100b6578063da4856a11161007a578063da4856a114610739578063db5fdb9114610759578063e54ff04014610786578063ee0bdb1c146107a6578063f2fde38b146107b9578063ff428f09146107d957600080fd5b8063b13c82ea1461069e578063b150fc55146106be578063b187bd26146106e0578063b4d591bb146106f5578063c128d1701461070a57600080fd5b80639ab730d7116100fd5780639ab730d7146105fb5780639d7824541461061b5780639f86029c1461063b5780639fd0506d1461065b578063adaf575f1461067057600080fd5b80638da5cb5b146105245780638e3ba8c9146105515780638fd3ab80146105715780639057412d146105865780639a8a0592146105b457600080fd5b8063396c16b7116101d2578063689f90c311610196578063689f90c3146104925780636a4db160146104a75780637c9d2708146104c75780638129fc1c146104e75780638456cb59146104ef57806389c619dd1461050457600080fd5b8063396c16b7146103f05780633a495e0b146104105780633f4ba83a14610430578063451d5332146104455780634f4bb3e51461047257600080fd5b80632310dd3c116102195780632310dd3c1461032f57806323d75e3114610361578063295d819e1461038e57806332cf4cd5146103ae5780633951cbe6146103ce57600080fd5b80630271510814610256578063036de8af1461029d57806307299652146102bf5780630900f010146102ef578063203e4a9b1461030f575b600080fd5b34801561026257600080fd5b50610287604051806040016040528060058152602001640312e302e360dc1b81525081565b60405161029491906143fd565b60405180910390f35b3480156102a957600080fd5b506102bd6102b8366004614427565b6107ee565b005b3480156102cb57600080fd5b506102df6102da366004614452565b61085a565b6040519015158152602001610294565b3480156102fb57600080fd5b506102bd61030a366004614427565b61089a565b34801561031b57600080fd5b506102bd61032a366004614427565b6108ae565b34801561033b57600080fd5b5061034f61034a36600461447e565b61091e565b60405160ff9091168152602001610294565b34801561036d57600080fd5b50610376610929565b6040516001600160401b039091168152602001610294565b34801561039a57600080fd5b506102bd6103a9366004614452565b610942565b3480156103ba57600080fd5b506102bd6103c9366004614452565b610959565b3480156103da57600080fd5b506103e3610a85565b604051610294919061449b565b3480156103fc57600080fd5b506102df61040b3660046144e3565b610b0b565b34801561041c57600080fd5b506102bd61042b3660046144fc565b610b29565b34801561043c57600080fd5b506102bd610b7b565b34801561045157600080fd5b5061046561046036600461447e565b610b8d565b6040516102949190614575565b34801561047e57600080fd5b5061034f61048d366004614452565b610c41565b34801561049e57600080fd5b506102df610c5c565b3480156104b357600080fd5b506102bd6104c2366004614599565b610c6f565b3480156104d357600080fd5b506102bd6104e23660046144fc565b610cbd565b6102bd610d03565b3480156104fb57600080fd5b506102bd610e05565b34801561051057600080fd5b5061034f61051f3660046144e3565b610e18565b34801561053057600080fd5b50610539610e26565b6040516001600160a01b039091168152602001610294565b34801561055d57600080fd5b506102df61056c3660046145c5565b610e54565b34801561057d57600080fd5b506102bd610e8e565b34801561059257600080fd5b506105a66105a136600461468a565b610f90565b6040516102949291906146d9565b3480156105c057600080fd5b506105e87f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff9091168152602001610294565b34801561060757600080fd5b506102bd6106163660046144fc565b610fd5565b34801561062757600080fd5b506102bd610636366004614721565b61101b565b34801561064757600080fd5b506102bd610656366004614427565b611108565b34801561066757600080fd5b50610539611197565b34801561067c57600080fd5b5061069061068b36600461447e565b6111b0565b6040516102949291906147d7565b3480156106aa57600080fd5b506102bd6106b93660046144fc565b61127f565b3480156106ca57600080fd5b506106d36112c5565b60405161029491906147fc565b3480156106ec57600080fd5b506102df61144f565b34801561070157600080fd5b50610465611464565b34801561071657600080fd5b5061072a61072536600461447e565b6114cb565b60405190518152602001610294565b34801561074557600080fd5b506102bd610754366004614721565b611507565b34801561076557600080fd5b5061077961077436600461447e565b6116da565b604051610294919061485c565b34801561079257600080fd5b506107796107a136600461447e565b611705565b6103766107b43660046148eb565b611711565b3480156107c557600080fd5b506102bd6107d4366004614427565b611776565b3480156107e557600080fd5b50610376611834565b6107fe6107f9610e26565b61187c565b60006108086118c5565b80546001600160a01b038481166001600160a01b031983168117845560405193945091169182907f51c4874e0f23f262e04a38c51751336dde72126d67f53eb672aaff02996b3ef690600090a3505050565b600080610866846118f3565b905060006108748585610c41565b90508160ff168160ff161015801561088f575060008260ff16115b925050505b92915050565b6108a261194f565b6108ab81611981565b50565b6108b661194f565b6108bf81611a8f565b507ff05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5816108ea611d41565b54604080516001600160a01b03909316835261010090910460ff16602083015260009082015260600160405180910390a150565b6000610894826118f3565b6000610933611d6f565b546001600160401b0316919050565b61094c8282611d9d565b61095582611de6565b5050565b61096161194f565b8161ffff166000036109865760405163100b0f2760e11b815260040160405180910390fd5b806109a45760405163f839a0cb60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168261ffff16036109ec5760405163101b8f9560e11b815260040160405180910390fd5b60006109f6611e93565b61ffff8416600090815260209182526040908190208151928301909152548152905081610a21611e93565b61ffff851660009081526020919091526040902055610a3f83611de6565b8051604080519182526020820184905261ffff8516917f6b8e3e5d5cb35ca559551a3a468913b588421f8eeb87fabc088aa03638ce1369910160405180910390a2505050565b6060610a8f611ec1565b805480602002602001604051908101604052809291908181526020018280548015610b0157602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610ac85790505b5050505050905090565b6000610b15611eef565b600092835260205250604090205460ff1690565b610b3161194f565b610b3b8282611f1d565b7f6b9b1f20ce684fc1c23217395b766f44fb36a93fb907e41e4243fe2f9c101c2d82826001604051610b6f93929190614999565b60405180910390a15050565b610b8361194f565b610b8b611f51565b565b60606000610b99611fb7565b61ffff841660009081526020919091526040812060018101549092509003610bdf5760405163186b202960e11b815261ffff841660048201526024015b60405180910390fd5b60018101805460408051602080840282018101909252828152929190830182828015610c3457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c16575b5050505050915050919050565b6000610c55610c508484611fe5565b612024565b9392505050565b6000610c6661205c565b5460ff16919050565b610c7761194f565b610c81828261208a565b6040805161ffff8416815260ff831660208201527f463734bd482c3b124a4f4ee8cbda3b9beb1aa70b7346ca456fec770efc446c7b9101610b6f565b610cc561194f565b610ccf8282612146565b7f9a8d72d56c46cf95458ced32b1aa082ed04dd70c7119b6779521bb1893ee0b7382826001604051610b6f93929190614999565b610d0b612198565b600080516020614db08339815191528054600160401b810460ff1615906001600160401b0316600081158015610d3e5750825b90506000826001600160401b03166001148015610d5a5750303b155b905081158015610d68575080155b15610d865760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610db057845460ff60401b1916600160401b1785555b610db86121e1565b8315610dfe57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b610e106107f9610e26565b610b8b6121f1565b6000610894610c5083612252565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b600080600160ff84161b610e66611eef565b600086815260209190915260409020546101009004166001600160401b031611905092915050565b610e96612198565b610e9e61228e565b610ea99060016149d6565b600080516020614db08339815191528054600160401b900460ff1680610edc575080546001600160401b03808416911610155b15610efa5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b178155610f236122a4565b5460ff16610f4457604051632866815360e11b815260040160405180910390fd5b610f4c6121e9565b805460ff60401b191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602001610b6f565b6060600080610f9d6122d2565b5490506000610fab86610b8d565b90506000610fb98684612300565b9050610fc687828461245f565b945094505050505b9250929050565b610fdd61194f565b610fe782826125df565b7f9a8d72d56c46cf95458ced32b1aa082ed04dd70c7119b6779521bb1893ee0b7382826000604051610b6f93929190614999565b611023612637565b3360009081526020919091526040902054610100900460ff1661105b5760405163a0ae911d60e01b8152336004820152602401610bd6565b61106361144f565b15611081576040516309e3d0f360e11b815260040160405180910390fd5b61108b8383611d9d565b60006110978483612665565b90506110a3848261085a565b156111025760405163da4856a160e01b8152309063da4856a1906110cf908790879087906004016149fd565b600060405180830381600087803b1580156110e957600080fd5b505af11580156110fd573d6000803e3d6000fd5b505050505b50505050565b61111061194f565b600061111a611d41565b54610100900460ff169050600181116111465760405163831761d760e01b815260040160405180910390fd5b61114f826126ca565b611158826127d9565b604080516001600160a01b0384168152600060208201527f697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f9101610b6f565b60006111a16118c5565b546001600160a01b0316919050565b60606000806111bd612aa1565b61ffff8516600090815260209190915260409020600181015490915015806111ea5750600281015460ff16155b1561120e5760405163186b202960e11b815261ffff85166004820152602401610bd6565b600281015460018201805460408051602080840282018101909252828152929360ff169291849183018282801561126e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611250575b505050505091509250925050915091565b61128761194f565b6112918282612acf565b7f6b9b1f20ce684fc1c23217395b766f44fb36a93fb907e41e4243fe2f9c101c2d82826000604051610b6f93929190614999565b606060006112d1612af9565b80548060200260200160405190810160405280929190818152602001828054801561132557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611307575b505050505090506000815190506000816001600160401b0381111561134c5761134c6145e8565b60405190808252806020026020018201604052801561139757816020015b604080516060810182526000808252602080830182905292820152825260001990920191018161136a5790505b50905060005b82811015611447576113ad612637565b60008583815181106113c1576113c1614a47565b6020908102919091018101516001600160a01b031682528181019290925260409081016000208151606081018352905460ff808216151583526101008204811615159483019490945262010000900490921690820152825183908390811061142b5761142b614a47565b60200260200101819052508061144090614a5d565b905061139d565b509392505050565b60008061145a612b26565b5460021492915050565b606061146e612af9565b805480602002602001604051908101604052809291908181526020018280548015610b0157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114a4575050505050905090565b6040805160208101909152600081526114e2611e93565b61ffff9092166000908152602092835260409081902081519384019091525482525090565b61150f612b54565b61151761144f565b15611535576040516309e3d0f360e11b815260040160405180910390fd5b600080611543858585612b8c565b9150915080156115545750506116be565b60006115638460400151612c20565b90507f000000000000000000000000000000000000000000000000000000000000000061ffff16816000015161ffff16146115e3578051604051631ee5902560e11b815261ffff91821660048201527f00000000000000000000000000000000000000000000000000000000000000009091166024820152604401610bd6565b60006115f28260200151612d01565b6040808401516060850151915163ebd47c2f60e01b81529293506001600160a01b0384169263ebd47c2f9261162e9289928d9290600401614a76565b600060405180830381600087803b15801561164857600080fd5b505af115801561165c573d6000803e3d6000fd5b5050505061166d8560200151612d01565b6001600160a01b03168761ffff16857f1000a14cded4271da033293964b8a9ce647c150f445bb766d7d8219acefb665e8486606001516040516116b1929190614a9f565b60405180910390a4505050505b6116d56001600080516020614d9083398151915255565b505050565b606060006116e6612aa1565b61ffff84166000908152602091909152604090209050610c5581612d41565b606060006116e6611fb7565b600061171b612b54565b61172361144f565b15611741576040516309e3d0f360e11b815260040160405180910390fd5b6117518989898989898989612ec6565b905061176a6001600080516020614d9083398151915255565b98975050505050505050565b61177e61194f565b6117878161313a565b60006117916122d2565b905061179b613175565b60005b81548110156116d5578181815481106117b9576117b9614a47565b600091825260209091200154604051632c7b84dd60e11b81526001600160a01b038581166004830152909116906358f709ba90602401600060405180830381600087803b15801561180957600080fd5b505af115801561181d573d6000803e3d6000fd5b50505050808061182c90614a5d565b91505061179e565b600061183e6131c6565b9050600161184a613223565b336000908152602091825260408082206001600160401b038616835290925220805460ff191691151591909117905590565b33611885611197565b6001600160a01b0316141580156118a557506001600160a01b0381163314155b156108ab5760405163e2a08e5d60e01b8152336004820152602401610bd6565b60008061089460017fbfa91572ce1e5fe8776a160d3b1f862e83f5ee2c080a7423b4761602a3ad124a614acb565b6000806118fe612aa1565b61ffff8416600090815260209190915260408120600281015490925060ff16900361194257604051631fc0a48b60e01b815261ffff84166004820152602401610bd6565b6002015460ff1692915050565b33611958610e26565b6001600160a01b031614610b8b5760405163118cdaa760e01b8152336004820152602401610bd6565b611989612198565b61199281613251565b600061199c6122a4565b805490915060ff16156119b1576119b1614ade565b805460ff191660011781556040805163011fa75760e71b815290513091638fd3ab8091600480830192600092919082900301818387803b1580156119f457600080fd5b505af1158015611a08573d6000803e3d6000fd5b50505050306001600160a01b031663689f90c36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6e9190614af4565b611a7a57611a7a613291565b611a846000613329565b805460ff1916905550565b600080611a9a612637565b90506000611aa6613344565b90506000611ab2612af9565b90506000611abe611d41565b90506001600160a01b038616611ae757604051632f44bd7760e01b815260040160405180910390fd5b6001600160a01b03861660009081526020859052604090205460ff1615611b32576001600160a01b0386166000908152602085905260409020805461ff001916610100179055611c2f565b8054604060ff90911610611b595760405163891684c360e01b815260040160405180910390fd5b6040805160608101825260018082526020808301918252845460ff9081168486019081526001600160a01b038c166000908152928a905294822093518454935195518216620100000262ff0000199615156101000261ff00199215159290921661ffff19909516949094171794909416919091179091558254909116908290611be183614b16565b91906101000a81548160ff021916908360ff16021790555050611c026122d2565b8054600181018255600091825260209091200180546001600160a01b0319166001600160a01b0388161790555b81546001808201845560008481526020902090910180546001600160a01b0319166001600160a01b0389161790558154610100900460ff16908290611c7383614b16565b82546101009290920a60ff8181021990931691831602179091556001600160a01b03881660009081526020879052604090205485546001620100009092049092161b6001600160401b0391821681811793509116811703611cf257604051638d68f84d60e01b81526001600160a01b0388166004820152602401610bd6565b835467ffffffffffffffff19166001600160401b038216178455611d14613372565b505050506001600160a01b0392909216600090815260209290925250604090205462010000900460ff1690565b60008061089460017f8561949d1c6242cee5c5a5aeb6b9c190ee611d7742fcec65d9e5b1341ea04d8a614acb565b60008061089460017fad78307a8b51804c575f26039dcb87c58925afb3b7c08732f3b21b942aed7a77614acb565b80611da6611e93565b61ffff8416600090815260209190915260409020541461095557604051635788c0fd60e11b815261ffff8316600482015260248101829052604401610bd6565b6000611df0611ec1565b905060005b8154811015611e53578261ffff16828281548110611e1557611e15614a47565b60009182526020909120601082040154600f9091166002026101000a900461ffff1603611e4157505050565b80611e4b81614a5d565b915050611df5565b5080546001810182556000918252602090912060108204018054600f9092166002026101000a61ffff818102199093169390921691909102919091179055565b60008061089460017f4c5e3a4bc66f163a233a21bf8ef776e10842bce70809a1c964eb9acdc3d5cd4b614acb565b60008061089460017f8571232e6643c3c4913142bb252555aaa29e5ecb8975f1d3b7aa29ede8f2ed1e614acb565b60008061089460017f68dfeeddfa5e4e9adceec01a3aba274bdcbab3f6ac9956417a4332f2b08abddb614acb565b6000611f27611fb7565b61ffff84166000908152602091909152604090209050611f488383836134b3565b6116d583611de6565b611f5961144f565b611f7657604051637e38d1d360e11b815260040160405180910390fd5b611f806001613611565b604051600081527fe11c2112add17fb763d3bd59f63b10429c3e11373da4fb8ef6725107a2fdc4b0906020015b60405180910390a1565b60008061089460017faf3e857a2ae24065b1bd005f8a72dea35481e3cf2e40353c4c7dac4b0051e8fc614acb565b600080611ff18461361e565b905080611ffc611eef565b600085815260209190915260409020546101009004166001600160401b031691505092915050565b60005b6001600160401b0382161561205757612041600183614b35565b909116908061204f81614b16565b915050612027565b919050565b60008061089460017f5443fea4dc453d96b81ce55b62e11a4094cc4cbb8a360956a7253cfdb42506cc614acb565b8161ffff166000036120af57604051633d23e4d160e11b815260040160405180910390fd5b8060ff166000036120d35760405163831761d760e01b815260040160405180910390fd5b60006120dd612aa1565b61ffff8416600090815260209190915260409020600181015490915060ff808216908416111561212d576040516313c3d1b160e01b815260ff808516600483015282166024820152604401610bd6565b50600201805460ff191660ff9290921691909117905550565b6000612150612aa1565b61ffff841660009081526020919091526040902090506121718383836134b3565b600281015460ff16600003611f485760028101805460ff191660011790556116d583611de6565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610b8b57604051633c64f99360e21b815260040160405180910390fd5b6121e961368a565b610b8b613372565b6121f961144f565b15612217576040516309e3d0f360e11b815260040160405180910390fd5b6122216002613611565b604051600181527f0e2fb031ee032dc02d8011dc50b816eb450cf856abd8261680dac74f72165bd290602001611fad565b60008061225d613745565b905080612268611eef565b60009485526020526040909320546101009004929092166001600160401b031692915050565b6000600080516020614db0833981519152610933565b60008061089460017f7487ca88d037ca20519908b1ee7556206bef53bce0226a348750cb9d4f688e4f614acb565b60008061089460017f3031d39df71efbb605646fc51d7571499445af538fa6dd17ce8c07e8118ed979614acb565b6001828101516060919060ff166000846001600160401b03811115612327576123276145e8565b60405190808252806020026020018201604052801561236d57816020015b6040805180820190915260008152606060208201528152602001906001900390816123455790505b5090506000805b8381101561244a5760408051808201909152600081526060602082015261239b898761374f565b815190975090915082158015906123b55750838160ff1611155b156123df57604051630555a4b960e01b81526004810185905260ff82166024820152604401610bd6565b888160ff161061240e5760405163344fa80b60e11b815260ff82166004820152602481018a9052604401610bd6565b8060ff16935081858260ff168151811061242a5761242a614a47565b60200260200101819052505050808061244290614a5d565b915050612374565b5061245587856137a1565b5095945050505050565b805160609060009081612470612637565b90506000826001600160401b0381111561248c5761248c6145e8565b6040519080825280602002602001820160405280156124b5578160200160208202803683370190505b5090506000805b848110156125ce5760008882815181106124d8576124d8614a47565b6020908102919091018101516001600160a01b03811660008181529288905260408320548d5192945062010000900460ff16929163b5634c73908f908f908690811061252657612526614a47565b60200260200101516040518363ffffffff1660e01b815260040161254b929190614b77565b602060405180830381865afa158015612568573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258c9190614b94565b9050808685815181106125a1576125a1614a47565b60209081029190910101526125b68186614bad565b945050505080806125c690614a5d565b9150506124bc565b50909450925050505b935093915050565b60006125e9612aa1565b61ffff8416600090815260209190915260408120915061260983836137cf565b600283015490915060ff808316911611156111025760028201805460ff831660ff1990911617905550505050565b60008061089460017f49bca747e973430e858f2f5de357b8dba36ea6d375b81bdb5d53dfaabf0b3a80614acb565b60008061267284846139ff565b905061269f81612680612637565b336000908152602091909152604090205462010000900460ff16610e54565b156126c057604051631089c4a160e11b815260048101829052602401610bd6565b610c558133613a13565b60006126d4611ec1565b905060006126e0612637565b6001600160a01b0384166000908152602091909152604081205462010000900460ff1691506001821b905b8354811015610dfe57600084828154811061272857612728614a47565b600091825260208220601082040154600f9091166002026101000a900461ffff169150612753611fb7565b61ffff8316600090815260209190915260409020805490915084166001600160401b031615612786576127868288612acf565b6000612790612aa1565b61ffff8416600090815260209190915260409020805490915085166001600160401b0316156127c3576127c383896125df565b50505080806127d190614a5d565b91505061270b565b60006127e3612637565b905060006127ef613344565b905060006127fb612af9565b90506001600160a01b03841661282457604051632f44bd7760e01b815260040160405180910390fd5b6001600160a01b03841660009081526020849052604090205460ff1661286857604051630d583f4760e41b81526001600160a01b0385166004820152602401610bd6565b6001600160a01b038416600090815260208490526040902054610100900460ff166128b1576040516307d86e9160e21b81526001600160a01b0385166004820152602401610bd6565b6001600160a01b0384166000908152602084905260409020805461ff00191690556128da611d41565b8054610100900460ff169060016128f083614bc0565b82546101009290920a60ff8181021990931691831602179091556001600160a01b03861660009081526020869052604090205484546001600160401b036001620100009093049093169190911b1981168216925016811061295357612953614ade565b825467ffffffffffffffff19166001600160401b0382161783558154600090815b81811015612a7957876001600160a01b031685828154811061299857612998614a47565b6000918252602090912001546001600160a01b031603612a6757846129be600184614acb565b815481106129ce576129ce614a47565b9060005260206000200160009054906101000a90046001600160a01b03168582815481106129fe576129fe614a47565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555084805480612a3c57612a3c614bdd565b600082815260209020810160001990810180546001600160a01b031916905501905560019250612a79565b80612a7181614a5d565b915050612974565b5081612a8757612a87614ade565b612a8f613372565b612a9887613ab4565b50505050505050565b60008061089460017faf0a382368c2faefe3458a9184c278f02a5091cca99095e9051eb2cf76449aff614acb565b6000612ad9611fb7565b61ffff8416600090815260209190915260409020905061110282826137cf565b60008061089460017e758a264b9bdbe3295fe36bd6ff7abaa122f48bf70e90af04a1b8a32d21e4e2614acb565b60008061089460017f64bacf405c5d7f563d3ba5252584a52c37e4fee380fd825b10666c27b8258023614acb565b600080516020614d90833981519152805460011901612b8657604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6000806000612b9b86856139ff565b9050612ba7868261085a565b612bc757604051630451c4fb60e41b815260048101829052602401610bd6565b6000612bd282613c33565b90508015612c1457604051829087907f4069dff8c9df7e38d2867c0910bd96fd61787695e5380281148c04932d02bef290600090a36000935091506125d79050565b90969095509350505050565b604080516080810182526000808252602082018190529181018290526060808201529080612c4e8482613c74565b925090506001600160e01b0319811663099474d560e41b14612c8357604051635aaa8f5160e01b815260040160405180910390fd5b600284830181015161ffff16845290910190612c9f8483613c9f565b60208501919091529150612cb38483613c9f565b604085019190915291506000612cd28584600291810182015192910190565b93509050612ce5858461ffff8416613cc5565b60608601919091529250612cf985846137a1565b505050919050565b600060a082901c15612d295760405163033b960d60e41b815260048101839052602401610bd6565b5090565b6001600080516020614d9083398151915255565b6060600082600101805480602002602001604051908101604052809291908181526020018280548015612d9d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612d7f575b5050505050905080516001600160401b03811115612dbd57612dbd6145e8565b604051908082528060200260200182016040528015612e0257816020015b6040805180820190915260008082526020820152815260200190600190039081612ddb5790505b5091506000612e0f612637565b905060005b8251811015612cf9576040518060400160405280848381518110612e3a57612e3a614a47565b60200260200101516001600160a01b03168152602001836000868581518110612e6557612e65614a47565b6020908102919091018101516001600160a01b031682528101919091526040016000205462010000900460ff1690528451859083908110612ea857612ea8614a47565b60200260200101819052508080612ebe90614a5d565b915050612e14565b600087612ee6576040516351d7656b60e01b815260040160405180910390fd5b86612f045760405163717f139360e11b815260040160405180910390fd5b856001600160401b0316600003612f2457612f1d6131c6565b9050612f30565b612f2d86613d39565b50845b6060600060405180608001604052808c61ffff1681526020018b8152602001612f5f336001600160a01b031690565b815260200188888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050915250604080516060810182526001600160401b0386168152336020820152919250612fd291908101612fcb84613dd4565b9052613e4b565b9150506130006040518060800160405280606081526020016060815260200160608152602001600081525090565b6000806000806130468f8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613ebd92505050565b6040805160808101825294855260208501939093529183015260608201529450600093506130779250611e93915050565b61ffff8d16600090815260209190915260409020549050806130b957604051635788c0fd60e11b815261ffff8d16600482015260248101829052604401610bd6565b6130d48c8b8385604001518660200151876000015189613f7c565b336001600160a01b0316846001600160401b03167f63eefc6a01dedd195b6bca015db99eb7905ad05547b48c92500987395f78ae7b8e8e8c8c8860600151604051613123959493929190614bf3565b60405180910390a350505098975050505050505050565b61314261194f565b6001600160a01b03811661316c57604051631e4fbdf760e01b815260006004820152602401610bd6565b6108ab816140c9565b61317d611d41565b5460ff166131896122d2565b5414610b8b576131976122d2565b546131a0611d41565b5460405163d2a13a2960e01b8152600481019290925260ff166024820152604401610bd6565b60006131d0611d6f565b546001600160401b031690506131e4611d6f565b80546001600160401b03169060006131fb83614c3e565b91906101000a8154816001600160401b0302191690836001600160401b031602179055505090565b60008061089460017f36408a71599ca6e68632104165d777346e57bee9acd9f469d182a52bc8170e22614acb565b61325a8161413a565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7f000000000000000000000000000000000000000000000000000000000000000061ffff16306001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133189190614c64565b61ffff1614610b8b57610b8b614ade565b8061333261205c565b805460ff191691151591909117905550565b60008061089460017ffd6568c039679b3b7cc93c26c41d9379b7b1bec1677120493b467688302cb120614acb565b600061337c611d41565b90506000613388612af9565b82548154919250610100900460ff169081146133a6576133a6614ade565b60005b818110156133f2576133e08382815481106133c6576133c6614a47565b6000918252602090912001546001600160a01b0316613ab4565b806133ea81614a5d565b9150506133a9565b5060005b8181101561349b57600061340b826001614bad565b90505b828110156134885783818154811061342857613428614a47565b60009182526020909120015484546001600160a01b039091169085908490811061345457613454614a47565b6000918252602090912001546001600160a01b03160361347657613476614ade565b8061348081614a5d565b91505061340e565b508061349381614a5d565b9150506133f6565b508254604060ff90911611156116d5576116d5614ade565b60006134bd612637565b90506001600160a01b0383166134e657604051632f44bd7760e01b815260040160405180910390fd5b8361ffff1660000361350b57604051633d23e4d160e11b815260040160405180910390fd5b6001600160a01b038316600090815260208290526040902054610100900460ff16613554576040516307d86e9160e21b81526001600160a01b0384166004820152602401610bd6565b6001600160a01b03831660009081526020829052604090205482546201000090910460ff16906001821b906001600160401b0390821616156135b457604051638d68f84d60e01b81526001600160a01b0386166004820152602401610bd6565b835467ffffffffffffffff1981166001600160401b03918216929091169190911717835550506001908101805491820181556000908152602090200180546001600160a01b0319166001600160a01b039290921691909117905550565b8061361a612b26565b5550565b600080613629612aa1565b61ffff8416600090815260209190915260409020600181015490915015806136565750600281015460ff16155b1561367a5760405163186b202960e11b815261ffff84166004820152602401610bd6565b546001600160401b031692915050565b6136926141e8565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461370c57604051636345072160e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152336024820152604401610bd6565b341561372b5760405163bd28e88960e01b815260040160405180910390fd5b613735333361421f565b61373d614239565b6108ab6131c6565b6000610933613344565b604080518082019091526000815260606020820152818301600181015160ff9081168352600291820151918401919061378d90869084908416613cc5565b846020018194508290525050509250929050565b808251146109555781516040516355c5b3e360e11b8152600481019190915260248101829052604401610bd6565b6000806137da612637565b90506001600160a01b03841661380357604051632f44bd7760e01b815260040160405180910390fd5b6001600160a01b03841660009081526020829052604090205460ff1661384757604051630d583f4760e41b81526001600160a01b0385166004820152602401610bd6565b6001600160a01b03841660009081526020829052604081205484546201000090910460ff16916001831b916001600160401b039083161690036138a8576040516307d86e9160e21b81526001600160a01b0387166004820152602401610bd6565b84546001600160401b03821982161667ffffffffffffffff199091161785556001850154600090815b818110156139df57886001600160a01b03168860010182815481106138f8576138f8614a47565b6000918252602090912001546001600160a01b0316036139cd57876001016001836139239190614acb565b8154811061393357613933614a47565b6000918252602090912001546001890180546001600160a01b03909216918390811061396157613961614a47565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550876001018054806139a2576139a2614bdd565b600082815260209020810160001990810180546001600160a01b0319169055019055600192506139df565b806139d781614a5d565b9150506138d1565b50816139ed576139ed614ade565b50505060018401549250505092915050565b6000610c5583613a0e84613e4b565b614249565b613a4782613a1f612637565b6001600160a01b0384166000908152602091909152604090205462010000900460ff1661427c565b7f35a2101eaac94b493e0dfca061f9a7f087913fde8678e7cde0aca9897edba0e58282613a72612637565b6001600160a01b038581166000908152602092835260409081902054815195865293909116918401919091526201000090910460ff1690820152606001610b6f565b6000613abe612637565b90506000613aca613344565b90506000613ad6611d41565b90506000613ae2612af9565b6001600160a01b038616600090815260208681526040918290208251606081018452905460ff8082161515808452610100830482161515948401949094526201000090910416928101929092529192509080613b5057508060200151158015613b505750604081015160ff16155b613b5c57613b5c614ade565b604081015184546020830151600160ff9093169290921b166001600160401b03161515906000805b8654610100900460ff16811015613be657896001600160a01b0316868281548110613bb157613bb1614a47565b6000918252602090912001546001600160a01b031603613bd45760019150613be6565b80613bde81614a5d565b915050613b84565b5081151583151514613bfa57613bfa614ade565b81151581151514613c0d57613c0d614ade565b8554604085015160ff918216911610613c2857613c28614ade565b505050505050505050565b6000613c3e82610b0b565b15613c4b57506001919050565b6001613c55611eef565b600093845260205260408320805460ff19169115159190911790555090565b600080600080613c8d8686600491810182015192910190565b60e09190911b97909650945050505050565b600080600080613cb88686602091810182015192910190565b9097909650945050505050565b6060600082600003613ce8575050604080516000815260208101909152826125d7565b5050604051828201601f831680613cfd575060205b80830184810186838901015b81831015613d21578051835260209283019201613d09565b5050848452601f01601f191660405250935093915050565b613d41613223565b336000908152602091825260408082206001600160401b0385168352909252205460ff16613d9357604051637bef2ac760e01b81526001600160401b0382166004820152336024820152604401610bd6565b6000613d9d613223565b336000908152602091825260408082206001600160401b039590951682529390915291909120805460ff1916911515919091179055565b6060818101515161ffff1015613e065781606001515160405163a341969160e01b8152600401610bd691815260200190565b8151602080840151604080860151606087015180519251613e359663099474d560e41b96909594929101614c81565b6040516020818303038152906040529050919050565b606061ffff80168260400151511115613e805781604001515160405163a341969160e01b8152600401610bd691815260200190565b6040808301518051845160208087015194519294613ea694929390928692909101614cdd565b604051602081830303815290604052915050919050565b6060806060600080613ece87610b8d565b905060606000613edc6122d2565b5483519091506000819003613f04576040516334e7b19560e11b815260040160405180910390fd5b613f0e8983612300565b92505050600080613f208a848661245f565b9150915080341015613f4e576040516306a91e3760e51b815260048101829052346024820152604401610bd6565b6000613f5a8234614acb565b90508015613f6b57613f6b816142ca565b509299919850965090945092505050565b81516000613f88612637565b905086613fae57604051630ebc95af60e21b815261ffff8a166004820152602401610bd6565b8760005b838110156140bc576000868281518110613fce57613fce614a47565b60200260200101519050806001600160a01b0316634b5b05058a8481518110613ff957613ff9614a47565b60200260200101518e8b886000876001600160a01b03166001600160a01b0316815260200190815260200160002060000160029054906101000a900460ff1660ff168151811061404b5761404b614a47565b60200260200101518a8f896040518763ffffffff1660e01b8152600401614076959493929190614d1b565b6000604051808303818588803b15801561408f57600080fd5b505af11580156140a3573d6000803e3d6000fd5b50505050505080806140b490614a5d565b915050613fb2565b5050505050505050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001600160a01b0381163b6141a75760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610bd6565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b600080516020614db083398151915254600160401b900460ff16610b8b57604051631afcd79f60e31b815260040160405180910390fd5b6142276141e8565b61423082614336565b61095581614347565b6142416141e8565b610b8b614358565b6000828260405160200161425e929190614d5f565b60405160208183030381529060405280519060200120905092915050565b600160ff82161b61428b611eef565b60009384526020526040909220805468ffffffffffffffff00198116610100918290046001600160401b03908116951694909417029290921790915550565b604051600090339083908381818185875af1925050503d806000811461430c576040519150601f19603f3d011682016040523d82523d6000602084013e614311565b606091505b505090508061095557604051630b288dc560e21b815260048101839052602401610bd6565b61433e6141e8565b6108ab81614360565b61434f6141e8565b6108ab816143a5565b612d2d6141e8565b6143686141e8565b6000614372612b26565b60018155905060006143826118c5565b80546001600160a01b0319166001600160a01b0394909416939093179092555050565b6131426141e8565b60005b838110156143c85781810151838201526020016143b0565b50506000910152565b600081518084526143e98160208601602086016143ad565b601f01601f19169290920160200192915050565b602081526000610c5560208301846143d1565b80356001600160a01b038116811461205757600080fd5b60006020828403121561443957600080fd5b610c5582614410565b61ffff811681146108ab57600080fd5b6000806040838503121561446557600080fd5b823561447081614442565b946020939093013593505050565b60006020828403121561449057600080fd5b8135610c5581614442565b6020808252825182820181905260009190848201906040850190845b818110156144d757835161ffff16835292840192918401916001016144b7565b50909695505050505050565b6000602082840312156144f557600080fd5b5035919050565b6000806040838503121561450f57600080fd5b823561451a81614442565b915061452860208401614410565b90509250929050565b600081518084526020808501945080840160005b8381101561456a5781516001600160a01b031687529582019590820190600101614545565b509495945050505050565b602081526000610c556020830184614531565b803560ff8116811461205757600080fd5b600080604083850312156145ac57600080fd5b82356145b781614442565b915061452860208401614588565b600080604083850312156145d857600080fd5b8235915061452860208401614588565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261460f57600080fd5b81356001600160401b0380821115614629576146296145e8565b604051601f8301601f19908116603f01168101908282118183101715614651576146516145e8565b8160405283815286602085880101111561466a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561469d57600080fd5b82356146a881614442565b915060208301356001600160401b038111156146c357600080fd5b6146cf858286016145fe565b9150509250929050565b604080825283519082018190526000906020906060840190828701845b82811015614712578151845292840192908401906001016146f6565b50505092019290925292915050565b60008060006060848603121561473657600080fd5b833561474181614442565b92506020840135915060408401356001600160401b038082111561476457600080fd5b908501906060828803121561477857600080fd5b604051606081018181108382111715614793576147936145e8565b806040525082358152602083013560208201526040830135828111156147b857600080fd5b6147c4898286016145fe565b6040830152508093505050509250925092565b6040815260006147ea6040830185614531565b905060ff831660208301529392505050565b602080825282518282018190526000919060409081850190868401855b8281101561484f5781518051151585528681015115158786015285015160ff168585015260609093019290850190600101614819565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b8281101561484f57815180516001600160a01b0316855286015160ff16868501529284019290850190600101614879565b60008083601f8401126148bc57600080fd5b5081356001600160401b038111156148d357600080fd5b602083019150836020828501011115610fce57600080fd5b60008060008060008060008060c0898b03121561490757600080fd5b883561491281614442565b9750602089013596506040890135955060608901356001600160401b03808216821461493d57600080fd5b90955060808a0135908082111561495357600080fd5b61495f8c838d016148aa565b909650945060a08b013591508082111561497857600080fd5b506149858b828c016148aa565b999c989b5096995094979396929594505050565b61ffff9390931683526001600160a01b039190911660208301521515604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156149f6576149f66149c0565b5092915050565b61ffff8416815282602082015260606040820152815160608201526020820151608082015260006040830151606060a0840152614a3d60c08401826143d1565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201614a6f57614a6f6149c0565b5060010190565b84815261ffff84166020820152826040820152608060608201526000614a3d60808301846143d1565b6001600160a01b0383168152604060208201819052600090614ac3908301846143d1565b949350505050565b81810381811115610894576108946149c0565b634e487b7160e01b600052600160045260246000fd5b600060208284031215614b0657600080fd5b81518015158114610c5557600080fd5b600060ff821660ff8103614b2c57614b2c6149c0565b60010192915050565b6001600160401b038281168282160390808211156149f6576149f66149c0565b60ff81511682526000602082015160406020850152614ac360408501826143d1565b61ffff83168152604060208201526000614ac36040830184614b55565b600060208284031215614ba657600080fd5b5051919050565b80820180821115610894576108946149c0565b600060ff821680614bd357614bd36149c0565b6000190192915050565b634e487b7160e01b600052603160045260246000fd5b61ffff8616815284602082015260806040820152826080820152828460a0830137600060a08483010152600060a0601f19601f86011683010190508260608301529695505050505050565b60006001600160401b03808316818103614c5a57614c5a6149c0565b6001019392505050565b600060208284031215614c7657600080fd5b8151610c5581614442565b63ffffffff60e01b87168152600061ffff60f01b808860f01b166004840152866006840152856026840152808560f01b166046840152508251614ccb8160488501602087016143ad565b91909101604801979650505050505050565b84815283602082015261ffff60f01b8360f01b16604082015260008251614d0b8160428501602087016143ad565b9190910160420195945050505050565b61ffff8616815260a060208201526000614d3860a0830187614b55565b8281036040840152614d4a81876143d1565b60608401959095525050608001529392505050565b61ffff60f01b8360f01b16815260008251614d818160028501602087016143ad565b91909101600201939250505056fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a264697066735822122071a03c551127eda9f678fd3ea620f0a97764863f073d41f7728506ae6a84b62d64736f6c63430008130033"; + +type GmpManagerConstructorParams = + | [signer?: Signer] + | ConstructorParameters; + +const isSuperArgs = ( + xs: GmpManagerConstructorParams +): xs is ConstructorParameters => xs.length > 1; + +export class GmpManager__factory extends ContractFactory { + constructor(...args: GmpManagerConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + } + + override getDeployTransaction( + _chainId: BigNumberish, + overrides?: NonPayableOverrides & { from?: string } + ): Promise { + return super.getDeployTransaction(_chainId, overrides || {}); + } + override deploy( + _chainId: BigNumberish, + overrides?: NonPayableOverrides & { from?: string } + ) { + return super.deploy(_chainId, overrides || {}) as Promise< + GmpManager & { + deploymentTransaction(): ContractTransactionResponse; + } + >; + } + override connect(runner: ContractRunner | null): GmpManager__factory { + return super.connect(runner) as GmpManager__factory; + } + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): GmpManagerInterface { + return new Interface(_abi) as GmpManagerInterface; + } + static connect(address: string, runner?: ContractRunner | null): GmpManager { + return new Contract(address, _abi, runner) as unknown as GmpManager; + } +} diff --git a/evm/ts/src/ethers-contracts/1_1_0/factories/MultiTokenNtt__factory.ts b/evm/ts/src/ethers-contracts/1_1_0/factories/MultiTokenNtt__factory.ts new file mode 100644 index 000000000..24466b455 --- /dev/null +++ b/evm/ts/src/ethers-contracts/1_1_0/factories/MultiTokenNtt__factory.ts @@ -0,0 +1,1890 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { + Contract, + ContractFactory, + ContractTransactionResponse, + Interface, +} from "ethers"; +import type { + Signer, + BigNumberish, + AddressLike, + ContractDeployTransaction, + ContractRunner, +} from "ethers"; +import type { NonPayableOverrides } from "../common.js"; +import type { + MultiTokenNtt, + MultiTokenNttInterface, +} from "../MultiTokenNtt.js"; + +const _abi = [ + { + type: "constructor", + inputs: [ + { + name: "_gmpManager", + type: "address", + internalType: "contract IGmpManager", + }, + { + name: "_rateLimitDuration", + type: "uint64", + internalType: "uint64", + }, + { + name: "_skipRateLimiting", + type: "bool", + internalType: "bool", + }, + { + name: "_tokenImplementation", + type: "address", + internalType: "address", + }, + { + name: "_weth", + type: "address", + internalType: "address", + }, + ], + stateMutability: "nonpayable", + }, + { + type: "receive", + stateMutability: "payable", + }, + { + type: "function", + name: "NTT_MANAGER_VERSION", + inputs: [], + outputs: [ + { + name: "", + type: "string", + internalType: "string", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "WETH", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract IWETH", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "cancelOutboundQueuedTransfer", + inputs: [ + { + name: "messageSequence", + type: "uint64", + internalType: "uint64", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "completeInboundQueuedTransfer", + inputs: [ + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "nativeTokenTransfer", + type: "tuple", + internalType: "struct NativeTokenTransferCodec.NativeTokenTransfer", + components: [ + { + name: "amount", + type: "uint72", + internalType: "TrimmedAmount", + }, + { + name: "token", + type: "tuple", + internalType: "struct TokenInfo", + components: [ + { + name: "meta", + type: "tuple", + internalType: "struct TokenMeta", + components: [ + { + name: "name", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "symbol", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "decimals", + type: "uint8", + internalType: "uint8", + }, + ], + }, + { + name: "token", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + ], + }, + { + name: "sender", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "to", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "additionalPayload", + type: "bytes", + internalType: "bytes", + }, + ], + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "completeOutboundQueuedTransfer", + inputs: [ + { + name: "messageSequence", + type: "uint64", + internalType: "uint64", + }, + ], + outputs: [ + { + name: "", + type: "uint64", + internalType: "uint64", + }, + ], + stateMutability: "payable", + }, + { + type: "function", + name: "getCurrentInboundCapacity", + inputs: [ + { + name: "tokenId", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + name: "chainId_", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getCurrentOutboundCapacity", + inputs: [ + { + name: "tokenId", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + ], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getInboundLimitParams", + inputs: [ + { + name: "tokenId", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + name: "chainId_", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "", + type: "tuple", + internalType: "struct RateLimitLib.RateLimitParams", + components: [ + { + name: "limit", + type: "uint72", + internalType: "TrimmedAmount", + }, + { + name: "currentCapacity", + type: "uint72", + internalType: "TrimmedAmount", + }, + { + name: "lastTxTimestamp", + type: "uint64", + internalType: "uint64", + }, + ], + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getInboundQueuedTransfer", + inputs: [ + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + ], + outputs: [ + { + name: "", + type: "tuple", + internalType: "struct IMultiTokenRateLimiter.InboundQueuedTransfer", + components: [ + { + name: "txTimestamp", + type: "uint64", + internalType: "uint64", + }, + { + name: "sourceChainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "transferDigest", + type: "bytes20", + internalType: "bytes20", + }, + ], + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getMigratesImmutables", + inputs: [], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getOutboundLimitParams", + inputs: [ + { + name: "tokenId", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + ], + outputs: [ + { + name: "", + type: "tuple", + internalType: "struct RateLimitLib.RateLimitParams", + components: [ + { + name: "limit", + type: "uint72", + internalType: "TrimmedAmount", + }, + { + name: "currentCapacity", + type: "uint72", + internalType: "TrimmedAmount", + }, + { + name: "lastTxTimestamp", + type: "uint64", + internalType: "uint64", + }, + ], + }, + ], + stateMutability: "pure", + }, + { + type: "function", + name: "getOutboundQueuedTransfer", + inputs: [ + { + name: "queueSequence", + type: "uint64", + internalType: "uint64", + }, + ], + outputs: [ + { + name: "", + type: "tuple", + internalType: "struct IMultiTokenRateLimiter.OutboundQueuedTransfer", + components: [ + { + name: "recipient", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "refundAddress", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "sender", + type: "address", + internalType: "address", + }, + { + name: "amount", + type: "uint72", + internalType: "TrimmedAmount", + }, + { + name: "recipientChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "txTimestamp", + type: "uint64", + internalType: "uint64", + }, + { + name: "token", + type: "address", + internalType: "address", + }, + { + name: "transceiverInstructions", + type: "bytes", + internalType: "bytes", + }, + ], + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getPeer", + inputs: [ + { + name: "chainId_", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [ + { + name: "", + type: "tuple", + internalType: "struct Peers.Peer", + components: [ + { + name: "peerAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getToken", + inputs: [ + { + name: "tokenId", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + ], + outputs: [ + { + name: "", + type: "address", + internalType: "address", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getTokenId", + inputs: [ + { + name: "token", + type: "address", + internalType: "address", + }, + ], + outputs: [ + { + name: "", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + name: "", + type: "uint8", + internalType: "enum MultiTokenNtt.Mode", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "gmpManager", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract IGmpManager", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "initialize", + inputs: [], + outputs: [], + stateMutability: "payable", + }, + { + type: "function", + name: "isPaused", + inputs: [], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "migrate", + inputs: [], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "overrideLocalAsset", + inputs: [ + { + name: "token", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + name: "localToken", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "owner", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "address", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "pause", + inputs: [], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "pauser", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "address", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "rateLimitDuration", + inputs: [], + outputs: [ + { + name: "", + type: "uint64", + internalType: "uint64", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "receiveMessage", + inputs: [ + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "sourceChainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "sender", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "data", + type: "bytes", + internalType: "bytes", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setInboundLimit", + inputs: [ + { + name: "token", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + name: "limit", + type: "uint256", + internalType: "uint256", + }, + { + name: "chainId_", + type: "uint16", + internalType: "uint16", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setOutboundLimit", + inputs: [ + { + name: "token", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + name: "limit", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setPeer", + inputs: [ + { + name: "_chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "peerAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "tokenImplementation", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "address", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "tokenProxyCreationCode", + inputs: [], + outputs: [ + { + name: "", + type: "bytes", + internalType: "bytes", + }, + ], + stateMutability: "pure", + }, + { + type: "function", + name: "transfer", + inputs: [ + { + name: "args", + type: "tuple", + internalType: "struct MultiTokenNtt.TransferArgs", + components: [ + { + name: "token", + type: "address", + internalType: "address", + }, + { + name: "amount", + type: "uint256", + internalType: "uint256", + }, + { + name: "recipientChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "recipient", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "refundAddress", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "shouldQueue", + type: "bool", + internalType: "bool", + }, + { + name: "transceiverInstructions", + type: "bytes", + internalType: "bytes", + }, + { + name: "additionalPayload", + type: "bytes", + internalType: "bytes", + }, + ], + }, + ], + outputs: [ + { + name: "", + type: "uint64", + internalType: "uint64", + }, + ], + stateMutability: "payable", + }, + { + type: "function", + name: "transferOwnership", + inputs: [ + { + name: "newOwner", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "transferPauserCapability", + inputs: [ + { + name: "newPauser", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "unpause", + inputs: [], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "upgrade", + inputs: [ + { + name: "newImplementation", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "wrapAndTransferGasToken", + inputs: [ + { + name: "args", + type: "tuple", + internalType: "struct MultiTokenNtt.GasTokenTransferArgs", + components: [ + { + name: "amount", + type: "uint256", + internalType: "uint256", + }, + { + name: "recipientChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "recipient", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "refundAddress", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "shouldQueue", + type: "bool", + internalType: "bool", + }, + { + name: "transceiverInstructions", + type: "bytes", + internalType: "bytes", + }, + { + name: "additionalPayload", + type: "bytes", + internalType: "bytes", + }, + ], + }, + ], + outputs: [ + { + name: "", + type: "uint64", + internalType: "uint64", + }, + ], + stateMutability: "payable", + }, + { + type: "event", + name: "AdminChanged", + inputs: [ + { + name: "previousAdmin", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "newAdmin", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "BeaconUpgraded", + inputs: [ + { + name: "beacon", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "InboundTransferLimitUpdated", + inputs: [ + { + name: "chainId", + type: "uint16", + indexed: true, + internalType: "uint16", + }, + { + name: "oldLimit", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newLimit", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "InboundTransferQueued", + inputs: [ + { + name: "digest", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Initialized", + inputs: [ + { + name: "version", + type: "uint64", + indexed: false, + internalType: "uint64", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "NotPaused", + inputs: [ + { + name: "notPaused", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "OutboundTransferCancelled", + inputs: [ + { + name: "sequence", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "recipient", + type: "address", + indexed: false, + internalType: "address", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "OutboundTransferLimitUpdated", + inputs: [ + { + name: "oldLimit", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "newLimit", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "OutboundTransferQueued", + inputs: [ + { + name: "queueSequence", + type: "uint64", + indexed: false, + internalType: "uint64", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "OutboundTransferRateLimited", + inputs: [ + { + name: "sender", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "sequence", + type: "uint64", + indexed: false, + internalType: "uint64", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "currentCapacity", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "OwnershipTransferred", + inputs: [ + { + name: "previousOwner", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "newOwner", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Paused", + inputs: [ + { + name: "paused", + type: "bool", + indexed: false, + internalType: "bool", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "PauserTransferred", + inputs: [ + { + name: "oldPauser", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "newPauser", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "PeerUpdated", + inputs: [ + { + name: "chainId", + type: "uint16", + indexed: false, + internalType: "uint16", + }, + { + name: "oldPeerAddress", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + { + name: "newPeerAddress", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "TransferRedeemed", + inputs: [ + { + name: "digest", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "TransferSent", + inputs: [ + { + name: "sequence", + type: "uint64", + indexed: false, + internalType: "uint64", + }, + { + name: "tokenChain", + type: "uint16", + indexed: true, + internalType: "uint16", + }, + { + name: "token", + type: "bytes32", + indexed: true, + internalType: "bytes32", + }, + { + name: "recipient", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + { + name: "refundAddress", + type: "bytes32", + indexed: false, + internalType: "bytes32", + }, + { + name: "amount", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + { + name: "toChain", + type: "uint16", + indexed: true, + internalType: "uint16", + }, + { + name: "sender", + type: "address", + indexed: false, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Upgraded", + inputs: [ + { + name: "implementation", + type: "address", + indexed: true, + internalType: "address", + }, + ], + anonymous: false, + }, + { + type: "error", + name: "BurnAmountDifferentThanBalanceDiff", + inputs: [ + { + name: "balanceBefore", + type: "uint256", + internalType: "uint256", + }, + { + name: "balanceAfter", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "CancellerNotSender", + inputs: [ + { + name: "sender", + type: "address", + internalType: "address", + }, + { + name: "canceller", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "CapacityCannotExceedLimit", + inputs: [ + { + name: "newCurrentCapacity", + type: "uint72", + internalType: "TrimmedAmount", + }, + { + name: "newLimit", + type: "uint72", + internalType: "TrimmedAmount", + }, + ], + }, + { + type: "error", + name: "FailedToDeployToken", + inputs: [], + }, + { + type: "error", + name: "InboundQueuedTransferDigestMismatch", + inputs: [ + { + name: "digest", + type: "bytes20", + internalType: "bytes20", + }, + { + name: "expectedDigest", + type: "bytes20", + internalType: "bytes20", + }, + ], + }, + { + type: "error", + name: "InboundQueuedTransferNotFound", + inputs: [ + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + type: "error", + name: "InboundQueuedTransferStillQueued", + inputs: [ + { + name: "digest", + type: "bytes32", + internalType: "bytes32", + }, + { + name: "transferTimestamp", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "IncorrectPrefix", + inputs: [ + { + name: "prefix", + type: "bytes4", + internalType: "bytes4", + }, + ], + }, + { + type: "error", + name: "InvalidInitialization", + inputs: [], + }, + { + type: "error", + name: "InvalidPauser", + inputs: [ + { + name: "account", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "InvalidPeer", + inputs: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "peerAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + type: "error", + name: "InvalidPeerChainIdZero", + inputs: [], + }, + { + type: "error", + name: "InvalidPeerZeroAddress", + inputs: [], + }, + { + type: "error", + name: "InvalidRecipient", + inputs: [], + }, + { + type: "error", + name: "InvalidRefundAddress", + inputs: [], + }, + { + type: "error", + name: "InvalidSender", + inputs: [], + }, + { + type: "error", + name: "InvalidTargetChain", + inputs: [ + { + name: "targetChain", + type: "uint16", + internalType: "uint16", + }, + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + ], + }, + { + type: "error", + name: "LengthMismatch", + inputs: [ + { + name: "encodedLength", + type: "uint256", + internalType: "uint256", + }, + { + name: "expectedLength", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "NotAnEvmAddress", + inputs: [ + { + name: "", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + type: "error", + name: "NotEnoughCapacity", + inputs: [ + { + name: "token", + type: "tuple", + internalType: "struct TokenId", + components: [ + { + name: "chainId", + type: "uint16", + internalType: "uint16", + }, + { + name: "tokenAddress", + type: "bytes32", + internalType: "bytes32", + }, + ], + }, + { + name: "currentCapacity", + type: "uint256", + internalType: "uint256", + }, + { + name: "amount", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "NotInitializing", + inputs: [], + }, + { + type: "error", + name: "NotMigrating", + inputs: [], + }, + { + type: "error", + name: "NttTokenReceiverCallFailed", + inputs: [ + { + name: "recipient", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "NumberOfDecimalsNotEqual", + inputs: [ + { + name: "decimals", + type: "uint8", + internalType: "uint8", + }, + { + name: "decimalsOther", + type: "uint8", + internalType: "uint8", + }, + ], + }, + { + type: "error", + name: "OnlyDelegateCall", + inputs: [], + }, + { + type: "error", + name: "OnlyGmpManagerAllowed", + inputs: [], + }, + { + type: "error", + name: "OutboundQueuedTransferNotFound", + inputs: [ + { + name: "queueSequence", + type: "uint64", + internalType: "uint64", + }, + ], + }, + { + type: "error", + name: "OutboundQueuedTransferStillQueued", + inputs: [ + { + name: "queueSequence", + type: "uint64", + internalType: "uint64", + }, + { + name: "transferTimestamp", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "OwnableInvalidOwner", + inputs: [ + { + name: "owner", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "OwnableUnauthorizedAccount", + inputs: [ + { + name: "account", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "PayloadTooLong", + inputs: [ + { + name: "length", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "PayloadTooLong", + inputs: [ + { + name: "length", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "QueuedTransferWithPayload", + inputs: [], + }, + { + type: "error", + name: "ReentrancyGuardReentrantCall", + inputs: [], + }, + { + type: "error", + name: "RefundFailed", + inputs: [ + { + name: "refundAmount", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "RequireContractIsNotPaused", + inputs: [], + }, + { + type: "error", + name: "RequireContractIsPaused", + inputs: [], + }, + { + type: "error", + name: "StaticcallFailed", + inputs: [], + }, + { + type: "error", + name: "TransferAmountHasDust", + inputs: [ + { + name: "amount", + type: "uint256", + internalType: "uint256", + }, + { + name: "dust", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "TransferFailed", + inputs: [], + }, + { + type: "error", + name: "UndefinedRateLimiting", + inputs: [], + }, + { + type: "error", + name: "UnexpectedDeployer", + inputs: [ + { + name: "expectedOwner", + type: "address", + internalType: "address", + }, + { + name: "owner", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "UnexpectedMsgValue", + inputs: [], + }, + { + type: "error", + name: "ZeroAmount", + inputs: [], + }, +] as const; + +const _bytecode = + "0x6101606040523480156200001257600080fd5b506040516200632038038062006320833981016040819052620000359162000211565b8484846001600160401b0382161580156200004e575080155b806200006b57506001600160401b038216158015906200006b5750805b156200008a5760405163e543ef0560e01b815260040160405180910390fd5b506001600160401b03166080526001600160a01b031660a052620000ad62000147565b3060c0523360e05260408051634d4502c960e11b815290516001600160a01b03871691639a8a05929160048083019260209291908290030181865afa158015620000fb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001219190620002a0565b61ffff16610120526001600160a01b0391821661010052166101405250620002cd915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620001985760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620001f85780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6001600160a01b0381168114620001f857600080fd5b600080600080600060a086880312156200022a57600080fd5b85516200023781620001fb565b60208701519095506001600160401b03811681146200025557600080fd5b604087015190945080151581146200026c57600080fd5b60608701519093506200027f81620001fb565b60808701519092506200029281620001fb565b809150509295509295909350565b600060208284031215620002b357600080fd5b815161ffff81168114620002c657600080fd5b9392505050565b60805160a05160c05160e051610100516101205161014051615f116200040f600039600081816105b6015281816116df015281816127c9015281816136000152613643015260008181610c0e015281816112d8015281816118d701528181611d02015261341f01526000818161038e015261327c01526000818161335b015261339701526000612a2c0152600081816104e001528181611822015281816130cf01528181613947015261409301526000818161049401528181610af901528181610f5b015281816114e9015281816117c701528181611e2601528181611fdc015281816131710152818161436b015281816143a80152818161454a01528181614583015281816145b4015281816145ee01528181614791015281816147ce015281816148fc015281816149360152818161497b01526149b40152615f116000f3fe6080604052600436106102135760003560e01c80638456cb5911610118578063c033e0db116100a0578063ebd47c2f1161006f578063ebd47c2f14610680578063f1537686146106a0578063f2fde38b146106ce578063f7514fbc146106ee578063fd96063c1461070e57600080fd5b8063c033e0db146105ed578063c0b07bde14610600578063c128d17014610631578063e2069e1e1461066057600080fd5b806397c35146116100e757806397c35146146105695780639fd0506d1461057c578063a461758414610591578063ad5c4648146105a4578063b187bd26146105d857600080fd5b80638456cb591461050a5780638da5cb5b1461051f5780638fd3ab801461053457806394c913651461054957600080fd5b806332cf4cd51161019b578063689f90c31161016a578063689f90c31461043d5780636f6a51e61461046257806374aa7bfc146104825780637c9e8a10146104ce5780638129fc1c1461050257600080fd5b806332cf4cd5146103c85780633434a266146103e85780633f4ba83a146104085780634222f40b1461041d57600080fd5b80630ebfdc8a116101e25780630ebfdc8a146102df5780631bacc92b146102ff5780631f97c9a8146103215780632cc7fc821461034e5780632f3a3d5d1461037c57600080fd5b8063036de8af1461021f578063045169ad1461024157806307150aef146102615780630900f010146102bf57600080fd5b3661021a57005b600080fd5b34801561022b57600080fd5b5061023f61023a36600461500c565b610767565b005b34801561024d57600080fd5b5061023f61025c36600461505c565b6107d3565b34801561026d57600080fd5b5061028161027c3660046151ad565b61081f565b6040805182516001600160481b03908116825260208085015190911690820152918101516001600160401b0316908201526060015b60405180910390f35b3480156102cb57600080fd5b5061023f6102da36600461500c565b61089e565b3480156102eb57600080fd5b5061023f6102fa3660046151e5565b6108b2565b34801561030b57600080fd5b506103146108f7565b6040516102b69190615260565b34801561032d57600080fd5b5061034161033c366004615288565b61096f565b6040516102b691906152a5565b34801561035a57600080fd5b5061036e61036936600461533b565b610ae3565b6040519081526020016102b6565b34801561038857600080fd5b506103b07f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102b6565b3480156103d457600080fd5b5061023f6103e3366004615357565b610b48565b3480156103f457600080fd5b5061028161040336600461533b565b610b5e565b34801561041457600080fd5b5061023f610bc4565b34801561042957600080fd5b5061023f610438366004615383565b610bd6565b34801561044957600080fd5b50610452610e6c565b60405190151581526020016102b6565b34801561046e57600080fd5b5061023f61047d3660046154ca565b610e7f565b34801561048e57600080fd5b506104b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160401b0390911681526020016102b6565b3480156104da57600080fd5b506103b07f000000000000000000000000000000000000000000000000000000000000000081565b61023f61107f565b34801561051657600080fd5b5061023f611181565b34801561052b57600080fd5b506103b0611194565b34801561054057600080fd5b5061023f6111c2565b34801561055557600080fd5b506103b061056436600461533b565b6112d4565b6104b6610577366004615288565b611350565b34801561058857600080fd5b506103b061161d565b6104b661059f3660046155a2565b611636565b3480156105b057600080fd5b506103b07f000000000000000000000000000000000000000000000000000000000000000081565b3480156105e457600080fd5b5061045261168a565b6104b66105fb366004615684565b61169f565b34801561060c57600080fd5b50610314604051806040016040528060058152602001640312e312e360dc1b81525081565b34801561063d57600080fd5b5061065161064c366004615754565b611763565b604051905181526020016102b6565b34801561066c57600080fd5b5061036e61067b3660046151ad565b61179f565b34801561068c57600080fd5b5061023f61069b366004615771565b611817565b3480156106ac57600080fd5b506106c06106bb36600461500c565b61186d565b6040516102b692919061581c565b3480156106da57600080fd5b5061023f6106e936600461500c565b611915565b3480156106fa57600080fd5b5061023f610709366004615288565b611950565b34801561071a57600080fd5b5061072e61072936600461585d565b611bd8565b6040805182516001600160401b0316815260208084015161ffff1690820152918101516001600160601b031916908201526060016102b6565b610777610772611194565b611c55565b6000610781611c9e565b80546001600160a01b038481166001600160a01b031983168117845560405193945091169182907f51c4874e0f23f262e04a38c51751336dde72126d67f53eb672aaff02996b3ef690600090a3505050565b6107db611ccc565b60006107f46107ef3686900386018661533b565b611cfe565b90506108196108083686900386018661533b565b610813858480611dc7565b84611e20565b50505050565b604080516060810182526000808252602082018190529181019190915261084583611e69565b61ffff831660009081526020918252604090819020815160608101835290546001600160481b038082168352600160481b82041693820193909352600160901b9092046001600160401b03169082015290505b92915050565b6108a6611ccc565b6108af81611ec8565b50565b6108ba611ccc565b60006108ce6107ef3685900385018561533b565b90506108f26108e23685900385018561533b565b6108ed848480611dc7565b611fd6565b505050565b606073__$3a5f69cefc093539f925e73bc45cac585e$__63c55259906040518163ffffffff1660e01b8152600401600060405180830381865af4158015610942573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261096a91908101906158a6565b905090565b604080516101008101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c082019290925260e08101919091526109ba61200b565b6001600160401b03838116600090815260209283526040908190208151610100810183528154815260018201549481019490945260028101546001600160a01b0380821693860193909352600160a01b81046001600160481b03166060860152600160e81b900461ffff166080850152600381015492831660a0850152600160401b9092041660c083015260048101805460e084019190610a5a906158ee565b80601f0160208091040260200160405190810160405280929190818152602001828054610a86906158ee565b8015610ad35780601f10610aa857610100808354040283529160200191610ad3565b820191906000526020600020905b815481529060010190602001808311610ab657829003601f168201915b5050505050815250509050919050565b600080610aef83612039565b90506000610b1d827f0000000000000000000000000000000000000000000000000000000000000000612090565b90506000610b2a85611cfe565b9050610b3f6001600160481b03831682612156565b95945050505050565b610b50611ccc565b610b5a8282612176565b5050565b6040805160608101825260008082526020820181905291810191909152610b8482612039565b6040805160608101825291546001600160481b038082168452600160481b8204166020840152600160901b90046001600160401b03169082015292915050565b610bcc611ccc565b610bd461224e565b565b610bde611ccc565b610beb6020830183615754565b61ffff1615801590610c005750602082013515155b610c0957600080fd5b61ffff7f000000000000000000000000000000000000000000000000000000000000000016610c3b6020840184615754565b61ffff1603610ca55760405162461bcd60e51b815260206004820152602b60248201527f43616e6e6f74206f76657272696465206e617469766520746f6b656e2072657060448201526a3932b9b2b73a30ba34b7b760a91b60648201526084015b60405180910390fd5b6000610caf6122b4565b6001600160a01b038316600090815260209182526040908190208151808301909252805461ffff16825260010154918101829052915015610d8a57610cf76020840184615754565b61ffff16816000015161ffff16148015610d18575082602001358160200151145b610d8a5760405162461bcd60e51b815260206004820152603860248201527f4c6f63616c20746f6b656e20616c726561647920726570726573656e7473206160448201527f20646966666572656e7420666f726569676e20617373657400000000000000006064820152608401610c9c565b6000610d95836122e2565b90506040518060400160405280846001600160a01b0316815260200182815250610dbd6123fa565b6000610dcc6020880188615754565b61ffff168152602080820192909252604090810160009081208884013582528352819020835181546001600160a01b0319166001600160a01b03909116178155928201518051600185015591820151600284015501516003909101805460ff191660ff90921691909117905583610e416122b4565b6001600160a01b038516600090815260209190915260409020610e648282615922565b505050505050565b6000610e76612428565b5460ff16919050565b610e87612456565b610e8f61168a565b15610ead576040516309e3d0f360e11b815260040160405180910390fd5b6000610eb88261248e565b8051906020012090506000610ecc84611bd8565b80519091506001600160401b0316600003610efd57604051630301bcaf60e61b815260048101859052602401610c9c565b816001600160601b03191681604001516001600160601b03191614610f4f576040808201519051634af6f89b60e11b81526001600160601b031980851660048301529091166024820152604401610c9c565b80516001600160401b037f0000000000000000000000000000000000000000000000000000000000000000811691610f88911642615961565b1015610fbc5780516040516301cb739d60e71b8152600481018690526001600160401b039091166024820152604401610c9c565b610fc46125a1565b600085815260209182526040812080546001600160f01b031916905590840151610fed906125cf565b90506000610ffe85606001516126d2565b90506000611013866020015160200151611cfe565b90506000611043828361103c858b600001516001600160481b031661215690919063ffffffff16565b9190611dc7565b90506110628885858460008c608001518b602001518e604001516126fe565b505050505050610b5a6001600080516020615e9c83398151915255565b611087612a22565b600080516020615ebc8339815191528054600160401b810460ff1615906001600160401b03166000811580156110ba5750825b90506000826001600160401b031660011480156110d65750303b155b9050811580156110e4575080155b156111025760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561112c57845460ff60401b1916600160401b1785555b611134612a6b565b831561117a57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b61118c610772611194565b610bd4612a73565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6111ca612a22565b600080516020615ebc833981519152546001600160401b03166111ee906001615974565b600080516020615ebc8339815191528054600160401b900460ff1680611221575080546001600160401b03808416911610155b1561123f5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b178155611268612ad4565b5460ff1661128957604051632866815360e11b815260040160405180910390fd5b805460ff60401b191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16826000015161ffff16036113165761089882602001516126d2565b61131e6123fa565b825161ffff166000908152602091825260408082209483015182529390915291909120546001600160a01b0316919050565b600061135a612456565b61136261168a565b15611380576040516309e3d0f360e11b815260040160405180910390fd5b600061138a61200b565b6001600160401b03848116600090815260209283526040908190208151610100810183528154815260018201549481019490945260028101546001600160a01b0380821693860193909352600160a01b81046001600160481b03166060860152600160e81b900461ffff166080850152600381015492831660a0850152600160401b9092041660c083015260048101805460e08401919061142a906158ee565b80601f0160208091040260200160405190810160405280929190818152602001828054611456906158ee565b80156114a35780601f10611478576101008083540402835291602001916114a3565b820191906000526020600020905b81548152906001019060200180831161148657829003601f168201915b50505050508152505090508060a001516001600160401b03166000036114e757604051635feafa3160e11b81526001600160401b0384166004820152602401610c9c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160a001516001600160401b03164261152a9190615961565b10156115625760a081015160405163c06cf05f60e01b81526001600160401b0380861660048301529091166024820152604401610c9c565b61156a61200b565b6001600160401b038416600090815260209190915260408120818155600181018290556002810180546001600160f81b03191690556003810180546001600160e01b0319169055906115bf6004830182614f27565b50506115fe34848360c00151846060015185608001518660000151876020015188604001518960e0015160405180602001604052806000815250612b02565b9150506116186001600080516020615e9c83398151915255565b919050565b6000611627611c9e565b546001600160a01b0316919050565b6000611640612456565b61164861168a565b15611666576040516309e3d0f360e11b815260040160405180910390fd5b611671826001612c49565b90506116186001600080516020615e9c83398151915255565b600080611695612ce8565b5460021492915050565b60006116a9612456565b6116b161168a565b156116cf576040516309e3d0f360e11b815260040160405180910390fd5b60006040518061010001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815260200184600001518152602001846020015161ffff16815260200184604001518152602001846060015181526020018460800151151581526020018460a0015181526020018460c0015181525090506115fe816000612c49565b60408051602081019091526000815261177a612d16565b61ffff9092166000908152602092835260409081902081519384019091525482525090565b6000806117ab84611e69565b61ffff841660009081526020919091526040812091506117eb827f0000000000000000000000000000000000000000000000000000000000000000612090565b905060006117f886611cfe565b905061180d6001600160481b03831682612156565b9695505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611860576040516331ca071b60e21b815260040160405180910390fd5b61117a8585858585612d44565b604080518082019091526000808252602082015260008061188c6122b4565b6001600160a01b038516600090815260209182526040908190208151808301909252805461ffff16808352600190910154928201929092529150156118d5579360019350915050565b7f000000000000000000000000000000000000000000000000000000000000000061ffff1681526001600160a01b03841660208201529360009350915050565b61191d611ccc565b6001600160a01b03811661194757604051631e4fbdf760e01b815260006004820152602401610c9c565b6108af81612d9c565b611958612456565b61196061168a565b1561197e576040516309e3d0f360e11b815260040160405180910390fd5b600061198861200b565b6001600160401b03838116600090815260209283526040908190208151610100810183528154815260018201549481019490945260028101546001600160a01b0380821693860193909352600160a01b81046001600160481b03166060860152600160e81b900461ffff166080850152600381015492831660a0850152600160401b9092041660c083015260048101805460e084019190611a28906158ee565b80601f0160208091040260200160405190810160405280929190818152602001828054611a54906158ee565b8015611aa15780601f10611a7657610100808354040283529160200191611aa1565b820191906000526020600020905b815481529060010190602001808311611a8457829003601f168201915b50505050508152505090508060a001516001600160401b0316600003611ae557604051635feafa3160e11b81526001600160401b0383166004820152602401610c9c565b60408101516001600160a01b03163314611b2957604080820151905163ceb40a8560e01b81523360048201526001600160a01b039091166024820152604401610c9c565b611b3161200b565b6001600160401b038316600090815260209190915260408120818155600181018290556002810180546001600160f81b03191690556003810180546001600160e01b031916905590611b866004830182614f27565b5050611bc0826001600160401b031660001b8260c0015133846060015160016040518060200160405280600081525060008060001b6126fe565b506108af6001600080516020615e9c83398151915255565b6040805160608101825260008082526020820181905291810191909152611bfd6125a1565b6000928352602090815260409283902083516060808201865291546001600160401b0381168252600160401b810461ffff1693820193909352600160501b909204901b6001600160601b031916928101929092525090565b33611c5e61161d565b6001600160a01b031614158015611c7e57506001600160a01b0381163314155b156108af5760405163e2a08e5d60e01b8152336004820152602401610c9c565b60008061089860017fbfa91572ce1e5fe8776a160d3b1f862e83f5ee2c080a7423b4761602a3ad124a615961565b33611cd5611194565b6001600160a01b031614610bd45760405163118cdaa760e01b8152336004820152602401610c9c565b60007f000000000000000000000000000000000000000000000000000000000000000061ffff16826000015161ffff1603611d90576000611d4283602001516126d2565b90506000611d72826040518060400160405280600a815260200169646563696d616c73282960b01b815250612e0d565b905080806020019051810190611d88919061599b565b949350505050565b611d986123fa565b825161ffff1660009081526020918252604080822094830151825293909152919091206003015460ff16919050565b600080611dde611dd8600886612ed6565b84612ed6565b90506000611ded868684612ef2565b9050611e14611dfb82612f5b565b8360ff1660089190911b68ffffffffffffffff00161790565b925050505b9392505050565b6108f2827f0000000000000000000000000000000000000000000000000000000000000000611e4e86611e69565b61ffff85166000908152602091909152604090209190612fc3565b60008082604051602001611e7d91906159b8565b60408051601f198184030181529190528051602090910120611ec060017f6473f680a37cfb54f66445ef18036c9f891a682c70bb8e4674f5d36e211ba893615961565b189392505050565b611ed0612a22565b611ed98161308d565b6000611ee3612ad4565b805490915060ff1615611ef857611ef86159d3565b805460ff191660011781556040805163011fa75760e71b815290513091638fd3ab8091600480830192600092919082900301818387803b158015611f3b57600080fd5b505af1158015611f4f573d6000803e3d6000fd5b50505050306001600160a01b031663689f90c36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159e9565b611fc157611fc16130cd565b611fcb6000613211565b805460ff1916905550565b610b5a817f000000000000000000000000000000000000000000000000000000000000000061200485612039565b9190612fc3565b60008061089860017f88e530814ab5625345088d8b6ae477a7b1cc43d112909d0c9b66cab1ab9ed6c4615961565b6000808260405160200161204d91906159b8565b60408051601f198184030181529190528051602090910120611ec060017f2a12c4997b0cb4fe51033104ae9bc2615917156119cfe2b3cbe348041d8d94ba615961565b6000816001600160401b03166000036120c1578254600160481b900460ff1668ffffffffffffffff00179050610898565b82546001600160401b03600160901b820481164203916000918581169160081c168302816120f1576120f1615a06565b86546001600160401b03600160481b8204600890811c821694909304939093019350600092612124928592901c1661322c565b905061180d61213282612f5b565b8754600160481b900460ff1660ff1660089190911b68ffffffffffffffff00161790565b60006001600160401b03600884901c1660ff84168261180d838387612ef2565b8161ffff1660000361219b5760405163100b0f2760e11b815260040160405180910390fd5b806121b95760405163f839a0cb60e01b815260040160405180910390fd5b60006121c3612d16565b61ffff84166000908152602091825260409081902081519283019091525481529050816121ee612d16565b61ffff8516600081815260209283526040908190209390935583518351918252918101919091529081018390527f6b8e3e5d5cb35ca559551a3a468913b588421f8eeb87fabc088aa03638ce1369906060015b60405180910390a1505050565b61225661168a565b61227357604051637e38d1d360e11b815260040160405180910390fd5b61227d600161323b565b604051600081527fe11c2112add17fb763d3bd59f63b10429c3e11373da4fb8ef6725107a2fdc4b0906020015b60405180910390a1565b60008061089860017fa81f8799e09b034e31f6dacb11cac1c94b38068dd2e76779232a66ee50bfce26615961565b6040805160608101825260008082526020820181905291810191909152606061232b836040518060400160405280600881526020016773796d626f6c282960c01b815250612e0d565b905060008180602001905181019061234391906158a6565b905060006020820151905061237685604051806040016040528060068152602001656e616d65282960d01b815250612e0d565b925060008380602001905181019061238e91906158a6565b90506000602082015190506123c5876040518060400160405280600a815260200169646563696d616c73282960b01b815250612e0d565b94506000858060200190518101906123dd919061599b565b9187525060208601929092525060ff166040840152509092915050565b60008061089860017fb25908bf1d6944231b0893d0a6983df22fdaaae9d33fc474848a5fff468575fc615961565b60008061089860017f5443fea4dc453d96b81ce55b62e11a4094cc4cbb8a360956a7253cfdb42506cc615961565b600080516020615e9c83398151915280546001190161248857604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b80516080820151516060919061ffff10156124c55782608001515160405163a341969160e01b8152600401610c9c91815260200190565b608083015151632653551560e21b60ff8316600884901c6001600160401b0316602087015160405163dcb9bd4f60e01b815273__$4033db715c90f2390978d4fb71beaa4caa$__9163dcb9bd4f916125209190600401615a5a565b600060405180830381865af415801561253d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261256591908101906158a6565b60408089015160608a015160808b0151925161258997969594938991602001615a68565b60405160208183030381529060405292505050919050565b60008061089860017f4bc3912cbaafdafac09ae32823daf95236e8f3c7440dda1c7298418edff173c5615961565b6000806125df83602001516112d4565b90506001600160a01b038116610898576125f883613248565b604080518082019091526001600160a01b0382168152845160208201529091506126206123fa565b602085810180515161ffff166000908152928252604080842082518401518552835292839020845181546001600160a01b0319166001600160a01b0390911617815593820151805160018601559182015160028501559101516003909201805460ff191660ff90931692909217909155516126996122b4565b6001600160a01b03831660009081526020918252604090208251815461ffff191661ffff90911617815591015160019091015592915050565b600060a082901c156126fa5760405163033b960d60e41b815260048101839052602401610c9c565b5090565b60008061270a8961186d565b91509150600061272c61271c84611cfe565b6001600160481b038a1690612156565b9050861561278257604080518c81526001600160a01b038b1660208201529081018290527ff80e572ae1b63e2449629b6c7d783add85c36473926f216077f17ee002bcfd079060600160405180910390a16127ae565b6040518b907f504e6efe18ab9eed10dc6501a417f5b12a2f7f2b1593aed9b89f9bce3cf29a9190600090a25b60008260018111156127c2576127c2615806565b036128ed577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168a6001600160a01b0316036128d457604051632e1a7d4d60e01b8152600481018290526001600160a01b038b1690632e1a7d4d90602401600060405180830381600087803b15801561284257600080fd5b505af1158015612856573d6000803e3d6000fd5b505050506000896001600160a01b03168260405160006040518083038185875af1925050503d80600081146128a7576040519150601f19603f3d011682016040523d82523d6000602084013e6128ac565b606091505b50509050806128ce576040516312171d8360e31b815260040160405180910390fd5b50612969565b6128e86001600160a01b038b168a836132e5565b612969565b600182600181111561290157612901615806565b0361021a576040516340c10f1960e01b81526001600160a01b038a81166004830152602482018390528b16906340c10f1990604401600060405180830381600087803b15801561295057600080fd5b505af1158015612964573d6000803e3d6000fd5b505050505b855115612a0157886001600160a01b031663b0474b9c8b612989876126d2565b848a8a8a6040518763ffffffff1660e01b81526004016129ae96959493929190615af9565b600060405180830381600087803b1580156129c857600080fd5b505af19250505080156129d9575060015b612a0157604051630583627160e41b81526001600160a01b038a166004820152602401610c9c565b5050505050505050505050565b6001600080516020615e9c83398151915255565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bd457604051633c64f99360e21b815260040160405180910390fd5b610bd4613348565b612a7b61168a565b15612a99576040516309e3d0f360e11b815260040160405180910390fd5b612aa3600261323b565b604051600181527f0e2fb031ee032dc02d8011dc50b816eb450cf856abd8261680dac74f72165bd2906020016122aa565b60008061089860017f7487ca88d037ca20519908b1ee7556206bef53bce0226a348750cb9d4f688e4f615961565b6040805180820190915260008082526020820181905290606090612b258b61186d565b508091505060006040518060400160405280612b40846133fb565b8152602001838152509050612b926040518060a001604052808d6001600160481b03168152602001838152602001612b7e8a6001600160a01b031690565b81526020018b81526020018781525061248e565b925050612ba38d8a898f868a6134b2565b92506000612bc3612bb383611cfe565b6001600160481b038d1690612156565b6020808401518451604080516001600160401b038a1681529384018e905283018c9052606083018490526001600160a01b038b16608084015292935061ffff808e169391929116907face4867fe6fb81aab943eba9cdd00e13f386affe1946ce84f2f46ad4620372f49060a00160405180910390a45050509a9950505050505050505050565b6080820151600090819015612c62578360800151612c68565b83606001515b905060008460c0015151600014612c83578460c00151612ca0565b604080516001808252818301909252906020820181803683375050505b6080860183905260c086018190526040805160608101909152348152909150859061180d9060208101876001811115612cdb57612cdb615806565b8152602001839052613539565b60008061089860017f64bacf405c5d7f563d3ba5252584a52c37e4fee380fd825b10666c27b8258023615961565b60008061089860017febcc9f646b0f459ff8f387587d536b0af3484cf442e1577400f322334e7d1ef1615961565b612d4e8484613b14565b6000612d8f83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613b7892505050565b9050610e64868683613c7b565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6040805160048152602481019182905260609160009182916001600160a01b0387169190612e3c908790615b45565b60408051918290039091206020830180516001600160e01b03166001600160e01b031990921691909117905251612e739190615b45565b600060405180830381855afa9150503d8060008114612eae576040519150601f19603f3d011682016040523d82523d6000602084013e612eb3565b606091505b509150915081611d8857604051631222cd8360e01b815260040160405180910390fd5b60008160ff168360ff1610612eeb5781611e19565b5090919050565b60008160ff168360ff1603612f08575082611e19565b8160ff168360ff161115612f3c57612f208284615b61565b612f2b90600a615c5e565b612f359085615c6d565b9050611e19565b612f468383615b61565b612f5190600a615c5e565b612f359085615c8f565b60006001600160401b038211156126fa5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610c9c565b82546001600160481b0316612fd781613dec565b1561300557835468ffffffffffffffffff60481b1916600160481b6001600160481b03851602178455613048565b60006130118584612090565b905061301e848383613e0c565b85546001600160481b0391909116600160481b0268ffffffffffffffffff60481b19909116178555505b505081546001600160481b039190911679ffffffffffffffff000000000000000000ffffffffffffffffff1990911617600160901b426001600160401b031602179055565b61309681613eae565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316306001600160a01b0316637c9e8a106040518163ffffffff1660e01b8152600401602060405180830381865afa158015613135573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131599190615ca6565b6001600160a01b03161461316f5761316f6159d3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316306001600160a01b03166374aa7bfc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fb9190615cc3565b6001600160401b031614610bd457610bd46159d3565b8061321a612428565b805460ff191691151591909117905550565b6000818310612eeb5781611e19565b80613244612ce8565b5550565b604051631244d5fd60e31b815260009073__$3a5f69cefc093539f925e73bc45cac585e$__90639226afe8906132a49085907f000000000000000000000000000000000000000000000000000000000000000090600401615ce0565b602060405180830381865af41580156132c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190615ca6565b6040516001600160a01b0383166024820152604481018290526108f290849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613f5c565b61335061402e565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146133ca57604051636345072160e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152336024820152604401610c9c565b34156133e95760405163bd28e88960e01b815260040160405180910390fd5b6133f33333614065565b610bd461407f565b6040805160608101825260008082526020820181905291810191909152815161ffff7f0000000000000000000000000000000000000000000000000000000000000000811691160361345c5761089861345783602001516126d2565b6122e2565b6134646123fa565b825161ffff166000908152602091825260408082209483015182529382528390208351606081018552600182015481526002820154928101929092526003015460ff16928101929092525090565b6000806134bd612d16565b61ffff8816600090815260209190915260409020549050806134f25760405163f839a0cb60e01b815260040160405180910390fd5b476135028989848a8a8a8a61408f565b925060006135104783615961565b90508981101561352c5761352c613527828c615961565b614137565b5050509695505050505050565b600080600061354f84604001516000015161186d565b9150915083604001516020015160000361357c57604051631f2a200560e01b815260040160405180910390fd5b6040840151606001516135a257604051634e46966960e11b815260040160405180910390fd5b6040840151608001516135c85760405163717f139360e11b815260040160405180910390fd5b60006135dc856040015160000151306141a3565b90506000856020015160018111156135f6576135f6615806565b14801561363c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168560400151600001516001600160a01b0316145b156136df577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db08660400151602001516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156136a457600080fd5b505af11580156136b8573d6000803e3d6000fd5b5050505050846040015160200151856000018181516136d79190615961565b905250613704565b604085015160208101519051613704916001600160a01b039091169033903090614274565b6000613718866040015160000151306141a3565b90506137248282615961565b604087015160200152600183600181111561374157613741615806565b0361385a5760408681015180516020909101519151630852cd8d60e31b815260048101929092526001600160a01b0316906342966c6890602401600060405180830381600087803b15801561379557600080fd5b505af19250505080156137a6575060015b6138185760408681015180516020909101519151632770a7eb60e21b815230600482015260248101929092526001600160a01b031690639dc29fac90604401600060405180830381600087803b1580156137ff57600080fd5b505af1158015613813573d6000803e3d6000fd5b505050505b600061382c876040015160000151306141a3565b9050808314613858576040516302156a8f60e01b81526004810184905260248101829052604401610c9c565b505b5050600080600061386a85611cfe565b905061387e818860400151602001516142ac565b92506138936001600160481b03841682614318565b9150506138b16138a285612039565b546001600160481b0316613dec565b613a7e576138bf8482614367565b15613a7457856040015160a0015161391b57836138db85610ae3565b6040808901516020908101519151631d78001560e11b8152845161ffff166004820152930151602484015260448301919091526064820152608401610c9c565b604086015160e00151511561394357604051637a20891760e01b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ff428f096040518163ffffffff1660e01b81526004016020604051808303816000875af11580156139a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139c99190615cc3565b9050336001600160a01b03167ff33512b84e24a49905c26c6991942fc5a9652411769fc1e448f967cdb049f08a82896040015160200151613a0989610ae3565b604080516001600160401b03909416845260208401929092529082015260600160405180910390a2613a6981886040015160000151858a60400151604001518b60400151606001518c6040015160800151338e6040015160c001516143d7565b865161180d90614137565b613a7e8482614548565b613ab3613a8a85611e69565b60408089015181015161ffff1660009081526020929092529020546001600160481b0316613dec565b613aca57613aca84828860400151604001516145b2565b5060408086015160c081015160e08201518851835194840151606085015160809095015193959294613b09949293600093909289929091338a8a612b02565b979650505050505050565b61ffff821615801590613b2657508015155b613b2f57600080fd5b80613b38612d16565b61ffff84166000908152602091909152604090205414610b5a57604051635788c0fd60e11b815261ffff8316600482015260248101829052604401610c9c565b613b80614f61565b600080613b8d8482614631565b925090506001600160e01b03198116632653551560e21b14613bce576040516356d2569d60e01b81526001600160e01b031982166004820152602401610c9c565b818401600181015160099182015160ff8216600882901b68ffffffffffffffff0016178652919093019290613c03868561465c565b60208701919091529350613c1786856146c4565b60408701919091529350613c2b86856146c4565b606087019190915293506000613c4a8786600291810182015192910190565b955061ffff169050613c5d8786836146ea565b60808801919091529450613c71878661475f565b5050505050919050565b613c8361168a565b15613ca1576040516309e3d0f360e11b815260040160405180910390fd5b613ca9612456565b6000613cb48261248e565b8051602091820120908301519091506000613cce826125cf565b90506000613cdf8360200151611cfe565b90506000613d08828361103c858a600001516001600160481b031661215690919063ffffffff16565b90506000613d1987606001516126d2565b9050613d4e613d2b8660200151611e69565b61ffff8a16600090815260209190915260409020546001600160481b0316613dec565b613d93576000613d638660200151848b61478d565b90508015613d8257613d768a8a89614811565b50505050505050613dd5565b613d918660200151848b6148fa565b505b613da36138a28660200151612039565b613db557613db5856020015183614979565b613dce8985838560008c608001518e8e604001516126fe565b5050505050505b6108f26001600080516020615e9c83398151915255565b60006001600160401b03600883901c1615801561089857505060ff161590565b600080613e1984866149e3565b15613e5257613e288486614a08565b9050613e3483826149e3565b613e415760ff8316613e4b565b613e4b8382614a08565b9150613e6b565b613e5c8585614a08565b9050613e688382614a4d565b91505b613e7582866149e3565b15613ea657604051631e74e8fb60e31b81526001600160481b03808416600483015286166024820152604401610c9c565b509392505050565b6001600160a01b0381163b613f1b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610c9c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6000613fb1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614a929092919063ffffffff16565b8051909150156108f25780806020019051810190613fcf91906159e9565b6108f25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c9c565b600080516020615ebc83398151915254600160401b900460ff16610bd457604051631afcd79f60e31b815260040160405180910390fd5b61406d61402e565b61407682614aa1565b610b5a81614ab2565b61408761402e565b610bd4614ac3565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ee0bdb1c898989898989896040518863ffffffff1660e01b81526004016140e896959493929190615d06565b60206040518083038185885af1158015614106573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061412b9190615cc3565b98975050505050505050565b604051600090339083908381818185875af1925050503d8060008114614179576040519150601f19603f3d011682016040523d82523d6000602084013e61417e565b606091505b5050905080610b5a57604051630b288dc560e21b815260048101839052602401610c9c565b604080516001600160a01b0383811660248084019190915283518084039091018152604490920183526020820180516001600160e01b03166370a0823160e01b179052915160009283928392918716916141fd9190615b45565b600060405180830381855afa9150503d8060008114614238576040519150601f19603f3d011682016040523d82523d6000602084013e61423d565b606091505b50915091508161426057604051631222cd8360e01b815260040160405180910390fd5b80806020019051810190610b3f9190615d5d565b6040516001600160a01b03808516602483015283166044820152606481018290526108199085906323b872dd60e01b90608401613311565b60008260ff166000036142be57600080fd5b60006142cb838580611dc7565b905060006142e26001600160481b03831686612156565b9050808414613ea657836142f68282615961565b6040516338f831a560e11b815260048101929092526024820152604401610c9c565b600080614326600884612ed6565b9050611d8861434e6143496001600160401b03600888901c1660ff881685612ef2565b612f5b565b8260ff1660089190911b68ffffffffffffffff00161790565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160401b03166000036143a257506000610898565b611e19827f00000000000000000000000000000000000000000000000000000000000000006143d086612039565b9190614acb565b604051806101000160405280858152602001848152602001836001600160a01b03168152602001876001600160481b031681526020018661ffff168152602001426001600160401b03168152602001886001600160a01b031681526020018281525061444161200b565b6001600160401b03808b1660009081526020928352604090819020845181559284015160018401558301516002830180546060860151608087015161ffff16600160e81b0261ffff60e81b196001600160481b03909216600160a01b026001600160e81b03199093166001600160a01b0395861617929092171617905560a084015160038401805460c0870151909316600160401b026001600160e01b0319909316919093161717905560e082015160048201906144ff9082615dbc565b50506040516001600160401b038a1681527f69add1952a6a6b9cb86f04d05f0cb605cbb469a50ae916139d34495a9991481f915060200160405180910390a15050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160401b031660000361457d575050565b610b5a817f00000000000000000000000000000000000000000000000000000000000000006145ab85612039565b9190614afe565b7f00000000000000000000000000000000000000000000000000000000000000006001600160401b03166000036145e857505050565b6108f2827f000000000000000000000000000000000000000000000000000000000000000061461686611e69565b61ffff85166000908152602091909152604090209190614b7d565b60008060008061464a8686600491810182015192910190565b60e09190911b97909650945050505050565b6040805160a08101825260008183018181526060830182905260808301829052825282518084019093528083526020808401829052820192909252906146a28484614bf7565b90835292506146b18484614c51565b6020840191909152919491935090915050565b6000806000806146dd8686602091810182015192910190565b9097909650945050505050565b606060008260000361470d57505060408051600081526020810190915282614757565b5050604051828201601f831680614722575060205b80830184810186838901015b8183101561474657805183526020928301920161472e565b5050848452601f01601f1916604052505b935093915050565b80825114610b5a5781516040516355c5b3e360e11b8152600481019190915260248101829052604401610c9c565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160401b03166000036147c857506000611e19565b611d88837f00000000000000000000000000000000000000000000000000000000000000006147f687611e69565b61ffff86166000908152602091909152604090209190614acb565b6040518060600160405280426001600160401b031681526020018361ffff168152602001826001600160601b03191681525061484b6125a1565b6000858152602091825260409081902083518154938501519483015160601c600160501b027fffff0000000000000000000000000000000000000000ffffffffffffffffffff61ffff909616600160401b0269ffffffffffffffffffff199095166001600160401b0390921691909117939093179390931691909117909155517f7f63c9251d82a933210c2b6d0b0f116252c3c116788120e64e8e8215df6f3162906122419085815260200190565b7f00000000000000000000000000000000000000000000000000000000000000006001600160401b031660000361493057505050565b6108f2827f000000000000000000000000000000000000000000000000000000000000000061495e86611e69565b61ffff85166000908152602091909152604090209190614afe565b7f00000000000000000000000000000000000000000000000000000000000000006001600160401b03166000036149ae575050565b610b5a817f00000000000000000000000000000000000000000000000000000000000000006149dc85612039565b9190614b7d565b60006149ef8383614c83565b506001600160401b03600891821c81169290911c161190565b6000614a148383614c83565b611e19614a346001600160401b03600885811c8216919087901c16615e7b565b68ffffffffffffffff0060089190911b1660ff85161790565b6000614a598383614c83565b611e19614a796001600160401b03600885811c8216919087901c16615974565b68ffffffffffffffff0060089190911b1660ff84161790565b6060611d888484600085614cb8565b614aa961402e565b6108af81614d88565b614aba61402e565b6108af81614dcd565b612a0e61402e565b6000816001600160401b0316600003614ae657506000611e19565b6000614af28584612090565b9050610b3f8185614dd5565b806001600160401b0316600003614b1457505050565b6000614b208483612090565b845467ffffffffffffffff60901b1916600160901b426001600160401b0316021785559050614b4f8184614a08565b84546001600160481b0391909116600160481b0268ffffffffffffffffff60481b1990911617909355505050565b806001600160401b0316600003614b9357505050565b6000614b9f8483612090565b845467ffffffffffffffff60901b198116600160901b426001600160401b0316029081178755919250614b4f916001600160481b039182169082161790614be890841686614dfa565b6001600160481b031690614e5d565b6040805160608101825260008082526020820181905291810182905290614c1e84846146c4565b9083529250614c2d84846146c4565b6020840191909152600194810185015160ff16604084015291949390910192915050565b60408051808201909152600080825260208201819052600284840181015161ffff168352909201916146b184846146c4565b60ff82811690821680821461081957604051635ce6db6160e11b815260ff808416600483015282166024820152604401610c9c565b606082471015614d195760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c9c565b600080866001600160a01b03168587604051614d359190615b45565b60006040518083038185875af1925050503d8060008114614d72576040519150601f19603f3d011682016040523d82523d6000602084013e614d77565b606091505b5091509150613b0987838387614e89565b614d9061402e565b6000614d9a612ce8565b6001815590506000614daa611c9e565b80546001600160a01b0319166001600160a01b0394909416939093179092555050565b61191d61402e565b6000614de18383614c83565b506001600160401b03600891821c81169290911c161090565b6000614e068383614c83565b600883811c6001600160401b039081169184901c811682810192918311614e2d5782614e36565b6001600160401b035b925061180d614e4484612f5b565b68ffffffffffffffff0060089190911b1660ff88161790565b6000614e698383614c83565b600882811c6001600160401b039081169185901c1610612eeb5781611e19565b60608315614ef8578251600003614ef1576001600160a01b0385163b614ef15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c9c565b5081611d88565b611d888383815115614f0d5781518083602001fd5b8060405162461bcd60e51b8152600401610c9c9190615260565b508054614f33906158ee565b6000825580601f10614f43575050565b601f0160209004906000526020600020908101906108af9190614fd7565b6040518060a0016040528060006001600160481b03168152602001614fbe6040805160a081018252600081830181815260608301829052608083018290528252825180840190935280835260208381019190915290919082015290565b8152600060208201819052604082015260609081015290565b5b808211156126fa5760008155600101614fd8565b6001600160a01b03811681146108af57600080fd5b803561161881614fec565b60006020828403121561501e57600080fd5b8135611e1981614fec565b60006040828403121561503b57600080fd5b50919050565b61ffff811681146108af57600080fd5b803561161881615041565b60008060006080848603121561507157600080fd5b61507b8585615029565b925060408401359150606084013561509281615041565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156150d5576150d561509d565b60405290565b60405160a081016001600160401b03811182821017156150d5576150d561509d565b60405161010081016001600160401b03811182821017156150d5576150d561509d565b60405160e081016001600160401b03811182821017156150d5576150d561509d565b604051601f8201601f191681016001600160401b038111828210171561516a5761516a61509d565b604052919050565b60006040828403121561518457600080fd5b61518c6150b3565b9050813561519981615041565b808252506020820135602082015292915050565b600080606083850312156151c057600080fd5b6151ca8484615172565b915060408301356151da81615041565b809150509250929050565b600080606083850312156151f857600080fd5b6152028484615029565b946040939093013593505050565b60005b8381101561522b578181015183820152602001615213565b50506000910152565b6000815180845261524c816020860160208601615210565b601f01601f19169290920160200192915050565b602081526000611e196020830184615234565b6001600160401b03811681146108af57600080fd5b60006020828403121561529a57600080fd5b8135611e1981615273565b60208152815160208201526020820151604082015260018060a01b0360408301511660608201526001600160481b036060830151166080820152600060808301516152f660a084018261ffff169052565b5060a08301516001600160401b03811660c08401525060c08301516001600160a01b03811660e08401525060e083015161010083810152611d88610120840182615234565b60006040828403121561534d57600080fd5b611e198383615172565b6000806040838503121561536a57600080fd5b823561537581615041565b946020939093013593505050565b6000806060838503121561539657600080fd5b6153a08484615029565b915060408301356151da81614fec565b60ff811681146108af57600080fd5b600081830360a08112156153d257600080fd5b6153da6150b3565b915060608112156153ea57600080fd5b50604051606081018181106001600160401b038211171561540d5761540d61509d565b80604052508235815260208301356020820152604083013561542e816153b0565b604082015281526154428360608401615172565b602082015292915050565b60006001600160401b038211156154665761546661509d565b50601f01601f191660200190565b600082601f83011261548557600080fd5b81356154986154938261544d565b615142565b8181528460208386010111156154ad57600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156154dd57600080fd5b8235915060208301356001600160401b03808211156154fb57600080fd5b90840190610120828703121561551057600080fd5b6155186150db565b82356001600160481b038116811461552f57600080fd5b815261553e87602085016153bf565b602082015260c0830135604082015260e083013560608201526101008301358281111561556a57600080fd5b61557688828601615474565b6080830152508093505050509250929050565b80151581146108af57600080fd5b803561161881615589565b6000602082840312156155b457600080fd5b81356001600160401b03808211156155cb57600080fd5b9083019061010082860312156155e057600080fd5b6155e86150fd565b6155f183615001565b81526020830135602082015261560960408401615051565b6040820152606083013560608201526080830135608082015261562e60a08401615597565b60a082015260c08301358281111561564557600080fd5b61565187828601615474565b60c08301525060e08301358281111561566957600080fd5b61567587828601615474565b60e08301525095945050505050565b60006020828403121561569657600080fd5b81356001600160401b03808211156156ad57600080fd5b9083019060e082860312156156c157600080fd5b6156c9615120565b823581526156d960208401615051565b602082015260408301356040820152606083013560608201526156fe60808401615597565b608082015260a08301358281111561571557600080fd5b61572187828601615474565b60a08301525060c08301358281111561573957600080fd5b61574587828601615474565b60c08301525095945050505050565b60006020828403121561576657600080fd5b8135611e1981615041565b60008060008060006080868803121561578957600080fd5b85359450602086013561579b81615041565b93506040860135925060608601356001600160401b03808211156157be57600080fd5b818801915088601f8301126157d257600080fd5b8135818111156157e157600080fd5b8960208285010111156157f357600080fd5b9699959850939650602001949392505050565b634e487b7160e01b600052602160045260246000fd5b825161ffff16815260208084015190820152606081016002831061585057634e487b7160e01b600052602160045260246000fd5b8260408301529392505050565b60006020828403121561586f57600080fd5b5035919050565b60006158846154938461544d565b905082815283838301111561589857600080fd5b611e19836020830184615210565b6000602082840312156158b857600080fd5b81516001600160401b038111156158ce57600080fd5b8201601f810184136158df57600080fd5b611d8884825160208401615876565b600181811c9082168061590257607f821691505b60208210810361503b57634e487b7160e01b600052602260045260246000fd5b813561592d81615041565b61ffff811661ffff1983541617825550602082013560018201555050565b634e487b7160e01b600052601160045260246000fd5b818103818111156108985761089861594b565b6001600160401b038181168382160190808211156159945761599461594b565b5092915050565b6000602082840312156159ad57600080fd5b8151611e19816153b0565b815161ffff1681526020808301519082015260408101610898565b634e487b7160e01b600052600160045260246000fd5b6000602082840312156159fb57600080fd5b8151611e1981615589565b634e487b7160e01b600052601260045260246000fd5b8051805183526020810151602084015260ff60408201511660408401525060208101516108f26060840182805161ffff168252602090810151910152565b60a081016108988284615a1c565b6001600160e01b03198916815260f888901b6001600160f81b031916600482015260c087901b6001600160c01b03191660058201528551600090615ab381600d850160208b01615210565b808301905086600d82015285602d82015261ffff60f01b8560f01b16604d8201528351615ae781604f840160208801615210565b01604f019a9950505050505050505050565b6001600160a01b038781168252861660208201526040810185905260c060608201819052600090615b2c90830186615234565b61ffff9490941660808301525060a00152949350505050565b60008251615b57818460208701615210565b9190910192915050565b60ff82811682821603908111156108985761089861594b565b600181815b80851115615bb5578160001904821115615b9b57615b9b61594b565b80851615615ba857918102915b93841c9390800290615b7f565b509250929050565b600082615bcc57506001610898565b81615bd957506000610898565b8160018114615bef5760028114615bf957615c15565b6001915050610898565b60ff841115615c0a57615c0a61594b565b50506001821b610898565b5060208310610133831016604e8410600b8410161715615c38575081810a610898565b615c428383615b7a565b8060001904821115615c5657615c5661594b565b029392505050565b6000611e1960ff841683615bbd565b600082615c8a57634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176108985761089861594b565b600060208284031215615cb857600080fd5b8151611e1981614fec565b600060208284031215615cd557600080fd5b8151611e1981615273565b60c08101615cee8285615a1c565b6001600160a01b039290921660a09190910152919050565b61ffff871681528560208201528460408201526001600160401b038416606082015260c060808201526000615d3e60c0830185615234565b82810360a0840152615d508185615234565b9998505050505050505050565b600060208284031215615d6f57600080fd5b5051919050565b601f8211156108f257600081815260208120601f850160051c81016020861015615d9d5750805b601f850160051c820191505b81811015610e6457828155600101615da9565b81516001600160401b03811115615dd557615dd561509d565b615de981615de384546158ee565b84615d76565b602080601f831160018114615e1e5760008415615e065750858301515b600019600386901b1c1916600185901b178555610e64565b600085815260208120601f198616915b82811015615e4d57888601518255948401946001909101908401615e2e565b5085821015615e6b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160401b038281168282160390808211156159945761599461594b56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a264697066735822122062a19520808150a60ebbf0618d299f20049a6f931f7135dbf97b1c5f88009ecb64736f6c63430008130033"; + +type MultiTokenNttConstructorParams = + | [linkLibraryAddresses: MultiTokenNttLibraryAddresses, signer?: Signer] + | ConstructorParameters; + +const isSuperArgs = ( + xs: MultiTokenNttConstructorParams +): xs is ConstructorParameters => { + return ( + typeof xs[0] === "string" || + (Array.isArray as (arg: any) => arg is readonly any[])(xs[0]) || + "_isInterface" in xs[0] + ); +}; + +export class MultiTokenNtt__factory extends ContractFactory { + constructor(...args: MultiTokenNttConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + const [linkLibraryAddresses, signer] = args; + super( + _abi, + MultiTokenNtt__factory.linkBytecode(linkLibraryAddresses), + signer + ); + } + } + + static linkBytecode( + linkLibraryAddresses: MultiTokenNttLibraryAddresses + ): string { + let linkedBytecode = _bytecode; + + linkedBytecode = linkedBytecode.replace( + new RegExp("__\\$3a5f69cefc093539f925e73bc45cac585e\\$__", "g"), + linkLibraryAddresses["src/libraries/TokenDeployment.sol:TokenDeployment"] + .replace(/^0x/, "") + .toLowerCase() + ); + + linkedBytecode = linkedBytecode.replace( + new RegExp("__\\$4033db715c90f2390978d4fb71beaa4caa\\$__", "g"), + linkLibraryAddresses["src/libraries/TokenInfo.sol:TokenInfoLib"] + .replace(/^0x/, "") + .toLowerCase() + ); + + return linkedBytecode; + } + + override getDeployTransaction( + _gmpManager: AddressLike, + _rateLimitDuration: BigNumberish, + _skipRateLimiting: boolean, + _tokenImplementation: AddressLike, + _weth: AddressLike, + overrides?: NonPayableOverrides & { from?: string } + ): Promise { + return super.getDeployTransaction( + _gmpManager, + _rateLimitDuration, + _skipRateLimiting, + _tokenImplementation, + _weth, + overrides || {} + ); + } + override deploy( + _gmpManager: AddressLike, + _rateLimitDuration: BigNumberish, + _skipRateLimiting: boolean, + _tokenImplementation: AddressLike, + _weth: AddressLike, + overrides?: NonPayableOverrides & { from?: string } + ) { + return super.deploy( + _gmpManager, + _rateLimitDuration, + _skipRateLimiting, + _tokenImplementation, + _weth, + overrides || {} + ) as Promise< + MultiTokenNtt & { + deploymentTransaction(): ContractTransactionResponse; + } + >; + } + override connect(runner: ContractRunner | null): MultiTokenNtt__factory { + return super.connect(runner) as MultiTokenNtt__factory; + } + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): MultiTokenNttInterface { + return new Interface(_abi) as MultiTokenNttInterface; + } + static connect( + address: string, + runner?: ContractRunner | null + ): MultiTokenNtt { + return new Contract(address, _abi, runner) as unknown as MultiTokenNtt; + } +} + +export interface MultiTokenNttLibraryAddresses { + ["src/libraries/TokenDeployment.sol:TokenDeployment"]: string; + ["src/libraries/TokenInfo.sol:TokenInfoLib"]: string; +} diff --git a/evm/ts/src/ethers-contracts/1_1_0/index.ts b/evm/ts/src/ethers-contracts/1_1_0/index.ts index 48078a607..1babfb586 100644 --- a/evm/ts/src/ethers-contracts/1_1_0/index.ts +++ b/evm/ts/src/ethers-contracts/1_1_0/index.ts @@ -3,6 +3,10 @@ /* eslint-disable */ export type { NttManager } from "./NttManager.js"; export type { WormholeTransceiver } from "./WormholeTransceiver.js"; +export type { GmpManager } from "./GmpManager.js"; +export type { MultiTokenNtt } from "./MultiTokenNtt.js"; export * as factories from "./factories/index.js"; export { NttManager__factory } from "./factories/NttManager__factory.js"; export { WormholeTransceiver__factory } from "./factories/WormholeTransceiver__factory.js"; +export { GmpManager__factory } from "./factories/GmpManager__factory.js"; +export { MultiTokenNtt__factory } from "./factories/MultiTokenNtt__factory.js"; diff --git a/evm/ts/src/ethers-contracts/multiTokenNtt/index.ts b/evm/ts/src/ethers-contracts/multiTokenNtt/index.ts new file mode 100644 index 000000000..bcd350b9d --- /dev/null +++ b/evm/ts/src/ethers-contracts/multiTokenNtt/index.ts @@ -0,0 +1,15 @@ +import * as __1_1_0 from "../1_1_0/index.js"; + +const _1_1_0 = { + MultiTokenNtt: { + connect: __1_1_0.MultiTokenNtt__factory.connect, + }, + NttTransceiver: { + connect: __1_1_0.WormholeTransceiver__factory.connect, + }, + GmpManager: { + connect: __1_1_0.GmpManager__factory.connect, + }, +}; + +export { _1_1_0 }; diff --git a/evm/ts/src/index.ts b/evm/ts/src/index.ts index b9920fde8..46b77fc25 100644 --- a/evm/ts/src/index.ts +++ b/evm/ts/src/index.ts @@ -2,11 +2,21 @@ import { registerProtocol } from "@wormhole-foundation/sdk-definitions"; import { _platform } from "@wormhole-foundation/sdk-evm"; import { EvmNtt } from "./ntt.js"; import { EvmNttWithExecutor } from "./nttWithExecutor.js"; +import { EvmMultiTokenNtt } from "./multiTokenNtt.js"; +import { EvmMultiTokenNttWithExecutor } from "./multiTokenNttWithExecutor.js"; import "@wormhole-foundation/sdk-definitions-ntt"; registerProtocol(_platform, "Ntt", EvmNtt); registerProtocol(_platform, "NttWithExecutor", EvmNttWithExecutor); +registerProtocol(_platform, "MultiTokenNtt", EvmMultiTokenNtt); +registerProtocol( + _platform, + "MultiTokenNttWithExecutor", + EvmMultiTokenNttWithExecutor +); export * as ethers_contracts from "./ethers-contracts/index.js"; export * from "./ntt.js"; export * from "./nttWithExecutor.js"; +export * from "./multiTokenNtt.js"; +export * from "./multiTokenNttWithExecutor.js"; diff --git a/evm/ts/src/multiTokenNtt.ts b/evm/ts/src/multiTokenNtt.ts new file mode 100644 index 000000000..9727cc173 --- /dev/null +++ b/evm/ts/src/multiTokenNtt.ts @@ -0,0 +1,690 @@ +import { + Chain, + Network, + encoding, + nativeChainIds, + toChain, + toChainId, +} from "@wormhole-foundation/sdk-base"; +import { + AccountAddress, + ChainAddress, + ChainsConfig, + Contracts, + isNative, + serialize, + TokenAddress, + TokenId, + toNative, + toUniversal, + universalAddress, +} from "@wormhole-foundation/sdk-definitions"; +import type { EvmChains, EvmPlatformType } from "@wormhole-foundation/sdk-evm"; +import { + EvmAddress, + EvmPlatform, + EvmUnsignedTransaction, + addChainId, + addFrom, +} from "@wormhole-foundation/sdk-evm"; +import "@wormhole-foundation/sdk-evm-core"; + +import { + decodeTrimmedAmount, + encodeTrimmedAmount, + EncodedTrimmedAmount, + MultiTokenNtt, + Ntt, + TrimmedAmount, + untrim, +} from "@wormhole-foundation/sdk-definitions-ntt"; +import { Contract, ethers, Interface, type Provider } from "ethers"; +import { + GmpManagerBindings, + loadAbiVersion, + MultiTokenNttBindings, +} from "./multiTokenNttBindings.js"; +import { getAxelarGasFee } from "@wormhole-foundation/sdk-definitions-ntt"; +import { NativeTokenTransferCodec } from "./ethers-contracts/1_1_0/MultiTokenNtt.js"; + +export class EvmMultiTokenNtt + implements MultiTokenNtt +{ + readonly chainId: bigint; + readonly managerAddress: string; + readonly multiTokenNtt: MultiTokenNttBindings.MultiTokenNtt; + readonly gmpManager: GmpManagerBindings.GmpManager; + readonly abiBindings: ReturnType; + + constructor( + readonly network: N, + readonly chain: C, + readonly provider: Provider, + readonly contracts: Contracts & { multiTokenNtt?: MultiTokenNtt.Contracts }, + readonly version: string = "1.1.0" + ) { + if (!contracts.multiTokenNtt) throw new Error("No Ntt Contracts provided"); + + this.chainId = nativeChainIds.networkChainToNativeChainId.get( + network, + chain + ) as bigint; + + this.abiBindings = loadAbiVersion(this.version); + + this.managerAddress = contracts.multiTokenNtt.manager; + + this.multiTokenNtt = this.abiBindings.MultiTokenNtt.connect( + contracts.multiTokenNtt.manager, + this.provider + ); + + this.gmpManager = this.abiBindings.GmpManager.connect( + contracts.multiTokenNtt.gmpManager, + this.provider + ); + } + + async isPaused(): Promise { + return await this.multiTokenNtt.isPaused(); + } + + async getIsExecuted( + attestation: MultiTokenNtt.Attestation + ): Promise { + const isExecuted = await this.gmpManager.isMessageExecuted( + MultiTokenNtt.messageDigest( + attestation.emitterChain, + attestation.payload.nttManagerPayload + ) + ); + + return isExecuted && !(await this.getIsTransferInboundQueued(attestation)); + } + + async getIsTransferInboundQueued( + attestation: MultiTokenNtt.Attestation + ): Promise { + return ( + (await this.getInboundQueuedTransfer( + attestation.emitterChain, + attestation.payload.nttManagerPayload + )) !== null + ); + } + + async getIsApproved( + attestation: MultiTokenNtt.Attestation + ): Promise { + return await this.gmpManager.isMessageApprovedForChain( + toChainId(attestation.emitterChain), + MultiTokenNtt.messageDigest( + attestation.emitterChain, + attestation.payload.nttManagerPayload + ) + ); + } + + static async fromRpc( + provider: Provider, + config: ChainsConfig + ): Promise> { + const [network, chain] = await EvmPlatform.chainFromRpc(provider); + const conf = config[chain]!; + if (conf.network !== network) + throw new Error(`Network mismatch: ${conf.network} != ${network}`); + + const version = await EvmMultiTokenNtt.getVersion(provider, conf.contracts); + return new EvmMultiTokenNtt( + network as N, + chain, + provider, + conf.contracts, + version + ); + } + + private static versionCache = new Map(); + + static async getVersion( + provider: ethers.Provider, + contracts: Contracts & { multiTokenNtt?: MultiTokenNtt.Contracts } + ) { + const multiTokenNtt = contracts.multiTokenNtt; + if (!multiTokenNtt) { + throw new Error("No multiTokenNtt contracts configured"); + } + + // Use cached version to save on RPC calls + const cacheKey = `${multiTokenNtt.chain}-${multiTokenNtt.manager}`; + const cached = EvmMultiTokenNtt.versionCache.get(cacheKey); + if (cached) { + return cached; + } + + const contract = new ethers.Contract( + multiTokenNtt.manager, + ["function NTT_MANAGER_VERSION() public view returns (string)"], + provider + ); + try { + const abiVersion = await contract + .getFunction("NTT_MANAGER_VERSION") + .staticCall(); + if (!abiVersion) { + throw new Error("NTT_MANAGER_VERSION not found"); + } + EvmMultiTokenNtt.versionCache.set(cacheKey, abiVersion); + return abiVersion; + } catch (e) { + console.error( + `Failed to get NTT_MANAGER_VERSION from contract ${contracts.multiTokenNtt?.manager}` + ); + throw e; + } + } + + async getSendTransceivers( + destinationChain: Chain + ): Promise { + const sendTransceivers = + await this.gmpManager.getSendTransceiversWithIndicesForChain( + toChainId(destinationChain) + ); + + return await Promise.all( + sendTransceivers.map(async (transceiver) => { + const type = await this.getTransceiverType(transceiver.transceiver); + return { + address: transceiver.transceiver, + index: Number(transceiver.index), + type, + }; + }) + ); + } + + async getReceiveTransceivers( + sourceChain: Chain + ): Promise { + const receiveTransceivers = + await this.gmpManager.getReceiveTransceiversWithIndicesForChain( + toChainId(sourceChain) + ); + + return await Promise.all( + receiveTransceivers.map(async (transceiver) => { + const type = await this.getTransceiverType(transceiver.transceiver); + return { + address: transceiver.transceiver, + index: Number(transceiver.index), + type, + }; + }) + ); + } + + async transceiverAttestedToMessage( + fromChain: Chain, + transceiverMessage: MultiTokenNtt.Message, + index: number + ): Promise { + return await this.gmpManager.transceiverAttestedToMessage( + MultiTokenNtt.messageDigest(fromChain, transceiverMessage), + index + ); + } + + private async getTransceiverType( + transceiverAddress: string + ): Promise { + const transceiverInterface = new Interface([ + "function getTransceiverType() external view returns (string memory)", + ]); + + const transceiverContract = new Contract( + transceiverAddress, + transceiverInterface, + this.provider + ); + + return await transceiverContract + .getFunction("getTransceiverType") + .staticCall(); + } + + async createTransceiverInstructions( + dstChain: Chain, + gasLimit: bigint, + axelarGasMultiplier: number | "auto" = "auto" + ): Promise { + const sendTransceivers = await this.getSendTransceivers(dstChain); + + const instructions: Ntt.TransceiverInstruction[] = await Promise.all( + sendTransceivers.map(async (transceiver) => { + switch (transceiver.type.toLowerCase()) { + case "wormhole": + return { + index: transceiver.index, + payload: new Uint8Array([1]), // disable standard relayer, use executor route for automatic relay + }; + case "axelar": { + // If we fail to fetch the gas fee, then use 1 wei as a fallback. + // The Axelar GMP status API should return an invalid gas fee error + // which the track() method will surface, allowing a user to top up + // the gas fee. + const gasFee = await getAxelarGasFee( + this.network, + this.chain, + dstChain, + gasLimit, + axelarGasMultiplier + ).catch(() => 1n); + return { + index: transceiver.index, + payload: encoding.bignum.toBytes(gasFee, 32), + }; + } + default: + throw new Error( + `Unsupported transceiver type: ${transceiver.type} at index ${transceiver.index}` + ); + } + }) + ); + + // The contract requires the instructions to be sorted by transceiver index in ascending order. + instructions.sort((a, b) => a.index - b.index); + + return instructions; + } + + async quoteDeliveryPrice( + dstChain: Chain, + instructions: Ntt.TransceiverInstruction[] + ): Promise { + const [, totalPrice] = await this.gmpManager.quoteDeliveryPrice( + toChainId(dstChain), + Ntt.encodeTransceiverInstructions(instructions) + ); + return totalPrice; + } + + async *transfer( + sender: AccountAddress, + token: TokenAddress, + amount: bigint, + destination: ChainAddress, + destinationGasLimit: bigint, + axelarGasMultiplier: number | "auto" = "auto" + ): AsyncGenerator> { + const senderAddress = new EvmAddress(sender).toString(); + + const transceiverInstructions = await this.createTransceiverInstructions( + destination.chain, + destinationGasLimit, + axelarGasMultiplier + ); + + const totalPrice = await this.quoteDeliveryPrice( + destination.chain, + transceiverInstructions + ); + + const receiver = universalAddress(destination); + + let transferTx; + if (isNative(token)) { + const gasTokenTransferArgs = { + amount, + recipientChain: toChainId(destination.chain), + recipient: receiver, + refundAddress: receiver, + shouldQueue: false, + transceiverInstructions: Ntt.encodeTransceiverInstructions( + transceiverInstructions + ), + additionalPayload: "0x", + }; + + transferTx = + await this.multiTokenNtt.wrapAndTransferGasToken.populateTransaction( + gasTokenTransferArgs, + { value: amount + totalPrice } + ); + } else { + const tokenContract = EvmPlatform.getTokenImplementation( + this.provider, + token.toString() + ); + + const allowance = await tokenContract.allowance( + senderAddress, + this.managerAddress + ); + if (allowance < amount) { + const approveTx = await tokenContract.approve.populateTransaction( + this.managerAddress, + amount + ); + + yield this.createUnsignedTx( + addFrom(approveTx, senderAddress), + "Ntt.Approve" + ); + } + + const transferArgs = { + token: token.toString(), + amount, + recipientChain: toChainId(destination.chain), + recipient: receiver, + refundAddress: receiver, + shouldQueue: false, + transceiverInstructions: Ntt.encodeTransceiverInstructions( + transceiverInstructions + ), + additionalPayload: "0x", + }; + + transferTx = await this.multiTokenNtt.transfer.populateTransaction( + transferArgs, + { value: totalPrice } + ); + } + + yield this.createUnsignedTx( + addFrom(transferTx, senderAddress), + "Ntt.transfer" + ); + } + + async *redeem(attestation: MultiTokenNtt.Attestation) { + const transceivers = await this.getReceiveTransceivers( + attestation.emitterChain + ); + + const wormholeTransceiver = transceivers.find((t) => t.type === "wormhole"); + if (!wormholeTransceiver) { + throw new Error("No Wormhole transceiver registered for this chain"); + } + + const transceiver = this.abiBindings.NttTransceiver.connect( + wormholeTransceiver.address, + this.provider + ); + + const tx = await transceiver.receiveMessage.populateTransaction( + serialize(attestation) + ); + + yield this.createUnsignedTx(tx, "NttTransceiver.receiveMessage"); + } + + async getTokenMeta(token: TokenId): Promise { + const tokenAddress = token.address.toString(); + + const tokenImpl = EvmPlatform.getTokenImplementation( + this.provider, + tokenAddress + ); + + const getDecimals = EvmPlatform.getDecimals( + this.network, + this.chain, + this.provider, + tokenAddress + ); + + const [name, symbol, decimals] = await Promise.all([ + tokenImpl.name(), + tokenImpl.symbol(), + getDecimals, + ]); + + return { name, symbol, decimals }; + } + + async getCurrentOutboundCapacity(localToken: TokenId): Promise { + const { chain, address } = await this.getOriginalToken(localToken); + + return await this.multiTokenNtt.getCurrentOutboundCapacity({ + chainId: toChainId(chain), + tokenAddress: address.toUint8Array(), + }); + } + + async getOutboundLimit(localToken: TokenId): Promise { + const { chain, address } = await this.getOriginalToken(localToken); + + const encoded: EncodedTrimmedAmount = ( + await this.multiTokenNtt.getOutboundLimitParams({ + chainId: toChainId(chain), + tokenAddress: address.toUint8Array(), + }) + ).limit; + + const trimmedAmount: TrimmedAmount = decodeTrimmedAmount(encoded); + const tokenMeta = await this.getTokenMeta(localToken); + + return untrim(trimmedAmount, tokenMeta.decimals); + } + + async getCurrentInboundCapacity( + originalToken: MultiTokenNtt.OriginalTokenId, + fromChain: Chain + ): Promise { + return await this.multiTokenNtt.getCurrentInboundCapacity( + { + chainId: toChainId(originalToken.chain), + tokenAddress: originalToken.address.toUint8Array(), + }, + toChainId(fromChain) + ); + } + + async getInboundLimit( + originalToken: MultiTokenNtt.OriginalTokenId, + fromChain: Chain + ): Promise { + const localToken = await this.getLocalToken(originalToken); + if (localToken === null) return null; // Token not yet created + + const encoded: EncodedTrimmedAmount = ( + await this.multiTokenNtt.getInboundLimitParams( + { + chainId: toChainId(originalToken.chain), + tokenAddress: originalToken.address.toUint8Array(), + }, + toChainId(fromChain) + ) + ).limit; + + const trimmedAmount: TrimmedAmount = decodeTrimmedAmount(encoded); + if (trimmedAmount.amount === 0n && trimmedAmount.decimals === 0) + return null; + + const tokenMeta = await this.getTokenMeta(localToken); + + return untrim(trimmedAmount, tokenMeta.decimals); + } + + async getRateLimitDuration(): Promise { + return await this.multiTokenNtt.rateLimitDuration(); + } + + async getInboundQueuedTransfer( + fromChain: Chain, + transceiverMessage: MultiTokenNtt.Message + ): Promise { + const digest = MultiTokenNtt.messageDigest(fromChain, transceiverMessage); + const queuedTransfer = + await this.multiTokenNtt.getInboundQueuedTransfer(digest); + if (queuedTransfer.txTimestamp > 0n) { + const { sourceChainId, txTimestamp } = queuedTransfer; + const duration = await this.getRateLimitDuration(); + return { + sourceChain: toChain(sourceChainId), + rateLimitExpiryTimestamp: Number(txTimestamp + duration), + }; + } + return null; + } + + async *completeInboundQueuedTransfer( + fromChain: Chain, + transceiverMessage: MultiTokenNtt.Message + ) { + const { trimmedAmount, token, sender, to } = + transceiverMessage.payload.data; + + const digest = MultiTokenNtt.messageDigest(fromChain, transceiverMessage); + + const transfer: NativeTokenTransferCodec.NativeTokenTransferStruct = { + amount: encodeTrimmedAmount(trimmedAmount), + token: { + meta: { + name: encoding.bytes.encode(token.meta.name), + symbol: encoding.bytes.encode(token.meta.symbol), + decimals: token.meta.decimals, + }, + token: { + chainId: toChainId(token.token.chainId), + tokenAddress: token.token.tokenAddress.toString(), + }, + }, + sender: sender.toString(), + to: to.toString(), + additionalPayload: "0x", + }; + + const tx = + await this.multiTokenNtt.completeInboundQueuedTransfer.populateTransaction( + digest, + transfer + ); + + yield this.createUnsignedTx(tx, "Ntt.completeInboundQueuedTransfer"); + } + + async getOriginalToken( + localToken: TokenId + ): Promise { + const [tokenId] = await this.multiTokenNtt.getTokenId( + localToken.address.toString() + ); + + const chain = toChain(tokenId.chainId); + const address = toUniversal(chain, tokenId.tokenAddress); + + return { + chain, + address, + }; + } + + async isWrappedToken(localToken: TokenId): Promise { + const originalToken = await this.getOriginalToken(localToken); + return originalToken.chain !== this.chain; + } + + // This will return null if the token doesn't exist + async getLocalToken( + originalToken: MultiTokenNtt.OriginalTokenId + ): Promise { + const localToken = await this.multiTokenNtt.getToken({ + chainId: toChainId(originalToken.chain), + tokenAddress: originalToken.address.toUint8Array(), + }); + + if (localToken === ethers.ZeroAddress) return null; + + return { chain: this.chain, address: toNative(this.chain, localToken) }; + } + + async getWrappedNativeToken(): Promise { + const wethAddress = await this.multiTokenNtt.WETH(); + return { chain: this.chain, address: toNative(this.chain, wethAddress) }; + } + + // If the local token doesn't exist yet, this will return the address where it will be deployed + async calculateLocalTokenAddress( + originalToken: MultiTokenNtt.OriginalTokenId, + tokenMeta: MultiTokenNtt.TokenMeta + ): Promise> { + const tokenImplementation = await this.multiTokenNtt.tokenImplementation(); + + const initializeSelector = ethers.id("initialize(string,string,uint8)"); + + const coder = ethers.AbiCoder.defaultAbiCoder(); + + const constructorArgs = coder.encode( + ["address", "bytes"], + [ + tokenImplementation, + ethers.concat([ + initializeSelector.slice(0, 10), + coder.encode( + ["string", "string", "uint8"], + [ + tokenMeta.name.slice(0, 32), + tokenMeta.symbol.slice(0, 32), + tokenMeta.decimals, + ] + ), + ]), + ] + ); + + const creationCode = await this.multiTokenNtt.tokenProxyCreationCode(); + + const initCode = ethers.concat([creationCode, constructorArgs]); + const initCodeHash = ethers.keccak256(initCode); + + const salt = ethers.solidityPackedKeccak256( + ["uint16", "bytes32"], + [toChainId(originalToken.chain), originalToken.address.toUint8Array()] + ); + + // The address where the token will be deployed on the destination chain + const localTokenAddress = ethers.getCreate2Address( + this.managerAddress, + salt, + initCodeHash + ); + + return toNative(this.chain, localTokenAddress); + } + + createUnsignedTx( + txReq: ethers.TransactionRequest, + description: string, + parallelizable: boolean = false + ): EvmUnsignedTransaction { + return new EvmUnsignedTransaction( + addChainId(txReq, this.chainId), + this.network, + this.chain, + description, + parallelizable + ); + } + + // Upper bound estimate of gas limit needed to redeem on this chain + async estimateGasLimit( + originalToken: MultiTokenNtt.OriginalTokenId + ): Promise { + const existingToken = await this.getLocalToken(originalToken); + + if (!existingToken) { + // Redeeming will create the token on this chain + // so we need to account for the extra gas. + return 1_000_000n; + } + + // Upper estimate for redeeming an existing token. Based on observed gas usage + // (~178k gas: https://sepolia.etherscan.io/tx/0xd008af053861cdfea0b6c1f4d973ee59f0c4fcc2e2de57b9945a193cb185bb29) + // but padded to be well above the limit. + return 300_000n; + } +} diff --git a/evm/ts/src/multiTokenNttBindings.ts b/evm/ts/src/multiTokenNttBindings.ts new file mode 100644 index 000000000..ef74b2cda --- /dev/null +++ b/evm/ts/src/multiTokenNttBindings.ts @@ -0,0 +1,44 @@ +import { Provider } from "ethers"; +import { _1_1_0 } from "./ethers-contracts/multiTokenNtt/index.js"; +import { Ntt } from "@wormhole-foundation/sdk-definitions-ntt"; +import { NttTransceiverBindings } from "./bindings.js"; + +// This is a descending list of all ABI versions the SDK is aware of. +// We check for the first match in descending order, allowing for higher minor and patch versions +// being used by the live contract (these are supposed to still be compatible with older ABIs). +export const abiVersions = [["1.1.0", _1_1_0]] as const; +export type AbiVersion = (typeof abiVersions)[number][0]; + +export interface MultiTokenNttBindings { + MultiTokenNtt: MultiTokenNttBindings; + GmpManager: GmpManagerBindings; + NttTransceiver: NttTransceiverBindings; +} + +export namespace MultiTokenNttBindings { + export type MultiTokenNtt = ReturnType; +} + +export interface MultiTokenNttBindings { + connect( + address: string, + provider: Provider + ): MultiTokenNttBindings.MultiTokenNtt; +} + +export namespace GmpManagerBindings { + export type GmpManager = ReturnType; +} + +export interface GmpManagerBindings { + connect(address: string, provider: Provider): GmpManagerBindings.GmpManager; +} + +export function loadAbiVersion(targetVersion: string) { + for (const [abiVersion, abi] of abiVersions) { + if (Ntt.abiVersionMatches(targetVersion, abiVersion)) { + return abi; + } + } + throw new Error(`Unknown ABI version: ${targetVersion}`); +} diff --git a/evm/ts/src/multiTokenNttWithExecutor.ts b/evm/ts/src/multiTokenNttWithExecutor.ts new file mode 100644 index 000000000..f4815d939 --- /dev/null +++ b/evm/ts/src/multiTokenNttWithExecutor.ts @@ -0,0 +1,207 @@ +import { Interface, type Provider, type TransactionRequest } from "ethers"; +import { + AccountAddress, + ChainAddress, + ChainsConfig, + Contracts, + Network, + TokenId, + UnsignedTransaction, + isNative, + toChainId, + nativeChainIds, +} from "@wormhole-foundation/sdk-connect"; +import { + EvmChains, + EvmPlatform, + EvmPlatformType, + EvmAddress, + EvmUnsignedTransaction, + addChainId, +} from "@wormhole-foundation/sdk-evm"; +import { + Ntt, + type MultiTokenNtt, + type MultiTokenNttWithExecutor, +} from "@wormhole-foundation/sdk-definitions-ntt"; + +const multiTokenNttWithExecutorAddresses: Partial< + Record>> +> = { + Testnet: { + Sepolia: "0x70b1CD25Aa1DEbEf2BCa0eDbc11228C5EB4dAD0F", + Monad: "0xFEA937F7124E19124671f1685671d3f04a9Af4E4", + }, +}; + +export class EvmMultiTokenNttWithExecutor< + N extends Network, + C extends EvmChains = EvmChains, +> implements MultiTokenNttWithExecutor +{ + readonly chainId: bigint; + readonly managerAddress: string; + readonly multiTokenNttWithExecutorAddress: string; + + constructor( + readonly network: N, + readonly chain: C, + readonly provider: Provider, + readonly contracts: Contracts & { multiTokenNtt?: MultiTokenNtt.Contracts } + ) { + this.chainId = nativeChainIds.networkChainToNativeChainId.get( + network, + chain + ) as bigint; + + const managerAddress = contracts.multiTokenNtt?.manager; + if (!managerAddress) { + throw new Error( + `MultiTokenNtt manager address not found for chain ${chain} on network ${network}` + ); + } + this.managerAddress = managerAddress; + + const multiTokenNttWithExecutorAddress = + multiTokenNttWithExecutorAddresses[this.network]?.[this.chain]; + if (!multiTokenNttWithExecutorAddress) { + throw new Error( + `MultiTokenNttWithExecutor address not found for chain ${this.chain} on network ${this.network}` + ); + } + this.multiTokenNttWithExecutorAddress = multiTokenNttWithExecutorAddress; + } + + static async fromRpc( + provider: Provider, + config: ChainsConfig + ): Promise> { + const [network, chain] = await EvmPlatform.chainFromRpc(provider); + const conf = config[chain]!; + if (conf.network !== network) + throw new Error(`Network mismatch: ${conf.network} != ${network}`); + + return new EvmMultiTokenNttWithExecutor( + network as N, + chain, + provider, + conf.contracts + ); + } + + async *transfer( + sender: AccountAddress, + destination: ChainAddress, + token: TokenId, + amount: bigint, + quote: MultiTokenNttWithExecutor.Quote + ): AsyncGenerator> { + const senderAddress = new EvmAddress(sender).toString(); + const isNativeToken = isNative(token.address); + + const abi = [ + "function transfer(address multiTokenNtt, address token, uint256 amount, uint16 recipientChain, bytes32 recipient, bytes32 refundAddress, bytes transceiverInstructions, (uint256 value, address refundAddress, bytes signedQuote, bytes instructions) executorArgs, (uint16 dbps, address payee) feeArgs) external payable returns (uint64)", + "function transferETH(address multiTokenNtt, uint256 amount, uint16 recipientChain, bytes32 recipient, bytes32 refundAddress, bytes transceiverInstructions, (uint256 value, address refundAddress, bytes signedQuote, bytes instructions) executorArgs, (uint16 dbps, address payee) feeArgs) external payable returns (uint64)", + ]; + + const iface = new Interface(abi); + + const recipientChain = toChainId(destination.chain); + const recipient = destination.address.toUniversalAddress().toUint8Array(); + const refundAddress = sender.toUniversalAddress().toUint8Array(); + + const executorArgs = { + value: quote.estimatedCost, + refundAddress: senderAddress, + signedQuote: quote.signedQuote, + instructions: quote.relayInstructions, + }; + + const feeArgs = { + dbps: quote.referrerFeeDbps, + payee: quote.referrer.address.toString(), + }; + + let data: string; + let msgValue: bigint; + + if (isNativeToken) { + data = iface.encodeFunctionData("transferETH", [ + this.managerAddress, + amount, + recipientChain, + recipient, + refundAddress, + Ntt.encodeTransceiverInstructions(quote.transceiverInstructions), + executorArgs, + feeArgs, + ]); + msgValue = quote.estimatedCost + quote.deliveryPrice + amount; + } else { + const tokenAddress = new EvmAddress(token.address).toString(); + + const tokenContract = EvmPlatform.getTokenImplementation( + this.provider, + tokenAddress + ); + + const currentAllowance = await tokenContract.allowance( + senderAddress, + this.multiTokenNttWithExecutorAddress + ); + + if (currentAllowance < amount) { + const approveTx = await tokenContract.approve.populateTransaction( + this.multiTokenNttWithExecutorAddress, + amount + ); + + yield this.createUnsignedTx( + approveTx, + "MultiTokenNttWithExecutor.Approve" + ); + } + + data = iface.encodeFunctionData("transfer", [ + this.managerAddress, + tokenAddress, + amount, + recipientChain, + recipient, + refundAddress, + Ntt.encodeTransceiverInstructions(quote.transceiverInstructions), + executorArgs, + feeArgs, + ]); + msgValue = quote.estimatedCost + quote.deliveryPrice; + } + + const txReq: TransactionRequest = { + to: this.multiTokenNttWithExecutorAddress, + data, + value: msgValue, + from: senderAddress, + }; + + yield this.createUnsignedTx( + txReq, + isNativeToken + ? "MultiTokenNttWithExecutor.transferETH" + : "MultiTokenNttWithExecutor.transfer" + ); + } + + createUnsignedTx( + txReq: TransactionRequest, + description: string, + parallelizable: boolean = false + ): EvmUnsignedTransaction { + return new EvmUnsignedTransaction( + addChainId(txReq, this.chainId), + this.network, + this.chain, + description, + parallelizable + ); + } +} diff --git a/evm/ts/src/ntt.ts b/evm/ts/src/ntt.ts index b1db3b74f..6540b3f60 100644 --- a/evm/ts/src/ntt.ts +++ b/evm/ts/src/ntt.ts @@ -30,9 +30,12 @@ import { import "@wormhole-foundation/sdk-evm-core"; import { + decodeTrimmedAmount, + EncodedTrimmedAmount, EvmNttTransceiver, Ntt, NttTransceiver, + untrim, WormholeNttTransceiver, } from "@wormhole-foundation/sdk-definitions-ntt"; import { Contract, type Provider, type TransactionRequest } from "ethers"; @@ -288,17 +291,17 @@ export class EvmNtt async *setOwner(owner: AnyEvmAddress) { const canonicalOwner = new EvmAddress(owner).toString(); - const tx = await this.manager.transferOwnership.populateTransaction( - canonicalOwner - ); + const tx = + await this.manager.transferOwnership.populateTransaction(canonicalOwner); yield this.createUnsignedTx(tx, "Ntt.setOwner"); } async *setPauser(pauser: AnyEvmAddress) { const canonicalPauser = new EvmAddress(pauser).toString(); - const tx = await this.manager.transferPauserCapability.populateTransaction( - canonicalPauser - ); + const tx = + await this.manager.transferPauserCapability.populateTransaction( + canonicalPauser + ); yield this.createUnsignedTx(tx, "Ntt.setPauser"); } @@ -586,7 +589,7 @@ export class EvmNtt const encoded: EncodedTrimmedAmount = ( await this.manager.getOutboundLimitParams() ).limit; - const trimmedAmount: TrimmedAmount = decodeTrimmedAmount(encoded); + const trimmedAmount = decodeTrimmedAmount(encoded); const tokenDecimals = await this.getTokenDecimals(); return untrim(trimmedAmount, tokenDecimals); @@ -605,7 +608,7 @@ export class EvmNtt const encoded: EncodedTrimmedAmount = ( await this.manager.getInboundLimitParams(toChainId(fromChain)) ).limit; - const trimmedAmount: TrimmedAmount = decodeTrimmedAmount(encoded); + const trimmedAmount = decodeTrimmedAmount(encoded); const tokenDecimals = await this.getTokenDecimals(); return untrim(trimmedAmount, tokenDecimals); @@ -702,40 +705,3 @@ export class EvmNtt ); } } - -type EncodedTrimmedAmount = bigint; // uint72 - -type TrimmedAmount = { - amount: bigint; - decimals: number; -}; - -function decodeTrimmedAmount(encoded: EncodedTrimmedAmount): TrimmedAmount { - const decimals = Number(encoded & 0xffn); - const amount = encoded >> 8n; - return { - amount, - decimals, - }; -} - -function untrim(trimmed: TrimmedAmount, toDecimals: number): bigint { - const { amount, decimals: fromDecimals } = trimmed; - return scale(amount, fromDecimals, toDecimals); -} - -function scale( - amount: bigint, - fromDecimals: number, - toDecimals: number -): bigint { - if (fromDecimals == toDecimals) { - return amount; - } - - if (fromDecimals > toDecimals) { - return amount / 10n ** BigInt(fromDecimals - toDecimals); - } else { - return amount * 10n ** BigInt(toDecimals - fromDecimals); - } -} diff --git a/sdk/definitions/__tests__/axelar.test.ts b/sdk/definitions/__tests__/axelar.test.ts new file mode 100644 index 000000000..e8ad92c1b --- /dev/null +++ b/sdk/definitions/__tests__/axelar.test.ts @@ -0,0 +1,318 @@ +import { + getAxelarApiUrl, + getAxelarChain, + parseGMPStatus, + parseGMPError, + getAxelarGasFee, + getAxelarTransactionStatus, + GMPStatus, +} from "../src/axelar.js"; + +describe("Axelar Utility Functions", () => { + describe("getAxelarApiUrl", () => { + it("should return mainnet API URL for Mainnet network", () => { + const url = getAxelarApiUrl("Mainnet"); + expect(url).toBe("https://api.axelarscan.io"); + }); + + it("should return testnet API URL for Testnet network", () => { + const url = getAxelarApiUrl("Testnet"); + expect(url).toBe("https://testnet.api.axelarscan.io"); + }); + }); + + describe("getAxelarChain", () => { + it("should return axelar chain name for Ethereum", () => { + const chain = getAxelarChain("Ethereum"); + expect(chain).toBe("ethereum"); + }); + + it("should return axelar chain name for Monad", () => { + const chain = getAxelarChain("Monad"); + expect(chain).toBe("monad"); + }); + + it("should return axelar chain name for Sepolia", () => { + const chain = getAxelarChain("Sepolia"); + expect(chain).toBe("ethereum-sepolia"); + }); + + it("should throw error for unsupported chain", () => { + expect(() => getAxelarChain("Solana" as any)).toThrow( + "Unsupported axelar chain: Solana" + ); + }); + }); + + describe("parseGMPStatus", () => { + it("should parse error status", () => { + const response = { status: "error", error: { message: "some error" } }; + const status = parseGMPStatus(response); + expect(status).toBe(GMPStatus.DEST_EXECUTE_ERROR); + }); + + it("should parse executed status", () => { + const response = { status: "executed" }; + const status = parseGMPStatus(response); + expect(status).toBe(GMPStatus.DEST_EXECUTED); + }); + + it("should parse called status", () => { + const response = { status: "called" }; + const status = parseGMPStatus(response); + expect(status).toBe(GMPStatus.SRC_GATEWAY_CALLED); + }); + + it("should parse executing status", () => { + const response = { status: "executing" }; + const status = parseGMPStatus(response); + expect(status).toBe(GMPStatus.DEST_EXECUTING); + }); + }); + + describe("parseGMPError", () => { + it("should parse error from response", () => { + const response = { + error: { + error: { message: "execution failed" }, + sourceTransactionHash: "0xabc123", + chain: "ethereum", + }, + }; + const error = parseGMPError(response); + expect(error).toEqual({ + message: "execution failed", + txHash: "0xabc123", + chain: "ethereum", + }); + }); + + it("should parse insufficient fee error", () => { + const response = { + is_insufficient_fee: true, + call: { + transaction: { hash: "0xdef456" }, + chain: "monad", + }, + }; + const error = parseGMPError(response); + expect(error).toEqual({ + message: "Insufficient gas", + txHash: "0xdef456", + chain: "monad", + }); + }); + + it("should return undefined when no error", () => { + const response = { status: "executed" }; + const error = parseGMPError(response); + expect(error).toBeUndefined(); + }); + }); + + describe("getAxelarGasFee", () => { + const originalFetch = global.fetch; + let mockFetch: jest.Mock; + + beforeEach(() => { + mockFetch = jest.fn() as jest.Mock; + global.fetch = mockFetch as any; + }); + + afterEach(() => { + global.fetch = originalFetch; + }); + + it("should fetch and return gas fee", async () => { + const mockResponse = { + ok: true, + json: async () => "1000000000000000", + }; + mockFetch.mockResolvedValue(mockResponse); + + const fee = await getAxelarGasFee("Testnet", "Sepolia", "Monad", 500000n); + expect(fee).toBe(1000000000000000n); + expect(global.fetch).toHaveBeenCalledWith( + "https://testnet.api.axelarscan.io/gmp/estimateGasFee", + expect.objectContaining({ + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + sourceChain: "ethereum-sepolia", + destinationChain: "monad", + gasMultiplier: "auto", + gasLimit: "500000", + }), + }) + ); + }); + + it("should return minimum fee of 1 when API returns 0", async () => { + const mockResponse = { + ok: true, + json: async () => "0", + }; + mockFetch.mockResolvedValue(mockResponse); + + const fee = await getAxelarGasFee("Testnet", "Sepolia", "Monad", 500000n); + expect(fee).toBe(1n); + }); + + it("should throw error when API call fails", async () => { + const mockResponse = { + ok: false, + status: 500, + text: async () => "Internal server error", + }; + mockFetch.mockResolvedValue(mockResponse); + + await expect( + getAxelarGasFee("Testnet", "Sepolia", "Monad", 500000n) + ).rejects.toThrow("Failed to estimate gas fee: 500"); + }); + + it("should throw error when request times out", async () => { + mockFetch.mockImplementation(() => { + return new Promise((_, reject) => { + setTimeout(() => reject(new Error("Timeout")), 100); + }); + }); + + await expect( + getAxelarGasFee("Testnet", "Sepolia", "Monad", 500000n, 50) + ).rejects.toThrow("Timeout"); + }); + + it("should use mainnet API for Mainnet network", async () => { + const mockResponse = { + ok: true, + json: async () => "2000000000000000", + }; + mockFetch.mockResolvedValue(mockResponse); + + await getAxelarGasFee("Mainnet", "Ethereum", "Monad", 500000n); + expect(global.fetch).toHaveBeenCalledWith( + "https://api.axelarscan.io/gmp/estimateGasFee", + expect.any(Object) + ); + }); + }); + + describe("getAxelarTransactionStatus", () => { + const originalFetch = global.fetch; + let mockFetch: jest.Mock; + + beforeEach(() => { + mockFetch = jest.fn() as jest.Mock; + global.fetch = mockFetch as any; + }); + + afterEach(() => { + global.fetch = originalFetch; + }); + + it("should fetch and return transaction status", async () => { + const mockResponse = { + ok: true, + json: async () => ({ + data: [ + { + status: "executed", + }, + ], + }), + }; + mockFetch.mockResolvedValue(mockResponse); + + const result = await getAxelarTransactionStatus( + "Testnet", + "Sepolia", + "0xabc123" + ); + expect(result.status).toBe(GMPStatus.DEST_EXECUTED); + expect(result.error).toBeUndefined(); + expect(global.fetch).toHaveBeenCalledWith( + "https://testnet.api.axelarscan.io/gmp/searchGMP", + expect.objectContaining({ + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + sourceChain: "ethereum-sepolia", + txHash: "0xabc123", + }), + }) + ); + }); + + it("should return status with error when present", async () => { + const mockResponse = { + ok: true, + json: async () => ({ + data: [ + { + status: "error", + error: { + error: { message: "execution reverted" }, + sourceTransactionHash: "0xabc123", + chain: "ethereum", + }, + }, + ], + }), + }; + mockFetch.mockResolvedValue(mockResponse); + + const result = await getAxelarTransactionStatus( + "Testnet", + "Sepolia", + "0xabc123" + ); + expect(result.status).toBe(GMPStatus.DEST_EXECUTE_ERROR); + expect(result.error).toEqual({ + message: "execution reverted", + txHash: "0xabc123", + chain: "ethereum", + }); + }); + + it("should throw error when no transaction details found", async () => { + const mockResponse = { + ok: true, + json: async () => ({ + data: [], + }), + }; + mockFetch.mockResolvedValue(mockResponse); + + await expect( + getAxelarTransactionStatus("Testnet", "Sepolia", "0xabc123") + ).rejects.toThrow("No transaction details found"); + }); + + it("should throw error when API call fails", async () => { + const mockResponse = { + ok: false, + status: 500, + text: async () => "Internal server error", + }; + mockFetch.mockResolvedValue(mockResponse); + + await expect( + getAxelarTransactionStatus("Testnet", "Sepolia", "0xabc123") + ).rejects.toThrow("Failed to get transaction status: 500"); + }); + + it("should throw error when request times out", async () => { + mockFetch.mockImplementation( + () => + new Promise((_, reject) => { + setTimeout(() => reject(new Error("Timeout")), 100); + }) + ); + + await expect( + getAxelarTransactionStatus("Testnet", "Sepolia", "0xabc123", 50) + ).rejects.toThrow(); + }); + }); +}); diff --git a/sdk/definitions/src/axelar.ts b/sdk/definitions/src/axelar.ts new file mode 100644 index 000000000..fc2b5f0f9 --- /dev/null +++ b/sdk/definitions/src/axelar.ts @@ -0,0 +1,194 @@ +import { Chain, Network } from "@wormhole-foundation/sdk-base"; + +// The point if this module is to use direct API calls instead of importing the entire @axelar-network/axelarjs-sdk to stay lightweight. + +// Axelar chains: https://github.com/axelarnetwork/axelarjs-sdk/blob/53a957deb1209325b1e3d109e0985a64db6d9901/src/constants/EvmChain.ts#L1 +export const axelarChains: Partial> = { + Ethereum: "ethereum", + Monad: "monad", + Sepolia: "ethereum-sepolia", + // add more as needed +}; + +// https://github.com/axelarnetwork/axelarjs-sdk/blob/53a957deb1209325b1e3d109e0985a64db6d9901/src/libs/TransactionRecoveryApi/AxelarRecoveryApi.ts#L16 +export enum GMPStatus { + SRC_GATEWAY_CALLED = "source_gateway_called", + DEST_GATEWAY_APPROVED = "destination_gateway_approved", + DEST_EXECUTED = "destination_executed", + EXPRESS_EXECUTED = "express_executed", + DEST_EXECUTE_ERROR = "error", + DEST_EXECUTING = "executing", + APPROVING = "approving", + FORECALLED = "forecalled", + FORECALLED_WITHOUT_GAS_PAID = "forecalled_without_gas_paid", + NOT_EXECUTED = "not_executed", + NOT_EXECUTED_WITHOUT_GAS_PAID = "not_executed_without_gas_paid", + INSUFFICIENT_FEE = "insufficient_fee", + UNKNOWN_ERROR = "unknown_error", + CANNOT_FETCH_STATUS = "cannot_fetch_status", + SRC_GATEWAY_CONFIRMED = "confirmed", +} + +export interface GMPError { + txHash: string; + chain: string; + message: string; +} + +export function getAxelarApiUrl(network: Network): string { + return network === "Mainnet" + ? "https://api.axelarscan.io" + : "https://testnet.api.axelarscan.io"; +} + +export function getAxelarChain(chain: Chain): string { + const axelarChain = axelarChains[chain]; + if (!axelarChain) { + throw new Error(`Unsupported axelar chain: ${chain}`); + } + return axelarChain; +} + +export async function getAxelarGasFee( + network: Network, + sourceChain: Chain, + destinationChain: Chain, + gasLimit: bigint, + gasMultiplier: number | "auto" = "auto", + timeoutMs = 10000 +): Promise { + const url = `${getAxelarApiUrl(network)}/gmp/estimateGasFee`; + const axelarSourceChain = getAxelarChain(sourceChain); + const axelarDestinationChain = getAxelarChain(destinationChain); + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), timeoutMs); + + // Set a minimum fee of 1 to avoid 0-fee issue with relays not proceeding + // past the gas paid step + let fee = 1n; + + try { + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + sourceChain: axelarSourceChain, + destinationChain: axelarDestinationChain, + gasMultiplier, + gasLimit: gasLimit.toString(), + }), + signal: controller.signal, + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error( + `Failed to estimate gas fee: ${response.status} ${errorText}` + ); + } + + const result = await response.json(); + + const parsedFee = BigInt(result); + if (parsedFee > 0n) { + fee = parsedFee; + } + } finally { + clearTimeout(timeoutId); + } + + return fee; +} + +export async function getAxelarTransactionStatus( + network: Network, + sourceChain: Chain, + txHash: string, + timeoutMs = 10000 +): Promise<{ status: GMPStatus | string; error?: GMPError }> { + const url = `${getAxelarApiUrl(network)}/gmp/searchGMP`; + + const axelarSourceChain = getAxelarChain(sourceChain); + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), timeoutMs); + + try { + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + sourceChain: axelarSourceChain, + txHash: txHash, + }), + signal: controller.signal, + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error( + `Failed to get transaction status: ${response.status} ${errorText}` + ); + } + + const result = await response.json(); + if (!result.data || result.data.length === 0) { + throw new Error("No transaction details found"); + } + + const txDetails = result.data[0]; + return { + status: parseGMPStatus(txDetails), + error: parseGMPError(txDetails), + }; + } finally { + clearTimeout(timeoutId); + } +} + +export function parseGMPStatus(response: any): GMPStatus | string { + const { error, status } = response; + + switch (status) { + case "error": + if (error) return GMPStatus.DEST_EXECUTE_ERROR; + return status; + case "executed": + return GMPStatus.DEST_EXECUTED; + case "approved": + return GMPStatus.DEST_GATEWAY_APPROVED; + case "called": + return GMPStatus.SRC_GATEWAY_CALLED; + case "executing": + return GMPStatus.DEST_EXECUTING; + default: + return status; + } +} + +export function parseGMPError(response: any): GMPError | undefined { + if (response.error) { + return { + message: response.error.error.message, + txHash: response.error.sourceTransactionHash, + chain: response.error.chain, + }; + } else if (response.is_insufficient_fee) { + return { + message: "Insufficient gas", + txHash: response.call.transaction.hash, + chain: response.call.chain, + }; + } +} + +export function getAxelarExplorerUrl(network: Network, txHash: string): string { + return network === "Mainnet" + ? `https://axelarscan.io/gmp/${txHash}` + : `https://testnet.axelarscan.io/gmp/${txHash}`; +} diff --git a/sdk/definitions/src/index.ts b/sdk/definitions/src/index.ts index f2d804fdb..403172e5a 100644 --- a/sdk/definitions/src/index.ts +++ b/sdk/definitions/src/index.ts @@ -1,10 +1,18 @@ import { registerPayloadTypes } from "@wormhole-foundation/sdk-definitions"; -import { nttNamedPayloads } from "./layouts/index.js"; +import { + multiTokenNttNamedPayloads, + nttNamedPayloads, +} from "./layouts/index.js"; registerPayloadTypes("Ntt", nttNamedPayloads); +registerPayloadTypes("MultiTokenNtt", multiTokenNttNamedPayloads); export * from "./ntt.js"; export * from "./nttWithExecutor.js"; +export * from "./multiTokenNtt.js"; +export * from "./multiTokenNttWithExecutor.js"; +export * from "./trimmedAmount.js"; +export * from "./axelar.js"; export * from "./layouts/index.js"; export type * from "./layouts/index.js"; diff --git a/sdk/definitions/src/layouts/index.ts b/sdk/definitions/src/layouts/index.ts index 56a5f939c..a16b41b67 100644 --- a/sdk/definitions/src/layouts/index.ts +++ b/sdk/definitions/src/layouts/index.ts @@ -6,6 +6,10 @@ import { import { nttManagerMessageLayout } from "./manager.js"; import { transceiverInfo, transceiverRegistration } from "./transceiver.js"; import { nativeTokenTransferLayout } from "./transfer.js"; +import { + genericMessageLayout, + multiTokenNativeTokenTransferLayout, +} from "./multiToken.js"; import { wormholeTransceiverMessageLayout } from "./wormhole.js"; export const nttNamedPayloads = [ @@ -27,16 +31,32 @@ export const nttNamedPayloads = [ ["TransceiverRegistration", transceiverRegistration], ] as const satisfies NamedPayloads; +export const multiTokenNttNamedPayloads = [ + [ + "WormholeTransfer", + wormholeTransceiverMessageLayout( + nttManagerMessageLayout( + genericMessageLayout(multiTokenNativeTokenTransferLayout) + ) + ), + ], +] as const satisfies NamedPayloads; + // factory registration: declare module "@wormhole-foundation/sdk-definitions" { export namespace WormholeRegistry { interface PayloadLiteralToLayoutMapping - extends RegisterPayloadTypes<"Ntt", typeof nttNamedPayloads> {} + extends RegisterPayloadTypes<"Ntt", typeof nttNamedPayloads>, + RegisterPayloadTypes< + "MultiTokenNtt", + typeof multiTokenNttNamedPayloads + > {} } } export * from "./amount.js"; export * from "./manager.js"; +export * from "./multiToken.js"; export * from "./prefix.js"; export * from "./transceiver.js"; export * from "./transceiverInstructions.js"; @@ -45,6 +65,7 @@ export * from "./wormhole.js"; export type * from "./amount.js"; export type * from "./manager.js"; +export type * from "./multiToken.js"; export type * from "./prefix.js"; export type * from "./transceiver.js"; export type * from "./transceiverInstructions.js"; diff --git a/sdk/definitions/src/layouts/manager.ts b/sdk/definitions/src/layouts/manager.ts index 74c64b403..6e46b59f8 100644 --- a/sdk/definitions/src/layouts/manager.ts +++ b/sdk/definitions/src/layouts/manager.ts @@ -10,7 +10,7 @@ export type NttManagerMessage

= LayoutToType>>; export const nttManagerMessageLayout = < - const P extends CustomizableBytes = undefined + const P extends CustomizableBytes = undefined, >( customPayload?: P ) => diff --git a/sdk/definitions/src/layouts/multiToken.ts b/sdk/definitions/src/layouts/multiToken.ts new file mode 100644 index 000000000..557b16eb2 --- /dev/null +++ b/sdk/definitions/src/layouts/multiToken.ts @@ -0,0 +1,59 @@ +import { + customizableBytes, + CustomizableBytes, + Layout, +} from "@wormhole-foundation/sdk-base"; +import { layoutItems } from "@wormhole-foundation/sdk-definitions"; +import { trimmedAmountItem } from "./amount.js"; +import { prefixItem } from "./prefix.js"; + +const tokenMetaLayout = [ + { name: "name", ...layoutItems.fixedLengthStringItem(32) }, + { name: "symbol", ...layoutItems.fixedLengthStringItem(32) }, + { name: "decimals", binary: "uint", size: 1 }, +] as const satisfies Layout; + +export const tokenMetaLayoutItem = { + binary: "bytes", + layout: tokenMetaLayout, +} as const; + +const tokenIdLayout = [ + { name: "chainId", ...layoutItems.chainItem() }, + { name: "tokenAddress", ...layoutItems.universalAddressItem }, +] as const satisfies Layout; + +export const tokenIdLayoutItem = { + binary: "bytes", + layout: tokenIdLayout, +} as const; + +const tokenInfoLayout = [ + { name: "meta", ...tokenMetaLayoutItem }, + { name: "token", ...tokenIdLayoutItem }, +] as const satisfies Layout; + +export const tokenInfoLayoutItem = { + binary: "bytes", + layout: tokenInfoLayout, +} as const; + +export const multiTokenNativeTokenTransferLayout = [ + // bytes4 constant MTT_PREFIX = 0x994D5454; + prefixItem([0x99, 0x4d, 0x54, 0x54]), + { name: "trimmedAmount", ...trimmedAmountItem }, + { name: "token", ...tokenInfoLayoutItem }, + { name: "sender", ...layoutItems.universalAddressItem }, + { name: "to", ...layoutItems.universalAddressItem }, + customizableBytes({ name: "additionalPayload", lengthSize: 2 }), +] as const satisfies Layout; + +// GmpManager message layout +export const genericMessageLayout = (data?: D) => + [ + prefixItem([0x99, 0x47, 0x4d, 0x50]), + { name: "toChain", ...layoutItems.chainItem() }, + { name: "callee", ...layoutItems.universalAddressItem }, + { name: "sender", ...layoutItems.universalAddressItem }, + customizableBytes({ name: "data", lengthSize: 2 }, data), + ] as const satisfies Layout; diff --git a/sdk/definitions/src/layouts/prefix.ts b/sdk/definitions/src/layouts/prefix.ts index dff38c733..ae1eb2b9b 100644 --- a/sdk/definitions/src/layouts/prefix.ts +++ b/sdk/definitions/src/layouts/prefix.ts @@ -5,4 +5,4 @@ export const prefixItem = (prefix: Prefix) => binary: "bytes", custom: Uint8Array.from(prefix), omit: true, - } as const); + }) as const; diff --git a/sdk/definitions/src/layouts/transceiver.ts b/sdk/definitions/src/layouts/transceiver.ts index 76ef2914d..28f1e1b03 100644 --- a/sdk/definitions/src/layouts/transceiver.ts +++ b/sdk/definitions/src/layouts/transceiver.ts @@ -9,12 +9,12 @@ import { Prefix, prefixItem } from "./prefix.js"; export type TransceiverMessage< MP extends CustomizableBytes = undefined, - TP extends CustomizableBytes = undefined + TP extends CustomizableBytes = undefined, > = LayoutToType>>; export const transceiverMessageLayout = < const MP extends CustomizableBytes = undefined, - const TP extends CustomizableBytes = undefined + const TP extends CustomizableBytes = undefined, >( prefix: Prefix, nttManagerPayload?: MP, diff --git a/sdk/definitions/src/layouts/transceiverInstructions.ts b/sdk/definitions/src/layouts/transceiverInstructions.ts index 0bddb8093..0f3cc2f59 100644 --- a/sdk/definitions/src/layouts/transceiverInstructions.ts +++ b/sdk/definitions/src/layouts/transceiverInstructions.ts @@ -5,7 +5,7 @@ import { } from "@wormhole-foundation/sdk-base"; export const transceiverInstructionLayout = < - const P extends CustomizableBytes = undefined + const P extends CustomizableBytes = undefined, >( customPayload?: P ) => diff --git a/sdk/definitions/src/layouts/wormhole.ts b/sdk/definitions/src/layouts/wormhole.ts index 127a5038d..0d62f0844 100644 --- a/sdk/definitions/src/layouts/wormhole.ts +++ b/sdk/definitions/src/layouts/wormhole.ts @@ -5,11 +5,11 @@ import type { import { transceiverMessageLayout } from "./transceiver.js"; export type WormholeTransceiverMessage< - MP extends CustomizableBytes = undefined + MP extends CustomizableBytes = undefined, > = LayoutToType>>; export const wormholeTransceiverMessageLayout = < - MP extends CustomizableBytes = undefined + MP extends CustomizableBytes = undefined, >( nttManagerPayload?: MP ) => diff --git a/sdk/definitions/src/multiTokenNtt.ts b/sdk/definitions/src/multiTokenNtt.ts new file mode 100644 index 000000000..a0bd0b6f6 --- /dev/null +++ b/sdk/definitions/src/multiTokenNtt.ts @@ -0,0 +1,189 @@ +import { + encoding, + serializeLayout, + toChainId, + type Chain, + type Network, +} from "@wormhole-foundation/sdk-base"; + +import { + AccountAddress, + ChainAddress, + EmptyPlatformMap, + TokenAddress, + TokenId, + UniversalAddress, + UnsignedTransaction, + VAA, + keccak256, +} from "@wormhole-foundation/sdk-definitions"; + +import { + NttManagerMessage, + genericMessageLayout, + multiTokenNativeTokenTransferLayout, + nttManagerMessageLayout, +} from "./layouts/index.js"; + +import { Ntt } from "./ntt.js"; + +export namespace MultiTokenNtt { + const _protocol = "MultiTokenNtt"; + export type ProtocolName = typeof _protocol; + + export type Contracts = { + chain: Chain; + manager: string; + gmpManager: string; + axelarGasMultiplier?: number | "auto"; + }; + + export interface TokenMeta { + name: string; + symbol: string; + decimals: number; + } + + export type Message = NttManagerMessage< + ReturnType< + typeof genericMessageLayout + > + >; + + export type OriginalTokenId = { + chain: C; + address: UniversalAddress; + }; + + export type Attestation = VAA<"MultiTokenNtt:WormholeTransfer">; + + export type InboundQueuedTransfer = { + sourceChain: Chain; + rateLimitExpiryTimestamp: number; + }; + + /** + * messageDigest hashes a message for the Ntt manager, the digest is used + * to uniquely identify the message + * @param chain The chain that sent the message + * @param message The ntt message to hash + * @returns a 32 byte digest of the message + */ + export function messageDigest(chain: Chain, message: Message): Uint8Array { + return keccak256( + encoding.bytes.concat( + encoding.bignum.toBytes(toChainId(chain), 2), + serializeLayout( + nttManagerMessageLayout( + genericMessageLayout(multiTokenNativeTokenTransferLayout) + ), + message + ) + ) + ); + } +} + +export interface MultiTokenNtt { + isPaused(): Promise; + + getSendTransceivers(dstChain: Chain): Promise; + + getReceiveTransceivers(srcChain: Chain): Promise; + + transceiverAttestedToMessage( + fromChain: Chain, + transceiverMessage: MultiTokenNtt.Message, + index: number + ): Promise; + + createTransceiverInstructions( + dstChain: Chain, + gasLimit: bigint, + axelarGasMultiplier?: number | "auto" + ): Promise; + + quoteDeliveryPrice( + destination: Chain, + instructions: Ntt.TransceiverInstruction[] + ): Promise; + + transfer( + sender: AccountAddress, + token: TokenAddress, + amount: bigint, + destination: ChainAddress, + destinationGasLimit: bigint, + axelarGasMultiplier?: number | "auto" + ): AsyncGenerator>; + + redeem( + attestation: MultiTokenNtt.Attestation + ): AsyncGenerator>; + + getTokenMeta(token: TokenId): Promise; + + getCurrentOutboundCapacity(token: TokenId): Promise; + + getOutboundLimit(token: TokenId): Promise; + + getCurrentInboundCapacity( + originalToken: MultiTokenNtt.OriginalTokenId, + fromChain: Chain + ): Promise; + + getRateLimitDuration(): Promise; + + getInboundLimit( + originalToken: MultiTokenNtt.OriginalTokenId, + fromChain: Chain + ): Promise; + + getIsApproved(attestation: MultiTokenNtt.Attestation): Promise; + + getIsExecuted(attestation: MultiTokenNtt.Attestation): Promise; + + getIsTransferInboundQueued( + attestation: MultiTokenNtt.Attestation + ): Promise; + + getInboundQueuedTransfer( + fromChain: Chain, + transceiverMessage: MultiTokenNtt.Message + ): Promise; + + completeInboundQueuedTransfer( + fromChain: Chain, + transceiverMessage: MultiTokenNtt.Message + ): AsyncGenerator>; + + getOriginalToken(localToken: TokenId): Promise; + + isWrappedToken(localToken: TokenId): Promise; + + getLocalToken( + originalToken: MultiTokenNtt.OriginalTokenId + ): Promise; + + calculateLocalTokenAddress( + originalToken: MultiTokenNtt.OriginalTokenId, + tokenMeta: MultiTokenNtt.TokenMeta + ): Promise>; + + getWrappedNativeToken(): Promise; + + estimateGasLimit( + originalToken: MultiTokenNtt.OriginalTokenId + ): Promise; +} + +declare module "@wormhole-foundation/sdk-definitions" { + export namespace WormholeRegistry { + interface ProtocolToInterfaceMapping { + MultiTokenNtt: MultiTokenNtt; + } + interface ProtocolToPlatformMapping { + MultiTokenNtt: EmptyPlatformMap; + } + } +} diff --git a/sdk/definitions/src/multiTokenNttWithExecutor.ts b/sdk/definitions/src/multiTokenNttWithExecutor.ts new file mode 100644 index 000000000..5393ebe95 --- /dev/null +++ b/sdk/definitions/src/multiTokenNttWithExecutor.ts @@ -0,0 +1,39 @@ +import type { + AccountAddress, + Chain, + ChainAddress, + EmptyPlatformMap, + Network, + TokenId, + UnsignedTransaction, +} from "@wormhole-foundation/sdk-connect"; +import { NttWithExecutor } from "./nttWithExecutor.js"; +import { Ntt } from "./ntt.js"; + +export namespace MultiTokenNttWithExecutor { + export type Quote = NttWithExecutor.Quote & { + deliveryPrice: bigint; + transceiverInstructions: Ntt.TransceiverInstruction[]; + }; +} + +export interface MultiTokenNttWithExecutor { + transfer( + sender: AccountAddress, + destination: ChainAddress, + token: TokenId, + amount: bigint, + quote: MultiTokenNttWithExecutor.Quote + ): AsyncGenerator>; +} + +declare module "@wormhole-foundation/sdk-definitions" { + export namespace WormholeRegistry { + interface ProtocolToInterfaceMapping { + MultiTokenNttWithExecutor: MultiTokenNttWithExecutor; + } + interface ProtocolToPlatformMapping { + MultiTokenNttWithExecutor: EmptyPlatformMap<"MultiTokenNttWithExecutor">; + } + } +} diff --git a/sdk/definitions/src/ntt.ts b/sdk/definitions/src/ntt.ts index a82e194a8..7f8683c86 100644 --- a/sdk/definitions/src/ntt.ts +++ b/sdk/definitions/src/ntt.ts @@ -114,6 +114,12 @@ export namespace Ntt { payload: Uint8Array; }; + export type TransceiverMeta = { + address: string; + index: number; + type: string; + }; + export type Peer = { address: ChainAddress; tokenDecimals: number; diff --git a/sdk/definitions/src/trimmedAmount.ts b/sdk/definitions/src/trimmedAmount.ts new file mode 100644 index 000000000..c82a61db7 --- /dev/null +++ b/sdk/definitions/src/trimmedAmount.ts @@ -0,0 +1,48 @@ +import { TrimmedAmount } from "./layouts/amount.js"; + +export type EncodedTrimmedAmount = bigint; // uint72 + +export function decodeTrimmedAmount( + encoded: EncodedTrimmedAmount +): TrimmedAmount { + const decimals = Number(encoded & 0xffn); + const amount = encoded >> 8n; + return { + amount, + decimals, + }; +} + +export function encodeTrimmedAmount( + trimmed: TrimmedAmount +): EncodedTrimmedAmount { + const { amount, decimals } = trimmed; + if (decimals < 0 || decimals > 255) { + throw new Error("decimals out of range"); + } + if (amount < 0n || amount >= 1n << 64n) { + throw new Error("amount out of range"); + } + return (amount << 8n) | BigInt(decimals); +} + +export function untrim(trimmed: TrimmedAmount, toDecimals: number): bigint { + const { amount, decimals: fromDecimals } = trimmed; + return scale(amount, fromDecimals, toDecimals); +} + +export function scale( + amount: bigint, + fromDecimals: number, + toDecimals: number +): bigint { + if (fromDecimals == toDecimals) { + return amount; + } + + if (fromDecimals > toDecimals) { + return amount / 10n ** BigInt(fromDecimals - toDecimals); + } else { + return amount * 10n ** BigInt(toDecimals - fromDecimals); + } +} diff --git a/sdk/examples/package.json b/sdk/examples/package.json index a96e532bc..550209ecc 100644 --- a/sdk/examples/package.json +++ b/sdk/examples/package.json @@ -23,7 +23,8 @@ "scripts": { "route": "tsx src/route.ts", "demo": "tsx src/index.ts", - "prettier": "prettier --write ./src" + "prettier": "prettier --write ./src", + "multiToken": "tsx src/multiToken.ts" }, "devDependencies": { "dotenv": "^16.4.5", diff --git a/sdk/examples/src/multiToken.ts b/sdk/examples/src/multiToken.ts new file mode 100644 index 000000000..58a8f1737 --- /dev/null +++ b/sdk/examples/src/multiToken.ts @@ -0,0 +1,115 @@ +import { + canonicalAddress, + isAttested, + nativeTokenId, + routes, + wormhole, +} from "@wormhole-foundation/sdk"; +import evm from "@wormhole-foundation/sdk/evm"; + +// register protocol implementations +import "@wormhole-foundation/sdk-evm-ntt"; + +import { + MultiTokenNttExecutorRoute, + multiTokenNttExecutorRoute, +} from "@wormhole-foundation/sdk-route-ntt"; +import { getSigner } from "./helpers.js"; + +const config: MultiTokenNttExecutorRoute.Config = { + contracts: [ + { + chain: "Sepolia", + manager: "0x6c5aAE4622B835058A41879bA5e128019B9047d6", + gmpManager: "0xDaeE3A6B4196E3e46015b364F1DAe54CEAE74A91", + }, + { + chain: "Monad", + manager: "0x600D3C45Cd002E7359D12597Bb8058a0C32A20Df", + gmpManager: "0x641a6608e2959c0D7Fe2a5F267DFDA519ED43d98", + }, + ], +}; + +(async function () { + const wh = await wormhole("Testnet", [evm]); + + const src = wh.getChain("Sepolia"); + const dst = wh.getChain("Monad"); + + const srcSigner = await getSigner(src); + const dstSigner = await getSigner(dst); + + const r = multiTokenNttExecutorRoute(config); + + const resolver = wh.resolver([r]); + + const sendToken = nativeTokenId(src.chain); + + // given the send token, what can we possibly get on the destination chain? + const destTokens = await r.supportedDestinationTokens(sendToken, src, dst); + console.log( + "For the given source token and routes configured, the following tokens may be receivable: ", + destTokens.map((t) => canonicalAddress(t)) + ); + //grab the first one for the example + const destinationToken = destTokens[0]!; + + // creating a transfer request fetches token details + // since all routes will need to know about the tokens + const tr = await routes.RouteTransferRequest.create(wh, { + source: sendToken, + destination: destinationToken, + }); + + // resolve the transfer request to a set of routes that can perform it + const foundRoutes = await resolver.findRoutes(tr); + console.log( + "For the transfer parameters, we found these routes: ", + foundRoutes + ); + + // Taking the first route here, they'll be sorted by output amount + // but you can chose any of them + const bestRoute = foundRoutes[0]!; + console.log("Selected: ", bestRoute); + + // Figure out what options are available + const options = bestRoute.getDefaultOptions(); + console.log("This route offers the following default options", options); + + // Validate the transfer params passed + // This fetches the next bits of data necessary and parses amounts or other values + // it returns a new type: `ValidatedTransferParams`. + // This is a validated version of the input params which must be passed to the next step + const validated = await bestRoute.validate(tr, { + amount: "0.00001", + options, + }); + if (!validated.valid) throw validated.error; + console.log("Validated parameters: ", validated.params); + + // Fetch quote for the transfer + // this, too, returns a new type that must be passed to the next step (if you like the quote) + const quote = await bestRoute.quote(tr, validated.params); + if (!quote.success) throw quote.error; + console.log("Quote for transfer: ", quote); + + // Now the transfer may be initiated + // A receipt will be returned, guess what you gotta do with that? + let receipt = await bestRoute.initiate( + tr, + srcSigner.signer, + quote, + dstSigner.address + ); + console.log("Initiated transfer with receipt: ", receipt); + + for await (receipt of bestRoute.track(receipt, 120 * 1000)) { + if (routes.isManual(bestRoute) && isAttested(receipt)) { + console.log("completing transfer"); + await bestRoute.complete(srcSigner.signer, receipt); + } + console.log("receipt state:", receipt.state); + } +})(); diff --git a/sdk/examples/src/route.ts b/sdk/examples/src/route.ts index 677fbacf4..5940c1e2d 100644 --- a/sdk/examples/src/route.ts +++ b/sdk/examples/src/route.ts @@ -1,4 +1,9 @@ -import { canonicalAddress, routes, wormhole } from "@wormhole-foundation/sdk"; +import { + canonicalAddress, + routes, + Wormhole, + wormhole, +} from "@wormhole-foundation/sdk"; import evm from "@wormhole-foundation/sdk/evm"; import solana from "@wormhole-foundation/sdk/solana"; @@ -27,13 +32,8 @@ import { getSigner } from "./helpers.js"; nttAutomaticRoute({ tokens: NttTokens }), ]); - const srcTokens = await resolver.supportedSourceTokens(src); - console.log( - "Allowed source tokens: ", - srcTokens.map((t) => canonicalAddress(t)) - ); - // Just grab the first one - const sendToken = srcTokens[0]!; + const { chain, token } = NttTokens.Test[0]!; + const sendToken = Wormhole.tokenId(chain, token); // given the send token, what can we possibly get on the destination chain? const destTokens = await resolver.supportedDestinationTokens( diff --git a/sdk/route/src/executor/executor.ts b/sdk/route/src/executor/executor.ts index 9eebdddb3..c6becc543 100644 --- a/sdk/route/src/executor/executor.ts +++ b/sdk/route/src/executor/executor.ts @@ -42,7 +42,7 @@ import { fetchCapabilities, fetchSignedQuote, fetchStatus, - RelayStatus, + isRelayStatusFailed, } from "./utils.js"; import { Ntt, NttWithExecutor } from "@wormhole-foundation/sdk-definitions-ntt"; import { @@ -99,7 +99,7 @@ export namespace NttExecutorRoute { export type TransferReceipt< SC extends Chain = Chain, - DC extends Chain = Chain + DC extends Chain = Chain, > = _TransferReceipt & { params: ValidatedParams; }; @@ -711,12 +711,7 @@ export class NttExecutorRoute if (!txStatus) throw new Error("No transaction status found"); const relayStatus = txStatus.status; - if ( - relayStatus === RelayStatus.Failed || // this could happen if simulation fails - relayStatus === RelayStatus.Underpaid || // only happens if you don't pay at least the costEstimate - relayStatus === RelayStatus.Unsupported || // capabilities check didn't pass - relayStatus === RelayStatus.Aborted // An unrecoverable error indicating the attempt should stop (bad data, pre-flight checks failed, or chain-specific conditions) - ) { + if (isRelayStatusFailed(relayStatus)) { receipt = { ...receipt, state: TransferState.Failed, diff --git a/sdk/route/src/executor/multiToken.ts b/sdk/route/src/executor/multiToken.ts new file mode 100644 index 000000000..c76e0d867 --- /dev/null +++ b/sdk/route/src/executor/multiToken.ts @@ -0,0 +1,614 @@ +import { + Chain, + ChainAddress, + ChainContext, + Network, + Signer, + TokenId, + TransactionId, + TransferState, + Wormhole, + amount, + canonicalAddress, + finality, + isNative, + nativeTokenId, + routes, + signSendWait, + relayInstructionsLayout, + deserializeLayout, + guardians, + UniversalAddress, + chainToPlatform, + encoding, + serializeLayout, + signedQuoteLayout, + toChainId, +} from "@wormhole-foundation/sdk-connect"; +import "@wormhole-foundation/sdk-definitions-ntt"; +import { MultiTokenNttRoute, NttRoute } from "../types.js"; +import { + MultiTokenNtt, + MultiTokenNttWithExecutor, + Ntt, + NttWithExecutor, +} from "@wormhole-foundation/sdk-definitions-ntt"; +import { + calculateReferrerFee, + Capabilities, + fetchCapabilities, + fetchSignedQuote, + fetchStatus, +} from "./utils.js"; +import { getDefaultReferrerAddress } from "./consts.js"; +import { NttExecutorRoute } from "./executor.js"; + +export namespace MultiTokenNttExecutorRoute { + export type Config = { + contracts: MultiTokenNtt.Contracts[]; + referrerFee?: ReferrerFeeConfig; + axelarGasMultiplier?: number | "auto"; + }; + + export type ReferrerFeeConfig = NttExecutorRoute.ReferrerFeeConfig; +} + +type Op = MultiTokenNttRoute.Options; +type Tp = routes.TransferParams; +type Vr = routes.ValidationResult; + +type Vp = MultiTokenNttRoute.ValidatedParams; + +type Q = routes.Quote; +type QR = routes.QuoteResult; + +type R = MultiTokenNttRoute.TransferReceipt; + +export function multiTokenNttExecutorRoute( + config: MultiTokenNttExecutorRoute.Config +) { + class MultiTokenNttExecutorRouteImpl< + N extends Network, + > extends MultiTokenNttExecutorRoute { + static override config = config; + } + return MultiTokenNttExecutorRouteImpl; +} + +export class MultiTokenNttExecutorRoute + extends routes.AutomaticRoute + implements routes.StaticRouteMethods +{ + static NATIVE_GAS_DROPOFF_SUPPORTED: boolean = true; + + // Since we set the config on the static class, access it with this param + // the MultiTokenNttExecutorRoute.config will always be empty + readonly staticConfig: MultiTokenNttExecutorRoute.Config = + // @ts-ignore + this.constructor.config; + static config: MultiTokenNttExecutorRoute.Config = { contracts: [] }; + + static meta = { name: "MultiTokenNttExecutorRoute" }; + + static supportedNetworks(): Network[] { + return MultiTokenNttRoute.resolveSupportedNetworks(this.config.contracts); + } + + static supportedChains(network: Network): Chain[] { + return MultiTokenNttRoute.resolveSupportedChains( + this.config.contracts, + network + ); + } + + static async supportedDestinationTokens( + sourceToken: TokenId, + fromChain: ChainContext, + toChain: ChainContext + ): Promise { + const destinationTokenId = await MultiTokenNttRoute.getDestinationTokenId( + sourceToken, + fromChain, + toChain, + this.config.contracts + ); + return [destinationTokenId]; + } + + static isProtocolSupported( + chain: ChainContext + ): boolean { + return chain.supportsProtocol("MultiTokenNtt"); + } + + getDefaultOptions(): Op { + return { + nativeGas: 0, + }; + } + + async isWrappedToken(token: TokenId): Promise { + return await MultiTokenNttRoute.isWrappedToken( + this.wh.getChain(token.chain), + token, + this.staticConfig.contracts + ); + } + + async getOriginalToken(token: TokenId): Promise { + return await MultiTokenNttRoute.getOriginalToken( + this.wh.getChain(token.chain), + token, + this.staticConfig.contracts + ); + } + + async validate( + request: routes.RouteTransferRequest, + params: Tp + ): Promise { + if (request.fromChain.chain === request.toChain.chain) { + return { + valid: false, + error: new Error("Source and destination chains must differ"), + params, + }; + } + + const options = params.options ?? this.getDefaultOptions(); + + if ( + options.nativeGas !== undefined && + (options.nativeGas < 0 || options.nativeGas > 1) + ) { + return { + valid: false, + error: new Error("Invalid native gas percentage"), + params, + }; + } + + const parsedAmount = amount.parse(params.amount, request.source.decimals); + + const trimmedAmount = NttRoute.trimAmount( + parsedAmount, + request.destination.decimals + ); + + const sourceContracts = MultiTokenNttRoute.resolveContracts( + this.staticConfig.contracts, + request.fromChain.chain + ); + + const destinationContracts = MultiTokenNttRoute.resolveContracts( + this.staticConfig.contracts, + request.toChain.chain + ); + + const sourceNtt = await request.fromChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: sourceContracts, + }); + + const sourceToken = isNative(request.source.id.address) + ? await sourceNtt.getWrappedNativeToken() + : request.source.id; + + const originalTokenId = await sourceNtt.getOriginalToken(sourceToken); + + const sendTransceivers = await sourceNtt.getSendTransceivers( + request.toChain.chain + ); + + const referrerFeeDbps = this.getReferrerFeeDbps(request); + + const gasLimit = await this.estimateGasLimit(request, originalTokenId); + + const validatedParams: Vp = { + amount: params.amount, + normalizedParams: { + amount: trimmedAmount, + sourceContracts, + destinationContracts, + referrerFeeDbps, + sourceTokenId: request.source.id, + destinationTokenId: request.destination.id, + originalTokenId, + gasLimit, + sendTransceivers, + }, + options, + }; + + return { valid: true, params: validatedParams }; + } + + async quote( + request: routes.RouteTransferRequest, + params: Vp + ): Promise { + const { fromChain, toChain } = request; + + try { + const executorQuote = await this.fetchExecutorQuote(request, params); + + const { deliveryPrice, transceiverInstructions } = + await this.fetchDeliveryPriceAndInstructions( + fromChain, + toChain, + params + ); + + const { remainingAmount, estimatedCost, gasDropOff, expires } = + executorQuote; + + const receivedAmount = amount.scale( + amount.fromBaseUnits(remainingAmount, request.source.decimals), + request.destination.decimals + ); + + const result: QR = { + success: true, + params, + sourceToken: { + token: request.source.id, + amount: params.normalizedParams.amount, + }, + destinationToken: { + token: request.destination.id, + amount: receivedAmount, + }, + relayFee: { + token: nativeTokenId(fromChain.chain), + amount: amount.fromBaseUnits( + estimatedCost + deliveryPrice, + fromChain.config.nativeTokenDecimals + ), + }, + destinationNativeGas: amount.fromBaseUnits( + gasDropOff, + toChain.config.nativeTokenDecimals + ), + eta: + finality.estimateFinalityTime(request.fromChain.chain) + + guardians.guardianAttestationEta * 1000, + expires, + details: { + ...executorQuote, + deliveryPrice, + transceiverInstructions, + }, + }; + + const destinationNtt = await toChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: params.normalizedParams.destinationContracts, + }); + + const duration = await destinationNtt.getRateLimitDuration(); + const warnings = await MultiTokenNttRoute.checkRateLimit( + destinationNtt, + fromChain.chain, + params.normalizedParams.originalTokenId, + receivedAmount, + duration + ); + if (warnings) { + result.warnings = warnings; + } + + return result; + } catch (e: unknown) { + return { + success: false, + error: e instanceof Error ? e : new Error(String(e)), + }; + } + } + + getReferrerFeeDbps(request: routes.RouteTransferRequest): bigint { + let referrerFeeDbps = 0n; + if (this.staticConfig.referrerFee) { + referrerFeeDbps = this.staticConfig.referrerFee.feeDbps; + if (this.staticConfig.referrerFee.perTokenOverrides) { + const sourceTokenAddress = canonicalAddress(request.source.id); + const override = + this.staticConfig.referrerFee.perTokenOverrides[ + request.source.id.chain + ]?.[sourceTokenAddress]; + if (override?.referrerFeeDbps !== undefined) { + referrerFeeDbps = override.referrerFeeDbps; + } + } + } + return referrerFeeDbps; + } + + getReferrerAddress(fromChain: ChainContext): ChainAddress { + let referrer = getDefaultReferrerAddress(fromChain.chain); + const referrerFeeConfig = this.staticConfig.referrerFee; + if (referrerFeeConfig) { + const platform = chainToPlatform(fromChain.chain); + const referrerAddress = + referrerFeeConfig.referrerAddresses?.[platform] ?? ""; + if (referrerAddress) { + referrer = Wormhole.chainAddress(fromChain.chain, referrerAddress); + } + } + return referrer; + } + + async validateCapabilities( + fromChain: ChainContext, + toChain: ChainContext + ): Promise<{ + sourceCapabilities: Capabilities; + destinationCapabilities: Capabilities; + }> { + const capabilities = await fetchCapabilities(fromChain.network); + const sourceCapabilities = capabilities[toChainId(fromChain.chain)]; + if (!sourceCapabilities) { + throw new Error("Unsupported source chain"); + } + + const destinationCapabilities = capabilities[toChainId(toChain.chain)]; + if ( + !destinationCapabilities || + !destinationCapabilities.requestPrefixes.includes("ERN1") + ) { + throw new Error("Unsupported destination chain"); + } + + return { sourceCapabilities, destinationCapabilities }; + } + + calculateGasDropOff(gasDropOffLimit: bigint, params: Vp): bigint { + return params.options.nativeGas && gasDropOffLimit > 0n + ? (BigInt(Math.round(params.options.nativeGas * 100)) * gasDropOffLimit) / + 100n + : 0n; + } + + async estimateGasLimit( + request: routes.RouteTransferRequest, + originalTokenId: MultiTokenNtt.OriginalTokenId + ): Promise { + return MultiTokenNttRoute.estimateGasLimit( + request, + originalTokenId, + this.staticConfig.contracts, + this.staticConfig.referrerFee?.perTokenOverrides + ); + } + + async fetchExecutorQuote( + request: routes.RouteTransferRequest, + params: Vp + ): Promise { + const { fromChain, toChain } = request; + + const referrer = this.getReferrerAddress(fromChain); + + const { referrerFee, remainingAmount, referrerFeeDbps } = + calculateReferrerFee( + params.normalizedParams.amount, + params.normalizedParams.referrerFeeDbps ?? 0n, + request.destination.decimals + ); + if (remainingAmount <= 0n) { + throw new Error("Amount after fee <= 0"); + } + + const { destinationCapabilities } = await this.validateCapabilities( + fromChain, + toChain + ); + + const { recipient } = request; + + const gasDropOffLimit = BigInt(destinationCapabilities.gasDropOffLimit); + const gasDropOff = this.calculateGasDropOff(gasDropOffLimit, params); + + const relayRequests = []; + + // Add the gas instruction + relayRequests.push({ + request: { + type: "GasInstruction" as const, + gasLimit: params.normalizedParams.gasLimit, + msgValue: 0n, + }, + }); + + // Add the gas drop-off instruction if applicable + if (gasDropOff > 0n) { + relayRequests.push({ + request: { + type: "GasDropOffInstruction" as const, + dropOff: gasDropOff, + // If the recipient is undefined (e.g. the user hasn't connected their wallet yet), + // we temporarily use a dummy address to fetch a quote. + // The recipient address is validated later in the `initiate` method, which will throw if it's still missing. + recipient: recipient + ? recipient.address.toUniversalAddress() + : new UniversalAddress(new Uint8Array(32)), + }, + }); + } + + const relayInstructions = serializeLayout(relayInstructionsLayout, { + requests: relayRequests, + }); + + const quote = await fetchSignedQuote( + fromChain.network, + fromChain.chain, + toChain.chain, + encoding.hex.encode(relayInstructions, true) + ); + + if (!quote.estimatedCost) { + throw new Error("No estimated cost"); + } + + const estimatedCost = BigInt(quote.estimatedCost); + const signedQuoteBytes = encoding.hex.decode(quote.signedQuote); + const signedQuote = deserializeLayout(signedQuoteLayout, signedQuoteBytes); + + return { + signedQuote: signedQuoteBytes, + relayInstructions: relayInstructions, + estimatedCost, + payeeAddress: signedQuote.quote.payeeAddress, + referrer, + referrerFee, + remainingAmount, + referrerFeeDbps, + expires: signedQuote.quote.expiryTime, + gasDropOff, + }; + } + + async fetchDeliveryPriceAndInstructions( + fromChain: ChainContext, + toChain: ChainContext, + params: Vp + ): Promise<{ + deliveryPrice: bigint; + transceiverInstructions: Ntt.TransceiverInstruction[]; + }> { + const sourceNtt = await fromChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: params.normalizedParams.sourceContracts, + }); + + const transceiverInstructions = + await sourceNtt.createTransceiverInstructions( + toChain.chain, + params.normalizedParams.gasLimit, + this.staticConfig.axelarGasMultiplier + ); + + const deliveryPrice = await sourceNtt.quoteDeliveryPrice( + toChain.chain, + transceiverInstructions + ); + + return { deliveryPrice, transceiverInstructions }; + } + + async initiate( + request: routes.RouteTransferRequest, + signer: Signer, + quote: Q, + to: ChainAddress + ): Promise { + if (!quote.details) { + throw new Error("Missing quote details"); + } + + const { details, params } = quote; + + const { fromChain } = request; + + const relayInstructions = deserializeLayout( + relayInstructionsLayout, + details.relayInstructions + ); + + // Make sure that the gas drop-off recipient matches the actual recipient + relayInstructions.requests.forEach(({ request }) => { + if ( + request.type === "GasDropOffInstruction" && + !request.recipient.equals(to.address.toUniversalAddress()) + ) { + throw new Error("Gas drop-off recipient does not match"); + } + }); + + const sender = Wormhole.parseAddress(signer.chain(), signer.address()); + + const multiTokenNttWithExecutor = await fromChain.getProtocol( + "MultiTokenNttWithExecutor", + { + multiTokenNtt: params.normalizedParams.sourceContracts, + } + ); + + const initTransfer = multiTokenNttWithExecutor.transfer( + sender, + to, + request.source.id, + amount.units(params.normalizedParams.amount), + details + ); + const txids = await signSendWait(fromChain, initTransfer, signer); + + // Status the transfer immediately before returning + let statusAttempts = 0; + + const statusTransferImmediately = async () => { + while (statusAttempts < 20) { + try { + const [txStatus] = await fetchStatus( + fromChain.network, + txids.at(-1)!.txid, + fromChain.chain + ); + + if (txStatus) { + break; + } + } catch (_) { + // is ok we just try again! + } + statusAttempts++; + await new Promise((resolve) => setTimeout(resolve, 2000)); + } + }; + + // Spawn a loop in the background that will status this transfer until + // the API gives a successful response. We don't await the result + // here because we don't need it for the return value. + statusTransferImmediately(); + + return { + from: fromChain.chain, + to: to.chain, + state: TransferState.SourceInitiated, + originTxs: txids, + params, + trackingInfo: { transceiverAttested: {} }, + }; + } + + async complete(signer: Signer, receipt: R): Promise { + return await MultiTokenNttRoute.complete( + signer, + this.wh.getChain(receipt.to), + receipt + ); + } + + async resume(tx: TransactionId): Promise { + return await MultiTokenNttRoute.resume( + tx, + this.wh, + this.staticConfig.contracts + ); + } + + async finalize(signer: Signer, receipt: R): Promise { + return await MultiTokenNttRoute.finalize( + signer, + this.wh.getChain(receipt.to), + receipt + ); + } + + async *track(receipt: R, timeout?: number) { + return yield* MultiTokenNttRoute.track( + this.wh, + receipt, + false, + timeout + ); + } +} diff --git a/sdk/route/src/executor/utils.ts b/sdk/route/src/executor/utils.ts index 037797233..ad70b0e32 100644 --- a/sdk/route/src/executor/utils.ts +++ b/sdk/route/src/executor/utils.ts @@ -131,6 +131,15 @@ export async function fetchStatus( } } +export function isRelayStatusFailed(status: string): boolean { + return ( + status === RelayStatus.Failed || // this could happen if simulation fails + status === RelayStatus.Underpaid || // only happens if you don't pay at least the costEstimate + status === RelayStatus.Unsupported || // capabilities check didn't pass + status === RelayStatus.Aborted + ); +} + const MAX_U16 = 65_535n; export function calculateReferrerFee( _amount: sdkAmount.Amount, diff --git a/sdk/route/src/index.ts b/sdk/route/src/index.ts index 4f95b888b..5da1ae561 100644 --- a/sdk/route/src/index.ts +++ b/sdk/route/src/index.ts @@ -1,4 +1,6 @@ export * from "./types.js"; export * from "./manual.js"; export * from "./automatic.js"; +export * from "./multiTokenManual.js"; export * from "./executor/executor.js"; +export * from "./executor/multiToken.js"; diff --git a/sdk/route/src/multiTokenManual.ts b/sdk/route/src/multiTokenManual.ts new file mode 100644 index 000000000..51283a247 --- /dev/null +++ b/sdk/route/src/multiTokenManual.ts @@ -0,0 +1,296 @@ +import { + Chain, + ChainAddress, + ChainContext, + Network, + Signer, + TokenId, + TransactionId, + TransferState, + Wormhole, + amount, + routes, + signSendWait, + finality, + guardians, + isNative, +} from "@wormhole-foundation/sdk-connect"; +import "@wormhole-foundation/sdk-definitions-ntt"; +import { MultiTokenNttRoute, NttRoute } from "./types.js"; +import { MultiTokenNtt } from "@wormhole-foundation/sdk-definitions-ntt"; + +type Op = routes.Options; +type Tp = routes.TransferParams; +type Vr = routes.ValidationResult; + +type Vp = MultiTokenNttRoute.ValidatedParams; +type QR = routes.QuoteResult; +type Q = routes.Quote; + +type R = MultiTokenNttRoute.TransferReceipt; + +export function multiTokenNttManualRoute(config: MultiTokenNttRoute.Config) { + class MultiTokenNttRouteImpl< + N extends Network, + > extends MultiTokenNttManualRoute { + static override config = config; + } + return MultiTokenNttRouteImpl; +} + +export class MultiTokenNttManualRoute + extends routes.FinalizableRoute + implements routes.StaticRouteMethods +{ + static NATIVE_GAS_DROPOFF_SUPPORTED: boolean = false; + static IS_AUTOMATIC: boolean = false; + + // @ts-ignore + // Since we set the config on the static class, access it with this param + // the MultiTokenNttManualRoute.config will always be empty + readonly staticConfig: MultiTokenNttRoute.Config = this.constructor.config; + static config: MultiTokenNttRoute.Config = { contracts: [] }; + + static meta = { name: "MultiTokenNttManualRoute" }; + + static supportedNetworks(): Network[] { + return MultiTokenNttRoute.resolveSupportedNetworks(this.config.contracts); + } + + static supportedChains(network: Network): Chain[] { + return MultiTokenNttRoute.resolveSupportedChains( + this.config.contracts, + network + ); + } + + static async supportedDestinationTokens( + sourceToken: TokenId, + fromChain: ChainContext, + toChain: ChainContext + ): Promise { + const destinationTokenId = await MultiTokenNttRoute.getDestinationTokenId( + sourceToken, + fromChain, + toChain, + this.config.contracts + ); + return [destinationTokenId]; + } + + static isProtocolSupported( + chain: ChainContext + ): boolean { + return chain.supportsProtocol("MultiTokenNtt"); + } + + getDefaultOptions(): Op { + return {}; + } + + async isWrappedToken(token: TokenId): Promise { + return await MultiTokenNttRoute.isWrappedToken( + this.wh.getChain(token.chain), + token, + this.staticConfig.contracts + ); + } + + async getOriginalToken(token: TokenId): Promise { + return await MultiTokenNttRoute.getOriginalToken( + this.wh.getChain(token.chain), + token, + this.staticConfig.contracts + ); + } + + async validate( + request: routes.RouteTransferRequest, + params: Tp + ): Promise { + if (request.fromChain.chain === request.toChain.chain) { + return { + valid: false, + error: new Error("Source and destination chains must differ"), + params, + }; + } + + const options = params.options ?? this.getDefaultOptions(); + + const parsedAmount = amount.parse(params.amount, request.source.decimals); + + const trimmedAmount = NttRoute.trimAmount( + parsedAmount, + request.destination.decimals + ); + + const sourceContracts = MultiTokenNttRoute.resolveContracts( + this.staticConfig.contracts, + request.fromChain.chain + ); + + const destinationContracts = MultiTokenNttRoute.resolveContracts( + this.staticConfig.contracts, + request.toChain.chain + ); + + const sourceNtt = await request.fromChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: sourceContracts, + }); + + const sourceToken = isNative(request.source.id.address) + ? await sourceNtt.getWrappedNativeToken() + : request.source.id; + + const originalTokenId = await sourceNtt.getOriginalToken(sourceToken); + + const sendTransceivers = await sourceNtt.getSendTransceivers( + request.toChain.chain + ); + + const gasLimit = await this.estimateGasLimit(request, originalTokenId); + + const validatedParams: Vp = { + amount: params.amount, + normalizedParams: { + amount: trimmedAmount, + sourceContracts, + destinationContracts, + sourceTokenId: request.source.id, + destinationTokenId: request.destination.id, + originalTokenId, + sendTransceivers, + gasLimit, + }, + options, + }; + + return { valid: true, params: validatedParams }; + } + + async estimateGasLimit( + request: routes.RouteTransferRequest, + originalTokenId: MultiTokenNtt.OriginalTokenId + ): Promise { + return MultiTokenNttRoute.estimateGasLimit( + request, + originalTokenId, + this.staticConfig.contracts, + this.staticConfig.perTokenOverrides + ); + } + + async quote( + request: routes.RouteTransferRequest, + params: Vp + ): Promise { + const dstAmount = amount.scale( + params.normalizedParams.amount, + request.destination.decimals + ); + + const result: QR = { + success: true, + params, + sourceToken: { + token: request.source.id, + amount: params.normalizedParams.amount, + }, + destinationToken: { + token: request.destination.id, + amount: dstAmount, + }, + eta: + finality.estimateFinalityTime(request.fromChain.chain) + + guardians.guardianAttestationEta * 1000, + }; + + const { fromChain, toChain } = request; + + const destinationNtt = await toChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: params.normalizedParams.destinationContracts, + }); + + const duration = await destinationNtt.getRateLimitDuration(); + const warnings = await MultiTokenNttRoute.checkRateLimit( + destinationNtt, + fromChain.chain, + params.normalizedParams.originalTokenId, + dstAmount, + duration + ); + if (warnings) { + result.warnings = warnings; + } + + return result; + } + + async initiate( + request: routes.RouteTransferRequest, + signer: Signer, + quote: Q, + to: ChainAddress + ): Promise { + const { params } = quote; + const { fromChain } = request; + const sender = Wormhole.parseAddress(signer.chain(), signer.address()); + + const ntt = await fromChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: params.normalizedParams.sourceContracts, + }); + + const initXfer = ntt.transfer( + sender, + params.normalizedParams.sourceTokenId.address, + amount.units(params.normalizedParams.amount), + to, + params.normalizedParams.gasLimit, + this.staticConfig.axelarGasMultiplier + ); + const txids = await signSendWait(fromChain, initXfer, signer); + + return { + from: fromChain.chain, + to: to.chain, + state: TransferState.SourceInitiated, + originTxs: txids, + params, + trackingInfo: { transceiverAttested: {} }, + }; + } + + async complete(signer: Signer, receipt: R): Promise { + return await MultiTokenNttRoute.complete( + signer, + this.wh.getChain(receipt.to), + receipt + ); + } + + async resume(tx: TransactionId): Promise { + return await MultiTokenNttRoute.resume( + tx, + this.wh, + this.staticConfig.contracts + ); + } + + async finalize(signer: Signer, receipt: R): Promise { + return await MultiTokenNttRoute.finalize( + signer, + this.wh.getChain(receipt.to), + receipt + ); + } + + async *track(receipt: R, timeout?: number) { + return yield* MultiTokenNttRoute.track( + this.wh, + receipt, + true, + timeout + ); + } +} diff --git a/sdk/route/src/tracking.ts b/sdk/route/src/tracking.ts new file mode 100644 index 000000000..0984b289a --- /dev/null +++ b/sdk/route/src/tracking.ts @@ -0,0 +1,99 @@ +import { + Network, + TransferState, + isFailed, + routes, + isAttested, +} from "@wormhole-foundation/sdk-connect"; +import { MultiTokenNttRoute } from "./types.js"; +import { + getAxelarTransactionStatus, + getAxelarExplorerUrl, +} from "@wormhole-foundation/sdk-definitions-ntt"; +import { fetchStatus, isRelayStatusFailed } from "./executor/utils.js"; + +export async function trackExecutor< + R extends MultiTokenNttRoute.TransferReceipt, +>(network: Network, receipt: R): Promise { + if (!isAttested(receipt) && !isFailed(receipt)) { + return receipt; + } + + // Check if the relay was successful or failed + if (receipt.originTxs.length === 0) { + throw new Error("No origin transactions found in receipt"); + } + const txid = receipt.originTxs.at(-1)!.txid; + const [txStatus] = await fetchStatus(network, txid, receipt.from); + if (!txStatus) throw new Error("No transaction status found"); + + const relayStatus = txStatus.status; + if (isRelayStatusFailed(relayStatus)) { + return { + ...receipt, + state: TransferState.Failed, + error: new routes.RelayFailedError( + `Relay failed with status: ${relayStatus}` + ), + }; + } + + // Clear error state if relay status is not an error + if (isFailed(receipt)) { + return { + ...receipt, + state: TransferState.Attested, + // @ts-ignore + error: undefined, + }; + } + + return receipt; +} + +export async function trackAxelar( + network: Network, + receipt: R +): Promise { + if (!isAttested(receipt) && !isFailed(receipt)) { + return receipt; + } + + // Check relayer status + if (receipt.originTxs.length === 0) { + throw new Error("No origin transactions found in receipt"); + } + const txid = receipt.originTxs.at(-1)!.txid; + const axelarStatus = await getAxelarTransactionStatus( + network, + receipt.from, + txid + ); + + if (axelarStatus.error) { + return { + ...receipt, + state: TransferState.Failed, + error: new routes.RelayFailedError( + `Axelar error: ${axelarStatus.error.message}`, + // @ts-ignore + { + url: getAxelarExplorerUrl(network, txid), + name: "Axelarscan", + } + ), + }; + } + + // Clear error state if relay status is not an error + if (isFailed(receipt)) { + return { + ...receipt, + state: TransferState.Attested, + // @ts-ignore + error: undefined, + }; + } + + return receipt; +} diff --git a/sdk/route/src/types.ts b/sdk/route/src/types.ts index 6848bd25f..e400602cf 100644 --- a/sdk/route/src/types.ts +++ b/sdk/route/src/types.ts @@ -3,18 +3,34 @@ import { ChainAddress, ChainContext, Network, + QuoteWarning, + Signer, TokenId, + TransactionId, + TransferState, + UnattestedTokenId, VAA, Wormhole, WormholeMessageId, TransferReceipt as _TransferReceipt, amount, canonicalAddress, + isAttested, + isCompleted, + isDestinationQueued, + isFailed, isNative, + isRedeemed, + isSameToken, + isSourceFinalized, + isSourceInitiated, nativeTokenId, routes, + signSendWait, + toUniversal, } from "@wormhole-foundation/sdk-connect"; -import { Ntt } from "@wormhole-foundation/sdk-definitions-ntt"; +import { MultiTokenNtt, Ntt } from "@wormhole-foundation/sdk-definitions-ntt"; +import { trackAxelar, trackExecutor } from "./tracking.js"; export namespace NttRoute { // Currently only wormhole attestations supported @@ -80,14 +96,14 @@ export namespace NttRoute { export type ManualTransferReceipt< SC extends Chain = Chain, - DC extends Chain = Chain + DC extends Chain = Chain, > = _TransferReceipt & { params: ValidatedParams; }; export type AutomaticTransferReceipt< SC extends Chain = Chain, - DC extends Chain = Chain + DC extends Chain = Chain, > = _TransferReceipt & { params: ValidatedParams; }; @@ -264,3 +280,585 @@ export namespace NttRoute { return truncatedAmount; } } +export namespace MultiTokenNttRoute { + export type Config = { + contracts: MultiTokenNtt.Contracts[]; + perTokenOverrides?: MultiTokenNttRoute.PerTokenGasLimit; + axelarGasMultiplier?: number | "auto"; + }; + + export type NormalizedParams = { + amount: amount.Amount; + sourceContracts: MultiTokenNtt.Contracts; + destinationContracts: MultiTokenNtt.Contracts; + sourceTokenId: TokenId; + destinationTokenId: TokenId; + originalTokenId: MultiTokenNtt.OriginalTokenId; + sendTransceivers: Ntt.TransceiverMeta[]; + gasLimit: bigint; + referrerFeeDbps?: bigint; + }; + + export type Options = { + // 0.0 - 1.0 percentage of the maximum gas drop-off amount + nativeGas?: number; + }; + + export interface ValidatedParams + extends routes.ValidatedTransferParams { + normalizedParams: NormalizedParams; + } + + export type AttestationReceipt = { + id: WormholeMessageId; + attestation: VAA<"MultiTokenNtt:WormholeTransfer">; + }; + + export type TransferReceipt< + SC extends Chain = Chain, + DC extends Chain = Chain, + > = _TransferReceipt & { + params: ValidatedParams; + trackingInfo: { + transceiverAttested: { [type: string]: boolean }; + }; + }; + + export function resolveSupportedNetworks( + contracts: MultiTokenNtt.Contracts[] + ): Network[] { + return ["Mainnet", "Testnet"]; + } + + export function resolveSupportedChains( + contracts: MultiTokenNtt.Contracts[], + network: Network + ): Chain[] { + return contracts.flatMap((c) => c.chain); + } + + export function resolveContracts( + contracts: MultiTokenNtt.Contracts[], + chain: Chain + ): MultiTokenNtt.Contracts { + const cfg = contracts.find((c) => c.chain === chain); + if (!cfg) { + throw new Error( + "Cannot find MultiTokenNtt contracts in config for: " + chain + ); + } + return cfg; + } + + // Helper function to get the destination TokenId + export async function getDestinationTokenId( + sourceToken: TokenId, + fromChain: ChainContext, + toChain: ChainContext, + contracts: MultiTokenNtt.Contracts[], + originalToken?: MultiTokenNtt.OriginalTokenId + ): Promise { + if (sourceToken.chain !== fromChain.chain) { + throw new Error("Source token must be native to the source chain"); + } + + const sourceNtt = await fromChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: MultiTokenNttRoute.resolveContracts( + contracts, + fromChain.chain + ), + }); + + const destinationNtt = await toChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: MultiTokenNttRoute.resolveContracts( + contracts, + toChain.chain + ), + }); + + if (isNative(sourceToken.address)) { + sourceToken = await sourceNtt.getWrappedNativeToken(); + } + + originalToken = + originalToken ?? (await sourceNtt.getOriginalToken(sourceToken)); + + // If the token exists on the destination chain, return it + const destinationToken = await destinationNtt.getLocalToken(originalToken); + if (destinationToken) { + // If the destination token is the wrapped native token, + // return the native token since it gets unwrapped by the contract + const wrappedNativeToken = await destinationNtt.getWrappedNativeToken(); + if (isSameToken(wrappedNativeToken, destinationToken)) { + return nativeTokenId(toChain.chain); + } + return destinationToken; + } + + // Otherwise the token will be created by the contract when the transfer is completed + const tokenMeta = await sourceNtt.getTokenMeta(sourceToken); + + // The destination token address is deterministic, so calculate it here + // NOTE: there is a very slim race condition where the token is overridden before a transfer is completed + const destinationTokenAddress = + await destinationNtt.calculateLocalTokenAddress(originalToken, tokenMeta); + + return { + chain: toChain.chain, + address: destinationTokenAddress, + isUnattested: true, + // TODO: decimals may need to be adjusted for non-EVM platforms if we support them + decimals: tokenMeta.decimals, + originalTokenId: Wormhole.tokenId( + sourceToken.chain, + sourceToken.address.toString() + ), + } as UnattestedTokenId; + } + + export type PerTokenGasLimit = Partial< + Record< + Chain, + Record< + string, + { + gasLimit?: bigint; + } + > + > + >; + + export async function estimateGasLimit( + request: routes.RouteTransferRequest, + originalTokenId: MultiTokenNtt.OriginalTokenId, + contracts: MultiTokenNtt.Contracts[], + overrides?: PerTokenGasLimit + ): Promise { + if (overrides) { + const destinationTokenAddress = canonicalAddress(request.destination.id); + const override = + overrides[request.destination.id.chain]?.[destinationTokenAddress]; + if (override?.gasLimit !== undefined) { + return override.gasLimit; + } + } + + const destinationContracts = MultiTokenNttRoute.resolveContracts( + contracts, + request.toChain.chain + ); + + const destinationNtt = await request.toChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: destinationContracts, + }); + + const gasLimit = await destinationNtt.estimateGasLimit(originalTokenId); + + return gasLimit; + } + + export async function checkRateLimit( + destinationNtt: MultiTokenNtt, + fromChain: Chain, + originalTokenId: MultiTokenNtt.OriginalTokenId, + receivedAmount: amount.Amount, + duration: bigint + ): Promise { + if (duration > 0n) { + const inboundLimit = await destinationNtt.getInboundLimit( + originalTokenId, + fromChain + ); + + if (inboundLimit !== null) { + const capacity = await destinationNtt.getCurrentInboundCapacity( + originalTokenId, + fromChain + ); + + if ( + NttRoute.isCapacityThresholdExceeded( + amount.units(receivedAmount), + capacity + ) + ) { + return [ + { + type: "DestinationCapacityWarning", + delayDurationSec: Number(duration), + }, + ]; + } + } + } + return undefined; + } + + export async function isWrappedToken( + chain: ChainContext, + token: TokenId, + contracts: MultiTokenNtt.Contracts[] + ): Promise { + const ntt = await chain.getProtocol("MultiTokenNtt", { + multiTokenNtt: MultiTokenNttRoute.resolveContracts( + contracts, + chain.chain + ), + }); + + return await ntt.isWrappedToken(token); + } + + export async function getOriginalToken( + chain: ChainContext, + token: TokenId, + contracts: MultiTokenNtt.Contracts[] + ): Promise { + const ntt = await chain.getProtocol("MultiTokenNtt", { + multiTokenNtt: MultiTokenNttRoute.resolveContracts( + contracts, + chain.chain + ), + }); + + const originalToken = await ntt.getOriginalToken(token); + if (originalToken === null) { + throw new Error("Token is not a wrapped token"); + } + + return { + chain: originalToken.chain, + address: originalToken.address.toNative(originalToken.chain), + }; + } + + export async function complete( + signer: Signer, + chain: ChainContext, + receipt: R + ): Promise { + if (!isAttested(receipt) && !isFailed(receipt)) { + if (isRedeemed(receipt)) return receipt; + throw new Error( + "The source must be finalized in order to complete the transfer" + ); + } + + if (!receipt.attestation) { + throw new Error("No attestation found on the transfer receipt"); + } + + const ntt = await chain.getProtocol("MultiTokenNtt", { + multiTokenNtt: receipt.params.normalizedParams.destinationContracts, + }); + + const { sendTransceivers } = receipt.params.normalizedParams; + const wormhole = sendTransceivers.find( + (t) => t.type.toLowerCase() === "wormhole" + ); + if (!wormhole) { + throw new Error( + "No Wormhole transceiver found, cannot complete manual transfer" + ); + } + + const wormholeAttested = await ntt.transceiverAttestedToMessage( + receipt.from, + receipt.attestation.attestation.payload.nttManagerPayload, + wormhole.index + ); + if (wormholeAttested) { + // already attested by the wormhole transceiver + return receipt; + } + + const completeXfer = ntt.redeem(receipt.attestation.attestation); + + await signSendWait(chain, completeXfer, signer); + + return receipt; + } + + export async function finalize( + signer: Signer, + chain: ChainContext, + receipt: R + ): Promise { + if (!isDestinationQueued(receipt)) { + throw new Error( + "The transfer must be destination queued in order to finalize" + ); + } + + const { + attestation: { attestation: vaa }, + } = receipt; + + const ntt = await chain.getProtocol("MultiTokenNtt", { + multiTokenNtt: receipt.params.normalizedParams.destinationContracts, + }); + const completeTransfer = ntt.completeInboundQueuedTransfer( + receipt.from, + vaa.payload.nttManagerPayload + ); + const finalizeTxids = await signSendWait(chain, completeTransfer, signer); + return { + ...receipt, + state: TransferState.DestinationFinalized, + destinationTxs: [...(receipt.destinationTxs ?? []), ...finalizeTxids], + }; + } + + export async function resume( + tx: TransactionId, + wh: Wormhole, + contracts: MultiTokenNtt.Contracts[] + ): Promise { + const fromChain = wh.getChain(tx.chain); + const [msg] = await fromChain.parseTransaction(tx.txid); + if (!msg) throw new Error("No Wormhole messages found"); + + const vaa = await wh.getVaa(msg, "MultiTokenNtt:WormholeTransfer"); + if (!vaa) throw new Error("No VAA found for transaction: " + tx.txid); + + const { payload } = vaa.payload.nttManagerPayload; + + const sourceContracts = MultiTokenNttRoute.resolveContracts( + contracts, + fromChain.chain + ); + if ( + !payload.sender.equals( + toUniversal(fromChain.chain, sourceContracts.manager) + ) + ) { + throw new Error("Invalid source manager"); + } + + const destinationContracts = MultiTokenNttRoute.resolveContracts( + contracts, + payload.toChain + ); + + const { trimmedAmount } = payload.data; + const amt = amount.fromBaseUnits( + trimmedAmount.amount, + trimmedAmount.decimals + ); + + const originalTokenId: MultiTokenNtt.OriginalTokenId = { + chain: payload.data.token.token.chainId, + address: payload.data.token.token.tokenAddress, + }; + + const sourceNtt = await fromChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: sourceContracts, + }); + let sourceTokenId = await sourceNtt.getLocalToken(originalTokenId); + if (sourceTokenId === null) throw new Error("Source token not found"); + + const sourceWrappedNativeToken = await sourceNtt.getWrappedNativeToken(); + if (isSameToken(sourceWrappedNativeToken, sourceTokenId)) { + sourceTokenId = nativeTokenId(fromChain.chain); + } + + const destinationTokenId = await MultiTokenNttRoute.getDestinationTokenId( + sourceTokenId, + fromChain, + wh.getChain(payload.toChain), + contracts, + originalTokenId + ); + + const sendTransceivers = await sourceNtt.getSendTransceivers( + payload.toChain + ); + + const msgId: WormholeMessageId = { + chain: vaa.emitterChain, + emitter: vaa.emitterAddress, + sequence: vaa.sequence, + }; + + return { + from: vaa.emitterChain, + to: payload.toChain, + state: TransferState.Attested, + originTxs: [tx], + attestation: { + id: msgId, + attestation: vaa, + }, + params: { + amount: amount.display(amt), + normalizedParams: { + amount: amt, + sourceContracts, + destinationContracts, + sourceTokenId, + destinationTokenId, + originalTokenId, + sendTransceivers, + gasLimit: 0n, + }, + options: {}, + }, + trackingInfo: { transceiverAttested: {} }, + } as R; + } + + export async function* track( + wh: Wormhole, + receipt: R, + isManual?: boolean, + timeout?: number + ) { + let leftover = timeout ? timeout : 60 * 60 * 1000; + while (leftover > 0 && !isCompleted(receipt)) { + const start = Date.now(); + + if (isSourceInitiated(receipt) || isSourceFinalized(receipt)) { + const txid = receipt.originTxs.at(-1)!; + + // TODO: can pass txid when this is published: https://github.com/wormhole-foundation/wormhole-sdk-ts/pull/909 + const fromChain: ChainContext = wh.getChain(receipt.from); + const [msg] = await fromChain.parseTransaction(txid.txid); + if (!msg) throw new Error("No Wormhole messages found"); + + const vaa = await wh.getVaa( + msg, + "MultiTokenNtt:WormholeTransfer", + timeout + ); + if (!vaa) throw new Error("No VAA found for transaction: " + txid.txid); + + const msgId: WormholeMessageId = { + chain: vaa.emitterChain, + emitter: vaa.emitterAddress, + sequence: vaa.sequence, + }; + + receipt = { + ...receipt, + state: TransferState.Attested, + attestation: { + id: msgId, + attestation: vaa, + }, + }; + yield receipt; + } + + const toChain = wh.getChain(receipt.to); + const destinationNtt = await toChain.getProtocol("MultiTokenNtt", { + multiTokenNtt: receipt.params.normalizedParams.destinationContracts, + }); + + // Check if the transfer was redeemed + if (isAttested(receipt) || isFailed(receipt)) { + if (!receipt.attestation) { + throw new Error("No attestation found"); + } + + const vaa = receipt.attestation.attestation; + + if (await destinationNtt.getIsApproved(vaa)) { + // All transceivers have approved the transfer + receipt = { + ...receipt, + state: TransferState.DestinationInitiated, + attestation: receipt.attestation, + }; + yield receipt; + } else { + const { sendTransceivers } = receipt.params.normalizedParams; + + // The Wormhole transceiver may wait to attest until all other transceivers have attested + // so we want to check it last + const sortedTransceivers = [...sendTransceivers].sort((a, b) => { + const aType = a.type.toLowerCase(); + const bType = b.type.toLowerCase(); + if (aType === "wormhole" && bType !== "wormhole") return 1; + if (aType !== "wormhole" && bType === "wormhole") return -1; + return 0; + }); + + for (const transceiver of sortedTransceivers) { + const transceiverType = transceiver.type.toLowerCase(); + if (receipt.trackingInfo.transceiverAttested[transceiverType]) { + continue; + } + + const attested = await destinationNtt.transceiverAttestedToMessage( + receipt.from, + vaa.payload.nttManagerPayload, + transceiver.index + ); + if (attested) { + receipt.trackingInfo.transceiverAttested[transceiverType] = true; + if (isFailed(receipt)) { + // Reset the receipt status if the transceiver attested + receipt = { + ...receipt, + attestation: receipt.attestation!, + state: TransferState.Attested, + }; + yield receipt; + } + continue; + } + + if (transceiverType === "wormhole") { + // Manual transfers don't use executor + if (!isManual) { + receipt = await trackExecutor(wh.network, receipt); + } + } else if (transceiverType === "axelar") { + receipt = await trackAxelar(wh.network, receipt); + } else { + throw new Error( + `Unsupported transceiver type: ${transceiver.type}` + ); + } + yield receipt; + // We are breaking here so we only track one transceiver at a time + // until all transceivers have attested. Otherwise the receipt state + // may jump around too much resulting in a glitchy UI. + break; + } + } + } + + if (isRedeemed(receipt) || isDestinationQueued(receipt)) { + const vaa = receipt.attestation.attestation; + + const queuedTransfer = await destinationNtt.getInboundQueuedTransfer( + vaa.emitterChain, + vaa.payload.nttManagerPayload + ); + if (queuedTransfer !== null) { + receipt = { + ...receipt, + state: TransferState.DestinationQueued, + queueReleaseTime: new Date( + queuedTransfer.rateLimitExpiryTimestamp * 1000 + ), + }; + } else if (await destinationNtt.getIsExecuted(vaa)) { + receipt = { + ...receipt, + state: TransferState.DestinationFinalized, + }; + } + } + + yield receipt; + + // Sleep for a bit so we don't spam requests + await new Promise((resolve) => setTimeout(resolve, 5000)); + leftover -= Date.now() - start; + } + + return receipt; + } +} diff --git a/solana/ts/lib/bindings.ts b/solana/ts/lib/bindings.ts index d60bc735e..bee7550fc 100644 --- a/solana/ts/lib/bindings.ts +++ b/solana/ts/lib/bindings.ts @@ -26,20 +26,20 @@ export namespace NttBindings { export type NativeTokenTransfer = V extends "1.0.0" ? _1_0_0.RawExampleNativeTokenTransfers : V extends "2.0.0" - ? _2_0_0.RawExampleNativeTokenTransfers - : _3_0_0.RawExampleNativeTokenTransfers; + ? _2_0_0.RawExampleNativeTokenTransfers + : _3_0_0.RawExampleNativeTokenTransfers; export type Quoter = V extends "1.0.0" ? _1_0_0.RawNttQuoter : V extends "2.0.0" - ? _2_0_0.RawNttQuoter - : _3_0_0.RawNttQuoter; + ? _2_0_0.RawNttQuoter + : _3_0_0.RawNttQuoter; export type Transceiver = V extends "1.0.0" ? _1_0_0.RawExampleNativeTokenTransfers : V extends "2.0.0" - ? _2_0_0.RawExampleNativeTokenTransfers - : _3_0_0.RawNttTransceiver; + ? _2_0_0.RawExampleNativeTokenTransfers + : _3_0_0.RawNttTransceiver; type ProgramAccounts = IdlAccounts< NttBindings.NativeTokenTransfer diff --git a/solana/ts/lib/ntt.ts b/solana/ts/lib/ntt.ts index e5b56cee2..c0401773d 100644 --- a/solana/ts/lib/ntt.ts +++ b/solana/ts/lib/ntt.ts @@ -200,8 +200,8 @@ export namespace NTT { connection.rpcEndpoint === rpc.rpcAddress("Devnet", "Solana") ? "6sbzC1eH4FTujJXWj51eQe25cYvr4xfXbJ1vAj7j2k5J" // The CI pubkey, funded on ci network : connection.rpcEndpoint.startsWith("http://localhost") - ? "98evdAiWr7ey9MAQzoQQMwFQkTsSR6KkWQuFqKrgwNwb" // the anchor pubkey, funded on local network - : "Hk3SdYTJFpawrvRz4qRztuEt2SqoCG7BGj2yJfDJSFbJ"; // The default pubkey is funded on mainnet and devnet we need a funded account to simulate the transaction below + ? "98evdAiWr7ey9MAQzoQQMwFQkTsSR6KkWQuFqKrgwNwb" // the anchor pubkey, funded on local network + : "Hk3SdYTJFpawrvRz4qRztuEt2SqoCG7BGj2yJfDJSFbJ"; // The default pubkey is funded on mainnet and devnet we need a funded account to simulate the transaction below sender = new PublicKey(address); } @@ -210,9 +210,8 @@ export namespace NTT { const ix = await program.methods.version().accountsStrict({}).instruction(); // Since we don't need the very very very latest blockhash, using finalized // ensures the blockhash will be found when we immediately simulate the tx - const { blockhash } = await program.provider.connection.getLatestBlockhash( - "finalized" - ); + const { blockhash } = + await program.provider.connection.getLatestBlockhash("finalized"); const msg = new TransactionMessage({ payerKey: sender, recentBlockhash: blockhash, diff --git a/solana/ts/lib/quoter.ts b/solana/ts/lib/quoter.ts index 9105eac96..f4b6d16e3 100644 --- a/solana/ts/lib/quoter.ts +++ b/solana/ts/lib/quoter.ts @@ -219,9 +219,8 @@ export class NttQuoter { const programData = programDataAddress(this.program.programId); - const accInfo = await this.program.provider.connection.getAccountInfo( - programData - ); + const accInfo = + await this.program.provider.connection.getAccountInfo(programData); if (!accInfo) throw new Error("Could not find program data account"); const deserProgramData = deserializeLayout(programDataLayout, accInfo.data); diff --git a/solana/ts/sdk/nttWithExecutor.ts b/solana/ts/sdk/nttWithExecutor.ts index 24fd25496..a2bff24fe 100644 --- a/solana/ts/sdk/nttWithExecutor.ts +++ b/solana/ts/sdk/nttWithExecutor.ts @@ -135,9 +135,8 @@ export class SolanaNttWithExecutor true, tokenProgram ); - const referrerAtaAccount = await this.connection.getAccountInfo( - referrerAta - ); + const referrerAtaAccount = + await this.connection.getAccountInfo(referrerAta); if (!referrerAtaAccount) { message.instructions.push( createAssociatedTokenAccountIdempotentInstruction(