From 791f33bd03800611f97e5f2f590ed01c9ef4f2cd Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Tue, 22 Nov 2022 13:21:54 -0500 Subject: [PATCH 01/17] making fixtures type-safe --- packages/protocol/test/bridge/Bridge.test.ts | 19 ++- .../test/bridge/libs/LibBridgeData.test.ts | 23 ++-- .../test/bridge/libs/LibBridgeInvoke.test.ts | 12 +- .../test/bridge/libs/LibBridgeProcess.test.ts | 129 ++---------------- .../test/bridge/libs/LibBridgeRetry.test.ts | 70 ++++------ .../test/bridge/libs/LibBridgeSend.test.ts | 26 +++- .../test/bridge/libs/LibBridgeSignal.test.ts | 8 +- 7 files changed, 101 insertions(+), 186 deletions(-) diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 6a137d3cde..5461e4dd19 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1,12 +1,17 @@ import { expect } from "chai" -import { AddressManager, Bridge, EtherVault } from "../../typechain" +import { + AddressManager, + Bridge, + EtherVault, + LibTrieProof, + TestHeaderSync, + TestLibBridgeData, +} from "../../typechain" import { ethers } from "hardhat" import { BigNumber, Signer } from "ethers" import { Message } from "../utils/message" import { Block, BlockHeader, EthGetProofResponse } from "../utils/rpc" -// import { getSlot, MessageStatus } from "../../tasks/utils" import RLP from "rlp" -// const helpers = require("@nomicfoundation/hardhat-network-helpers") async function deployBridge( signer: Signer, @@ -14,7 +19,9 @@ async function deployBridge( destChain: number, srcChain: number ): Promise<{ bridge: Bridge; etherVault: EtherVault }> { - const libTrieProof = await (await ethers.getContractFactory("LibTrieProof")) + const libTrieProof: LibTrieProof = await ( + await ethers.getContractFactory("LibTrieProof") + ) .connect(signer) .deploy() @@ -476,7 +483,7 @@ describe("integration:Bridge", function () { .connect(l2Signer) .setAddress(`${srcChainId}.bridge`, l1Bridge.address) - const headerSync = await ( + const headerSync: TestHeaderSync = await ( await ethers.getContractFactory("TestHeaderSync") ) .connect(l2Signer) @@ -701,7 +708,7 @@ describe("integration:Bridge", function () { ["latest", false] ) - const libData = await ( + const libData: TestLibBridgeData = await ( await ethers.getContractFactory("TestLibBridgeData") ).deploy() diff --git a/packages/protocol/test/bridge/libs/LibBridgeData.test.ts b/packages/protocol/test/bridge/libs/LibBridgeData.test.ts index 4409a8dcae..591ed845a5 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeData.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeData.test.ts @@ -1,16 +1,19 @@ import { expect } from "chai" import { ethers } from "hardhat" +import { TestLibBridgeData } from "../../../typechain" +import { MessageStatus } from "../../../tasks/utils" +import { Message } from "../../utils/message" import { TAIKO_BRIDGE_MESSAGE } from "../../constants/messages" describe("LibBridgeData", function () { async function deployLibBridgeDataFixture() { const [owner, nonOwner] = await ethers.getSigners() - const libData = await ( + const libData: TestLibBridgeData = await ( await ethers.getContractFactory("TestLibBridgeData") ).deploy() - const testMessage = { + const testMessage: Message = { id: 1, sender: owner.address, srcChainId: 1, @@ -33,12 +36,6 @@ describe("LibBridgeData", function () { const testVar = [TAIKO_BRIDGE_MESSAGE, testMessage] - const MessageStatus = { - NEW: 0, - RETRIABLE: 1, - DONE: 2, - } - return { owner, nonOwner, @@ -46,7 +43,6 @@ describe("LibBridgeData", function () { testMessage, testTypes, testVar, - MessageStatus, } } @@ -54,7 +50,6 @@ describe("LibBridgeData", function () { it("should return properly hashed message", async function () { const { libData, testMessage, testTypes } = await deployLibBridgeDataFixture() - // dummy struct to test with const testVar = [TAIKO_BRIDGE_MESSAGE, testMessage] const hashed = await libData.hashMessage(testMessage) @@ -72,7 +67,7 @@ describe("LibBridgeData", function () { const { libData } = await deployLibBridgeDataFixture() // dummy struct to test with - const testMessage = { + const testMessage: Message = { id: 0, sender: "0xDA1Ea1362475997419D2055dD43390AEE34c6c37", srcChainId: 31336, @@ -98,8 +93,7 @@ describe("LibBridgeData", function () { describe("updateMessageStatus()", async function () { it("should emit upon successful change, and value should be changed correctly", async function () { - const { libData, testMessage, MessageStatus } = - await deployLibBridgeDataFixture() + const { libData, testMessage } = await deployLibBridgeDataFixture() const signal = await libData.hashMessage(testMessage) @@ -113,8 +107,7 @@ describe("LibBridgeData", function () { }) it("unchanged MessageStatus should not emit event", async function () { - const { libData, testMessage, MessageStatus } = - await deployLibBridgeDataFixture() + const { libData, testMessage } = await deployLibBridgeDataFixture() const signal = await libData.hashMessage(testMessage) diff --git a/packages/protocol/test/bridge/libs/LibBridgeInvoke.test.ts b/packages/protocol/test/bridge/libs/LibBridgeInvoke.test.ts index 7a9c444adb..eba7340ca9 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeInvoke.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeInvoke.test.ts @@ -1,11 +1,15 @@ -// import { expect } from "chai" import { expect } from "chai" import { ethers } from "hardhat" import { Message } from "../../utils/message" +import { + TestLibBridgeData, + TestLibBridgeInvoke, + TestReceiver, +} from "../../../typechain" describe("LibBridgeInvoke", function () { async function deployLibBridgeDataFixture() { - const libData = await ( + const libData: TestLibBridgeData = await ( await ethers.getContractFactory("TestLibBridgeData") ).deploy() return { libData } @@ -14,7 +18,7 @@ describe("LibBridgeInvoke", function () { async function deployLibBridgeInvokeFixture() { const [owner, nonOwner] = await ethers.getSigners() - const libInvoke = await ( + const libInvoke: TestLibBridgeInvoke = await ( await ethers.getContractFactory("TestLibBridgeInvoke") ) .connect(owner) @@ -89,7 +93,7 @@ describe("LibBridgeInvoke", function () { const { libData } = await deployLibBridgeDataFixture() - const testReceiver = await ( + const testReceiver: TestReceiver = await ( await ethers.getContractFactory("TestReceiver") ).deploy() diff --git a/packages/protocol/test/bridge/libs/LibBridgeProcess.test.ts b/packages/protocol/test/bridge/libs/LibBridgeProcess.test.ts index 6d176e0f6d..c593331b53 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeProcess.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeProcess.test.ts @@ -1,8 +1,14 @@ import { expect } from "chai" import hre, { ethers } from "hardhat" import { Message } from "../../utils/message" -import { AddressManager, Bridge } from "../../../typechain" -import { getSlot } from "../../../tasks/utils" +import { + AddressManager, + EtherVault, + LibTrieProof, + TestLibBridgeData, + TestLibBridgeProcess, +} from "../../../typechain" +import { getSlot, MessageStatus } from "../../../tasks/utils" import * as fs from "fs" import * as path from "path" const helpers = require("@nomicfoundation/hardhat-network-helpers") @@ -51,7 +57,9 @@ describe("LibBridgeProcess", function () { ).deploy() await addressManager.init() - const etherVault = await (await ethers.getContractFactory("EtherVault")) + const etherVault: EtherVault = await ( + await ethers.getContractFactory("EtherVault") + ) .connect(etherVaultOwner) .deploy() @@ -71,7 +79,7 @@ describe("LibBridgeProcess", function () { value: ethers.utils.parseEther("10.0"), }) - const libTrieLink = await ( + const libTrieLink: LibTrieProof = await ( await ethers.getContractFactory("LibTrieProof") ) .connect(owner) @@ -89,7 +97,7 @@ describe("LibBridgeProcess", function () { .deploy() await libProcessLink.deployed() - const libProcess = await ( + const libProcess: TestLibBridgeProcess = await ( await ethers.getContractFactory("TestLibBridgeProcess", { libraries: { LibBridgeProcess: libProcessLink.address, @@ -101,7 +109,7 @@ describe("LibBridgeProcess", function () { await libProcess.init(addressManager.address) - const testLibData = await ( + const testLibData: TestLibBridgeData = await ( await ethers.getContractFactory("TestLibBridgeData") ).deploy() @@ -109,18 +117,11 @@ describe("LibBridgeProcess", function () { .connect(etherVaultOwner) .authorize(libProcess.address, true) - const MessageStatus = { - NEW: 0, - RETRIABLE: 1, - DONE: 2, - } - return { owner, srcChainId, messageOwner, libProcess, - MessageStatus, stateSlot, blockChainId, nonOwner, @@ -128,60 +129,6 @@ describe("LibBridgeProcess", function () { addressManager, } } - async function deployBridgeFixture() { - const [owner, etherVault] = await ethers.getSigners() - - const addressManager: AddressManager = await ( - await ethers.getContractFactory("AddressManager") - ).deploy() - await addressManager.init() - - const chainId = hre.network.config.chainId ?? 0 - - await addressManager.setAddress( - `${chainId}.ether_vault`, - etherVault.address - ) - - const libTrieProof = await ( - await ethers.getContractFactory("LibTrieProof") - ).deploy() - - const libBridgeProcess = await ( - await ethers.getContractFactory("LibBridgeProcess", { - libraries: { - LibTrieProof: libTrieProof.address, - }, - }) - ).deploy() - - const libBridgeRetry = await ( - await ethers.getContractFactory("LibBridgeRetry") - ).deploy() - - const BridgeFactory = await ethers.getContractFactory("Bridge", { - libraries: { - LibBridgeProcess: libBridgeProcess.address, - LibBridgeRetry: libBridgeRetry.address, - LibTrieProof: libTrieProof.address, - }, - }) - - const bridge: Bridge = await BridgeFactory.connect(owner).deploy() - - await bridge.init(addressManager.address) - - const headerSync = await ( - await ethers.getContractFactory("TestHeaderSync") - ).deploy() - - await addressManager.setAddress(`${chainId}.taiko`, headerSync.address) - - return { - bridge, - headerSync, - } - } describe("processMessage()", async function () { it("should throw if gaslimit == 0 & msg.sender != message.owner", async function () { @@ -239,7 +186,6 @@ describe("LibBridgeProcess", function () { libProcess, testLibData, blockChainId, - MessageStatus, stateSlot, } = await deployLibBridgeProcessFixture() @@ -271,51 +217,6 @@ describe("LibBridgeProcess", function () { libProcess.processMessage(message, ethers.constants.HashZero) ).to.be.revertedWith("B:status") }) - - it("should throw if signal has not been received", async function () { - const { - owner, - srcChainId, - nonOwner, - libProcess, - blockChainId, - addressManager, - } = await deployLibBridgeProcessFixture() - const { bridge } = await deployBridgeFixture() - - await addressManager.setAddress( - `${srcChainId}.bridge`, - bridge.address - ) - - const message: Message = { - id: 1, - sender: owner.address, - srcChainId: srcChainId, - destChainId: blockChainId, - owner: owner.address, - to: nonOwner.address, - refundAddress: owner.address, - depositValue: 1, - callValue: 1, - processingFee: 1, - gasLimit: 100000000, - data: ethers.constants.HashZero, - memo: "", - } - await expect( - libProcess.processMessage(message, ethers.constants.HashZero) - ).to.be.reverted - - // Reverts because there is no HeaderSync, can't test without - }) - - it("if message fails, refund should go to the intended account and amount", async function () { - await deployLibBridgeProcessFixture() - }) - - it("should pass properly, message should be processed and marked DONE", async function () { - await deployLibBridgeProcessFixture() - }) + // Remaining test cases require integration, will be covered in Bridge.test.ts }) }) diff --git a/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts b/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts index e71335c825..10fbf2ac93 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts @@ -1,7 +1,15 @@ import { expect } from "chai" import hre, { ethers } from "hardhat" import { Message } from "../../utils/message" -import { getSlot, decode } from "../../../tasks/utils" +import { getSlot, decode, MessageStatus } from "../../../tasks/utils" +import { + AddressManager, + EtherVault, + TestBadReceiver, + TestLibBridgeData, + TestLibBridgeRetry, + TestReceiver, +} from "../../../typechain" const helpers = require("@nomicfoundation/hardhat-network-helpers") describe("LibBridgeRetry", function () { @@ -9,17 +17,19 @@ describe("LibBridgeRetry", function () { const [owner, refundAddress, nonOwner, etherVaultOwner] = await ethers.getSigners() - const addressManager = await ( + const addressManager: AddressManager = await ( await ethers.getContractFactory("AddressManager") ).deploy() await addressManager.init() - const badAddressManager = await ( + const badAddressManager: AddressManager = await ( await ethers.getContractFactory("AddressManager") ).deploy() await badAddressManager.init() - const etherVault = await (await ethers.getContractFactory("EtherVault")) + const etherVault: EtherVault = await ( + await ethers.getContractFactory("EtherVault") + ) .connect(etherVaultOwner) .deploy() @@ -57,11 +67,11 @@ describe("LibBridgeRetry", function () { }) ).connect(owner) - const libRetry = await libRetryFactory.deploy() + const libRetry: TestLibBridgeRetry = await libRetryFactory.deploy() await libRetry.init(addressManager.address) await libRetry.deployed() - const badLibRetry = await libRetryFactory.deploy() + const badLibRetry: TestLibBridgeRetry = await libRetryFactory.deploy() await badLibRetry.init(badAddressManager.address) await badLibRetry.deployed() @@ -69,23 +79,16 @@ describe("LibBridgeRetry", function () { .connect(etherVaultOwner) .authorize(libRetry.address, true) - const testLibData = await ( + const testLibData: TestLibBridgeData = await ( await ethers.getContractFactory("TestLibBridgeData") ).deploy() - const MessageStatus = { - NEW: 0, - RETRIABLE: 1, - DONE: 2, - } - return { owner, refundAddress, nonOwner, libRetry, testLibData, - MessageStatus, badLibRetry, } } @@ -167,15 +170,10 @@ describe("LibBridgeRetry", function () { }) it("if etherVault resolves to address(0), retry should fail and messageStatus should not change if not lastAttempt since no ether received", async function () { - const { - owner, - refundAddress, - testLibData, - MessageStatus, - badLibRetry, - } = await deployLibBridgeRetryFixture() - - const testReceiver = await ( + const { owner, refundAddress, testLibData, badLibRetry } = + await deployLibBridgeRetryFixture() + + const testReceiver: TestReceiver = await ( await ethers.getContractFactory("TestReceiver") ).deploy() @@ -224,15 +222,10 @@ describe("LibBridgeRetry", function () { }) it("should fail, but since lastAttempt == true messageStatus should be set to DONE", async function () { - const { - owner, - libRetry, - refundAddress, - testLibData, - MessageStatus, - } = await deployLibBridgeRetryFixture() - - const testBadReceiver = await ( + const { owner, libRetry, refundAddress, testLibData } = + await deployLibBridgeRetryFixture() + + const testBadReceiver: TestBadReceiver = await ( await ethers.getContractFactory("TestBadReceiver") ).deploy() @@ -284,15 +277,10 @@ describe("LibBridgeRetry", function () { }) it("should succeed, set message status to done, invoke message succesfsully", async function () { - const { - owner, - libRetry, - refundAddress, - testLibData, - MessageStatus, - } = await deployLibBridgeRetryFixture() - - const testReceiver = await ( + const { owner, libRetry, refundAddress, testLibData } = + await deployLibBridgeRetryFixture() + + const testReceiver: TestReceiver = await ( await ethers.getContractFactory("TestReceiver") ).deploy() diff --git a/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts b/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts index 12b26ad3e8..9f831b41fb 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts @@ -1,22 +1,42 @@ import { expect } from "chai" import hre, { ethers } from "hardhat" +import { + AddressManager, + TestLibBridgeSend, + EtherVault, +} from "../../../typechain" import { Message } from "../../utils/message" describe("LibBridgeSend", function () { async function deployLibBridgeSendFixture() { - const [owner, nonOwner, etherVault] = await ethers.getSigners() + const [owner, nonOwner, etherVaultOwner] = await ethers.getSigners() - const addressManager = await ( + const addressManager: AddressManager = await ( await ethers.getContractFactory("AddressManager") ).deploy() await addressManager.init() + + const etherVault: EtherVault = await ( + await ethers.getContractFactory("EtherVault") + ) + .connect(etherVaultOwner) + .deploy() + + await etherVault.deployed() + await etherVault.init(addressManager.address) + + await owner.sendTransaction({ + to: etherVault.address, + value: ethers.utils.parseEther("10.0"), + }) + const blockChainId = hre.network.config.chainId ?? 0 await addressManager.setAddress( `${blockChainId}.ether_vault`, etherVault.address ) - const libSend = await ( + const libSend: TestLibBridgeSend = await ( await ethers.getContractFactory("TestLibBridgeSend") ) .connect(owner) diff --git a/packages/protocol/test/bridge/libs/LibBridgeSignal.test.ts b/packages/protocol/test/bridge/libs/LibBridgeSignal.test.ts index 12e2aef883..7ea337d1f1 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeSignal.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeSignal.test.ts @@ -1,6 +1,7 @@ import { expect } from "chai" import { ethers } from "hardhat" -import { TestLibBridgeSignal } from "../../../typechain" +import { TestLibBridgeData, TestLibBridgeSignal } from "../../../typechain" +import { Message } from "../../utils/message" describe("integration:LibBridgeSignal", function () { async function deployLibBridgeSignalFixture() { @@ -10,7 +11,7 @@ describe("integration:LibBridgeSignal", function () { await ethers.getContractFactory("TestLibBridgeSignal") ).deploy() - const testMessage = { + const testMessage: Message = { id: 1, sender: owner.address, srcChainId: 1, @@ -29,7 +30,7 @@ describe("integration:LibBridgeSignal", function () { return { owner, nonOwner, libSignal, testMessage } } async function deployLibBridgeDataFixture() { - const libData = await ( + const libData: TestLibBridgeData = await ( await ethers.getContractFactory("TestLibBridgeData") ).deploy() return { libData } @@ -57,6 +58,7 @@ describe("integration:LibBridgeSignal", function () { ).to.be.revertedWith("B:signal") }) }) + describe("isSignalSent()", async function () { it("properly sent message should be received", async function () { const { owner, libSignal, testMessage } = From 854deec5d1c22862183291ffed71c734dbff990b Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Tue, 22 Nov 2022 13:35:09 -0500 Subject: [PATCH 02/17] linting --- packages/protocol/test/bridge/Bridge.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 450ec0c3a5..f5b1edeed5 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1,7 +1,6 @@ import { expect } from "chai" import { ethers } from "hardhat" import { BigNumber, Signer } from "ethers" -import { ethers } from "hardhat" import { Message } from "../utils/message" import { AddressManager, @@ -14,7 +13,6 @@ import { import { Block, BlockHeader, EthGetProofResponse } from "../utils/rpc" import RLP from "rlp" - async function deployBridge( signer: Signer, addressManager: AddressManager, From f44f86c70b60bc44dae7c527b393242fab115c98 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Tue, 22 Nov 2022 13:50:46 -0500 Subject: [PATCH 03/17] fix libsend tests --- packages/protocol/test/bridge/libs/LibBridgeSend.test.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts b/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts index 9f831b41fb..23416ecd0a 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeSend.test.ts @@ -25,11 +25,6 @@ describe("LibBridgeSend", function () { await etherVault.deployed() await etherVault.init(addressManager.address) - await owner.sendTransaction({ - to: etherVault.address, - value: ethers.utils.parseEther("10.0"), - }) - const blockChainId = hre.network.config.chainId ?? 0 await addressManager.setAddress( `${blockChainId}.ether_vault`, @@ -43,6 +38,9 @@ describe("LibBridgeSend", function () { .deploy() await libSend.init(addressManager.address) + await etherVault + .connect(etherVaultOwner) + .authorize(libSend.address, true) const srcChainId = 1 From 2552093b83124b7dfe699763880e40614dd7a5a5 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Wed, 23 Nov 2022 23:03:08 -0500 Subject: [PATCH 04/17] added missing test case LibBridgeRetry --- .../test/bridge/libs/LibBridgeRetry.test.ts | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts b/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts index 2e90baa2ab..2ded2ca789 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeRetry.test.ts @@ -90,6 +90,7 @@ describe("LibBridgeRetry", function () { libRetry, testLibData, badLibRetry, + etherVault, } } @@ -276,6 +277,63 @@ describe("LibBridgeRetry", function () { ) }) + it("should fail, messageStatus is still RETRIABLE and balance is returned to etherVault", async function () { + const { owner, libRetry, testLibData, etherVault } = + await deployLibBridgeRetryFixture() + + const testBadReceiver: TestBadReceiver = await ( + await ethers.getContractFactory("TestBadReceiver") + ).deploy() + + await testBadReceiver.deployed() + + const destChainId = 5 + const message: Message = { + id: 1, + sender: owner.address, + srcChainId: 1, + destChainId: destChainId, + owner: owner.address, + to: testBadReceiver.address, + refundAddress: ethers.constants.AddressZero, + depositValue: 0, + callValue: 1, + processingFee: 1, + gasLimit: 300000, + data: ethers.constants.HashZero, + memo: "", + } + + const signal = await testLibData.hashMessage(message) + + await helpers.setStorageAt( + libRetry.address, + await getSlot(hre, signal, 202), + MessageStatus.RETRIABLE + ) + + const originalBalance = await ethers.provider.getBalance( + etherVault.address + ) + await libRetry.retryMessage(message, false) + const balancePlusRefund = await ethers.provider.getBalance( + etherVault.address + ) + + expect( + await decode( + hre, + "uint256", + await ethers.provider.getStorageAt( + libRetry.address, + getSlot(hre, signal, 202) + ) + ) + ).to.equal(MessageStatus.RETRIABLE.toString()) + + expect(balancePlusRefund).to.be.equal(originalBalance) + }) + it("should succeed, set message status to done, invoke message succesfsully", async function () { const { owner, libRetry, refundAddress, testLibData } = await deployLibBridgeRetryFixture() From 149680893ce14089ff18d3347ce98fd0a567403d Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Sat, 26 Nov 2022 13:26:25 -0500 Subject: [PATCH 05/17] retryMessage tests attempt --- packages/protocol/test/bridge/Bridge.test.ts | 236 ++++++++++++++++++- 1 file changed, 233 insertions(+), 3 deletions(-) diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index f5b1edeed5..9516f50a77 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1,5 +1,5 @@ import { expect } from "chai" -import { ethers } from "hardhat" +import hre, { ethers } from "hardhat" import { BigNumber, Signer } from "ethers" import { Message } from "../utils/message" import { @@ -10,6 +10,7 @@ import { TestHeaderSync, TestLibBridgeData, } from "../../typechain" +import { getSlot } from "../../tasks/utils" import { Block, BlockHeader, EthGetProofResponse } from "../utils/rpc" import RLP from "rlp" @@ -1019,11 +1020,240 @@ describe("integration:Bridge", function () { [{ header: blockHeader, proof: encodedProof }] ) - // ROGER: this is where we at, we need now to deploy a custom TestHeaderSync that implements - // IHeaderSync where we can manually save synced headers. await l2Bridge.processMessage(message, signalProof, { gasLimit: BigNumber.from(2000000), }) }) }) + + describe("isMessageSent()", function () { + it("should return false, since no message was sent", async function () { + const { owner, l1Bridge, srcChainId, enabledDestChainId } = + await deployBridgeFixture() + + const m: Message = { + id: 1, + sender: owner.address, + srcChainId: srcChainId, + destChainId: enabledDestChainId, + owner: owner.address, + to: owner.address, + refundAddress: owner.address, + depositValue: 1000, + callValue: 1000, + processingFee: 1000, + gasLimit: 10000, + data: ethers.constants.HashZero, + memo: "", + } + + const libData = await ( + await ethers.getContractFactory("TestLibBridgeData") + ).deploy() + const signal = await libData.hashMessage(m) + + expect(await l1Bridge.isMessageSent(signal)).to.be.eq(false) + }) + + it("should return true if message was sent properly", async function () { + const { owner, l1Bridge, srcChainId, enabledDestChainId } = + await deployBridgeFixture() + + const m: Message = { + id: 1, + sender: owner.address, + srcChainId: srcChainId, + destChainId: enabledDestChainId, + owner: owner.address, + to: owner.address, + refundAddress: owner.address, + depositValue: 1000, + callValue: 1000, + processingFee: 1000, + gasLimit: 10000, + data: ethers.constants.HashZero, + memo: "", + } + + const expectedAmount = + m.depositValue + m.callValue + m.processingFee + const tx = await l1Bridge.sendMessage(m, { + value: expectedAmount, + }) + + const receipt = await tx.wait() + + const [messageSentEvent] = receipt.events as any as Event[] + + const { signal } = (messageSentEvent as any).args + + expect(signal).not.to.be.eq(ethers.constants.HashZero) + + expect(await l1Bridge.isMessageSent(signal)).to.be.eq(true) + }) + }) + + describe("retryMessage()", function () { + async function retriableMessageSetup() { + const { + owner, + l2Signer, + nonOwner, + l2NonOwner, + l1Bridge, + l2Bridge, + addressManager, + enabledDestChainId, + l1EtherVault, + l2EtherVault, + srcChainId, + headerSync, + } = await deployBridgeFixture() + + const m: Message = { + id: 1, + sender: owner.address, + srcChainId: srcChainId, + destChainId: enabledDestChainId, + owner: owner.address, + to: owner.address, + refundAddress: owner.address, + depositValue: 1000, + callValue: 1000, + processingFee: 1000, + gasLimit: 1, + data: ethers.constants.HashZero, + memo: "", + } + + const expectedAmount = + m.depositValue + m.callValue + m.processingFee + const tx = await l1Bridge.sendMessage(m, { + value: expectedAmount, + }) + + const receipt = await tx.wait() + + const [messageSentEvent] = receipt.events as any as Event[] + + const { signal, message } = (messageSentEvent as any).args + + expect(signal).not.to.be.eq(ethers.constants.HashZero) + + const messageStatus = await l1Bridge.getMessageStatus(signal) + + expect(messageStatus).to.be.eq(0) + + const sender = l1Bridge.address + + const key = ethers.utils.keccak256( + ethers.utils.solidityPack( + ["address", "bytes32"], + [sender, signal] + ) + ) + + // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot + // in the response + const block: Block = await ethers.provider.send( + "eth_getBlockByNumber", + ["latest", false] + ) + + await headerSync.setSyncedHeader(block.hash) + + const logsBloom = block.logsBloom.toString().substring(2) + + const blockHeader: BlockHeader = { + parentHash: block.parentHash, + ommersHash: block.sha3Uncles, + beneficiary: block.miner, + stateRoot: block.stateRoot, + transactionsRoot: block.transactionsRoot, + receiptsRoot: block.receiptsRoot, + logsBloom: logsBloom + .match(/.{1,64}/g)! + .map((s: string) => "0x" + s), + difficulty: block.difficulty, + height: block.number, + gasLimit: block.gasLimit, + gasUsed: block.gasUsed, + timestamp: block.timestamp, + extraData: block.extraData, + mixHash: block.mixHash, + nonce: block.nonce, + baseFeePerGas: block.baseFeePerGas + ? parseInt(block.baseFeePerGas) + : 0, + } + + // rpc call to get the merkle proof what value is at key on the bridge contract + const proof: EthGetProofResponse = await ethers.provider.send( + "eth_getProof", + [l1Bridge.address, [key], block.hash] + ) + + // RLP encode the proof together for LibTrieProof to decode + const encodedProof = ethers.utils.defaultAbiCoder.encode( + ["bytes", "bytes"], + [ + RLP.encode(proof.accountProof), + RLP.encode(proof.storageProof[0].proof), + ] + ) + // encode the SignalProof struct from LibBridgeSignal + const signalProof = ethers.utils.defaultAbiCoder.encode( + [ + "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", + ], + [{ header: blockHeader, proof: encodedProof }] + ) + + // @Jeff I'm attempting to make it process a message in such a way + // that it fails intentionally and is marked retriable. It doesn't + // seem to be working, any clues on how to go about this? + + // I set message.gasLimit to 1 and try to have a nonOwner call the + // processMessage() so it should use the message.gasLimit + // but it just processes normally outside the processMessage + // block + + // await expect( + // await l2Bridge + // .connect(l2NonOwner) + // .processMessage(message, signalProof, { + // gasLimit: BigNumber.from(2000000), + // }) + // ).to.be.reverted + + console.log("message processed") + + return { + message, + l2Signer, + l2NonOwner, + l1Bridge, + l2Bridge, + addressManager, + headerSync, + owner, + nonOwner, + srcChainId, + enabledDestChainId, + l1EtherVault, + l2EtherVault, + signal, + } + } + it.only("setup message to fail first processMessage", async function () { + const { l2Bridge, signal } = await retriableMessageSetup() + const storageSlot = await getSlot(hre, signal, 202) + const storageAt = await ethers.provider.send("eth_getStorageAt", [ + l2Bridge.address, + storageSlot, + "latest", + ]) + console.log(storageAt) + }) + }) }) From 0bf5fddb47b3088890520acaed10082b4c38dbef Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Mon, 28 Nov 2022 12:56:37 -0800 Subject: [PATCH 06/17] retriable message --- .../bridge/libs/LibBridgeProcess.sol | 1 + packages/protocol/test/bridge/Bridge.test.ts | 41 ++++++++++--------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol b/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol index ad3f4d5934..d13520d606 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol @@ -94,6 +94,7 @@ library LibBridgeProcess { uint256 gasLimit = msg.sender == message.owner ? gasleft() : message.gasLimit; + bool success = LibBridgeInvoke.invokeMessageCall( state, message, diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 9516f50a77..0aa87e0990 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -7,6 +7,7 @@ import { Bridge, EtherVault, LibTrieProof, + TestBadReceiver, TestHeaderSync, TestLibBridgeData, } from "../../typechain" @@ -1110,13 +1111,21 @@ describe("integration:Bridge", function () { headerSync, } = await deployBridgeFixture() + const testBadReceiver: TestBadReceiver = await ( + await ethers.getContractFactory("TestBadReceiver") + ) + .connect(l2Signer) + .deploy() + + await testBadReceiver.deployed() + const m: Message = { id: 1, sender: owner.address, srcChainId: srcChainId, destChainId: enabledDestChainId, owner: owner.address, - to: owner.address, + to: testBadReceiver.address, refundAddress: owner.address, depositValue: 1000, callValue: 1000, @@ -1128,7 +1137,7 @@ describe("integration:Bridge", function () { const expectedAmount = m.depositValue + m.callValue + m.processingFee - const tx = await l1Bridge.sendMessage(m, { + const tx = await l1Bridge.connect(owner).sendMessage(m, { value: expectedAmount, }) @@ -1201,6 +1210,7 @@ describe("integration:Bridge", function () { RLP.encode(proof.storageProof[0].proof), ] ) + // encode the SignalProof struct from LibBridgeSignal const signalProof = ethers.utils.defaultAbiCoder.encode( [ @@ -1209,24 +1219,16 @@ describe("integration:Bridge", function () { [{ header: blockHeader, proof: encodedProof }] ) - // @Jeff I'm attempting to make it process a message in such a way - // that it fails intentionally and is marked retriable. It doesn't - // seem to be working, any clues on how to go about this? - - // I set message.gasLimit to 1 and try to have a nonOwner call the - // processMessage() so it should use the message.gasLimit - // but it just processes normally outside the processMessage - // block - - // await expect( - // await l2Bridge - // .connect(l2NonOwner) - // .processMessage(message, signalProof, { - // gasLimit: BigNumber.from(2000000), - // }) - // ).to.be.reverted + await l2Bridge + .connect(l2NonOwner) + .processMessage(message, signalProof, { + gasLimit: BigNumber.from(2000000), + }) - console.log("message processed") + const status = await l2Bridge.getMessageStatus(signal) + expect(status).to.be.eq(1) // message is retriable now + // because the LibBridgeInvoke call failed, because + // message.to is a bad receiver and throws upon receipt return { message, @@ -1253,6 +1255,7 @@ describe("integration:Bridge", function () { storageSlot, "latest", ]) + console.log(storageAt) }) }) From d6a1ff8852dfb268aabba554e99f43cc7b023e70 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Tue, 29 Nov 2022 18:21:55 -0500 Subject: [PATCH 07/17] added setup for testing isSignalReceived() --- .../test/bridge/TestSignalSender.sol | 17 ++ packages/protocol/test/bridge/Bridge.test.ts | 227 +++++++++++++++++- 2 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 packages/protocol/contracts/test/bridge/TestSignalSender.sol diff --git a/packages/protocol/contracts/test/bridge/TestSignalSender.sol b/packages/protocol/contracts/test/bridge/TestSignalSender.sol new file mode 100644 index 0000000000..9008f65fc9 --- /dev/null +++ b/packages/protocol/contracts/test/bridge/TestSignalSender.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +// +// ╭━━━━╮╱╱╭╮╱╱╱╱╱╭╮╱╱╱╱╱╭╮ +// ┃╭╮╭╮┃╱╱┃┃╱╱╱╱╱┃┃╱╱╱╱╱┃┃ +// ╰╯┃┃┣┻━┳┫┃╭┳━━╮┃┃╱╱╭━━┫╰━┳━━╮ +// ╱╱┃┃┃╭╮┣┫╰╯┫╭╮┃┃┃╱╭┫╭╮┃╭╮┃━━┫ +// ╱╱┃┃┃╭╮┃┃╭╮┫╰╯┃┃╰━╯┃╭╮┃╰╯┣━━┃ +// ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ +pragma solidity ^0.8.9; + +import "../../bridge/IBridge.sol"; + +contract TestSignalSender { + function sendSignal(IBridge bridge, bytes32 signal) public { + bridge.sendSignal((signal)); + } +} \ No newline at end of file diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 0aa87e0990..4faabb1ccf 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1247,7 +1247,7 @@ describe("integration:Bridge", function () { signal, } } - it.only("setup message to fail first processMessage", async function () { + it("setup message to fail first processMessage", async function () { const { l2Bridge, signal } = await retriableMessageSetup() const storageSlot = await getSlot(hre, signal, 202) const storageAt = await ethers.provider.send("eth_getStorageAt", [ @@ -1259,4 +1259,229 @@ describe("integration:Bridge", function () { console.log(storageAt) }) }) + + describe("isMessageReceived()", function () { + it("should return true", async function () { + const { + owner, + l1Bridge, + srcChainId, + enabledDestChainId, + l2Bridge, + headerSync, + } = await deployBridgeFixture() + + const m: Message = { + id: 1, + sender: owner.address, + srcChainId: srcChainId, + destChainId: enabledDestChainId, + owner: owner.address, + to: owner.address, + refundAddress: owner.address, + depositValue: 1000, + callValue: 1000, + processingFee: 1000, + gasLimit: 10000, + data: ethers.constants.HashZero, + memo: "", + } + + const expectedAmount = + m.depositValue + m.callValue + m.processingFee + const tx = await l1Bridge.sendMessage(m, { + value: expectedAmount, + }) + + const receipt = await tx.wait() + + const [messageSentEvent] = receipt.events as any as Event[] + + const { signal } = (messageSentEvent as any).args + + const sender = l1Bridge.address + + const key = ethers.utils.keccak256( + ethers.utils.solidityPack( + ["address", "bytes32"], + [sender, signal] + ) + ) + + // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot + // in the response + const block: Block = await ethers.provider.send( + "eth_getBlockByNumber", + ["latest", false] + ) + + await headerSync.setSyncedHeader(block.hash) + + const logsBloom = block.logsBloom.toString().substring(2) + + const blockHeader: BlockHeader = { + parentHash: block.parentHash, + ommersHash: block.sha3Uncles, + beneficiary: block.miner, + stateRoot: block.stateRoot, + transactionsRoot: block.transactionsRoot, + receiptsRoot: block.receiptsRoot, + logsBloom: logsBloom + .match(/.{1,64}/g)! + .map((s: string) => "0x" + s), + difficulty: block.difficulty, + height: block.number, + gasLimit: block.gasLimit, + gasUsed: block.gasUsed, + timestamp: block.timestamp, + extraData: block.extraData, + mixHash: block.mixHash, + nonce: block.nonce, + baseFeePerGas: block.baseFeePerGas + ? parseInt(block.baseFeePerGas) + : 0, + } + + // rpc call to get the merkle proof what value is at key on the bridge contract + const proof: EthGetProofResponse = await ethers.provider.send( + "eth_getProof", + [l1Bridge.address, [key], block.hash] + ) + + // RLP encode the proof together for LibTrieProof to decode + const encodedProof = ethers.utils.defaultAbiCoder.encode( + ["bytes", "bytes"], + [ + RLP.encode(proof.accountProof), + RLP.encode(proof.storageProof[0].proof), + ] + ) + // encode the SignalProof struct from LibBridgeSignal + const signalProof = ethers.utils.defaultAbiCoder.encode( + [ + "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", + ], + [{ header: blockHeader, proof: encodedProof }] + ) + + expect( + await l2Bridge.isMessageReceived( + signal, + srcChainId, + signalProof + ) + ).to.be.eq(true) + }) + }) + + describe("isSignalReceived()", function () { + it.only("should return true", async function () { + const { nonOwner, l1Bridge, srcChainId, l2Bridge, headerSync } = + await deployBridgeFixture() + + const testSignalSender = await ( + await ethers.getContractFactory("TestSignalSender") + ).deploy() + + const tx = await testSignalSender.sendSignal( + l2Bridge.address, + ethers.utils.keccak256(ethers.utils.hexlify(1000)), + { gasLimit: BigNumber.from(2000000) } + ) + + // const tx = await l1Bridge + // .connect(nonOwner) + // .sendSignal(ethers.utils.keccak256(ethers.utils.hexlify(1000))) + + const receipt = await tx.wait() + + const [messageSentEvent] = receipt.events as any as Event[] + + const { signal } = (messageSentEvent as any).args + + const sender = await nonOwner.getAddress() + + const key = ethers.utils.keccak256( + ethers.utils.solidityPack( + ["address", "bytes32"], + [sender, signal] + ) + ) + + // // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot + // // in the response + // const block: Block = await ethers.provider.send( + // "eth_getBlockByNumber", + // ["latest", false] + // ) + + // await headerSync.setSyncedHeader(block.hash) + + // const logsBloom = block.logsBloom.toString().substring(2) + + // const blockHeader: BlockHeader = { + // parentHash: block.parentHash, + // ommersHash: block.sha3Uncles, + // beneficiary: block.miner, + // stateRoot: block.stateRoot, + // transactionsRoot: block.transactionsRoot, + // receiptsRoot: block.receiptsRoot, + // logsBloom: logsBloom + // .match(/.{1,64}/g)! + // .map((s: string) => "0x" + s), + // difficulty: block.difficulty, + // height: block.number, + // gasLimit: block.gasLimit, + // gasUsed: block.gasUsed, + // timestamp: block.timestamp, + // extraData: block.extraData, + // mixHash: block.mixHash, + // nonce: block.nonce, + // baseFeePerGas: block.baseFeePerGas + // ? parseInt(block.baseFeePerGas) + // : 0, + // } + + // // get storageValue for the key + // const storageValue = await ethers.provider.getStorageAt( + // l2Bridge.address, + // key, + // block.number + // ) + // // // make sure it equals 1 so our proof will pass + // expect(storageValue).to.be.eq( + // "0x0000000000000000000000000000000000000000000000000000000000000001" + // ) + // // rpc call to get the merkle proof what value is at key on the bridge contract + // const proof: EthGetProofResponse = await ethers.provider.send( + // "eth_getProof", + // [l2Bridge.address, [key], block.hash] + // ) + + // // RLP encode the proof together for LibTrieProof to decode + // const encodedProof = ethers.utils.defaultAbiCoder.encode( + // ["bytes", "bytes"], + // [ + // RLP.encode(proof.accountProof), + // RLP.encode(proof.storageProof[0].proof), + // ] + // ) + // // encode the SignalProof struct from LibBridgeSignal + // const signalProof = ethers.utils.defaultAbiCoder.encode( + // [ + // "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", + // ], + // [{ header: blockHeader, proof: encodedProof }] + // ) + + // expect( + // await l2Bridge.isSignalReceived( + // signal, + // srcChainId, + // sender, + // signalProof + // ) + // ).to.be.eq(true) + }) + }) }) From 8e5c5940d4f4da5e41dd2616fc64069882a10ef3 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Tue, 29 Nov 2022 19:27:30 -0500 Subject: [PATCH 08/17] fix --- packages/protocol/test/bridge/Bridge.test.ts | 113 ++++++++++--------- 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 4faabb1ccf..a911c59222 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1376,16 +1376,26 @@ describe("integration:Bridge", function () { describe("isSignalReceived()", function () { it.only("should return true", async function () { - const { nonOwner, l1Bridge, srcChainId, l2Bridge, headerSync } = - await deployBridgeFixture() + const { + nonOwner, + l1Bridge, + srcChainId, + l2Bridge, + headerSync, + l2Signer, + } = await deployBridgeFixture() const testSignalSender = await ( await ethers.getContractFactory("TestSignalSender") - ).deploy() + ) + .connect(l2Signer) + .deploy() + + const signal = ethers.utils.keccak256(ethers.utils.hexlify(1000)) const tx = await testSignalSender.sendSignal( l2Bridge.address, - ethers.utils.keccak256(ethers.utils.hexlify(1000)), + signal, { gasLimit: BigNumber.from(2000000) } ) @@ -1393,13 +1403,14 @@ describe("integration:Bridge", function () { // .connect(nonOwner) // .sendSignal(ethers.utils.keccak256(ethers.utils.hexlify(1000))) - const receipt = await tx.wait() + // const receipt = await tx.wait() + await tx.wait() - const [messageSentEvent] = receipt.events as any as Event[] + // const [messageSentEvent] = receipt.events as any as Event[] - const { signal } = (messageSentEvent as any).args + // const { signal } = (messageSentEvent as any).args - const sender = await nonOwner.getAddress() + const sender = await l2Signer.getAddress() const key = ethers.utils.keccak256( ethers.utils.solidityPack( @@ -1408,50 +1419,50 @@ describe("integration:Bridge", function () { ) ) - // // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot - // // in the response - // const block: Block = await ethers.provider.send( - // "eth_getBlockByNumber", - // ["latest", false] - // ) + // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot + // in the response + const block: Block = await ethers.provider.send( + "eth_getBlockByNumber", + ["latest", false] + ) - // await headerSync.setSyncedHeader(block.hash) - - // const logsBloom = block.logsBloom.toString().substring(2) - - // const blockHeader: BlockHeader = { - // parentHash: block.parentHash, - // ommersHash: block.sha3Uncles, - // beneficiary: block.miner, - // stateRoot: block.stateRoot, - // transactionsRoot: block.transactionsRoot, - // receiptsRoot: block.receiptsRoot, - // logsBloom: logsBloom - // .match(/.{1,64}/g)! - // .map((s: string) => "0x" + s), - // difficulty: block.difficulty, - // height: block.number, - // gasLimit: block.gasLimit, - // gasUsed: block.gasUsed, - // timestamp: block.timestamp, - // extraData: block.extraData, - // mixHash: block.mixHash, - // nonce: block.nonce, - // baseFeePerGas: block.baseFeePerGas - // ? parseInt(block.baseFeePerGas) - // : 0, - // } - - // // get storageValue for the key - // const storageValue = await ethers.provider.getStorageAt( - // l2Bridge.address, - // key, - // block.number - // ) - // // // make sure it equals 1 so our proof will pass - // expect(storageValue).to.be.eq( - // "0x0000000000000000000000000000000000000000000000000000000000000001" - // ) + await headerSync.setSyncedHeader(block.hash) + + const logsBloom = block.logsBloom.toString().substring(2) + + const blockHeader: BlockHeader = { + parentHash: block.parentHash, + ommersHash: block.sha3Uncles, + beneficiary: block.miner, + stateRoot: block.stateRoot, + transactionsRoot: block.transactionsRoot, + receiptsRoot: block.receiptsRoot, + logsBloom: logsBloom + .match(/.{1,64}/g)! + .map((s: string) => "0x" + s), + difficulty: block.difficulty, + height: block.number, + gasLimit: block.gasLimit, + gasUsed: block.gasUsed, + timestamp: block.timestamp, + extraData: block.extraData, + mixHash: block.mixHash, + nonce: block.nonce, + baseFeePerGas: block.baseFeePerGas + ? parseInt(block.baseFeePerGas) + : 0, + } + + // get storageValue for the key + const storageValue = await ethers.provider.getStorageAt( + l2Bridge.address, + key, + block.number + ) + // // make sure it equals 1 so our proof will pass + expect(storageValue).to.be.eq( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ) // // rpc call to get the merkle proof what value is at key on the bridge contract // const proof: EthGetProofResponse = await ethers.provider.send( // "eth_getProof", From d3b96788ff1d096ce70a5c4adcf0ba5c4255f304 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Thu, 1 Dec 2022 16:34:26 -0800 Subject: [PATCH 09/17] lint --- packages/protocol/test/bridge/Bridge.test.ts | 86 +++++++------------ .../test/bridge/libs/LibBridgeData.test.ts | 1 - 2 files changed, 31 insertions(+), 56 deletions(-) diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index a911c59222..7bffcf862a 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1376,40 +1376,15 @@ describe("integration:Bridge", function () { describe("isSignalReceived()", function () { it.only("should return true", async function () { - const { - nonOwner, - l1Bridge, - srcChainId, - l2Bridge, - headerSync, - l2Signer, - } = await deployBridgeFixture() - - const testSignalSender = await ( - await ethers.getContractFactory("TestSignalSender") - ) - .connect(l2Signer) - .deploy() - - const signal = ethers.utils.keccak256(ethers.utils.hexlify(1000)) + const { l2Bridge, headerSync, l2Signer } = + await deployBridgeFixture() - const tx = await testSignalSender.sendSignal( - l2Bridge.address, - signal, - { gasLimit: BigNumber.from(2000000) } - ) + const signal = ethers.utils.hexlify(ethers.utils.randomBytes(32)) - // const tx = await l1Bridge - // .connect(nonOwner) - // .sendSignal(ethers.utils.keccak256(ethers.utils.hexlify(1000))) + const tx = await l2Bridge.connect(l2Signer).sendSignal(signal) - // const receipt = await tx.wait() await tx.wait() - // const [messageSentEvent] = receipt.events as any as Event[] - - // const { signal } = (messageSentEvent as any).args - const sender = await l2Signer.getAddress() const key = ethers.utils.keccak256( @@ -1421,40 +1396,40 @@ describe("integration:Bridge", function () { // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot // in the response - const block: Block = await ethers.provider.send( + const block: Block = await l2Signer.provider.send( "eth_getBlockByNumber", ["latest", false] ) await headerSync.setSyncedHeader(block.hash) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } + // const logsBloom = block.logsBloom.toString().substring(2) + + // const blockHeader: BlockHeader = { + // parentHash: block.parentHash, + // ommersHash: block.sha3Uncles, + // beneficiary: block.miner, + // stateRoot: block.stateRoot, + // transactionsRoot: block.transactionsRoot, + // receiptsRoot: block.receiptsRoot, + // logsBloom: logsBloom + // .match(/.{1,64}/g)! + // .map((s: string) => "0x" + s), + // difficulty: block.difficulty, + // height: block.number, + // gasLimit: block.gasLimit, + // gasUsed: block.gasUsed, + // timestamp: block.timestamp, + // extraData: block.extraData, + // mixHash: block.mixHash, + // nonce: block.nonce, + // baseFeePerGas: block.baseFeePerGas + // ? parseInt(block.baseFeePerGas) + // : 0, + // } // get storageValue for the key - const storageValue = await ethers.provider.getStorageAt( + const storageValue = await l2Signer.provider.getStorageAt( l2Bridge.address, key, block.number @@ -1463,6 +1438,7 @@ describe("integration:Bridge", function () { expect(storageValue).to.be.eq( "0x0000000000000000000000000000000000000000000000000000000000000001" ) + // // rpc call to get the merkle proof what value is at key on the bridge contract // const proof: EthGetProofResponse = await ethers.provider.send( // "eth_getProof", diff --git a/packages/protocol/test/bridge/libs/LibBridgeData.test.ts b/packages/protocol/test/bridge/libs/LibBridgeData.test.ts index 401f55b1f9..591ed845a5 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeData.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeData.test.ts @@ -4,7 +4,6 @@ import { TestLibBridgeData } from "../../../typechain" import { MessageStatus } from "../../../tasks/utils" import { Message } from "../../utils/message" import { TAIKO_BRIDGE_MESSAGE } from "../../constants/messages" -import { MessageStatus } from "../../../tasks/utils" describe("LibBridgeData", function () { async function deployLibBridgeDataFixture() { From 78d9e8b43790b92d5b1ffccdcb1e8240d263ca28 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Mon, 5 Dec 2022 11:16:28 -0500 Subject: [PATCH 10/17] switched isSignalReceived test to l1 so eth_getProof is supported --- packages/protocol/test/bridge/Bridge.test.ts | 125 ++++++++++--------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 7bffcf862a..131b1dfb9d 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1376,16 +1376,22 @@ describe("integration:Bridge", function () { describe("isSignalReceived()", function () { it.only("should return true", async function () { - const { l2Bridge, headerSync, l2Signer } = + const { l1Bridge, headerSync, srcChainId } = await deployBridgeFixture() const signal = ethers.utils.hexlify(ethers.utils.randomBytes(32)) - const tx = await l2Bridge.connect(l2Signer).sendSignal(signal) + const nonOwnerSigner = await ethers.provider.getSigner() + + const tx = await l1Bridge.connect(nonOwnerSigner).sendSignal(signal) await tx.wait() - const sender = await l2Signer.getAddress() + // const tx = await l2Bridge.connect(l2Signer).sendSignal(signal) + + // await tx.wait() + + const sender = await nonOwnerSigner.getAddress() const key = ethers.utils.keccak256( ethers.utils.solidityPack( @@ -1394,43 +1400,41 @@ describe("integration:Bridge", function () { ) ) - // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot - // in the response - const block: Block = await l2Signer.provider.send( + const block: Block = await ethers.provider.send( "eth_getBlockByNumber", ["latest", false] ) await headerSync.setSyncedHeader(block.hash) - // const logsBloom = block.logsBloom.toString().substring(2) - - // const blockHeader: BlockHeader = { - // parentHash: block.parentHash, - // ommersHash: block.sha3Uncles, - // beneficiary: block.miner, - // stateRoot: block.stateRoot, - // transactionsRoot: block.transactionsRoot, - // receiptsRoot: block.receiptsRoot, - // logsBloom: logsBloom - // .match(/.{1,64}/g)! - // .map((s: string) => "0x" + s), - // difficulty: block.difficulty, - // height: block.number, - // gasLimit: block.gasLimit, - // gasUsed: block.gasUsed, - // timestamp: block.timestamp, - // extraData: block.extraData, - // mixHash: block.mixHash, - // nonce: block.nonce, - // baseFeePerGas: block.baseFeePerGas - // ? parseInt(block.baseFeePerGas) - // : 0, - // } + const logsBloom = block.logsBloom.toString().substring(2) + + const blockHeader: BlockHeader = { + parentHash: block.parentHash, + ommersHash: block.sha3Uncles, + beneficiary: block.miner, + stateRoot: block.stateRoot, + transactionsRoot: block.transactionsRoot, + receiptsRoot: block.receiptsRoot, + logsBloom: logsBloom + .match(/.{1,64}/g)! + .map((s: string) => "0x" + s), + difficulty: block.difficulty, + height: block.number, + gasLimit: block.gasLimit, + gasUsed: block.gasUsed, + timestamp: block.timestamp, + extraData: block.extraData, + mixHash: block.mixHash, + nonce: block.nonce, + baseFeePerGas: block.baseFeePerGas + ? parseInt(block.baseFeePerGas) + : 0, + } // get storageValue for the key - const storageValue = await l2Signer.provider.getStorageAt( - l2Bridge.address, + const storageValue = await ethers.provider.getStorageAt( + l1Bridge.address, key, block.number ) @@ -1439,36 +1443,33 @@ describe("integration:Bridge", function () { "0x0000000000000000000000000000000000000000000000000000000000000001" ) - // // rpc call to get the merkle proof what value is at key on the bridge contract - // const proof: EthGetProofResponse = await ethers.provider.send( - // "eth_getProof", - // [l2Bridge.address, [key], block.hash] - // ) - - // // RLP encode the proof together for LibTrieProof to decode - // const encodedProof = ethers.utils.defaultAbiCoder.encode( - // ["bytes", "bytes"], - // [ - // RLP.encode(proof.accountProof), - // RLP.encode(proof.storageProof[0].proof), - // ] - // ) - // // encode the SignalProof struct from LibBridgeSignal - // const signalProof = ethers.utils.defaultAbiCoder.encode( - // [ - // "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - // ], - // [{ header: blockHeader, proof: encodedProof }] - // ) - - // expect( - // await l2Bridge.isSignalReceived( - // signal, - // srcChainId, - // sender, - // signalProof - // ) - // ).to.be.eq(true) + // rpc call to get the merkle proof what value is at key on the bridge contract + const proof: EthGetProofResponse = await ethers.provider.send( + "eth_getProof", + [l1Bridge.address, [key], block.hash] + ) + + // RLP encode the proof together for LibTrieProof to decode + const encodedProof = ethers.utils.defaultAbiCoder.encode( + ["bytes", "bytes"], + [ + RLP.encode(proof.accountProof), + RLP.encode(proof.storageProof[0].proof), + ] + ) + // encode the SignalProof struct from LibBridgeSignal + const signalProof = ethers.utils.defaultAbiCoder.encode( + [ + "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", + ], + [{ header: blockHeader, proof: encodedProof }] + ) + + expect( + await l1Bridge + .connect(nonOwnerSigner) + .isSignalReceived(signal, srcChainId, sender, signalProof) + ).to.be.eq(true) }) }) }) From 80098c79e8bdce029a5171c558b1d24ab30742d9 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Mon, 5 Dec 2022 14:44:15 -0500 Subject: [PATCH 11/17] fix isSignalReceived() test --- packages/protocol/test/bridge/Bridge.test.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 131b1dfb9d..88345dc24f 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1375,15 +1375,13 @@ describe("integration:Bridge", function () { }) describe("isSignalReceived()", function () { - it.only("should return true", async function () { - const { l1Bridge, headerSync, srcChainId } = + it("should return true", async function () { + const { l1Bridge, headerSync, srcChainId, l2Bridge, owner } = await deployBridgeFixture() const signal = ethers.utils.hexlify(ethers.utils.randomBytes(32)) - const nonOwnerSigner = await ethers.provider.getSigner() - - const tx = await l1Bridge.connect(nonOwnerSigner).sendSignal(signal) + const tx = await l1Bridge.connect(owner).sendSignal(signal) await tx.wait() @@ -1391,7 +1389,7 @@ describe("integration:Bridge", function () { // await tx.wait() - const sender = await nonOwnerSigner.getAddress() + const sender = owner.address const key = ethers.utils.keccak256( ethers.utils.solidityPack( @@ -1466,9 +1464,12 @@ describe("integration:Bridge", function () { ) expect( - await l1Bridge - .connect(nonOwnerSigner) - .isSignalReceived(signal, srcChainId, sender, signalProof) + await l2Bridge.isSignalReceived( + signal, + srcChainId, + sender, + signalProof + ) ).to.be.eq(true) }) }) From f4a86817917f001707f533f669c860f1fd6ad401 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Mon, 5 Dec 2022 15:12:16 -0500 Subject: [PATCH 12/17] fix isSignalReceived() test --- packages/protocol/test/bridge/Bridge.test.ts | 7 ++----- packages/protocol/test/bridge/libs/LibBridgeData.test.ts | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 88345dc24f..a35c08b83f 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1385,10 +1385,6 @@ describe("integration:Bridge", function () { await tx.wait() - // const tx = await l2Bridge.connect(l2Signer).sendSignal(signal) - - // await tx.wait() - const sender = owner.address const key = ethers.utils.keccak256( @@ -1462,7 +1458,8 @@ describe("integration:Bridge", function () { ], [{ header: blockHeader, proof: encodedProof }] ) - + // proving functionality; l2Bridge can check if l1Bridge receives a signal + // allowing for dapp cross layer communication expect( await l2Bridge.isSignalReceived( signal, diff --git a/packages/protocol/test/bridge/libs/LibBridgeData.test.ts b/packages/protocol/test/bridge/libs/LibBridgeData.test.ts index 029726d78a..7da0b4791e 100644 --- a/packages/protocol/test/bridge/libs/LibBridgeData.test.ts +++ b/packages/protocol/test/bridge/libs/LibBridgeData.test.ts @@ -4,7 +4,6 @@ import { TestLibBridgeData } from "../../../typechain" import { K_BRIDGE_MESSAGE } from "../../constants/messages" import { MessageStatus } from "../../../tasks/utils" import { Message } from "../../utils/message" -import { TAIKO_BRIDGE_MESSAGE } from "../../constants/messages" describe("LibBridgeData", function () { async function deployLibBridgeDataFixture() { From 6049e3bd09bc21f40863aeb653d87e29f95f7181 Mon Sep 17 00:00:00 2001 From: dantaik <99078276+dantaik@users.noreply.github.com> Date: Tue, 6 Dec 2022 13:40:19 +0800 Subject: [PATCH 13/17] Update LibConstants.sol --- packages/protocol/contracts/libs/LibConstants.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/protocol/contracts/libs/LibConstants.sol b/packages/protocol/contracts/libs/LibConstants.sol index 804497d523..bcdfd0d608 100644 --- a/packages/protocol/contracts/libs/LibConstants.sol +++ b/packages/protocol/contracts/libs/LibConstants.sol @@ -17,7 +17,6 @@ library LibConstants { // This number is calculated from K_MAX_NUM_BLOCKS to make // the 'the maximum value of the multiplier' close to 20.0 uint256 public constant K_ZKPROOFS_PER_BLOCK = 1; - uint256 public constant K_VERIFICATION_DELAY = 60 minutes; uint256 public constant K_MAX_VERIFICATIONS_PER_TX = 20; uint256 public constant K_COMMIT_DELAY_CONFIRMS = 4; uint256 public constant K_MAX_PROOFS_PER_FORK_CHOICE = 5; From 714cdbcd5594369e2dcca075dc48e3fd10f402fd Mon Sep 17 00:00:00 2001 From: dantaik <99078276+dantaik@users.noreply.github.com> Date: Tue, 6 Dec 2022 13:41:07 +0800 Subject: [PATCH 14/17] format --- packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol | 2 +- packages/protocol/contracts/test/bridge/TestSignalSender.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol b/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol index c30a04608a..9925ccef2b 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol @@ -95,7 +95,7 @@ library LibBridgeProcess { uint256 gasLimit = msg.sender == message.owner ? gasleft() : message.gasLimit; - + bool success = LibBridgeInvoke.invokeMessageCall({ state: state, message: message, diff --git a/packages/protocol/contracts/test/bridge/TestSignalSender.sol b/packages/protocol/contracts/test/bridge/TestSignalSender.sol index 9008f65fc9..3844d58df3 100644 --- a/packages/protocol/contracts/test/bridge/TestSignalSender.sol +++ b/packages/protocol/contracts/test/bridge/TestSignalSender.sol @@ -14,4 +14,4 @@ contract TestSignalSender { function sendSignal(IBridge bridge, bytes32 signal) public { bridge.sendSignal((signal)); } -} \ No newline at end of file +} From 103ee0010e7e1667e04479584fa7cb4ef3c29369 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Tue, 6 Dec 2022 15:44:30 -0500 Subject: [PATCH 15/17] migrated repeated code to fixtures and util functions --- packages/protocol/tasks/utils.ts | 65 ++ packages/protocol/test/bridge/Bridge.test.ts | 653 +++---------------- 2 files changed, 161 insertions(+), 557 deletions(-) diff --git a/packages/protocol/tasks/utils.ts b/packages/protocol/tasks/utils.ts index 8c2c948c00..57d5577ddd 100644 --- a/packages/protocol/tasks/utils.ts +++ b/packages/protocol/tasks/utils.ts @@ -1,5 +1,7 @@ import * as fs from "fs" import * as log from "./log" +import { Block, BlockHeader, EthGetProofResponse } from "../test/utils/rpc" +import RLP from "rlp" async function deployContract( hre: any, @@ -84,6 +86,67 @@ const MessageStatus = { FAILED: 3, } +async function getLatestBlockHeader(hre: any) { + const block: Block = await hre.ethers.provider.send( + "eth_getBlockByNumber", + ["latest", false] + ) + + const logsBloom = block.logsBloom.toString().substring(2) + + const blockHeader: BlockHeader = { + parentHash: block.parentHash, + ommersHash: block.sha3Uncles, + beneficiary: block.miner, + stateRoot: block.stateRoot, + transactionsRoot: block.transactionsRoot, + receiptsRoot: block.receiptsRoot, + logsBloom: logsBloom.match(/.{1,64}/g)!.map((s: string) => "0x" + s), + difficulty: block.difficulty, + height: block.number, + gasLimit: block.gasLimit, + gasUsed: block.gasUsed, + timestamp: block.timestamp, + extraData: block.extraData, + mixHash: block.mixHash, + nonce: block.nonce, + baseFeePerGas: block.baseFeePerGas ? parseInt(block.baseFeePerGas) : 0, + } + + return { block, blockHeader } +} + +async function getSignalProof( + hre: any, + contractAddress: string, + key: string, + blockHash: string, + blockHeader: BlockHeader +) { + const proof: EthGetProofResponse = await hre.ethers.provider.send( + "eth_getProof", + [contractAddress, [key], blockHash] + ) + + // RLP encode the proof together for LibTrieProof to decode + const encodedProof = hre.ethers.utils.defaultAbiCoder.encode( + ["bytes", "bytes"], + [ + RLP.encode(proof.accountProof), + RLP.encode(proof.storageProof[0].proof), + ] + ) + // encode the SignalProof struct from LibBridgeSignal + const signalProof = hre.ethers.utils.defaultAbiCoder.encode( + [ + "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", + ], + [{ header: blockHeader, proof: encodedProof }] + ) + + return signalProof +} + export { deployContract, getDeployer, @@ -94,4 +157,6 @@ export { getSlot, decode, MessageStatus, + getLatestBlockHeader, + getSignalProof, } diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 1ea4c3306a..5249313b3c 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -1,5 +1,5 @@ import { expect } from "chai" -import { ethers } from "hardhat" +import hre, { ethers } from "hardhat" import { BigNumber, Signer } from "ethers" import { Message } from "../utils/message" import { @@ -12,6 +12,7 @@ import { TestLibBridgeData, } from "../../typechain" import { Block, BlockHeader, EthGetProofResponse } from "../utils/rpc" +import { getLatestBlockHeader, getSignalProof } from "../../tasks/utils" import RLP from "rlp" async function deployBridge( @@ -494,6 +495,22 @@ describe("integration:Bridge", function () { .connect(l2Signer) .setAddress(`${enabledDestChainId}.taiko`, headerSync.address) + const m: Message = { + id: 1, + sender: owner.address, + srcChainId: srcChainId, + destChainId: enabledDestChainId, + owner: owner.address, + to: owner.address, + refundAddress: owner.address, + depositValue: 1000, + callValue: 1000, + processingFee: 1000, + gasLimit: 10000, + data: ethers.constants.HashZero, + memo: "", + } + return { owner, l2Signer, @@ -507,6 +524,7 @@ describe("integration:Bridge", function () { l2EtherVault, srcChainId, headerSync, + m, } } @@ -567,30 +585,8 @@ describe("integration:Bridge", function () { }) it("should throw if messageStatus of message is != NEW", async function () { - const { - owner, - l1Bridge, - srcChainId, - enabledDestChainId, - l2Bridge, - headerSync, - } = await deployBridgeFixture() - - const m: Message = { - id: 1, - sender: owner.address, - srcChainId: srcChainId, - destChainId: enabledDestChainId, - owner: owner.address, - to: owner.address, - refundAddress: owner.address, - depositValue: 1000, - callValue: 1000, - processingFee: 1000, - gasLimit: 10000, - data: ethers.constants.HashZero, - memo: "", - } + const { l1Bridge, l2Bridge, headerSync, m } = + await deployBridgeFixture() const expectedAmount = m.depositValue + m.callValue + m.processingFee @@ -613,58 +609,16 @@ describe("integration:Bridge", function () { ) ) - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(block.hash) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - - // rpc call to get the merkle proof what value is at key on the bridge contract - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] - ) - - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.hash, + blockHeader ) // upon successful processing, this immediately gets marked as DONE @@ -677,35 +631,8 @@ describe("integration:Bridge", function () { }) it("should throw if message signalproof is not valid", async function () { - const { - owner, - l1Bridge, - srcChainId, - enabledDestChainId, - l2Bridge, - headerSync, - } = await deployBridgeFixture() - - const m: Message = { - id: 1, - sender: owner.address, - srcChainId: srcChainId, - destChainId: enabledDestChainId, - owner: owner.address, - to: owner.address, - refundAddress: owner.address, - depositValue: 1000, - callValue: 1000, - processingFee: 1000, - gasLimit: 10000, - data: ethers.constants.HashZero, - memo: "", - } - - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { l1Bridge, l2Bridge, headerSync, m } = + await deployBridgeFixture() const libData: TestLibBridgeData = await ( await ethers.getContractFactory("TestLibBridgeData") @@ -721,53 +648,16 @@ describe("integration:Bridge", function () { [sender, signal] ) ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(ethers.constants.HashZero) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] - ) - - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.hash, + blockHeader ) await expect( @@ -776,30 +666,8 @@ describe("integration:Bridge", function () { }) it("should throw if message has not been received", async function () { - const { - owner, - l1Bridge, - srcChainId, - enabledDestChainId, - l2Bridge, - headerSync, - } = await deployBridgeFixture() - - const m: Message = { - id: 1, - sender: owner.address, - srcChainId: srcChainId, - destChainId: enabledDestChainId, - owner: owner.address, - to: owner.address, - refundAddress: owner.address, - depositValue: 1000, - callValue: 1000, - processingFee: 1000, - gasLimit: 10000, - data: ethers.constants.HashZero, - memo: "", - } + const { l1Bridge, l2Bridge, headerSync, m } = + await deployBridgeFixture() const expectedAmount = m.depositValue + m.callValue + m.processingFee @@ -828,38 +696,10 @@ describe("integration:Bridge", function () { ) ) - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(ethers.constants.HashZero) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - // get storageValue for the key const storageValue = await ethers.provider.getStorageAt( l1Bridge.address, @@ -870,26 +710,13 @@ describe("integration:Bridge", function () { expect(storageValue).to.be.eq( "0x0000000000000000000000000000000000000000000000000000000000000001" ) - // rpc call to get the merkle proof what value is at key on the bridge contract - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] - ) - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.hash, + blockHeader ) await expect( @@ -898,30 +725,8 @@ describe("integration:Bridge", function () { }) it("processes a message when the signal has been verified from the sending chain", async () => { - const { - owner, - l1Bridge, - srcChainId, - enabledDestChainId, - l2Bridge, - headerSync, - } = await deployBridgeFixture() - - const m: Message = { - id: 1, - sender: owner.address, - srcChainId: srcChainId, - destChainId: enabledDestChainId, - owner: owner.address, - to: owner.address, - refundAddress: owner.address, - depositValue: 1000, - callValue: 1000, - processingFee: 1000, - gasLimit: 10000, - data: ethers.constants.HashZero, - memo: "", - } + const { l1Bridge, l2Bridge, headerSync, m } = + await deployBridgeFixture() const expectedAmount = m.depositValue + m.callValue + m.processingFee @@ -950,38 +755,10 @@ describe("integration:Bridge", function () { ) ) - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(block.hash) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - // get storageValue for the key const storageValue = await ethers.provider.getStorageAt( l1Bridge.address, @@ -992,56 +769,26 @@ describe("integration:Bridge", function () { expect(storageValue).to.be.eq( "0x0000000000000000000000000000000000000000000000000000000000000001" ) - // rpc call to get the merkle proof what value is at key on the bridge contract - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] - ) - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.hash, + blockHeader ) expect( - await l2Bridge.processMessage(message, signalProof, { - gasLimit: BigNumber.from(2000000), - }) - ).to.emit(l2Bridge, "MessageStatusChanged") - }) - }) - - describe("isMessageSent()", function () { - it("should return false, since no message was sent", async function () { - const { owner, l1Bridge, srcChainId, enabledDestChainId } = - await deployBridgeFixture() - - const m: Message = { - id: 1, - sender: owner.address, - srcChainId: srcChainId, - destChainId: enabledDestChainId, - owner: owner.address, - to: owner.address, - refundAddress: owner.address, - depositValue: 1000, - callValue: 1000, - processingFee: 1000, - gasLimit: 10000, - data: ethers.constants.HashZero, - memo: "", - } + await l2Bridge.processMessage(message, signalProof, { + gasLimit: BigNumber.from(2000000), + }) + ).to.emit(l2Bridge, "MessageStatusChanged") + }) + }) + + describe("isMessageSent()", function () { + it("should return false, since no message was sent", async function () { + const { l1Bridge, m } = await deployBridgeFixture() const libData = await ( await ethers.getContractFactory("TestLibBridgeData") @@ -1052,24 +799,7 @@ describe("integration:Bridge", function () { }) it("should return true if message was sent properly", async function () { - const { owner, l1Bridge, srcChainId, enabledDestChainId } = - await deployBridgeFixture() - - const m: Message = { - id: 1, - sender: owner.address, - srcChainId: srcChainId, - destChainId: enabledDestChainId, - owner: owner.address, - to: owner.address, - refundAddress: owner.address, - depositValue: 1000, - callValue: 1000, - processingFee: 1000, - gasLimit: 10000, - data: ethers.constants.HashZero, - memo: "", - } + const { l1Bridge, m } = await deployBridgeFixture() const expectedAmount = m.depositValue + m.callValue + m.processingFee @@ -1269,38 +999,10 @@ describe("integration:Bridge", function () { ) ) - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(block.hash) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - // get storageValue for the key const storageValue = await ethers.provider.getStorageAt( l1Bridge.address, @@ -1312,57 +1014,22 @@ describe("integration:Bridge", function () { "0x0000000000000000000000000000000000000000000000000000000000000001" ) - // rpc call to get the merkle proof what value is at key on the bridge contract - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.hash, + blockHeader ) - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] - ) await expect( l2Bridge.isMessageReceived(signal, srcChainId, signalProof) ).to.be.revertedWith("Invalid large internal hash") }) it("should return true", async function () { - const { - owner, - l1Bridge, - srcChainId, - enabledDestChainId, - l2Bridge, - headerSync, - } = await deployBridgeFixture() - - const m: Message = { - id: 1, - sender: owner.address, - srcChainId: srcChainId, - destChainId: enabledDestChainId, - owner: owner.address, - to: owner.address, - refundAddress: owner.address, - depositValue: 1000, - callValue: 1000, - processingFee: 1000, - gasLimit: 10000, - data: ethers.constants.HashZero, - memo: "", - } + const { l1Bridge, srcChainId, l2Bridge, headerSync, m } = + await deployBridgeFixture() const expectedAmount = m.depositValue + m.callValue + m.processingFee @@ -1385,40 +1052,10 @@ describe("integration:Bridge", function () { ) ) - // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot - // in the response - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(block.hash) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - // get storageValue for the key const storageValue = await ethers.provider.getStorageAt( l1Bridge.address, @@ -1430,26 +1067,12 @@ describe("integration:Bridge", function () { "0x0000000000000000000000000000000000000000000000000000000000000001" ) - // rpc call to get the merkle proof what value is at key on the bridge contract - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] - ) - - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.hash, + blockHeader ) expect( @@ -1515,38 +1138,10 @@ describe("integration:Bridge", function () { ) ) - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(block.hash) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - // get storageValue for the key const storageValue = await ethers.provider.getStorageAt( l1Bridge.address, @@ -1558,26 +1153,12 @@ describe("integration:Bridge", function () { "0x0000000000000000000000000000000000000000000000000000000000000001" ) - // rpc call to get the merkle proof what value is at key on the bridge contract - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] - ) - - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.hash, + blockHeader ) await expect( @@ -1609,38 +1190,10 @@ describe("integration:Bridge", function () { ) ) - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(block.hash) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - // get storageValue for the key const storageValue = await ethers.provider.getStorageAt( l1Bridge.address, @@ -1652,26 +1205,12 @@ describe("integration:Bridge", function () { "0x0000000000000000000000000000000000000000000000000000000000000001" ) - // rpc call to get the merkle proof what value is at key on the bridge contract - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] - ) - - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.hash, + blockHeader ) // proving functionality; l2Bridge can check if l1Bridge receives a signal // allowing for dapp cross layer communication From 9d13030b328ad9f09d505df922de2020cffecaed Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Wed, 7 Dec 2022 09:48:39 -0500 Subject: [PATCH 16/17] switching eth_getProof parameter to block.number from block.hash --- packages/protocol/tasks/utils.ts | 2 +- packages/protocol/test/bridge/Bridge.test.ts | 77 ++++---------------- 2 files changed, 16 insertions(+), 63 deletions(-) diff --git a/packages/protocol/tasks/utils.ts b/packages/protocol/tasks/utils.ts index 57d5577ddd..290af45dbe 100644 --- a/packages/protocol/tasks/utils.ts +++ b/packages/protocol/tasks/utils.ts @@ -120,7 +120,7 @@ async function getSignalProof( hre: any, contractAddress: string, key: string, - blockHash: string, + blockHash: number, blockHeader: BlockHeader ) { const proof: EthGetProofResponse = await hre.ethers.provider.send( diff --git a/packages/protocol/test/bridge/Bridge.test.ts b/packages/protocol/test/bridge/Bridge.test.ts index 5249313b3c..77a4dc4769 100644 --- a/packages/protocol/test/bridge/Bridge.test.ts +++ b/packages/protocol/test/bridge/Bridge.test.ts @@ -11,9 +11,7 @@ import { TestHeaderSync, TestLibBridgeData, } from "../../typechain" -import { Block, BlockHeader, EthGetProofResponse } from "../utils/rpc" import { getLatestBlockHeader, getSignalProof } from "../../tasks/utils" -import RLP from "rlp" async function deployBridge( signer: Signer, @@ -617,7 +615,7 @@ describe("integration:Bridge", function () { hre, l1Bridge.address, key, - block.hash, + block.number, blockHeader ) @@ -656,7 +654,7 @@ describe("integration:Bridge", function () { hre, l1Bridge.address, key, - block.hash, + block.number, blockHeader ) @@ -715,7 +713,7 @@ describe("integration:Bridge", function () { hre, l1Bridge.address, key, - block.hash, + block.number, blockHeader ) @@ -774,7 +772,7 @@ describe("integration:Bridge", function () { hre, l1Bridge.address, key, - block.hash, + block.number, blockHeader ) @@ -887,61 +885,16 @@ describe("integration:Bridge", function () { ) ) - // use this instead of ethers.provider.getBlock() beccause it doesnt have stateRoot - // in the response - const block: Block = await ethers.provider.send( - "eth_getBlockByNumber", - ["latest", false] - ) + const { block, blockHeader } = await getLatestBlockHeader(hre) await headerSync.setSyncedHeader(block.hash) - const logsBloom = block.logsBloom.toString().substring(2) - - const blockHeader: BlockHeader = { - parentHash: block.parentHash, - ommersHash: block.sha3Uncles, - beneficiary: block.miner, - stateRoot: block.stateRoot, - transactionsRoot: block.transactionsRoot, - receiptsRoot: block.receiptsRoot, - logsBloom: logsBloom - .match(/.{1,64}/g)! - .map((s: string) => "0x" + s), - difficulty: block.difficulty, - height: block.number, - gasLimit: block.gasLimit, - gasUsed: block.gasUsed, - timestamp: block.timestamp, - extraData: block.extraData, - mixHash: block.mixHash, - nonce: block.nonce, - baseFeePerGas: block.baseFeePerGas - ? parseInt(block.baseFeePerGas) - : 0, - } - - // rpc call to get the merkle proof what value is at key on the bridge contract - const proof: EthGetProofResponse = await ethers.provider.send( - "eth_getProof", - [l1Bridge.address, [key], block.hash] - ) - - // RLP encode the proof together for LibTrieProof to decode - const encodedProof = ethers.utils.defaultAbiCoder.encode( - ["bytes", "bytes"], - [ - RLP.encode(proof.accountProof), - RLP.encode(proof.storageProof[0].proof), - ] - ) - - // encode the SignalProof struct from LibBridgeSignal - const signalProof = ethers.utils.defaultAbiCoder.encode( - [ - "tuple(tuple(bytes32 parentHash, bytes32 ommersHash, address beneficiary, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, bytes32[8] logsBloom, uint256 difficulty, uint128 height, uint64 gasLimit, uint64 gasUsed, uint64 timestamp, bytes extraData, bytes32 mixHash, uint64 nonce, uint256 baseFeePerGas) header, bytes proof)", - ], - [{ header: blockHeader, proof: encodedProof }] + const signalProof = await getSignalProof( + hre, + l1Bridge.address, + key, + block.number, + blockHeader ) await l2Bridge @@ -1018,7 +971,7 @@ describe("integration:Bridge", function () { hre, l1Bridge.address, key, - block.hash, + block.number, blockHeader ) @@ -1071,7 +1024,7 @@ describe("integration:Bridge", function () { hre, l1Bridge.address, key, - block.hash, + block.number, blockHeader ) @@ -1157,7 +1110,7 @@ describe("integration:Bridge", function () { hre, l1Bridge.address, key, - block.hash, + block.number, blockHeader ) @@ -1209,7 +1162,7 @@ describe("integration:Bridge", function () { hre, l1Bridge.address, key, - block.hash, + block.number, blockHeader ) // proving functionality; l2Bridge can check if l1Bridge receives a signal From 371aee38252150f71acea68d88a4cf19d27ce8d7 Mon Sep 17 00:00:00 2001 From: RogerLamTd Date: Wed, 7 Dec 2022 10:02:10 -0500 Subject: [PATCH 17/17] rename var --- packages/protocol/tasks/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/protocol/tasks/utils.ts b/packages/protocol/tasks/utils.ts index 290af45dbe..3820c49a29 100644 --- a/packages/protocol/tasks/utils.ts +++ b/packages/protocol/tasks/utils.ts @@ -120,12 +120,12 @@ async function getSignalProof( hre: any, contractAddress: string, key: string, - blockHash: number, + blockNumber: number, blockHeader: BlockHeader ) { const proof: EthGetProofResponse = await hre.ethers.provider.send( "eth_getProof", - [contractAddress, [key], blockHash] + [contractAddress, [key], blockNumber] ) // RLP encode the proof together for LibTrieProof to decode