@across-protocol/contracts 3.0.17 → 3.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/scripts/svm/addressToPublicKey.d.ts +1 -0
- package/dist/scripts/svm/addressToPublicKey.js +20 -0
- package/dist/scripts/svm/bridgeLiabilityToHubPool.d.ts +28 -0
- package/dist/scripts/svm/bridgeLiabilityToHubPool.js +231 -0
- package/dist/scripts/svm/closeRelayerPdas.js +6 -7
- package/dist/scripts/svm/enableRoute.js +7 -1
- package/dist/scripts/svm/executeRebalanceToHubPool.d.ts +32 -0
- package/dist/scripts/svm/executeRebalanceToHubPool.js +355 -0
- package/dist/scripts/svm/executeRebalanceToSpokePool.d.ts +1 -0
- package/dist/scripts/svm/executeRebalanceToSpokePool.js +253 -0
- package/dist/scripts/svm/proposeRebalanceToHubPool.d.ts +27 -0
- package/dist/scripts/svm/proposeRebalanceToHubPool.js +117 -0
- package/dist/scripts/svm/proposeRebalanceToSpokePool.d.ts +1 -0
- package/dist/scripts/svm/proposeRebalanceToSpokePool.js +101 -0
- package/dist/scripts/svm/publicKeyToAddress.d.ts +1 -0
- package/dist/scripts/svm/publicKeyToAddress.js +20 -0
- package/dist/scripts/svm/queryDeposits.js +1 -0
- package/dist/scripts/svm/queryFills.js +11 -12
- package/dist/scripts/svm/queryRoute.js +7 -1
- package/dist/scripts/svm/queryState.js +1 -0
- package/dist/scripts/svm/remoteHubPoolPauseDeposits.d.ts +1 -0
- package/dist/scripts/svm/remoteHubPoolPauseDeposits.js +205 -0
- package/dist/scripts/svm/simpleDeposit.js +7 -1
- package/dist/scripts/svm/simpleFill.js +5 -4
- package/dist/scripts/svm/utils/constants.d.ts +4 -0
- package/dist/scripts/svm/utils/constants.js +8 -1
- package/dist/scripts/svm/utils/helpers.d.ts +31 -0
- package/dist/scripts/svm/utils/helpers.js +50 -1
- package/dist/scripts/svm/utils/poolRebalanceTree.d.ts +22 -0
- package/dist/scripts/svm/utils/poolRebalanceTree.js +20 -0
- package/dist/src/SvmUtils.d.ts +24 -2
- package/dist/src/SvmUtils.js +107 -26
- package/dist/target/types/svm_spoke.d.ts +47 -42
- package/dist/tasks/enableL1TokenAcrossEcosystem.js +3 -33
- package/dist/tasks/types.d.ts +2 -0
- package/dist/tasks/types.js +2 -0
- package/dist/tasks/utils.d.ts +12 -0
- package/dist/tasks/utils.js +34 -0
- package/dist/test/svm/SvmSpoke.Bundle.js +15 -16
- package/dist/test/svm/SvmSpoke.Deposit.js +18 -26
- package/dist/test/svm/SvmSpoke.Fill.AcrossPlus.js +1 -1
- package/dist/test/svm/SvmSpoke.Fill.js +13 -14
- package/dist/test/svm/SvmSpoke.Ownership.js +10 -16
- package/dist/test/svm/SvmSpoke.RefundClaims.js +9 -8
- package/dist/test/svm/SvmSpoke.Routes.js +10 -6
- package/dist/test/svm/SvmSpoke.SlowFill.AcrossPlus.js +59 -2
- package/dist/test/svm/SvmSpoke.SlowFill.js +23 -18
- package/dist/test/svm/SvmSpoke.TokenBridge.js +3 -5
- package/dist/test/svm/SvmSpoke.common.js +2 -1
- package/dist/test/svm/utils.d.ts +4 -5
- package/dist/test/svm/utils.js +24 -18
- package/package.json +2 -2
|
@@ -1,2 +1,33 @@
|
|
|
1
|
+
import { RelayerRefundLeafSolana, RelayerRefundLeafType } from "../../../test/svm/utils";
|
|
2
|
+
import { BigNumber } from "ethers";
|
|
3
|
+
import { PublicKey } from "@solana/web3.js";
|
|
4
|
+
import { MerkleTree } from "@uma/common";
|
|
5
|
+
export declare const requireEnv: (name: string) => string;
|
|
6
|
+
export declare const getSolanaChainId: (cluster: "devnet" | "mainnet") => BigNumber;
|
|
7
|
+
export declare const formatUsdc: (amount: BigNumber) => string;
|
|
1
8
|
export declare const fromBase58ToBytes32: (input: string) => string;
|
|
2
9
|
export declare const fromBytes32ToAddress: (input: string) => string;
|
|
10
|
+
export declare function constructEmptyPoolRebalanceTree(chainId: BigNumber, groupIndex: number): {
|
|
11
|
+
poolRebalanceLeaf: {
|
|
12
|
+
chainId: BigNumber;
|
|
13
|
+
groupIndex: BigNumber;
|
|
14
|
+
bundleLpFees: never[];
|
|
15
|
+
netSendAmounts: never[];
|
|
16
|
+
runningBalances: never[];
|
|
17
|
+
leafId: BigNumber;
|
|
18
|
+
l1Tokens: never[];
|
|
19
|
+
};
|
|
20
|
+
poolRebalanceTree: MerkleTree<{
|
|
21
|
+
chainId: BigNumber;
|
|
22
|
+
groupIndex: BigNumber;
|
|
23
|
+
bundleLpFees: never[];
|
|
24
|
+
netSendAmounts: never[];
|
|
25
|
+
runningBalances: never[];
|
|
26
|
+
leafId: BigNumber;
|
|
27
|
+
l1Tokens: never[];
|
|
28
|
+
}>;
|
|
29
|
+
};
|
|
30
|
+
export declare const constructSimpleRebalanceTreeToHubPool: (netSendAmount: BigNumber, solanaChainId: BigNumber, svmUsdc: PublicKey) => {
|
|
31
|
+
merkleTree: MerkleTree<RelayerRefundLeafType>;
|
|
32
|
+
leaves: RelayerRefundLeafSolana[];
|
|
33
|
+
};
|
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fromBytes32ToAddress = exports.fromBase58ToBytes32 = void 0;
|
|
3
|
+
exports.constructSimpleRebalanceTreeToHubPool = exports.fromBytes32ToAddress = exports.fromBase58ToBytes32 = exports.formatUsdc = exports.getSolanaChainId = exports.requireEnv = void 0;
|
|
4
|
+
exports.constructEmptyPoolRebalanceTree = constructEmptyPoolRebalanceTree;
|
|
4
5
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
6
|
+
const utils_1 = require("../../../test/svm/utils");
|
|
7
|
+
const ethers_1 = require("ethers");
|
|
8
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
9
|
+
const common_1 = require("@uma/common");
|
|
10
|
+
const requireEnv = (name) => {
|
|
11
|
+
if (!process.env[name])
|
|
12
|
+
throw new Error(`Environment variable ${name} is not set`);
|
|
13
|
+
return process.env[name];
|
|
14
|
+
};
|
|
15
|
+
exports.requireEnv = requireEnv;
|
|
16
|
+
const getSolanaChainId = (cluster) => {
|
|
17
|
+
return ethers_1.BigNumber.from(BigInt(ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.toUtf8Bytes(`solana-${cluster}`))) & BigInt("0xFFFFFFFFFFFFFFFF"));
|
|
18
|
+
};
|
|
19
|
+
exports.getSolanaChainId = getSolanaChainId;
|
|
20
|
+
const formatUsdc = (amount) => {
|
|
21
|
+
return ethers_1.ethers.utils.formatUnits(amount, 6);
|
|
22
|
+
};
|
|
23
|
+
exports.formatUsdc = formatUsdc;
|
|
5
24
|
const fromBase58ToBytes32 = (input) => {
|
|
6
25
|
const decodedBytes = anchor_1.utils.bytes.bs58.decode(input);
|
|
7
26
|
return "0x" + Buffer.from(decodedBytes).toString("hex");
|
|
@@ -19,3 +38,33 @@ const fromBytes32ToAddress = (input) => {
|
|
|
19
38
|
return "0x" + address;
|
|
20
39
|
};
|
|
21
40
|
exports.fromBytes32ToAddress = fromBytes32ToAddress;
|
|
41
|
+
function constructEmptyPoolRebalanceTree(chainId, groupIndex) {
|
|
42
|
+
const poolRebalanceLeaf = {
|
|
43
|
+
chainId,
|
|
44
|
+
groupIndex: ethers_1.BigNumber.from(groupIndex),
|
|
45
|
+
bundleLpFees: [],
|
|
46
|
+
netSendAmounts: [],
|
|
47
|
+
runningBalances: [],
|
|
48
|
+
leafId: ethers_1.BigNumber.from(0),
|
|
49
|
+
l1Tokens: [],
|
|
50
|
+
};
|
|
51
|
+
const rebalanceParamType = "tuple( uint256 chainId, uint256[] bundleLpFees, int256[] netSendAmounts, int256[] runningBalances, uint256 groupIndex, uint8 leafId, address[] l1Tokens )";
|
|
52
|
+
const rebalanceHashFn = (input) => ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.defaultAbiCoder.encode([rebalanceParamType], [input]));
|
|
53
|
+
const poolRebalanceTree = new common_1.MerkleTree([poolRebalanceLeaf], rebalanceHashFn);
|
|
54
|
+
return { poolRebalanceLeaf, poolRebalanceTree };
|
|
55
|
+
}
|
|
56
|
+
const constructSimpleRebalanceTreeToHubPool = (netSendAmount, solanaChainId, svmUsdc) => {
|
|
57
|
+
const relayerRefundLeaves = [];
|
|
58
|
+
relayerRefundLeaves.push({
|
|
59
|
+
isSolana: true,
|
|
60
|
+
leafId: new anchor_1.BN(0),
|
|
61
|
+
chainId: new anchor_1.BN(solanaChainId.toString()),
|
|
62
|
+
amountToReturn: new anchor_1.BN(netSendAmount.toString()),
|
|
63
|
+
mintPublicKey: new web3_js_1.PublicKey(svmUsdc),
|
|
64
|
+
refundAddresses: [],
|
|
65
|
+
refundAmounts: [],
|
|
66
|
+
});
|
|
67
|
+
const merkleTree = new common_1.MerkleTree(relayerRefundLeaves, utils_1.relayerRefundHashFn);
|
|
68
|
+
return { merkleTree, leaves: relayerRefundLeaves };
|
|
69
|
+
};
|
|
70
|
+
exports.constructSimpleRebalanceTreeToHubPool = constructSimpleRebalanceTreeToHubPool;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MerkleTree } from "@uma/common";
|
|
2
|
+
import { BigNumber } from "ethers";
|
|
3
|
+
export declare function constructSimpleRebalanceTree(l1TokenAddress: string, netSendAmount: BigNumber, chainId: BigNumber): {
|
|
4
|
+
poolRebalanceLeaf: {
|
|
5
|
+
chainId: BigNumber;
|
|
6
|
+
groupIndex: BigNumber;
|
|
7
|
+
bundleLpFees: BigNumber[];
|
|
8
|
+
netSendAmounts: BigNumber[];
|
|
9
|
+
runningBalances: BigNumber[];
|
|
10
|
+
leafId: BigNumber;
|
|
11
|
+
l1Tokens: string[];
|
|
12
|
+
};
|
|
13
|
+
poolRebalanceTree: MerkleTree<{
|
|
14
|
+
chainId: BigNumber;
|
|
15
|
+
groupIndex: BigNumber;
|
|
16
|
+
bundleLpFees: BigNumber[];
|
|
17
|
+
netSendAmounts: BigNumber[];
|
|
18
|
+
runningBalances: BigNumber[];
|
|
19
|
+
leafId: BigNumber;
|
|
20
|
+
l1Tokens: string[];
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.constructSimpleRebalanceTree = constructSimpleRebalanceTree;
|
|
4
|
+
const common_1 = require("@uma/common");
|
|
5
|
+
const ethers_1 = require("ethers");
|
|
6
|
+
function constructSimpleRebalanceTree(l1TokenAddress, netSendAmount, chainId) {
|
|
7
|
+
const poolRebalanceLeaf = {
|
|
8
|
+
chainId,
|
|
9
|
+
groupIndex: ethers_1.BigNumber.from(1), // Not 0 as this script is not relaying root bundles, only sending tokens to spoke.
|
|
10
|
+
bundleLpFees: [ethers_1.BigNumber.from(0)],
|
|
11
|
+
netSendAmounts: [netSendAmount],
|
|
12
|
+
runningBalances: [netSendAmount],
|
|
13
|
+
leafId: ethers_1.BigNumber.from(0),
|
|
14
|
+
l1Tokens: [l1TokenAddress],
|
|
15
|
+
};
|
|
16
|
+
const rebalanceParamType = "tuple( uint256 chainId, uint256[] bundleLpFees, int256[] netSendAmounts, int256[] runningBalances, uint256 groupIndex, uint8 leafId, address[] l1Tokens )";
|
|
17
|
+
const rebalanceHashFn = (input) => ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.defaultAbiCoder.encode([rebalanceParamType], [input]));
|
|
18
|
+
const poolRebalanceTree = new common_1.MerkleTree([poolRebalanceLeaf], rebalanceHashFn);
|
|
19
|
+
return { poolRebalanceLeaf, poolRebalanceTree };
|
|
20
|
+
}
|
package/dist/src/SvmUtils.d.ts
CHANGED
|
@@ -4,12 +4,32 @@ export declare function findProgramAddress(label: string, program: PublicKey, ex
|
|
|
4
4
|
publicKey: web3.PublicKey;
|
|
5
5
|
bump: number;
|
|
6
6
|
};
|
|
7
|
-
export declare function readEvents<IDL extends Idl = Idl>(connection: Connection, txSignature: string, programs: Program<IDL>[], commitment?: Finality): Promise<
|
|
7
|
+
export declare function readEvents<IDL extends Idl = Idl>(connection: Connection, txSignature: string, programs: Program<IDL>[], commitment?: Finality): Promise<{
|
|
8
|
+
program: web3.PublicKey;
|
|
9
|
+
data: any;
|
|
10
|
+
name: string | undefined;
|
|
11
|
+
}[]>;
|
|
12
|
+
export declare function readEventsUntilFound<IDL extends Idl = Idl>(connection: Connection, txSignature: string, programs: Program<IDL>[]): Promise<{
|
|
13
|
+
program: web3.PublicKey;
|
|
14
|
+
data: any;
|
|
15
|
+
name: string | undefined;
|
|
16
|
+
}[]>;
|
|
8
17
|
export declare function getEvent(events: any[], program: PublicKey, eventName: string): any;
|
|
9
|
-
export
|
|
18
|
+
export interface EventType {
|
|
19
|
+
program: PublicKey;
|
|
20
|
+
data: any;
|
|
21
|
+
name: string;
|
|
22
|
+
slot: number;
|
|
23
|
+
confirmationStatus: string;
|
|
24
|
+
blockTime: number;
|
|
25
|
+
signature: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function readProgramEvents(connection: Connection, program: Program<any>, finality?: Finality, options?: SignaturesForAddressOptions): Promise<EventType[]>;
|
|
10
28
|
export declare function subscribeToCpiEventsForProgram(connection: Connection, program: Program<any>, callback: (events: any[]) => void): Promise<number>;
|
|
11
29
|
export declare const evmAddressToPublicKey: (address: string) => PublicKey;
|
|
30
|
+
export declare const publicKeyToEvmAddress: (publicKey: PublicKey | string) => string;
|
|
12
31
|
export declare function calculateRelayHashUint8Array(relayData: any, chainId: BN): Uint8Array;
|
|
32
|
+
export declare function calculateRelayEventHashUint8Array(relayEventData: any, chainId: BN): Uint8Array;
|
|
13
33
|
export declare const readUInt256BE: (buffer: Buffer) => BigInt;
|
|
14
34
|
export declare class LargeAccountsCoder<A extends string = string> extends BorshAccountsCoder<A> {
|
|
15
35
|
private getAccountLayouts;
|
|
@@ -47,4 +67,6 @@ export declare function sendTransactionWithLookupTable(connection: Connection, i
|
|
|
47
67
|
txSignature: string;
|
|
48
68
|
lookupTableAddress: PublicKey;
|
|
49
69
|
}>;
|
|
70
|
+
export declare function hashNonEmptyMessage(message: Buffer): Uint8Array;
|
|
71
|
+
export declare function strPublicKey(publicKey: PublicKey): string;
|
|
50
72
|
export {};
|
package/dist/src/SvmUtils.js
CHANGED
|
@@ -26,14 +26,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.AcrossPlusMessageCoder = exports.MulticallHandlerCoder = exports.LargeAccountsCoder = exports.readUInt256BE = exports.evmAddressToPublicKey = void 0;
|
|
29
|
+
exports.AcrossPlusMessageCoder = exports.MulticallHandlerCoder = exports.LargeAccountsCoder = exports.readUInt256BE = exports.publicKeyToEvmAddress = exports.evmAddressToPublicKey = void 0;
|
|
30
30
|
exports.findProgramAddress = findProgramAddress;
|
|
31
31
|
exports.readEvents = readEvents;
|
|
32
|
+
exports.readEventsUntilFound = readEventsUntilFound;
|
|
32
33
|
exports.getEvent = getEvent;
|
|
33
34
|
exports.readProgramEvents = readProgramEvents;
|
|
34
35
|
exports.subscribeToCpiEventsForProgram = subscribeToCpiEventsForProgram;
|
|
35
36
|
exports.calculateRelayHashUint8Array = calculateRelayHashUint8Array;
|
|
37
|
+
exports.calculateRelayEventHashUint8Array = calculateRelayEventHashUint8Array;
|
|
36
38
|
exports.sendTransactionWithLookupTable = sendTransactionWithLookupTable;
|
|
39
|
+
exports.hashNonEmptyMessage = hashNonEmptyMessage;
|
|
40
|
+
exports.strPublicKey = strPublicKey;
|
|
37
41
|
//TODO: we will need to move this to a better location and integrate it more directly with other utils & files in time.
|
|
38
42
|
// eslint-disable-next-line node/no-extraneous-import
|
|
39
43
|
const borsh = __importStar(require("@coral-xyz/borsh"));
|
|
@@ -64,26 +68,30 @@ function findProgramAddress(label, program, extraSeeds) {
|
|
|
64
68
|
return { publicKey: res[0], bump: res[1] };
|
|
65
69
|
}
|
|
66
70
|
async function readEvents(connection, txSignature, programs, commitment = "confirmed") {
|
|
67
|
-
const txResult = await connection.getTransaction(txSignature, {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
const txResult = await connection.getTransaction(txSignature, { commitment, maxSupportedTransactionVersion: 0 });
|
|
72
|
+
if (txResult === null)
|
|
73
|
+
return [];
|
|
74
|
+
return processEventFromTx(txResult, programs);
|
|
75
|
+
}
|
|
76
|
+
function processEventFromTx(txResult, programs) {
|
|
77
|
+
const eventAuthorities = new Map();
|
|
72
78
|
for (const program of programs) {
|
|
73
|
-
eventAuthorities.set(program.programId.toString(), findProgramAddress("__event_authority", program.programId).publicKey
|
|
79
|
+
eventAuthorities.set(program.programId.toString(), findProgramAddress("__event_authority", program.programId).publicKey);
|
|
74
80
|
}
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
const events = [];
|
|
82
|
+
// Resolve any potential addresses that were passed from address lookup tables.
|
|
83
|
+
const messageAccountKeys = txResult.transaction.message.getAccountKeys({
|
|
84
|
+
accountKeysFromLookups: txResult.meta?.loadedAddresses,
|
|
85
|
+
});
|
|
79
86
|
for (const ixBlock of txResult.meta?.innerInstructions ?? []) {
|
|
80
87
|
for (const ix of ixBlock.instructions) {
|
|
81
88
|
for (const program of programs) {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
const ixProgramId = messageAccountKeys.get(ix.programIdIndex);
|
|
90
|
+
const singleIxAccount = ix.accounts.length === 1 ? messageAccountKeys.get(ix.accounts[0]) : undefined;
|
|
91
|
+
if (ixProgramId !== undefined &&
|
|
92
|
+
singleIxAccount !== undefined &&
|
|
93
|
+
program.programId.equals(ixProgramId) &&
|
|
94
|
+
eventAuthorities.get(ixProgramId.toString())?.equals(singleIxAccount)) {
|
|
87
95
|
const ixData = anchor_1.utils.bytes.bs58.decode(ix.data);
|
|
88
96
|
const eventData = anchor_1.utils.bytes.base64.encode(Buffer.from(new Uint8Array(ixData).slice(8)));
|
|
89
97
|
const event = program.coder.events.decode(eventData);
|
|
@@ -98,6 +106,22 @@ async function readEvents(connection, txSignature, programs, commitment = "confi
|
|
|
98
106
|
}
|
|
99
107
|
return events;
|
|
100
108
|
}
|
|
109
|
+
// Helper function to wait for an event to be emitted. Should only be used in tests where txSignature is known to emit.
|
|
110
|
+
async function readEventsUntilFound(connection, txSignature, programs) {
|
|
111
|
+
const startTime = Date.now();
|
|
112
|
+
let txResult = null;
|
|
113
|
+
while (Date.now() - startTime < 5000) {
|
|
114
|
+
// 5 seconds timeout to wait to find the event.
|
|
115
|
+
txResult = await connection.getTransaction(txSignature, {
|
|
116
|
+
commitment: "confirmed",
|
|
117
|
+
maxSupportedTransactionVersion: 0,
|
|
118
|
+
});
|
|
119
|
+
if (txResult !== null)
|
|
120
|
+
return processEventFromTx(txResult, programs);
|
|
121
|
+
await new Promise((resolve) => setTimeout(resolve, 50)); // 50 ms delay between retries.
|
|
122
|
+
}
|
|
123
|
+
throw new Error("No event found within 5 seconds");
|
|
124
|
+
}
|
|
101
125
|
function getEvent(events, program, eventName) {
|
|
102
126
|
for (const event of events) {
|
|
103
127
|
if (event.name === eventName && program.toString() === event.program.toString()) {
|
|
@@ -106,13 +130,32 @@ function getEvent(events, program, eventName) {
|
|
|
106
130
|
}
|
|
107
131
|
throw new Error("Event " + eventName + " not found");
|
|
108
132
|
}
|
|
109
|
-
async function readProgramEvents(connection, program,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
133
|
+
async function readProgramEvents(connection, program, finality = "confirmed", options = { limit: 1000 }) {
|
|
134
|
+
const allSignatures = [];
|
|
135
|
+
// Fetch all signatures in sequential batches
|
|
136
|
+
while (true) {
|
|
137
|
+
const signatures = await connection.getSignaturesForAddress(program.programId, options, finality);
|
|
138
|
+
allSignatures.push(...signatures);
|
|
139
|
+
// Update options for the next batch. Set before to the last fetched signature.
|
|
140
|
+
if (signatures.length > 0) {
|
|
141
|
+
options = { ...options, before: signatures[signatures.length - 1].signature };
|
|
142
|
+
}
|
|
143
|
+
if (options.limit && signatures.length < options.limit)
|
|
144
|
+
break; // Exit early if the number of signatures < limit
|
|
114
145
|
}
|
|
115
|
-
|
|
146
|
+
// Fetch events for all signatures in parallel
|
|
147
|
+
const eventsWithSlots = await Promise.all(allSignatures.map(async (signature) => {
|
|
148
|
+
const events = await readEvents(connection, signature.signature, [program], finality);
|
|
149
|
+
return events.map((event) => ({
|
|
150
|
+
...event,
|
|
151
|
+
confirmationStatus: signature.confirmationStatus || "Unknown",
|
|
152
|
+
blockTime: signature.blockTime || 0,
|
|
153
|
+
signature: signature.signature,
|
|
154
|
+
slot: signature.slot,
|
|
155
|
+
name: event.name || "Unknown",
|
|
156
|
+
}));
|
|
157
|
+
}));
|
|
158
|
+
return eventsWithSlots.flat(); // Flatten the array of events & return.
|
|
116
159
|
}
|
|
117
160
|
async function subscribeToCpiEventsForProgram(connection, program, callback) {
|
|
118
161
|
const subscriptionId = connection.onLogs(new web3_js_1.PublicKey(findProgramAddress("__event_authority", program.programId).publicKey.toString()), async (logs) => {
|
|
@@ -125,12 +168,19 @@ const evmAddressToPublicKey = (address) => {
|
|
|
125
168
|
return new web3_js_1.PublicKey(ethers_1.ethers.utils.arrayify(bytes32Address));
|
|
126
169
|
};
|
|
127
170
|
exports.evmAddressToPublicKey = evmAddressToPublicKey;
|
|
171
|
+
const publicKeyToEvmAddress = (publicKey) => {
|
|
172
|
+
// Convert the input to a PublicKey if it's a string
|
|
173
|
+
const pubKeyBuffer = typeof publicKey === "string" ? new web3_js_1.PublicKey(publicKey).toBuffer() : publicKey.toBuffer();
|
|
174
|
+
// Extract the last 20 bytes to get the Ethereum address
|
|
175
|
+
const addressBuffer = pubKeyBuffer.slice(-20);
|
|
176
|
+
// Convert the buffer to a hex string and prepend '0x'
|
|
177
|
+
return `0x${addressBuffer.toString("hex")}`;
|
|
178
|
+
};
|
|
179
|
+
exports.publicKeyToEvmAddress = publicKeyToEvmAddress;
|
|
128
180
|
// TODO: we are inconsistant with where we are placing some utils. we have some stuff here, some stuff that we might
|
|
129
181
|
// want to re-use within the test directory. more over, when moving things into the canonical across repo, we should
|
|
130
182
|
// re-use the test utils there.
|
|
131
183
|
function calculateRelayHashUint8Array(relayData, chainId) {
|
|
132
|
-
const messageBuffer = Buffer.alloc(4);
|
|
133
|
-
messageBuffer.writeUInt32LE(relayData.message.length, 0);
|
|
134
184
|
const contentToHash = Buffer.concat([
|
|
135
185
|
relayData.depositor.toBuffer(),
|
|
136
186
|
relayData.recipient.toBuffer(),
|
|
@@ -143,8 +193,28 @@ function calculateRelayHashUint8Array(relayData, chainId) {
|
|
|
143
193
|
Buffer.from(relayData.depositId),
|
|
144
194
|
new anchor_1.BN(relayData.fillDeadline).toArrayLike(Buffer, "le", 4),
|
|
145
195
|
new anchor_1.BN(relayData.exclusivityDeadline).toArrayLike(Buffer, "le", 4),
|
|
146
|
-
|
|
147
|
-
|
|
196
|
+
hashNonEmptyMessage(relayData.message), // Replace with hash of message, so that relay hash can be recovered from event.
|
|
197
|
+
chainId.toArrayLike(Buffer, "le", 8),
|
|
198
|
+
]);
|
|
199
|
+
const relayHash = ethers_1.ethers.utils.keccak256(contentToHash);
|
|
200
|
+
const relayHashBuffer = Buffer.from(relayHash.slice(2), "hex");
|
|
201
|
+
return new Uint8Array(relayHashBuffer);
|
|
202
|
+
}
|
|
203
|
+
// Same method as above, but message in the relayData is already hashed, as fetched from fill events.
|
|
204
|
+
function calculateRelayEventHashUint8Array(relayEventData, chainId) {
|
|
205
|
+
const contentToHash = Buffer.concat([
|
|
206
|
+
relayEventData.depositor.toBuffer(),
|
|
207
|
+
relayEventData.recipient.toBuffer(),
|
|
208
|
+
relayEventData.exclusiveRelayer.toBuffer(),
|
|
209
|
+
relayEventData.inputToken.toBuffer(),
|
|
210
|
+
relayEventData.outputToken.toBuffer(),
|
|
211
|
+
relayEventData.inputAmount.toArrayLike(Buffer, "le", 8),
|
|
212
|
+
relayEventData.outputAmount.toArrayLike(Buffer, "le", 8),
|
|
213
|
+
relayEventData.originChainId.toArrayLike(Buffer, "le", 8),
|
|
214
|
+
Buffer.from(relayEventData.depositId),
|
|
215
|
+
new anchor_1.BN(relayEventData.fillDeadline).toArrayLike(Buffer, "le", 4),
|
|
216
|
+
new anchor_1.BN(relayEventData.exclusivityDeadline).toArrayLike(Buffer, "le", 4),
|
|
217
|
+
Buffer.from(relayEventData.messageHash), // Renamed to messageHash in the event data.
|
|
148
218
|
chainId.toArrayLike(Buffer, "le", 8),
|
|
149
219
|
]);
|
|
150
220
|
const relayHash = ethers_1.ethers.utils.keccak256(contentToHash);
|
|
@@ -413,3 +483,14 @@ async function sendTransactionWithLookupTable(connection, instructions, sender)
|
|
|
413
483
|
const txSignature = await connection.sendTransaction(versionedTx);
|
|
414
484
|
return { txSignature, lookupTableAddress };
|
|
415
485
|
}
|
|
486
|
+
function hashNonEmptyMessage(message) {
|
|
487
|
+
if (message.length > 0) {
|
|
488
|
+
const hash = ethers_1.ethers.utils.keccak256(message);
|
|
489
|
+
return Uint8Array.from(Buffer.from(hash.slice(2), "hex"));
|
|
490
|
+
}
|
|
491
|
+
// else return zeroed bytes32
|
|
492
|
+
return new Uint8Array(32);
|
|
493
|
+
}
|
|
494
|
+
function strPublicKey(publicKey) {
|
|
495
|
+
return new web3_js_1.PublicKey(publicKey).toString();
|
|
496
|
+
}
|
|
@@ -808,11 +808,7 @@ export type SvmSpoke = {
|
|
|
808
808
|
"### Required Accounts:",
|
|
809
809
|
"- signer (Signer): The account that authorizes the closure. Must be the relayer in the fill_status PDA.",
|
|
810
810
|
"- state (Writable): Spoke state PDA. Seed: [\"state\",state.seed] where seed is 0 on mainnet.",
|
|
811
|
-
"- fill_status (Writable): The FillStatusAccount PDA to be closed.
|
|
812
|
-
"",
|
|
813
|
-
"### Parameters:",
|
|
814
|
-
"- _relay_hash: The hash identifying the relay for which the fill status account is being closed.",
|
|
815
|
-
"- relay_data: The data structure containing information about the relay."
|
|
811
|
+
"- fill_status (Writable): The FillStatusAccount PDA to be closed."
|
|
816
812
|
];
|
|
817
813
|
"discriminator": [
|
|
818
814
|
224,
|
|
@@ -855,45 +851,9 @@ export type SvmSpoke = {
|
|
|
855
851
|
{
|
|
856
852
|
"name": "fillStatus";
|
|
857
853
|
"writable": true;
|
|
858
|
-
"pda": {
|
|
859
|
-
"seeds": [
|
|
860
|
-
{
|
|
861
|
-
"kind": "const";
|
|
862
|
-
"value": [
|
|
863
|
-
102,
|
|
864
|
-
105,
|
|
865
|
-
108,
|
|
866
|
-
108,
|
|
867
|
-
115
|
|
868
|
-
];
|
|
869
|
-
},
|
|
870
|
-
{
|
|
871
|
-
"kind": "arg";
|
|
872
|
-
"path": "relayHash";
|
|
873
|
-
}
|
|
874
|
-
];
|
|
875
|
-
};
|
|
876
|
-
}
|
|
877
|
-
];
|
|
878
|
-
"args": [
|
|
879
|
-
{
|
|
880
|
-
"name": "relayHash";
|
|
881
|
-
"type": {
|
|
882
|
-
"array": [
|
|
883
|
-
"u8",
|
|
884
|
-
32
|
|
885
|
-
];
|
|
886
|
-
};
|
|
887
|
-
},
|
|
888
|
-
{
|
|
889
|
-
"name": "relayData";
|
|
890
|
-
"type": {
|
|
891
|
-
"defined": {
|
|
892
|
-
"name": "v3RelayData";
|
|
893
|
-
};
|
|
894
|
-
};
|
|
895
854
|
}
|
|
896
855
|
];
|
|
856
|
+
"args": [];
|
|
897
857
|
},
|
|
898
858
|
{
|
|
899
859
|
"name": "closeInstructionParams";
|
|
@@ -5041,6 +5001,19 @@ export type SvmSpoke = {
|
|
|
5041
5001
|
66
|
|
5042
5002
|
];
|
|
5043
5003
|
},
|
|
5004
|
+
{
|
|
5005
|
+
"name": "tokensBridged";
|
|
5006
|
+
"discriminator": [
|
|
5007
|
+
200,
|
|
5008
|
+
201,
|
|
5009
|
+
199,
|
|
5010
|
+
39,
|
|
5011
|
+
5,
|
|
5012
|
+
238,
|
|
5013
|
+
214,
|
|
5014
|
+
196
|
|
5015
|
+
];
|
|
5016
|
+
},
|
|
5044
5017
|
{
|
|
5045
5018
|
"name": "v3FundsDeposited";
|
|
5046
5019
|
"discriminator": [
|
|
@@ -5375,6 +5348,10 @@ export type SvmSpoke = {
|
|
|
5375
5348
|
{
|
|
5376
5349
|
"name": "relayer";
|
|
5377
5350
|
"type": "pubkey";
|
|
5351
|
+
},
|
|
5352
|
+
{
|
|
5353
|
+
"name": "fillDeadline";
|
|
5354
|
+
"type": "u32";
|
|
5378
5355
|
}
|
|
5379
5356
|
];
|
|
5380
5357
|
};
|
|
@@ -5808,6 +5785,34 @@ export type SvmSpoke = {
|
|
|
5808
5785
|
];
|
|
5809
5786
|
};
|
|
5810
5787
|
},
|
|
5788
|
+
{
|
|
5789
|
+
"name": "tokensBridged";
|
|
5790
|
+
"type": {
|
|
5791
|
+
"kind": "struct";
|
|
5792
|
+
"fields": [
|
|
5793
|
+
{
|
|
5794
|
+
"name": "amountToReturn";
|
|
5795
|
+
"type": "u64";
|
|
5796
|
+
},
|
|
5797
|
+
{
|
|
5798
|
+
"name": "chainId";
|
|
5799
|
+
"type": "u64";
|
|
5800
|
+
},
|
|
5801
|
+
{
|
|
5802
|
+
"name": "leafId";
|
|
5803
|
+
"type": "u32";
|
|
5804
|
+
},
|
|
5805
|
+
{
|
|
5806
|
+
"name": "l2TokenAddress";
|
|
5807
|
+
"type": "pubkey";
|
|
5808
|
+
},
|
|
5809
|
+
{
|
|
5810
|
+
"name": "caller";
|
|
5811
|
+
"type": "pubkey";
|
|
5812
|
+
}
|
|
5813
|
+
];
|
|
5814
|
+
};
|
|
5815
|
+
},
|
|
5811
5816
|
{
|
|
5812
5817
|
"name": "transferLiability";
|
|
5813
5818
|
"type": {
|
|
@@ -5,38 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const config_1 = require("hardhat/config");
|
|
7
7
|
const assert_1 = __importDefault(require("assert"));
|
|
8
|
-
const utils_1 = require("./utils");
|
|
9
8
|
const constants_1 = require("../utils/constants");
|
|
10
|
-
|
|
11
|
-
* Given a token symbol, determine whether it is a valid key for the TOKEN_SYMBOLS_MAP object.
|
|
12
|
-
*/
|
|
13
|
-
function isTokenSymbol(symbol) {
|
|
14
|
-
return constants_1.TOKEN_SYMBOLS_MAP[symbol] !== undefined;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Given a token symbol from the HubPool chain and a remote chain ID, resolve the relevant token symbol and address.
|
|
18
|
-
*/
|
|
19
|
-
function resolveTokenOnChain(mainnetSymbol, chainId) {
|
|
20
|
-
(0, assert_1.default)(isTokenSymbol(mainnetSymbol), `Unrecognised token symbol (${mainnetSymbol})`);
|
|
21
|
-
let symbol = mainnetSymbol;
|
|
22
|
-
// Handle USDC special case where L1 USDC is mapped to different token symbols on L2s.
|
|
23
|
-
if (mainnetSymbol === "USDC") {
|
|
24
|
-
const symbols = ["USDC", "USDC.e", "USDbC", "USDzC"];
|
|
25
|
-
const tokenSymbol = symbols.find((symbol) => constants_1.TOKEN_SYMBOLS_MAP[symbol]?.addresses[chainId]);
|
|
26
|
-
if (!isTokenSymbol(tokenSymbol)) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
symbol = tokenSymbol;
|
|
30
|
-
}
|
|
31
|
-
else if (symbol === "DAI" && chainId === constants_1.CHAIN_IDs.BLAST) {
|
|
32
|
-
symbol = "USDB";
|
|
33
|
-
}
|
|
34
|
-
const address = constants_1.TOKEN_SYMBOLS_MAP[symbol].addresses[chainId];
|
|
35
|
-
if (!address) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
return { symbol, address };
|
|
39
|
-
}
|
|
9
|
+
const utils_1 = require("./utils");
|
|
40
10
|
const { ARBITRUM, OPTIMISM } = constants_1.CHAIN_IDs;
|
|
41
11
|
const NO_SYMBOL = "----";
|
|
42
12
|
const NO_ADDRESS = "------------------------------------------";
|
|
@@ -65,7 +35,7 @@ const getChainsFromList = (taskArgInput) => taskArgInput
|
|
|
65
35
|
throw new Error(`Defaulted to network \`hardhat\`; specify \`--network mainnet\` or \`--network sepolia\``);
|
|
66
36
|
}
|
|
67
37
|
const _matchedSymbol = Object.keys(constants_1.TOKEN_SYMBOLS_MAP).find((_symbol) => _symbol === symbol);
|
|
68
|
-
(0, assert_1.default)(isTokenSymbol(_matchedSymbol));
|
|
38
|
+
(0, assert_1.default)((0, utils_1.isTokenSymbol)(_matchedSymbol));
|
|
69
39
|
const matchedSymbol = _matchedSymbol;
|
|
70
40
|
const l1Token = constants_1.TOKEN_SYMBOLS_MAP[matchedSymbol].addresses[hubChainId];
|
|
71
41
|
(0, assert_1.default)(l1Token !== undefined, `Could not find ${symbol} in TOKEN_SYMBOLS_MAP`);
|
|
@@ -98,7 +68,7 @@ const getChainsFromList = (taskArgInput) => taskArgInput
|
|
|
98
68
|
const chainIds = enabledChainIds.filter((chainId) => inputChains.includes(chainId));
|
|
99
69
|
console.log("\nLoading L2 companion token address for provided L1 token.");
|
|
100
70
|
const tokens = Object.fromEntries(chainIds.map((chainId) => {
|
|
101
|
-
const token = resolveTokenOnChain(matchedSymbol, chainId);
|
|
71
|
+
const token = (0, utils_1.resolveTokenOnChain)(matchedSymbol, chainId);
|
|
102
72
|
if (token === undefined) {
|
|
103
73
|
return [chainId, { symbol: NO_SYMBOL, address: NO_ADDRESS }];
|
|
104
74
|
}
|
package/dist/tasks/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TokenSymbol } from "./types";
|
|
1
2
|
export declare const zeroAddress = "0x0000000000000000000000000000000000000000";
|
|
2
3
|
export declare const minimalSpokePoolInterface: ({
|
|
3
4
|
inputs: ({
|
|
@@ -46,3 +47,14 @@ export declare const minimalAdapterInterface: {
|
|
|
46
47
|
type: string;
|
|
47
48
|
}[];
|
|
48
49
|
export declare function askYesNoQuestion(query: string): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* Given a token symbol from the HubPool chain and a remote chain ID, resolve the relevant token symbol and address.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveTokenOnChain(mainnetSymbol: string, chainId: number): {
|
|
54
|
+
symbol: TokenSymbol;
|
|
55
|
+
address: string;
|
|
56
|
+
} | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Given a token symbol, determine whether it is a valid key for the TOKEN_SYMBOLS_MAP object.
|
|
59
|
+
*/
|
|
60
|
+
export declare function isTokenSymbol(symbol: unknown): symbol is TokenSymbol;
|
package/dist/tasks/utils.js
CHANGED
|
@@ -5,8 +5,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.minimalAdapterInterface = exports.minimalSpokePoolInterface = exports.zeroAddress = void 0;
|
|
7
7
|
exports.askYesNoQuestion = askYesNoQuestion;
|
|
8
|
+
exports.resolveTokenOnChain = resolveTokenOnChain;
|
|
9
|
+
exports.isTokenSymbol = isTokenSymbol;
|
|
10
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
11
|
const ethers_1 = require("ethers");
|
|
9
12
|
const readline_1 = __importDefault(require("readline"));
|
|
13
|
+
const constants_1 = require("../utils/constants");
|
|
10
14
|
exports.zeroAddress = ethers_1.ethers.constants.AddressZero;
|
|
11
15
|
exports.minimalSpokePoolInterface = [
|
|
12
16
|
{
|
|
@@ -162,3 +166,33 @@ async function askYesNoQuestion(query) {
|
|
|
162
166
|
return false;
|
|
163
167
|
return askYesNoQuestion(query);
|
|
164
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Given a token symbol from the HubPool chain and a remote chain ID, resolve the relevant token symbol and address.
|
|
171
|
+
*/
|
|
172
|
+
function resolveTokenOnChain(mainnetSymbol, chainId) {
|
|
173
|
+
(0, assert_1.default)(isTokenSymbol(mainnetSymbol), `Unrecognised token symbol (${mainnetSymbol})`);
|
|
174
|
+
let symbol = mainnetSymbol;
|
|
175
|
+
// Handle USDC special case where L1 USDC is mapped to different token symbols on L2s.
|
|
176
|
+
if (mainnetSymbol === "USDC") {
|
|
177
|
+
const symbols = ["USDC", "USDC.e", "USDbC", "USDzC"];
|
|
178
|
+
const tokenSymbol = symbols.find((symbol) => constants_1.TOKEN_SYMBOLS_MAP[symbol]?.addresses[chainId]);
|
|
179
|
+
if (!isTokenSymbol(tokenSymbol)) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
symbol = tokenSymbol;
|
|
183
|
+
}
|
|
184
|
+
else if (symbol === "DAI" && chainId === constants_1.CHAIN_IDs.BLAST) {
|
|
185
|
+
symbol = "USDB";
|
|
186
|
+
}
|
|
187
|
+
const address = constants_1.TOKEN_SYMBOLS_MAP[symbol].addresses[chainId];
|
|
188
|
+
if (!address) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
return { symbol, address };
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Given a token symbol, determine whether it is a valid key for the TOKEN_SYMBOLS_MAP object.
|
|
195
|
+
*/
|
|
196
|
+
function isTokenSymbol(symbol) {
|
|
197
|
+
return constants_1.TOKEN_SYMBOLS_MAP[symbol] !== undefined;
|
|
198
|
+
}
|