trustless-generic-relayer/ethereum/ts-test/2_core_relayer.ts

581 lines
20 KiB
TypeScript

import { expect } from "chai"
import { ethers, providers } from "ethers"
import { ChainId, tryNativeToHexString } from "@certusone/wormhole-sdk"
import { ChainInfo, RELAYER_DEPLOYER_PRIVATE_KEY } from "./helpers/consts"
import { generateRandomString } from "./helpers/utils"
import {
CoreRelayer__factory,
IWormhole__factory,
MockRelayerIntegration__factory,
} from "../../sdk/src"
import {
init,
loadChains,
loadCoreRelayers,
loadMockIntegrations,
} from "../ts-scripts/helpers/env"
import { MockRelayerIntegration, IWormholeRelayer } from "../../sdk/src"
import { getDeliveryInfoBySourceTx, DeliveryInfo, RedeliveryInfo } from "../../sdk/src"
const ETHEREUM_ROOT = `${__dirname}/..`
init()
const chains = loadChains()
const coreRelayers = loadCoreRelayers()
const mockIntegrations = loadMockIntegrations()
describe("Core Relayer Integration Test - Two Chains", () => {
// signers
const sourceChain = chains.find((c) => c.chainId == 2) as ChainInfo
const targetChain = chains.find((c) => c.chainId == 4) as ChainInfo
const providerSource = new ethers.providers.StaticJsonRpcProvider(sourceChain.rpc)
const providerTarget = new ethers.providers.StaticJsonRpcProvider(targetChain.rpc)
const walletSource = new ethers.Wallet(RELAYER_DEPLOYER_PRIVATE_KEY, providerSource)
const walletTarget = new ethers.Wallet(RELAYER_DEPLOYER_PRIVATE_KEY, providerTarget)
const sourceCoreRelayerAddress = coreRelayers.find(
(p) => p.chainId == sourceChain.chainId
)?.address as string
const sourceMockIntegrationAddress = mockIntegrations.find(
(p) => p.chainId == sourceChain.chainId
)?.address as string
const targetCoreRelayerAddress = coreRelayers.find(
(p) => p.chainId == targetChain.chainId
)?.address as string
const targetMockIntegrationAddress = mockIntegrations.find(
(p) => p.chainId == targetChain.chainId
)?.address as string
const sourceCoreRelayer = CoreRelayer__factory.connect(
sourceCoreRelayerAddress,
walletSource
)
const sourceMockIntegration = MockRelayerIntegration__factory.connect(
sourceMockIntegrationAddress,
walletSource
)
const targetCoreRelayer = CoreRelayer__factory.connect(
targetCoreRelayerAddress,
walletTarget
)
const targetMockIntegration = MockRelayerIntegration__factory.connect(
targetMockIntegrationAddress,
walletTarget
)
it("Executes a delivery", async () => {
const arbitraryPayload = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
console.log(`Sent message: ${arbitraryPayload}`)
const value = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
500000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
console.log(`Quoted gas delivery fee: ${value}`)
const tx = await sourceMockIntegration.sendMessage(
arbitraryPayload,
targetChain.chainId,
targetMockIntegrationAddress,
{ value, gasLimit: 500000 }
)
console.log("Sent delivery request!")
const rx = await tx.wait()
console.log("Message confirmed!")
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 4000)
})
console.log("Checking if message was relayed")
const message = await targetMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload}`)
console.log(`Received message: ${message}`)
expect(message).to.equal(arbitraryPayload)
})
it("Executes a forward", async () => {
const arbitraryPayload1 = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
const arbitraryPayload2 = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
console.log(`Sent message: ${arbitraryPayload1}`)
const value = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
500000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
const extraForwardingValue = await targetCoreRelayer.quoteGas(
sourceChain.chainId,
500000,
await targetCoreRelayer.getDefaultRelayProvider()
)
console.log(`Quoted gas delivery fee: ${value.add(extraForwardingValue)}`)
const furtherInstructions: MockRelayerIntegration.FurtherInstructionsStruct = {
keepSending: true,
newMessages: [arbitraryPayload2, "0x00"],
chains: [sourceChain.chainId],
gasLimits: [500000],
}
const tx = await sourceMockIntegration.sendMessagesWithFurtherInstructions(
[arbitraryPayload1],
furtherInstructions,
[targetChain.chainId],
[value.add(extraForwardingValue)],
{ value: value.add(extraForwardingValue), gasLimit: 500000 }
)
console.log("Sent delivery request!")
const rx = await tx.wait()
console.log("Message confirmed!")
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 4000)
})
console.log("Checking if message was relayed")
const message1 = await targetMockIntegration.getMessage()
console.log(
`Sent message: ${arbitraryPayload1} (expecting ${arbitraryPayload2} from forward)`
)
console.log(`Received message on target: ${message1}`)
expect(message1).to.equal(arbitraryPayload1)
console.log("Checking if forward message was relayed back")
const message2 = await sourceMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload2}`)
console.log(`Received message on source: ${message2}`)
expect(message2).to.equal(arbitraryPayload2)
})
it("Executes a multidelivery", async () => {
const arbitraryPayload1 = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
console.log(`Sent message: ${arbitraryPayload1}`)
const value1 = await sourceCoreRelayer.quoteGas(
sourceChain.chainId,
500000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
const value2 = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
500000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
console.log(`Quoted gas delivery fee: ${value1.add(value2)}`)
const furtherInstructions: MockRelayerIntegration.FurtherInstructionsStruct = {
keepSending: false,
newMessages: [],
chains: [],
gasLimits: [],
}
const tx = await sourceMockIntegration.sendMessagesWithFurtherInstructions(
[arbitraryPayload1],
furtherInstructions,
[sourceChain.chainId, targetChain.chainId],
[value1, value2],
{ value: value1.add(value2), gasLimit: 500000 }
)
console.log("Sent delivery request!")
const rx = await tx.wait()
console.log("Message confirmed!")
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 4000)
})
console.log("Checking if first message was relayed")
const message1 = await sourceMockIntegration.getMessage()
console.log(
`Sent message: ${arbitraryPayload1}`
)
console.log(`Received message: ${message1}`)
expect(message1).to.equal(arbitraryPayload1)
console.log("Checking if second message was relayed")
const message2 = await targetMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload1}`)
console.log(`Received message: ${message2}`)
expect(message2).to.equal(arbitraryPayload1)
})
it("Executes a multiforward", async () => {
const arbitraryPayload1 = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
const arbitraryPayload2 = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
console.log(`Sent message: ${arbitraryPayload1}`)
const value1 = await sourceCoreRelayer.quoteGas(
sourceChain.chainId,
1000000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
const value2 = (await targetCoreRelayer.quoteGas(
sourceChain.chainId,
500000,
await targetCoreRelayer.getDefaultRelayProvider()
))
const value3 = (await targetCoreRelayer.quoteGas(
targetChain.chainId,
500000,
await targetCoreRelayer.getDefaultRelayProvider()
))
console.log(`Quoted gas delivery fee: ${value1.add(value2).add(value3)}`)
const furtherInstructions: MockRelayerIntegration.FurtherInstructionsStruct = {
keepSending: true,
newMessages: [arbitraryPayload2, "0x00"],
chains: [sourceChain.chainId, targetChain.chainId],
gasLimits: [500000, 500000],
}
const tx = await sourceMockIntegration.sendMessagesWithFurtherInstructions(
[arbitraryPayload1],
furtherInstructions,
[targetChain.chainId],
[value1.add(value2).add(value3)],
{ value: value1.add(value2).add(value3), gasLimit: 500000 }
)
console.log("Sent delivery request!")
const rx = await tx.wait()
console.log("Message confirmed!")
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 8000)
})
console.log("Checking if first forward was relayed")
const message1 = await sourceMockIntegration.getMessage()
console.log(
`Sent message: ${arbitraryPayload2}`
)
console.log(`Received message: ${message1}`)
expect(message1).to.equal(arbitraryPayload2)
console.log("Checking if second forward was relayed")
const message2 = await targetMockIntegration.getMessage()
console.log(
`Sent message: ${arbitraryPayload2}`
)
console.log(`Received message: ${message2}`)
expect(message2).to.equal(arbitraryPayload2)
})
it("Executes a redelivery", async () => {
const arbitraryPayload = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
console.log(`Sent message: ${arbitraryPayload}`)
const valueNotEnough = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
10000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
const value = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
500000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
console.log(`Quoted gas delivery fee (not enough): ${valueNotEnough}`)
const tx = await sourceMockIntegration.sendMessage(
arbitraryPayload,
targetChain.chainId,
targetMockIntegrationAddress,
{ value: valueNotEnough, gasLimit: 500000 }
)
console.log("Sent delivery request!")
const rx = await tx.wait()
console.log("Message confirmed!")
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 2000)
})
console.log("Checking if message was relayed (it shouldn't have been!)")
const message = await targetMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload}`)
console.log(`Received message: ${message}`)
expect(message).to.not.equal(arbitraryPayload)
console.log("Resending the message");
const request: IWormholeRelayer.ResendByTxStruct = {
sourceChain: sourceChain.chainId,
sourceTxHash: tx.hash,
sourceNonce: 1,
targetChain: targetChain.chainId,
deliveryIndex: 2,
multisendIndex: 0,
newMaxTransactionFee: value,
newReceiverValue: 0,
newRelayParameters: sourceCoreRelayer.getDefaultRelayParams()
};
await sourceCoreRelayer.resend(request, sourceCoreRelayer.getDefaultRelayProvider(), {value: value, gasLimit: 500000}).then((t)=>t.wait);
console.log("Message resent");
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 4000)
})
console.log("Checking if message was relayed")
const messageNew = await targetMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload}`)
console.log(`Received message: ${messageNew}`)
expect(messageNew).to.equal(arbitraryPayload)
})
it("Executes a redelivery when delivery succeeds but forward fails", async () => {
const arbitraryPayload1 = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
const arbitraryPayload2 = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
console.log(`Sent message: ${arbitraryPayload1}`)
const value = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
500000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
const notEnoughExtraForwardingValue = await targetCoreRelayer.quoteGas(
sourceChain.chainId,
10000,
await targetCoreRelayer.getDefaultRelayProvider()
)
const enoughExtraForwardingValue = await targetCoreRelayer.quoteGas(
sourceChain.chainId,
500000,
await targetCoreRelayer.getDefaultRelayProvider()
)
console.log(`Quoted gas delivery fee: ${value.add(notEnoughExtraForwardingValue)}`)
const furtherInstructions: MockRelayerIntegration.FurtherInstructionsStruct = {
keepSending: true,
newMessages: [arbitraryPayload2, "0x00"],
chains: [sourceChain.chainId],
gasLimits: [500000],
}
const tx = await sourceMockIntegration.sendMessagesWithFurtherInstructions(
[arbitraryPayload1],
furtherInstructions,
[targetChain.chainId],
[value.add(notEnoughExtraForwardingValue)],
{ value: value.add(notEnoughExtraForwardingValue), gasLimit: 500000 })
console.log("Sent delivery request!")
const rx = await tx.wait()
console.log("Message confirmed!")
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 4000)
})
console.log("Checking if message was relayed")
const message1 = await targetMockIntegration.getMessage()
console.log(
`Sent message: ${arbitraryPayload1} (expecting ${arbitraryPayload2} from forward)`
)
console.log(`Received message on target: ${message1}`)
expect(message1).to.equal(arbitraryPayload1)
console.log("Checking if forward message was relayed back (it shouldn't have been!)")
const message2 = await sourceMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload2}`)
console.log(`Received message on source: ${message2}`)
expect(message2).to.not.equal(arbitraryPayload2)
let info: DeliveryInfo = (await getDeliveryInfoBySourceTx({environment: "DEVNET", sourceChain: sourceChain.chainId, sourceTransaction: tx.hash})) as DeliveryInfo
let status = info.targetChainStatuses[0].events[0].status
console.log(`Status: ${status}`)
// RESEND THE MESSAGE SOMEHOW!
console.log("Resending the message");
const request: IWormholeRelayer.ResendByTxStruct = {
sourceChain: targetChain.chainId,
sourceTxHash: info.targetChainStatuses[0].events[0].transactionHash as string,
sourceNonce: 1,
targetChain: sourceChain.chainId,
deliveryIndex: 2,
multisendIndex: 0,
newMaxTransactionFee: value,
newReceiverValue: 0,
newRelayParameters: sourceCoreRelayer.getDefaultRelayParams()
};
await sourceCoreRelayer.resend(request, sourceCoreRelayer.getDefaultRelayProvider(), {value: value.add(enoughExtraForwardingValue), gasLimit: 500000}).then((t)=>t.wait);
console.log("Message resent");
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 4000)
})
console.log("Checking if message was relayed")
const message3 = await targetMockIntegration.getMessage()
console.log(
`Sent message: ${arbitraryPayload1} (expecting ${arbitraryPayload2} from forward)`
)
console.log(`Received message on target: ${message3}`)
expect(message3).to.equal(arbitraryPayload1)
console.log("Checking if forward message was relayed back (it should now have been!)")
const message4 = await sourceMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload2}`)
console.log(`Received message on source: ${message4}`)
expect(message4).to.equal(arbitraryPayload2)
})
it("Tests the Typescript SDK during a delivery", async () => {
const arbitraryPayload = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
console.log(`Sent message: ${arbitraryPayload}`)
const value = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
500000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
console.log(`Quoted gas delivery fee: ${value}`)
const tx = await sourceMockIntegration.sendMessage(
arbitraryPayload,
targetChain.chainId,
targetMockIntegrationAddress,
{ value, gasLimit: 500000 }
)
console.log("Sent delivery request!")
const rx = await tx.wait()
console.log("Message confirmed!")
console.log("Checking status using SDK");
let info: DeliveryInfo = (await getDeliveryInfoBySourceTx({environment: "DEVNET", sourceChain: sourceChain.chainId, sourceTransaction: tx.hash})) as DeliveryInfo
let status = info.targetChainStatuses[0].events[0].status
expect(status.substring(0, 22)).to.equal("Delivery didn't happen")
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 6000)
})
const message = await targetMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload}`)
console.log(`Received message: ${message}`)
expect(message).to.equal(arbitraryPayload)
console.log("Checking status using SDK");
info = await getDeliveryInfoBySourceTx({environment: "DEVNET", sourceChain: sourceChain.chainId, sourceTransaction: tx.hash}) as DeliveryInfo;
status = info.targetChainStatuses[0].events[0].status
expect(status).to.equal("Delivery Success")
})
it("Tests the Typescript SDK during a redelivery", async () => {
const arbitraryPayload = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
)
console.log(`Sent message: ${arbitraryPayload}`)
const valueNotEnough = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
10000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
const value = await sourceCoreRelayer.quoteGas(
targetChain.chainId,
500000,
await sourceCoreRelayer.getDefaultRelayProvider()
)
console.log(`Quoted gas delivery fee: ${value}`)
const tx = await sourceMockIntegration.sendMessage(
arbitraryPayload,
targetChain.chainId,
targetMockIntegrationAddress,
{ value: valueNotEnough, gasLimit: 500000 }
)
console.log("Sent delivery request!")
const rx = await tx.wait()
console.log("Message confirmed!")
console.log("Checking status using SDK");
let info: DeliveryInfo = (await getDeliveryInfoBySourceTx({environment: "DEVNET", sourceChain: sourceChain.chainId, sourceTransaction: tx.hash })) as DeliveryInfo
let status = info.targetChainStatuses[0].events[0].status
expect(status.substring(0, 22)).to.equal("Delivery didn't happen")
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 6000)
})
const message = await targetMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload}`)
console.log(`Received message: ${message}`)
expect(message).to.not.equal(arbitraryPayload)
console.log("Checking status using SDK");
info = await getDeliveryInfoBySourceTx({environment: "DEVNET", sourceChain: sourceChain.chainId, sourceTransaction: tx.hash}) as DeliveryInfo;
status = info.targetChainStatuses[0].events[0].status
expect(status).to.equal("Receiver Failure")
console.log("Resending the message");
const request: IWormholeRelayer.ResendByTxStruct = {
sourceChain: sourceChain.chainId,
sourceTxHash: tx.hash,
sourceNonce: 1,
targetChain: targetChain.chainId,
deliveryIndex: 2,
multisendIndex: 0,
newMaxTransactionFee: value,
newReceiverValue: 0,
newRelayParameters: sourceCoreRelayer.getDefaultRelayParams()
};
const newTx = await sourceCoreRelayer.resend(request, sourceCoreRelayer.getDefaultRelayProvider(), {value: value, gasLimit: 500000});
await newTx.wait();
console.log("Message resent");
await new Promise((resolve) => {
setTimeout(() => {
resolve(0)
}, 6000)
})
console.log("Checking if message was relayed")
const messageNew = await targetMockIntegration.getMessage()
console.log(`Sent message: ${arbitraryPayload}`)
console.log(`Received message: ${messageNew}`)
expect(messageNew).to.equal(arbitraryPayload)
console.log("Checking status using SDK");
info = await getDeliveryInfoBySourceTx({environment: "DEVNET", sourceChain: sourceChain.chainId, sourceTransaction: tx.hash}) as DeliveryInfo;
status = info.targetChainStatuses[0].events[1].status
expect(status).to.equal("Delivery Success")
})
})