Skip to content

Commit

Permalink
fix: process from root linea (#5084)
Browse files Browse the repository at this point in the history
* feat: claimMessage interface

* chore: rebuild

* feat: linea process from root

* test: linea process from root unit tests

* feat: deploy testnet linea hub connector

* feat: hub subgraph for linea hub connector

* chore: rename
  • Loading branch information
liu-zhipeng authored Oct 30, 2023
1 parent ecee8c2 commit f10e3a8
Show file tree
Hide file tree
Showing 19 changed files with 931 additions and 69 deletions.
2 changes: 1 addition & 1 deletion ops/testnet/prod/core/config.tf
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ locals {
}
hubDomain = "1735353714"
proverBatchSize = {
# "1668247156" = 10,
"1668247156" = 10,
"9991" = 10,
"1735353714" = 10,
# "2053862260" = 10,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { DEFAULT_LOAD_SIZE, DEFAULT_SAFE_CONFIRMATIONS } from ".";

const markableDomainsForRootMessage = [
"6450786", // BNB
"1668247156", // Linea Goerli
];

export const retrieveOriginMessages = async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export { getProcessFromPolygonRootArgs } from "./polygon";
export { getProcessFromGnosisRootArgs } from "./gnosis";
export { getProcessFromArbitrumRootArgs } from "./arbitrum";
export { getProcessFromZkSyncRootArgs } from "./zksync";
export { getProcessFromLineaRootArgs } from "./linea";

export type GetProcessArgsParams = {
spokeChainId: number;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { createLoggingContext } from "@connext/nxtp-utils";
import { BigNumber } from "ethers";

import { LineaSDK } from "../../../mockable";
import { AlreadyProcessed, NoRootAvailable } from "../errors";
import { getContext } from "../processFromRoot";

import { GetProcessArgsParams } from ".";

export const getProcessFromLineaRootArgs = async ({
spokeChainId,
hubChainId,
hubProvider,
spokeProvider,
message: _message,
sendHash,
_requestContext,
}: GetProcessArgsParams): Promise<[BigNumber, string]> => {
const { logger } = getContext();
const { requestContext, methodContext } = createLoggingContext(getProcessFromLineaRootArgs.name, _requestContext);
logger.info("Method start", requestContext, methodContext);

const sdk = new LineaSDK({
l1RpcUrl: hubProvider, // L1 rpc url
l2RpcUrl: spokeProvider, // L2 rpc url
network: hubChainId === 1 ? "linea-mainnet" : "linea-goerli", // network you want to interact with (either linea-mainnet or linea-goerli)
mode: "read-only", // contract wrapper class mode (read-only or read-write), read-only: only read contracts state, read-write: read contracts state and claim messages
});

// get Message Status
const messages = await sdk.getL2Contract().getMessagesByTransactionHash(sendHash);

if (!messages?.length) {
throw new NoRootAvailable(spokeChainId, hubChainId, requestContext, methodContext, {
error: `${sendHash} has no message sent`,
});
}

// returns on-chain message status by message hash
const messageStatus = await sdk.getL1Contract().getMessageStatus(messages[0].messageHash);
logger.info("Got Message status on hub chain from linea", requestContext, methodContext, {
sendHash,
message: messages[0],
messageStatus,
});

if (messageStatus === "CLAIMED") {
throw new AlreadyProcessed(spokeChainId, hubChainId, requestContext, methodContext, {
sendHash,
messageStatus,
});
} else if (messageStatus === "CLAIMABLE") {
return [messages[0].messageNonce, messages[0].calldata];
} else {
throw new NoRootAvailable(spokeChainId, hubChainId, requestContext, methodContext, {
error: `Linea Unknown message status`,
});
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
getProcessFromGnosisRootArgs,
getProcessFromArbitrumRootArgs,
getProcessFromZkSyncRootArgs,
getProcessFromLineaRootArgs,
} from "../helpers";
import { getContext } from "../processFromRoot";

Expand Down Expand Up @@ -70,6 +71,16 @@ export const processorConfigs: Record<string, ProcessConfig> = {
hubConnectorPrefix: "ZkSync",
processorFunctionName: "processMessageFromRoot",
},
"1818848877": {
getArgs: getProcessFromLineaRootArgs,
hubConnectorPrefix: "Linea",
processorFunctionName: "claimMessage",
},
"1668247156": {
getArgs: getProcessFromLineaRootArgs,
hubConnectorPrefix: "Linea",
processorFunctionName: "claimMessage",
},
};

export const processFromRoot = async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { createRequestContext, expect, mkAddress, mkHash } from "@connext/nxtp-utils";
import { stub, SinonStub } from "sinon";
import { BigNumber } from "ethers";

import * as MockableFns from "../../../../src/mockable";
import { getProcessFromLineaRootArgs } from "../../../../src/tasks/processFromRoot/helpers";
import { AlreadyProcessed, NoRootAvailable } from "../../../../src/tasks/processFromRoot/errors";

let getL1Contract: SinonStub;
let getL2Contract: SinonStub;

class MockLineaSDK {
public getL1Contract = getL1Contract;
public getL2Contract = getL2Contract;
}

describe("Helpers: Linea", () => {
beforeEach(() => {
stub(MockableFns, "LineaSDK").value(MockLineaSDK);
});

it("should throw error if no messages", async () => {
getL2Contract = stub().returns({
getMessagesByTransactionHash: stub().resolves([]),
} as any);
await expect(
getProcessFromLineaRootArgs({
spokeChainId: 1,
spokeDomainId: "1",
spokeProvider: "world",
hubChainId: 2,
hubDomainId: "2",
hubProvider: "hello",
sendHash: mkHash("0xbaa"),
blockNumber: 123,
message: mkHash("0xbbbb"),
_requestContext: createRequestContext("foo"),
}),
).to.be.rejectedWith(NoRootAvailable);
});

it("should throw error if already processed", async () => {
getL2Contract = stub().returns({
getMessagesByTransactionHash: stub().resolves([
{
messageSender: mkAddress("a"),
destination: mkAddress("b"),
fee: BigNumber.from(0),
value: BigNumber.from(0),
messageNonce: BigNumber.from(1),
calldata: "0x",
messageHash: mkHash("0xa"),
},
]),
} as any);
getL1Contract = stub().returns({
getMessageStatus: stub().resolves("CLAIMED"),
});
await expect(
getProcessFromLineaRootArgs({
spokeChainId: 1,
spokeDomainId: "1",
spokeProvider: "world",
hubChainId: 2,
hubDomainId: "2",
hubProvider: "hello",
sendHash: mkHash("0xbaa"),
blockNumber: 123,
message: mkHash("0xbbbb"),
_requestContext: createRequestContext("foo"),
}),
).to.be.rejectedWith(AlreadyProcessed);
});

it("should throw error if unknown status", async () => {
getL2Contract = stub().returns({
getMessagesByTransactionHash: stub().resolves([
{
messageSender: mkAddress("a"),
destination: mkAddress("b"),
fee: BigNumber.from(0),
value: BigNumber.from(0),
messageNonce: BigNumber.from(1),
calldata: "0x",
messageHash: mkHash("0xa"),
},
]),
} as any);
getL1Contract = stub().returns({
getMessageStatus: stub().resolves("UNKNOWN"),
});
await expect(
getProcessFromLineaRootArgs({
spokeChainId: 1,
spokeDomainId: "1",
spokeProvider: "world",
hubChainId: 2,
hubDomainId: "2",
hubProvider: "hello",
sendHash: mkHash("0xbaa"),
blockNumber: 123,
message: mkHash("0xbbbb"),
_requestContext: createRequestContext("foo"),
}),
).to.be.rejectedWith(NoRootAvailable);
});

it("should work", async () => {
getL2Contract = stub().returns({
getMessagesByTransactionHash: stub().resolves([
{
messageSender: mkAddress("a"),
destination: mkAddress("b"),
fee: BigNumber.from(0),
value: BigNumber.from(0),
messageNonce: BigNumber.from(1),
calldata: mkHash("0xa"),
messageHash: mkHash("0xb"),
},
]),
} as any);
getL1Contract = stub().returns({
getMessageStatus: stub().resolves("CLAIMABLE"),
});
const args = await getProcessFromLineaRootArgs({
spokeChainId: 1,
spokeDomainId: "1",
spokeProvider: "world",
hubChainId: 2,
hubDomainId: "2",
hubProvider: "hello",
sendHash: mkHash("0xbaa"),
blockNumber: 123,
message: mkHash("0xbbbb"),
_requestContext: createRequestContext("foo"),
});

expect(args).to.deep.eq([BigNumber.from(1), mkHash("0xa")]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"function MIRROR_DOMAIN() view returns (uint32)",
"function ROOT_MANAGER() view returns (address)",
"function acceptProposedOwner()",
"function claimMessage(bytes _calldata, uint256 _nonce)",
"function delay() view returns (uint256)",
"function mirrorConnector() view returns (address)",
"function owner() view returns (address)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ contract LineaHubConnector is HubConnector, LineaBase {
return _verifySender(AMB, _expected);
}

/**
* @notice Deliver a message to the destination chain.
* @param _calldata The calldata used by the destination message service to call/forward to the destination contract.
* @param _nonce Unique message number.
*/
function claimMessage(bytes calldata _calldata, uint256 _nonce) external {
// * @param _from = mirror connector address. The msg.sender calling the origin message service.
// * @param _to = hub connector address. The destination address on the destination chain.
// * @param _value = 0. The value to be transferred to the destination address.
// * @param _fee = 0. The message service fee on the origin chain.
// * @param _feeRecipient = address(0). Address that will receive the fees.
LineaAmb(AMB).claimMessage(mirrorConnector, address(this), 0, 0, payable(address(0)), _calldata, _nonce);
}

/**
* @dev Messaging uses this function to send data to l2 via amb
*/
Expand Down
50 changes: 25 additions & 25 deletions packages/deployments/contracts/deployConfig/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,31 +288,31 @@ export const MESSAGING_PROTOCOL_CONFIGS: Record<string, MessagingProtocolConfig>
reserveGas: DEFAULT_RESERVE_GAS,
delayBlocks: DEFAULT_DELAY_BLOCKS,
},
97: {
prefix: "Multichain",
networkName: "Chapel",
ambs: {
// AnyCallV6Proxy on goerli
// https://goerli.etherscan.io/address/0x3D4e1981f822e87A1A4C05F2e4b3bcAdE5406AE3
hub: "0x3D4e1981f822e87A1A4C05F2e4b3bcAdE5406AE3",
// AnyCallV6Proxy on chapel/bsc testnet
// https://testnet.bscscan.com/address/0xD2b88BA56891d43fB7c108F23FE6f92FEbD32045
spoke: "0xD2b88BA56891d43fB7c108F23FE6f92FEbD32045",
},
processGas: DEFAULT_PROCESS_GAS,
reserveGas: DEFAULT_RESERVE_GAS,
delayBlocks: DEFAULT_DELAY_BLOCKS,
custom: {
hub: {
mirrorChainId: "97",
gasCap: "20000000000000000", // calcSrcFee: 10000320000000000
},
spoke: {
mirrorChainId: "5",
gasCap: "20000000000000000", // calcSrcFee: 10000320000000000
},
},
},
// 97: {
// prefix: "Multichain",
// networkName: "Chapel",
// ambs: {
// // AnyCallV6Proxy on goerli
// // https://goerli.etherscan.io/address/0x3D4e1981f822e87A1A4C05F2e4b3bcAdE5406AE3
// hub: "0x3D4e1981f822e87A1A4C05F2e4b3bcAdE5406AE3",
// // AnyCallV6Proxy on chapel/bsc testnet
// // https://testnet.bscscan.com/address/0xD2b88BA56891d43fB7c108F23FE6f92FEbD32045
// spoke: "0xD2b88BA56891d43fB7c108F23FE6f92FEbD32045",
// },
// processGas: DEFAULT_PROCESS_GAS,
// reserveGas: DEFAULT_RESERVE_GAS,
// delayBlocks: DEFAULT_DELAY_BLOCKS,
// custom: {
// hub: {
// mirrorChainId: "97",
// gasCap: "20000000000000000", // calcSrcFee: 10000320000000000
// },
// spoke: {
// mirrorChainId: "5",
// gasCap: "20000000000000000", // calcSrcFee: 10000320000000000
// },
// },
// },
1442: {
prefix: "PolygonZk",
ambs: {
Expand Down
22 changes: 20 additions & 2 deletions packages/deployments/contracts/deployments.json
Original file line number Diff line number Diff line change
Expand Up @@ -59803,7 +59803,7 @@
"blockNumber": 7769643
},
"LineaHubConnector": {
"address": "0xe154f99dcef23005B58A445A8E7c654B399B5D4b",
"address": "0x677d171172b395B2526ebb7Eb5Aa1a230b975ac0",
"abi": [
{
"inputs": [
Expand Down Expand Up @@ -60067,6 +60067,24 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "_calldata",
"type": "bytes"
},
{
"internalType": "uint256",
"name": "_nonce",
"type": "uint256"
}
],
"name": "claimMessage",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "delay",
Expand Down Expand Up @@ -60233,7 +60251,7 @@
"type": "receive"
}
],
"blockNumber": 9177569
"blockNumber": 9957169
},
"LineaHubConnectorStaging": {
"address": "0x8b524d816113D79838A5Ea3cEAa5e51Be79014c5",
Expand Down
Loading

0 comments on commit f10e3a8

Please sign in to comment.