Compare commits
31 Commits
8a1afa6f6d
...
ab9b884ee6
Author | SHA1 | Date |
---|---|---|
John Saigle | ab9b884ee6 | |
Bruce Riley | d44451d7b5 | |
Evan Gray | 6adb1e899a | |
Bruce Riley | 473b095b3f | |
bruce-riley | 73cbcabcec | |
Dirk Brink | d63f2ca532 | |
Evan Gray | e6dfb9115e | |
bruce-riley | 034c570b33 | |
Dirk Brink | a566c3d3bf | |
Csongor Kiss | 9620fca895 | |
Bruce Riley | 35f0b343ed | |
Jeff Schroeder | bda43b2ac7 | |
Jeff Schroeder | 14d73dafe0 | |
Michael Nguyen | ddf5ba159c | |
bruce-riley | 9af1fac9e1 | |
John Saigle | 35fd22c0a3 | |
John Saigle | 2aa0f75e8c | |
John Saigle | 7b7078dab9 | |
John Saigle | d3c6ebd2fa | |
John Saigle | 76bc26bcfc | |
John Saigle | d91b4c1941 | |
John Saigle | 8eb96f1bfe | |
John Saigle | e197979eb7 | |
John Saigle | 8e483eb574 | |
John Saigle | 5ec1594496 | |
John Saigle | 20a50075f9 | |
John Saigle | 704d73c66d | |
John Saigle | 85780c272b | |
John Saigle | 83c78079a3 | |
John Saigle | 4252d039dd | |
John Saigle | 90ec6c94da |
|
@ -44,6 +44,7 @@ As these 3rd party audits are completed and issues are sufficiently addressed, w
|
|||
- **[Jan 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-01-ottersec-terra.pdf)**: _Terra Classic Contract Upgrades_
|
||||
- **[Feb 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-09-cyfrin-wormhole-evm-cctp-v2-1.pdf)**: _CCTP EVM Contracts_
|
||||
- **[Mar 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-11-cyfrin-wormhole-evm-ntt.pdf)**: _NTT EVM Contracts_
|
||||
- **[Mar 2024 - Cantina](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-cantina-wormhole-evm-ntt.pdf)**: _NTT EVM Contracts_
|
||||
- **[Mar 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-03-28-ottersec-solana-ntt.pdf)**: _NTT Solana Contracts_
|
||||
- **[Mar 2024 - Neodyme](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-12-neodyme-solana-ntt.pdf)**: _NTT Solana Contracts_
|
||||
|
||||
|
|
|
@ -253,9 +253,10 @@ Options:
|
|||
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
|
||||
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
|
||||
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "wormchain",
|
||||
"cosmoshub", "evmos", "kujira", "neutron", "celestia", "stargaze", "seda",
|
||||
"dymension", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
|
||||
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
|
||||
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
|
||||
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"optimism_sepolia", "holesky", "polygon_sepolia"]
|
||||
-n, --network Network
|
||||
[required] [choices: "mainnet", "testnet", "devnet"]
|
||||
|
@ -311,18 +312,20 @@ Options:
|
|||
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
|
||||
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
|
||||
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "wormchain",
|
||||
"cosmoshub", "evmos", "kujira", "neutron", "celestia", "stargaze", "seda",
|
||||
"dymension", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
|
||||
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
|
||||
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
|
||||
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"optimism_sepolia", "holesky", "polygon_sepolia"]
|
||||
--dst-chain destination chain
|
||||
[required] [choices: "solana", "ethereum", "terra", "bsc", "polygon",
|
||||
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
|
||||
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
|
||||
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "wormchain",
|
||||
"cosmoshub", "evmos", "kujira", "neutron", "celestia", "stargaze", "seda",
|
||||
"dymension", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
|
||||
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
|
||||
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
|
||||
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"optimism_sepolia", "holesky", "polygon_sepolia"]
|
||||
--dst-addr destination address [string] [required]
|
||||
--token-addr token address [string] [default: native token]
|
||||
|
@ -355,9 +358,10 @@ Positionals:
|
|||
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
|
||||
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
|
||||
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "wormchain",
|
||||
"cosmoshub", "evmos", "kujira", "neutron", "celestia", "stargaze", "seda",
|
||||
"dymension", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
|
||||
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
|
||||
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
|
||||
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
|
||||
"optimism_sepolia", "holesky", "polygon_sepolia"]
|
||||
tx Source transaction hash [string]
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
|
||||
"@certusone/wormhole-sdk": "^0.10.13",
|
||||
"@certusone/wormhole-sdk": "^0.10.15",
|
||||
"@cosmjs/encoding": "^0.26.2",
|
||||
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
||||
"@injectivelabs/networks": "^1.10.7",
|
||||
|
@ -683,9 +683,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@certusone/wormhole-sdk": {
|
||||
"version": "0.10.13",
|
||||
"resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.13.tgz",
|
||||
"integrity": "sha512-04OCGoJUylTFNu4+g96Ax7jvn3M7FwVbTTcPNIjgta8QcC046kZBYAEd/yrK5hkDGqejQyJwO0ieaJfxL/kv1w==",
|
||||
"version": "0.10.15",
|
||||
"resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.15.tgz",
|
||||
"integrity": "sha512-XECfrvdYjsGPZWyR1bqWCPOiRw7+6upszpSvAXjKIqEnTNXOCYRkt5ae8TVh5oZxPjpts2X3t4Oi9WGcEssHpQ==",
|
||||
"dependencies": {
|
||||
"@certusone/wormhole-sdk-proto-web": "0.0.7",
|
||||
"@certusone/wormhole-sdk-wasm": "^0.0.1",
|
||||
|
@ -11917,9 +11917,9 @@
|
|||
"requires": {}
|
||||
},
|
||||
"@certusone/wormhole-sdk": {
|
||||
"version": "0.10.13",
|
||||
"resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.13.tgz",
|
||||
"integrity": "sha512-04OCGoJUylTFNu4+g96Ax7jvn3M7FwVbTTcPNIjgta8QcC046kZBYAEd/yrK5hkDGqejQyJwO0ieaJfxL/kv1w==",
|
||||
"version": "0.10.15",
|
||||
"resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.15.tgz",
|
||||
"integrity": "sha512-XECfrvdYjsGPZWyR1bqWCPOiRw7+6upszpSvAXjKIqEnTNXOCYRkt5ae8TVh5oZxPjpts2X3t4Oi9WGcEssHpQ==",
|
||||
"requires": {
|
||||
"@certusone/wormhole-sdk-proto-web": "0.0.7",
|
||||
"@certusone/wormhole-sdk-wasm": "^0.0.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@wormhole-foundation/wormhole-cli",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"sideEffects": [
|
||||
"src/side-effects.ts"
|
||||
],
|
||||
|
@ -30,7 +30,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
|
||||
"@certusone/wormhole-sdk": "^0.10.13",
|
||||
"@certusone/wormhole-sdk": "^0.10.15",
|
||||
"@cosmjs/encoding": "^0.26.2",
|
||||
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
||||
"@injectivelabs/networks": "^1.10.7",
|
||||
|
|
|
@ -62,6 +62,11 @@ export const getOriginalAsset = async (
|
|||
// case "rootstock":
|
||||
case "scroll":
|
||||
case "mantle":
|
||||
case "blast":
|
||||
case "xlayer":
|
||||
case "linea":
|
||||
case "berachain":
|
||||
case "seievm":
|
||||
case "sepolia":
|
||||
case "arbitrum_sepolia":
|
||||
case "base_sepolia":
|
||||
|
@ -125,6 +130,7 @@ export const getOriginalAsset = async (
|
|||
case "stargaze":
|
||||
case "seda":
|
||||
case "dymension":
|
||||
case "provenance":
|
||||
case "rootstock":
|
||||
throw new Error(`${chainName} not supported`);
|
||||
default:
|
||||
|
|
|
@ -72,6 +72,11 @@ export const getWrappedAssetAddress = async (
|
|||
// case "rootstock":
|
||||
case "scroll":
|
||||
case "mantle":
|
||||
case "blast":
|
||||
case "xlayer":
|
||||
case "linea":
|
||||
case "berachain":
|
||||
case "seievm":
|
||||
case "sepolia":
|
||||
case "arbitrum_sepolia":
|
||||
case "base_sepolia":
|
||||
|
@ -172,6 +177,7 @@ export const getWrappedAssetAddress = async (
|
|||
case "stargaze":
|
||||
case "seda":
|
||||
case "dymension":
|
||||
case "provenance":
|
||||
throw new Error(`${chainName} not supported`);
|
||||
default:
|
||||
impossible(chainName);
|
||||
|
|
|
@ -99,6 +99,11 @@ export const getProviderForChain = <T extends ChainId | ChainName>(
|
|||
// case "rootstock":
|
||||
case "scroll":
|
||||
case "mantle":
|
||||
case "blast":
|
||||
case "xlayer":
|
||||
case "linea":
|
||||
case "berachain":
|
||||
case "seievm":
|
||||
case "sepolia":
|
||||
case "arbitrum_sepolia":
|
||||
case "base_sepolia":
|
||||
|
@ -169,6 +174,7 @@ export const getProviderForChain = <T extends ChainId | ChainName>(
|
|||
case "stargaze":
|
||||
case "seda":
|
||||
case "dymension":
|
||||
case "provenance":
|
||||
case "rootstock":
|
||||
throw new Error(`${chainName} not supported`);
|
||||
default:
|
||||
|
|
|
@ -172,7 +172,7 @@ export const handler = async (
|
|||
}));
|
||||
} else if (argv.wormscan) {
|
||||
const wormscanurl =
|
||||
"https://api.wormscan.io/api/v1/observations/" +
|
||||
"https://api.wormholescan.io/api/v1/observations/" +
|
||||
vaa.emitterChain.toString() +
|
||||
"/" +
|
||||
vaa.emitterAddress.replace(/^(0x)/, "") +
|
||||
|
|
|
@ -200,6 +200,8 @@ async function executeSubmit(
|
|||
throw Error("seda is not supported yet");
|
||||
} else if (chain === "dymension") {
|
||||
throw Error("dymension is not supported yet");
|
||||
} else if (chain === "provenance") {
|
||||
throw Error("provenance is not supported yet");
|
||||
} else if (chain === "rootstock") {
|
||||
throw Error("rootstock is not supported yet");
|
||||
} else {
|
||||
|
|
|
@ -154,6 +154,8 @@ export const handler = async (
|
|||
throw Error("seda is not supported yet");
|
||||
} else if (srcChain === "dymension") {
|
||||
throw Error("dymension is not supported yet");
|
||||
} else if (srcChain === "provenance") {
|
||||
throw Error("provenance is not supported yet");
|
||||
} else if (srcChain === "rootstock") {
|
||||
throw Error("rootstock is not supported yet");
|
||||
} else {
|
||||
|
|
|
@ -171,6 +171,41 @@ const MAINNET = {
|
|||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 30,
|
||||
},
|
||||
scroll: {
|
||||
rpc: "https://rpc.ankr.com/scroll",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 534352,
|
||||
},
|
||||
mantle: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
blast: {
|
||||
rpc: "https://rpc.ankr.com/blast",
|
||||
key: getEnvVar("ETH_KEY"),
|
||||
chain_id: 81457,
|
||||
},
|
||||
xlayer: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
linea: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
berachain: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
seievm: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
sepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
|
@ -206,16 +241,6 @@ const MAINNET = {
|
|||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
scroll: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
mantle: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
arbitrum_sepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
|
@ -251,6 +276,11 @@ const MAINNET = {
|
|||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
provenance: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
const TESTNET = {
|
||||
|
@ -362,6 +392,41 @@ const TESTNET = {
|
|||
rpc: "https://rpc.atlantic-2.seinetwork.io",
|
||||
key: getEnvVar("SEI_KEY_TESTNET"),
|
||||
},
|
||||
scroll: {
|
||||
rpc: "https://rpc.ankr.com/scroll_sepolia_testnet",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 534353,
|
||||
},
|
||||
mantle: {
|
||||
rpc: "https://mantle-sepolia.drpc.org",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 5003,
|
||||
},
|
||||
blast: {
|
||||
rpc: "https://blast-sepolia.drpc.org",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 168587773,
|
||||
},
|
||||
xlayer: {
|
||||
rpc: "https://testrpc.xlayer.tech/",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 195,
|
||||
},
|
||||
linea: {
|
||||
rpc: "https://rpc.sepolia.linea.build",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 59141,
|
||||
},
|
||||
berachain: {
|
||||
rpc: "https://artio.rpc.berachain.com/",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 80085,
|
||||
},
|
||||
seievm: {
|
||||
rpc: "https://evm-rpc-arctic-1.sei-apis.com/",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 713715,
|
||||
},
|
||||
sepolia: {
|
||||
rpc: "https://rpc.ankr.com/eth_sepolia",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
|
@ -445,16 +510,6 @@ const TESTNET = {
|
|||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
scroll: {
|
||||
rpc: "https://rpc.ankr.com/scroll_sepolia_testnet",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 534353,
|
||||
},
|
||||
mantle: {
|
||||
rpc: "https://mantle-sepolia.drpc.org",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
chain_id: 5003,
|
||||
},
|
||||
arbitrum_sepolia: {
|
||||
rpc: "https://arbitrum-sepolia.publicnode.com",
|
||||
key: getEnvVar("ETH_KEY_TESTNET"),
|
||||
|
@ -490,6 +545,11 @@ const TESTNET = {
|
|||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
provenance: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
const DEVNET = {
|
||||
|
@ -584,6 +644,41 @@ const DEVNET = {
|
|||
rpc: undefined,
|
||||
key: undefined,
|
||||
},
|
||||
scroll: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
mantle: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
blast: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
xlayer: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
linea: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
berachain: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
seievm: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
sepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
|
@ -660,16 +755,6 @@ const DEVNET = {
|
|||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
scroll: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
mantle: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
arbitrum_sepolia: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
|
@ -705,6 +790,11 @@ const DEVNET = {
|
|||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
provenance: {
|
||||
rpc: undefined,
|
||||
key: undefined,
|
||||
chain_id: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,8 +3,8 @@ import {
|
|||
BridgeImplementation__factory,
|
||||
Implementation__factory,
|
||||
NFTBridgeImplementation__factory,
|
||||
WormholeRelayer__factory,
|
||||
} from "@certusone/wormhole-sdk/lib/esm/ethers-contracts";
|
||||
import { WormholeRelayer__factory } from "@certusone/wormhole-sdk/lib/esm/ethers-relayer-contracts";
|
||||
import { getWormholeRelayerAddress } from "@certusone/wormhole-sdk/lib/esm/relayer";
|
||||
import {
|
||||
CHAINS,
|
||||
|
|
|
@ -7,6 +7,7 @@ Algorand
|
|||
algosdk
|
||||
alist
|
||||
Aptos
|
||||
arbitrum
|
||||
authorisation
|
||||
authorise
|
||||
authorised
|
||||
|
@ -25,6 +26,7 @@ callstack
|
|||
CCTP
|
||||
celestia
|
||||
Celestia
|
||||
celo
|
||||
certusone
|
||||
Chainlink
|
||||
Coinspect
|
||||
|
@ -143,6 +145,7 @@ rustup
|
|||
satoshi
|
||||
secp
|
||||
seda
|
||||
seievm
|
||||
Sepolia
|
||||
serde
|
||||
setcap
|
||||
|
@ -192,6 +195,7 @@ wormchaind
|
|||
Wormholescan
|
||||
wormscan
|
||||
wormscanurl
|
||||
xlayer
|
||||
xpla
|
||||
XPLA
|
||||
Zellic
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
Ethereum (2) Standard Relayer,01000000030d003f39e29280cb340fdea6e91de35155ce11fac49da591cf7efd61f12f4d3f46663d7c4575ec830c35c1cc19017a79e28eedc1d10fcfff4595b1dbbfc9047d55990103bb91bf8f33762ee6b07abb3119c4ba748d092bfafe87d360db962d99c96462920abb4e6d076e9d54aeafe8dec563b1930a4305e2b3961cd363bc203be0649f270005245ef83e663fbc6e9cb3f2c9eebbe44eac2f6e5844c13610333d64340c7e4407611f4e11d676e9773502f6ca6c070975297cf6f372dce0875de3f8ba80b48f58010696ea72db18de430b5c071bb09d51d53d03197a33b1df0711b5f859149ddcfc7358c84573a7518b3719b67ec01fa07140dda7241b087807c1d4548c1876559d2801086fb2063f49bc33d1f25ee13ac31cbb2a0ba540f419df1cd03c91d0aeb8e97d5e6feae3da4362897531428190a8b458c327e256016ab6ac62cc1b1e931225baee01098bfe9db66d5d50eb6177143e8db1b23200c677266f02ac2d1c04b90ee9a1d1b476a9f4f93752555e86a54e2f5bb666866310f8f587356c594218aaf41d20fbce010ab66121eb5bf8f432e1ae32bb988dd7c33d482fe4d63abe1386d38cdddae0c03964d792f2704309bceaae0c1b322e46aa651c6e2a3c2611903cddbc87363bdc75000cb22b8172a90abf14aaee5a80bb97380275798e1f89479be50b54b4549e2fcbbf285af8ed730998caa93612dac4e80eff36ea82e945672e46128d7abe12c1936a000d4ef0a4d42e2be648eb6bd37d6184c123ab0a31dd804970416972e5be3fbd6a0044d9d2dd64a430cca95110ff36f2f363fa90a0ceb524f229b46caa85f9b18bc4000e0ddb23380953eaba05b8d493f2193860f10079a2ff6ffc00bd11db94e22b5f0e1ab3bf4517972a0aa2d7ed18551231e083e48ccc07e8d64ed20fbb6d57151b8200108a585d5960d95a50f9cd6c8ca4b8ae7a70b4549a052771edff1a0c3a409ea5cd286eae6c53eb280038605384d051e04e8c2c531c0f8713e36a5c4d71a044a40b0011fa3cd95765d64bbdc070008c3111ffaf46ada75e4dc39607c643b547c3f70d423f0f4ee2ae5d7ed4361869896dcb012368a0a9586881c579a877728fd761f53a0112447e5b97e5341c5ff2e91c0aba8b48ca985f369992f00fb17fdc9c0f6576b93c6beaf3a44dfe8972df1f28c4eda7336a7955e6d33a4cc1e1c324ad45de72d56e0000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdccca8200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000200000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
BSC (4) Standard Relayer,01000000030d002e0a85cefc9dc34ead9571b45e9a296c58d8c43c4272ef5e50c8d1d0367e828a37bc44055960b5542ec79b5081c2de229ae7a5555d409235792e3cdfac3d495201030941c73fc173d2f1bfa810a141db2343f3d4ff420c56ff09354b2718b5baa4887922208e9097f19f6607d8b79bfc7ad469d4bacd3f60ae9589fdad238aa1d95301051da5b430178acfde6091d4cfd836926097be2862e30b96d89d03f9d6b9bc1a8319c814c9186d30a564db790136e24229be6c21a115518fb2e0a7f3f5053771c4010616dbe51c1f120717f6522d72cf85e42315d65dd049fce9e691658d1a0e3d98c865c71d6fc5cf7682991c476bb5ade4048d71e3ce81ba5fa2632dbd17a352260f0108fbd37725bc32e5e9a872f0477be346ed302afd45d9b0e5724347adc0cd142c020f134770727c9d57fffa249980c3687cc98d62196064c30df7a7147f07ce3af60009f6a21b63b3c8c18f96b5ff71256d5ed0f630de90ee65eebdaf6b5916b4d6fdb276d7dfdae5e05ff52a2f77b8801cbcb1fb988c6b4adcddd9aaef2e78847500f1010abc2784590de571f08bf3003ecd50a564303376c0da7a145118153022be444d940238147ca54bf65f2c312389f568ba80b0c547413a8fb527452f09320f23347f000ce6b17e707f79583df2837cec6cf05f5d3f70b99f04ef6c3a54d55e770f2aca4a78da87446c11bb39ffbaebd324d7b369944049457bbc97256dd7b06a61127263010d42c86ce3294e2cae5304d94aeb30de4c686612d090f41998af8a1473fab4fa605579308201183510ba56602f2dbba3694959e052e0d2ec973f127308517898ba010e113a38c219ebb990c5bf15c9b155bb45bcc773b53dbc2c3fcac866ab00e0f2be61e3962b99e25bbe5fefe2b0af5fde001e35a71e1856b369b5a179d3c0a826b20110ea9e738d883dc8a194c9f180a1123c2496be82678047d6220600657df77b28fd1ec53df79bc47487af116070ed44a58ab86e05030892c2107342dba5f742eb390011759c6d8c25ed3f4a60b7c30473cef12f1652231ee5e2d98efc29ffe3290a6ef37fbee021b0dcddbfbf11104ca1d9451d3ed455816821e2c089538e7d605e0a380012a07c722f449b863d996f15185efa1fb5b056be6d404c8e793492edb5736372f27a9ee67e7b4998e81cee5f45626984d801b81ef7ebc980cde1959a48b1ad57c70000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdccca9200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000400000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Polygon (5) Standard Relayer,01000000030d004e90dfa99044e47b564eecadb2c658583064ac566daf77286761684cc687e9d65173cca86b6188c277847846681ae11bdbf1b966ae65180c7d878ff48135cfa00003f100618c84ff56ea49f563b432bad076350fae7cfcfb3dec92540803d84ea93b5da4c7fa7bd7ec363b9b612dcda7cfec9fbebdbce517dc30903f13c2ec5cb14e0105ce71d2e594f36caf27e8b769261e59b91e9e57fa16205c6d375074615088917e05130f24f1bf948431bcb025aecbf24dcf286297a3002c37ebe72acb5c2430c601068445c65befad456f1cc427c80b2243b23700c152afc60b298ccf5d24261bd9ee1627bc40aa527bc67de91de14cc0dfb2d99b9ec08d31a7ae3e1acef1ff22acbf0008991ec96f347b242770e978a6473da8c82b14dcb9a5ccc05dde4bcf1125e3d9481c25f188d07e1e4e68a916cd79ab21f41a5433d779660d15808e6c172c55accd0009425e5f3f71af0a6ebed1bb037590319bad260e2ebd8b889bc64f782e594792a52874c1973cf69b76f20a33317fa8f16e982afc85fe147ba742be1222d942dcf8000acb1b63f1a4f30702e2b883eecc8048ba91b38a09fffed33299b0e5aeabe09f7809fca5f75fc6a4022b902be7caf793a18d1371aecb3d9bf0d7d27640777b2cd7000cb6f2500ce351272a1d874e2c9516c566cd85702872e2b8b0fa09c54a0f03dbcd27c1ecb367da1dce046b4eeaea922f9ff172886ae4e50799248f58821e543f6d000d2c307443c8329b1c9e456334253c604b5d6c1d7f5dcd4406d9d8c4ed138b72f479ff2f412a41474f3d619a41c8bf216898b8e8a17d3cd7275e6929bcc221b848010e79b575b4795c6d3cccaef379c2f533de626df9a87a52389f38fac3f5d77b57aa317aaefa4386aac86638a9e19cd0dcbd92f9f087fed54c9e28cbb7eb7cc75b8401108d63f8802b17d2ae03a138c123b06a3be5fbed3d478672dc5009a6b6cdb13dea467ac4dcb16784cccd9ca9459ee98ceeafa0c9f444cdbd3654f034f288a24fe90111bd3e4eb9455c06c3aff08836f55add7b1bc5d389a1a02d02abcd5d54e5c1df1c31796b93b0b0e85320f8036a38513bc48008b4acc0890936bd46165f2589d69400127f69a920ebe11ad7b73eb13a8b2729d7a2972ef6b86ec2d9b2ca5f4e3b8b9cb70195f59e62b715724ed2221e32c4f537858d12506ec4d4cbf566982bf63bfb5a0100000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccaa200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000500000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Avalanche (6) Standard Relayer,01000000030d00bbfe94366547d476cc80ea55d4e62ee810c59951089c89f07d5e6dc088761384178868b90f76f3858fb749573a2eb03a4d05f8f680972d38ce5055385018a7bf010301035d39f88f4d0751269ae4e098bbe47f3591357c1b616b3e34a5c21c4c1f2c6bfd2b19a8078419699405f38d4c30b3d4970c8a7a37729dfc5c319f299883ac010566ec129bfd891f510f4b350743f2ba9c061b0b94d9cc20d0a75c20dd863722d830ad196d3cd9fb5158337e875a7848e8653d50ff7e7e63c41c2995e57e1c0397010604b345098da327b1ce27ee48a6d2bfd26a744090540042dc1d698a458f726b730f39815ab1254cc9b45bf1fb12ca62ea9b5f9f3285974c350fa7e23fe4a9c8bf010881a52213d65d8fcca6c99cea3b2d134518a451a277a0b92fcf0dba0684fc52c37254b8a2ffb450a1e0777bad5097d907cf5a48c7d70c037b3a362f1973b143d2010928b25ec1394bf9caaf9c95ef074babef722c15b0a4edccedac3fdbd6a6bd87d36ac2fb490e4605eb0d53db3eda85527fe5f00171a5a5a81b283c401ef0369794010ab5470061217ac4b94fcc45fc23292d51c04719493a2785a0caf76eb3497a402e13890bde914f07b680b84079f87bd1448ed8e4f2b1d6a60661986a6f51593d66000c28468c40328aca78777e19c2722b37057250178d92a2d66aab52d8b60bdfcb407696bdb1e2df2b002fa8e99647540a00b58c1d1f11e86a274ced8f8d8b268083010d5fa87309ca8cb8ac33c516a3c3ce860c2c69411c4f5abfec0d8ee7f08a917718371fc2e5445d27f9915cfd72396ab0b0f76fdc820f87dedfa6a129a376d39671000e028b814eb1f74fbf10a5fb2c465a254b0002830aad9201555d7f9b5061bf99f41cbeca0fbb2b6dda51fda40dfcf88be08b3c9a9ee1410347a0dff0f70a76fd560010fa217241fb64df96812ba7adea8ff477b4c03a76c25ebb3f8bc817afca2a735c7c8d0c57e02ced4c522dc5c5c02758eee91fd3bbf8f69057e93cce6ed177c9d500115cd9c43d6c791a3ad05cea7cfd97f76a1eefa267e134f0d8144b9fc527f93d2e017c44c427670248954d1d119b712412e032ace9f4879b8c36439c100318d0f000127cb2e52609a2ef2838b24744233ba084f76748d2b553abefc70cef8f05eb16731e013081b28eae042ef40f73104ba2b91760e9369168ed91bb98d985edc025f10100000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccab200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000600000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Fantom (10) Standard Relayer,01000000030d000afc75cbef72bcf6cc35dafdf4547edb0051789ac0afbd34c7cefa561a1cc2f0199f316ce3bb93d339f86dc44986d41e33677f33d9f9742c624befefbda05a370103d3cf95aa84035358f41d4b0f5dd0c59c2de8b69af4db84e29b5df51781d4a4437cb885054e625a4ad03324573e033bee6e4169fa7fa169c2fb4a5c4c7e69bee001051f843a340ffd3a605fd84480ef14d8595b1fffdd45a7e1c919c686ac1bd234bb4255d6ff88990e33dbeb751c06ff6ba5c63469fef50fb9924c135a2e81db0f91000678e5e902519def669dc1b03d3c9be4b84589a6322bcdf3c8cb056192a13774487a49709566d0cc68fdd9c6d1f368152f1c0728bba71031a867dbf8a170cf694e0008b25df04e7b4147bd3ae3960fe7f181968c084b63a89ca11c28e557d516e6ac3b623b56e9472041a8ce9fab0be14e9f6593caf203242f5a1a8c00c8a23f947183000919c402479e75615c767de34eb463099fc752c82aa9def7bb5dca812dc5d1a14c268f8c8a4c659be8fae0e51d2f0ed120cccac58344ca9b3df9a9cd21fe1919f9000a7c96e0c21eb74310637c8bccfac24bf91190dfca3a7499bae885a4dec541c58f241933b0d567854b6d8c2fcc284e9077ffab16d6c9c0f9b24cdc2f7875e0a8fc010ccdad41a3722e94317d99ec9542e3aa59ea9cf0297f450edc57c037408bdc5d5770df000375a79ae231aff1eb128c657d0965fe8e4fb5efef26720848b6e68a14010d419a91a2299ba3d983171250bfcda19b462c6cecd6c689ab44cd06d77b3c9bc71f532521b1334308bfed01640ab3c8d212f2e69f349c7697fabcf95f43afdce7010e2238dd50fac23d82778680768dc5cf4ffd02bbb351483dd625e034c9dd0be00a1a2c49f95238a7cfd7ec45038b4478a457e9b9c217fff574b7dd9d5663c6534600100fafc125ed044c06597a7563f22a5ed5071cda2e928bf401a71592af7abd6cf45b114d1d69ab5c784cd4adddbbf51b461e85c41f5792c5e309f86787196f9f560011141a93514e4236da671151dfce33f1fd24dd6e9cc88d16ba2fb8e04c664576b122cf795666f5b5df601b2243382b99852cd23840d91c6fd7dfbb33e27753794a0012880041feece8698f81bb66e9817ffeaa30eb58b5ee4f667a24fb05030fa2ffbc347cfc3f30bd9a18ae8e5e9c01ed40d46459d25e96c486cf849d5f4dbea188480000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccac200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000a00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Klaytn (13) Standard Relayer,01000000030d00c9b9d25eaf56c5936f66f147fe45061729bfad0514c1dbc21a6b3e8c41fd669c43f8fc2dd2792ad106d9b23d7d2161374fdb24084e4dc44b246986243177e4e30003a73bdd6b228644bdc483bc8910c39f120b83c315c33764c308d9f73bc2b30c4f26ce6b93e3de1cceab441db14445318075bde8e15e9aa77fa6c311e40bdc068000053e88ee079e28c6ebd2cdd47cee327b7ba9cd985c5b01352efc25689ebeca85844f7bc66da3266dbe5d5bba69ce0f3c217e87a051fb2de74c253c1193e52b171c01064a46327c3abc0f34caa2cef14341903e14a3b84e67d594f45d0105e2e3b4ebac3793967c20da12aa3f38101fae3f071fe870fbe574657c021949d3df3003a6a701082d5c3b48bd744256c9eeab8845402e5a937481c8ae1fc525da22c9987953e3467e19a6a31c66ba8bff7dcd24d7d23b02d44c79a09da9efacb5d9be8f0dce269d0109bc3c217eb4557cbd5b486ce13e577322808eddad286ff56f8c6403de7217a32a102e634be26acadd332b24a05a04068f823a74a6a41c4e2f91ab23f6217d8ac8010a823b3773e8a5c222bf5a28b95d2ebaa992ba4f8522337e8d2aba19bbe1ad72b4222e6a86a97e346ca937464098bf5f649f5f7e6e18e71d5b4aabdc0c19bb5130000cc6d232cfefef4ec108fbef959aa294074eacb83b6c7a8fe5f6b3e76b6d4b3c4679e1e6acb3186651d7fe984c1fa895c4afbb421b18074f917e3224b684d9006e000dd4936f7cbe9cbc64a98a654d4673e66dde3a5ccd52f8f3e16fa69c01f1e63b80362aa8f70c771b04a080bf847b5015914e189c9053e659c996dfb4e1275bd4ea000e8ab19b52ecc453b221bd23b3b437243da76ac0ad88e49e71baeaae300654d8344687f7cb1d69df24426e3d18e90ba39c1267c63725712ab125749642f8742c530110ab99b0e5b37c20f786b296923131c5df829498559e46f1e5c2971fed93ceab1700a61354b60fb640e369755a9978bc57df01a55391cb5fc7400c6caed0121a890111c844b51223b2fe13448366c8cd00edc91e688ec419aeec97bd41ae9776f317f1770c1742825c3cc1bde2c0f8928edc24874abf23d94d3d12f121b661d313913b0012f46057fb23e8b994dfd0168f8dce2f661ee24fb9ffa0be22a8b0ab4424f3ffc6567d9e5c124d2dcee0d3dae8eb786f0c1d4b38fa857e17310bd25e4092c371c20000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccaf200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000d00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Celo (14) Standard Relayer,01000000030d0059eacacdd28f4646e520abfc7ef33cf313a1b8f020a27e1808f0a58df34a5ebd1d8bf0e8aca4fb0db614558b1100c80be7ddb4d8ae50232d93240fc9364887ad01032085d87ad27eaa019d14cdeeea575f926ec1db44180cb1932b6ff54b56f0a9d73bab0e952fabcba8135fad9f187db120ea6fdf260cfb3869d973d3eb725c457a01050c37eebf1a94032b3fb7f53ffabeee25610a804c7f58c7ab7e82b8d103adbe1f3af1ae9967f1045c040aa5f3a4c8e4d8d5a3802ca826483e9a1a15f8e42399050106f88d72d019b83cb9b10309c8146e19769da72bb59a26369249fe39b51d475d570e57f5e19cd864af9835c4809b2668afb6690b24f271d37d9caf7089402a67140108e7ec94efd6c6c06e792c3a7e8885bf305cd652a76876d49697c99ddfc9a98b786bc215521a03151718cd81fc4619c72ffeeb29e6cd968dab9d512f7d2d0eba8800095b6f138e529675fe335e5a72f6bc1a35d20cf518786519c24ab014ceef61eb7133adcb701a7f75ccbacc12ab5e74dbc7c083ea8318d0eede51f486292c901e74010a538c2fbf35b4630f13e694da19fd3e2fa57438622af490fd3bb19a620f88be3678b5d6408c7177575d04a6559bc0bd19538f93e6dd5288d9931511ab8c512d31000c6563e95259a53f854c5441759804111e52ce42e5332df7ca601cb14091d3c6d81a37ffb91829cafc053e14af24a59ffcabc3fd774e1399901154d52d634057fa000dd639c68822ed4f29afbdfe349fb31cc367b065f5a3bfb73587e0aaf8dd0ad5161be5fd99d78628a7bdfa8c07ffaa47d6c4b58e6b470dabecfbe95db39a96496a010eb85a203b18444f5d26beac38279081d618a50a77f0fcb7d7ff3f51fb2705d9a167bf7c7a2506dc4ac90b946ee63d8a9ea6bfad8aa8494f99f2af5d15d190801b011018d5a390d01b98d9762222d97d3cb988573f256a7a3d512bb26db78f2e1284be020a6d5a9660a869dceba199308db403e0708c785e1c2715821f69a091f39d8b01110767d6f4f27f9db7ae9e4256b9a857e78571e92197cbc8218551da332fb4110e07dfcc73438b8473b91f3a93a4bd96be9dbaff86b524eb8dc1639da33f1f79a00012b00387cd213e2e6ec3973bd90d98eb4c500c9c6aa893cb1d607d9842a326b6e75a5644785dd5ff7c2eef012e938b6df215ed4e97b8223c078fc8a8dba92787770100000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccb0200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000e00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Moonbeam (16) Standard Relayer,01000000030d00147ce69eaecfb38adcf8f953bf97f1718fa3db81c1609e42ecedefee95f6fb216f20a5e3562e53a8016b4c5ac45c93f749ed3ba9381685037490286a55e5dbc50003aea201f953a34c7b5cbbccbec6c42d474107efa3c1f5f25137f0f7f1f8f3446f53fbf9b1d475f396cd04878e0bf9ef58014beec38c3fb698d38602fbdfb5f18b0105fb93126334289857302eaf327690a0d8457098fac094a6817b49f38841c385295998dfc8d50071f296053d8fc472685fee36dd8990c8230f3e276e1b873a75be0006241945f86c1abef3ee1286b1422c92bafed7b38c3daec22ba602526675b4d35e1938ab844b416b6a803bde5b12648d66e9bae68e34dc87450a69a64bbd2034ba00084ee90ad3baa0ee4ccb987f686246958634fd8834790f8b664f8ff60bf1d83e25636b9e9ccf6323234cdbd8e52c138c98f85d4ad2c40a15b136520adcf36180010109a76104932e8c3a7336ca6cdd33b1b69cbf750eb724e368fae15334ec880921963c9f5e317de2b6d7bfc634c1cf6d26567662dbe90a0f78989c2e09d8671ee004000a4b57433c1f5608e4c0e78fbb597271bdb79060a01126d555db0a00e4160e2a0e6194e6a2c815109b3ca69b14b8995fb8b5123c11e769b65865c0c48d547c15b0000c7be055a164a254ef1a8d423fb8a740f365e384dbfb1df6279ec1aa2f8e8ec33f5359e3dbc50ed0b6a6f81cc28a8df550e0b22f4039197c939fb08bf9af6207a2000dffa23f41b9167fbbcbff97425f015f62d68d4f469f0973bdecb8fab41a44c1f131ac820ee22318ea239a7455e1611c77aa7d26783aa1a11203b72f447519520c010e3ef1157fe2d4df059a0d4d3796783bcd9acbd30b9ba81273841a6f82c56b710417dbe60447e5c1bc362bdae2eb15cdcf2af4d0b76577b1b13925e0ab105b43340010443e60d8ca17b58f77996ddac9525cfaeaf5092ebea04f13fdf0aab8204bbaa23c04b1987b95836d36d706597b2439acddd2539d9f6c0bbeea970de801f9eaa500114a111aeaf1f695515f01fb174e606835292a99a2d953db84753369b7f6aec89a4e9e12db15b76a880b92983f28937e8e2569bd3a7eeddfe710c8fc4fce011ed80112433a42154cbdb6f1b1bdbccff6fdcb90e8b174540e63825af039b8fc43c1bd6211c1cb4849d6ca8cb2aaefedc684717faebe50b111a44f8224debf9aa0bbe5b00100000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccb1200000000000000000000000000000000000576f726d686f6c6552656c61796572010000001000000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Arbitrum (23) Standard Relayer,01000000030d002a7523753fc4db66ca547f99a7d2f3369ec80ba3694dc80270b7efced21f900454e5968e3d6b3166f98c53dee11aa62d537bca8016eab1371d155de2146fb0790003d60b1a8ec2b4ce27e2b7298bb3cb503008b945480d537546dba2a0b1afdc80e26bc0b07d9ee4f3ef40048e25d72d23de26d22dbbc7c23df6eef0367111ea466d00053542fa8dba6b62072372bf92ef566f1ade2a95f7abe97692d20bec89c9ad220e49718ebccd0697ca592458d79a73c3f489ba7b5bfc51d9cafc9fd3b54e5d82fa0006b1f4dfb7ee4bb3059c0f9fb81c6afd5b7703d7e0b54720067d7ff7c62755aa3f0e806c426c5a7238917f89cfda30b80e7633cff6005a5965cf61356f551964a50008ebe7c99a2e83a7515927246ac0accad976a388245acce1f41ab198d37b32dcd72717e17dd7339e04d0b97a89356fa994e5b1a036ec80eb681a9c3472c26dfa1400090e98acccf12cba83b7bb65b88f532afa0f86bc068e1313e186b49e9850650c7c6ebaccc02e627b5d7470ef9035c08cae8d874dc4b371945b289706deac7d9008010aa0f27bcfc63715902446fdf352554ea699e361b8e3dcbc57b840f8b5f7dc745e02847d83317d2029b73d47daca88852f1beb2a49004c1c1e9ef4b501f417dcc6010c724aa60c084bcc159af35a9d58078d667534cb67bcfca5f959e05eb1b0956d4a02ef98abc9ac677b779b1fbd7505b1621b0935d1a58d7373c36b96b99f8cc0fb000d3139b25069520a4bd9c61905e7fd83ce21eb5786b26b1e5b96772e4933a6eb163dd4031a1bed0cc65e39e00d0a000c917b69015696cb1eed816be864b65abfb2000e794260e5d734ae20e53ff34799b2a9a39f0f792371f8f27e70cd5c14a3d781816b7dc8a3da6ba886f2c21b304648c51c16892da6bacd10776182cb65c9c46b0101100efc7a08cb812ab047bd67e624197e8244adc6a1ce0d9ef30c469bb5918606e55e3aca65054e0f46e6e7eca8f20b9c4128791ba04496ae9713c5242883777a67011137416a6f4a919b2b4dfafb55c38669b93d66810ab0c77cd9285c71fe3a3e38a36b18c4fb1f6e0700b89afb8f74f056dd58846fb8d0444c3b405afb7755faa3990012747f08fba62aa374373a5c36b6fb29a36d4e382efb2b0a54b039aeb8f76fc764683b02c529802297429d0fb5320b1e6e5c63acf309e03e0f15f7a1fe74eff30f0000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccb2200000000000000000000000000000000000576f726d686f6c6552656c61796572010000001700000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Optimism (24) Standard Relayer,01000000030d006706123794be8c86c236a0416cc1d7730e1a892ae2f5f83cdce8cadf42d61ff10ced17f17d6e2af4cd2689b8e0ebd903cce7f5643e8d8b76f55411129c575365010311e848aaea7323cddfe9d1f45189acf490d3130b9961855aa00c20e7149395a17f133ce44cd4a16078f2f884806d901eb3c56c7fa11a6c628ae659ba602913ea01059d830b8110639295a06447b4f54ed72585a30256bf600b7f0fca48f71b30b74f02a4e64c1f2c4152a2f3b7e8ac28e8029c0f60fe4c92f00f5cff8e5daf2395210006dd08a89b93920292bafca3ab963d171e884cd3bbb9b857bf6f87ab27ad2792150ed5bf038693e6ccb855d2376fc0a4087747fd1154dcc4c20b75df05a758196f010809d6a0821706b2fda0e73c4ddb551981dad9dc1c2c8e85a902195cebd1d8565e528fd078005dfed95fdb92dcad5971ce68f7b5f897f72544a346a073129ac6a700098f24b7e0e5a26410c66b1b1945494d36b9fff6dacf16c5a6a22f01a9ecc021951fd6f992c0ba7ab688b5a90fcd9f96a7fd28bf044a576d58b1a9b85f6964d430000a0323d4671721c0262265a37ff9e3459196ebb928c3568ef4b15f5812ae411f1e4cf9acf02be0f66d380abdcbd1cede4c35483e680a0c330d4fa04551e7b39a63000c4d0e32decb9285203ec763ed6cab15a1fd91fa8bfaf3bfaf449a08e52b79bdb76a10fe2a67974ca57549811cea6b51f39d8abc47b7cd9969e7d6f3b86c3949a6000df8b8844a14ed09439311cf4588760e80ad2a6c460759a85145ded663c503882a367a8ea4727e147822bb6396102d0ce6b90d1e6b87b6ce727d5fdc202b83579f000eea060f748330d8c31e520b8c3b68873e47a6dabe9bd0889dcd7525700b90134b4892bb973ed3aca95343644e5e87b3615409f2a872be97b9a8aaa3566135465000105f7c654722a67c678528e8d6a64a26f5999c70cf33adacd1cfb64d0f8b0c26f81810ba862ac88aafaa90ab5a0669aad2610dd7ad16b1133f4c0dcd4d491a462f0111b698f2fe7cd834d2bdff5d4e2f0289d9631bb910db3e64b91689b7aee09b273679c4cc40da83f0a579a06c756abb9ad9d2ba150a4d18be34c5e88010c46dce6700120ff19d84f49d84cadf0c27f91955b36980271a571c17ac85daf121bb6d0490857cd79a89eb5e1532b74439887ea0f66a5f9ae804ff063b896b24d5014b8e95ff0000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccb3200000000000000000000000000000000000576f726d686f6c6552656c61796572010000001800000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Base (30) Standard Relayer,01000000030d00df8b4dd3d24304810ddbf4cf43fc4507b56728f76e6b1d102a6ba646d0c63b2b4148223e19ae06f40ca072fe16333a4c44748bc37457835966c69f35b4d27501010247e8f4a5a1e5a4f858444a50f419a477866f7ad10af94d62251ff5a7f4a42a9215002d6b5a7939224d6221d743a0107792b4a1efd42619732a34c7c2cdc4401100036fb6ef9f9c50657d7791bb344b948d6c812f1b4070381003a942419b174c4fc94cb8d63cec79e13982a2642d789054d0746498807da03d3c59a39efa29232dbf0104bbf027b263137578ea240576f12e3dc1470ceda63391dfeaaf0f71af0adfa764772a206847aa10646aef2ebdba8ca21b6c08088cb58942f2145c5120e0f94b86000674719843c99e12cd2b9b37f98431f8dd8bd2d74b0794291fd8d7b8b575bcc8964ee2c7982fb4932621996d587eb4ff4861e1d0e6d873ee1ee8b9f684f08426250108f33ed961639ec82c1be05528b8a75f6657bcebec68827e8f295899e41423e22205312e5e7bb6453004df0eadbe11eb79588ee16f5b35fc8db2f7dc7d457bfaa20009e439e5b37dacdec25d12cba1531efceb2f130a812d2d99fcb728282bce06dbe91fab11228716ea1d430ae8a08ecc2482e30b439b912b7b0dcc95cc80e98fe6da010a5224519f03cf83b67ed6d31a5495edcf66ac10da2d94bac542109be2d075f7230b63c1576641ad6d9a54b1fbd5fa7fbe3c08cd08f673318476aaf9fcef48c6e5010ba277e69a71938f8b1197cb6975968f7e4780fda8e6136d23d2c9f5cbbb15d2ae682321eb8b5f683c5825b74492e7a2a4d18ac20cd8c30fe3fa712bd71c8b6033010d06fba68375dfdf6d76c97d3a2e0ea1c9b243d8f7a37114406fc67cb7545c717402faf5175907d1ccd943f20d539b815eb936d430fc3dfb35c3316a2342dba38d010e4ca329b5c61f7faa4223595fe3dd4d14d77506c36013c6ce8e34834d48380f75536d12e3a9cef5446a33766a500a676c3d59b09e984e0f31be780bd736a8150b0010788d6362177378258f98c0a1a5a85b229b2316e43b28a08c68e0303fe2bae4a27cf109f07ed6efa6be02379b07b4ba02c9d81c478263eda7a3c279af2d4987fa0112d5b4f5a87674f8c4a686ac67806a45440d30861a43191ec72e5f75a733a8b51c189659e8ed8ff7be73d3a14780a46cb34a58a5308f7381d668e8db58198f185501000000006b45a1a900010000000000000000000000000000000000000000000000000000000000000004555704dcd5046cc4200000000000000000000000000000000000576f726d686f6c6552656c61796572010000001e000000000000000000000000706f82e9bb5b0813501714ab5974216704980e31
|
||||
Ethereum (2) Standard Relayer,010000000411011cc9ccac1e8e7926f87bba430c7d44bd74f2d894aff5f254ccc38117ea60dcdd5d5fe8764291740cc0b3bf9a933af8b7d5831a4036fd724cb4c4394ce681149a0102798dd4c1f6ed41f190eaeb8243f08678808cccb7e467d69abb83a88414211c032fba01893f5c408e307ceebd74ceae8d6605f5911e682d566cb66dd501e04f570103bb91bf8f33762ee6b07abb3119c4ba748d092bfafe87d360db962d99c96462920abb4e6d076e9d54aeafe8dec563b1930a4305e2b3961cd363bc203be0649f270004a87c289caf311c65374cbb573fb30b489aff09a66d7a09f9a95ec50f05981bca5266c862bc9bbeafd793debd4cf3eac2ee50f010df931bb6877f1090bad5b9b50105245ef83e663fbc6e9cb3f2c9eebbe44eac2f6e5844c13610333d64340c7e4407611f4e11d676e9773502f6ca6c070975297cf6f372dce0875de3f8ba80b48f58010696ea72db18de430b5c071bb09d51d53d03197a33b1df0711b5f859149ddcfc7358c84573a7518b3719b67ec01fa07140dda7241b087807c1d4548c1876559d280107451380b740bb8688e23e7e0875bfe5a44e511c4a581f81db9a8f097290bb42cc16ca0c609356f692ccedf5d8fc40bb12cdf0ed7af252992da2eac282e3de9fd000086fb2063f49bc33d1f25ee13ac31cbb2a0ba540f419df1cd03c91d0aeb8e97d5e6feae3da4362897531428190a8b458c327e256016ab6ac62cc1b1e931225baee01098bfe9db66d5d50eb6177143e8db1b23200c677266f02ac2d1c04b90ee9a1d1b476a9f4f93752555e86a54e2f5bb666866310f8f587356c594218aaf41d20fbce010ab66121eb5bf8f432e1ae32bb988dd7c33d482fe4d63abe1386d38cdddae0c03964d792f2704309bceaae0c1b322e46aa651c6e2a3c2611903cddbc87363bdc75000b443a31980905ef953c262a9521a815c6c676b84b00d3ae2e8783b212785863da7ca89406b27f9343529ca245552b5ddbcff32b84ff42c62bbad28e5cbd2f874d000d4ef0a4d42e2be648eb6bd37d6184c123ab0a31dd804970416972e5be3fbd6a0044d9d2dd64a430cca95110ff36f2f363fa90a0ceb524f229b46caa85f9b18bc4000e0ddb23380953eaba05b8d493f2193860f10079a2ff6ffc00bd11db94e22b5f0e1ab3bf4517972a0aa2d7ed18551231e083e48ccc07e8d64ed20fbb6d57151b82000f39eebea1eec93d3afc71cb9ce966daafc586d47863cdff25a413470d3cd5ee2d55fb1edbddfa5c7fcc9d5834db2f6f82a380e1e5d6da9112d4497ab28d3c385501108a585d5960d95a50f9cd6c8ca4b8ae7a70b4549a052771edff1a0c3a409ea5cd286eae6c53eb280038605384d051e04e8c2c531c0f8713e36a5c4d71a044a40b0011fa3cd95765d64bbdc070008c3111ffaf46ada75e4dc39607c643b547c3f70d423f0f4ee2ae5d7ed4361869896dcb012368a0a9586881c579a877728fd761f53a0112447e5b97e5341c5ff2e91c0aba8b48ca985f369992f00fb17fdc9c0f6576b93c6beaf3a44dfe8972df1f28c4eda7336a7955e6d33a4cc1e1c324ad45de72d56e0000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdccca8200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000200000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
BSC (4) Standard Relayer,010000000412017e9b9065c4e951aa2be60cf6245381abbccb02a3ac6b0f4ef3ad4cf5d20653d3523e21898e03fe391eb12b187da849ffe1126d85f4d11f94c428086e67e3680901026da8015f1f571f50d3a53846ac0f1c75edef71e7207f818605a0096083fa3095144fd514006caca2456c0924e44480115702b733bb10b51f7ae742a4980bd72d01030941c73fc173d2f1bfa810a141db2343f3d4ff420c56ff09354b2718b5baa4887922208e9097f19f6607d8b79bfc7ad469d4bacd3f60ae9589fdad238aa1d95301047e8ab11f6a80c2d09eb9717766af25cd68bcf8dd90385395110094ea4bde30393b1ce9caa4ad41cb254462a9ec56f9838b26ebf72f9034e9bd89a6be3c5d318100051da5b430178acfde6091d4cfd836926097be2862e30b96d89d03f9d6b9bc1a8319c814c9186d30a564db790136e24229be6c21a115518fb2e0a7f3f5053771c4010616dbe51c1f120717f6522d72cf85e42315d65dd049fce9e691658d1a0e3d98c865c71d6fc5cf7682991c476bb5ade4048d71e3ce81ba5fa2632dbd17a352260f0107e1725d04e8ae2dd9a418d04c4cda324c1e0ab23d4dc710e7a962231b5daf083c39e2ece6968a26bbf62f88af603b8191d39d0fcd7d66375e49010de37f5c52030108fbd37725bc32e5e9a872f0477be346ed302afd45d9b0e5724347adc0cd142c020f134770727c9d57fffa249980c3687cc98d62196064c30df7a7147f07ce3af60009f6a21b63b3c8c18f96b5ff71256d5ed0f630de90ee65eebdaf6b5916b4d6fdb276d7dfdae5e05ff52a2f77b8801cbcb1fb988c6b4adcddd9aaef2e78847500f1010abc2784590de571f08bf3003ecd50a564303376c0da7a145118153022be444d940238147ca54bf65f2c312389f568ba80b0c547413a8fb527452f09320f23347f000b09cfc420c968ea26f5ca6f4cffaeca802ad7419b7fd62b616d9d677ece38665712367d18c22deeec861ccc97dbb42b862493426639ae7d77f6594a6ec3a4dabb010ce6b17e707f79583df2837cec6cf05f5d3f70b99f04ef6c3a54d55e770f2aca4a78da87446c11bb39ffbaebd324d7b369944049457bbc97256dd7b06a61127263010d42c86ce3294e2cae5304d94aeb30de4c686612d090f41998af8a1473fab4fa605579308201183510ba56602f2dbba3694959e052e0d2ec973f127308517898ba010e113a38c219ebb990c5bf15c9b155bb45bcc773b53dbc2c3fcac866ab00e0f2be61e3962b99e25bbe5fefe2b0af5fde001e35a71e1856b369b5a179d3c0a826b2010ffddb788ef1f70a205d08d44a8d5762c5f5ae5b236eb2534b55e80193c558a6f460bf89a618cf57530ef32102b2e880fb088c062e0bae28f3386dc65cdd58c19c0110ea9e738d883dc8a194c9f180a1123c2496be82678047d6220600657df77b28fd1ec53df79bc47487af116070ed44a58ab86e05030892c2107342dba5f742eb390011759c6d8c25ed3f4a60b7c30473cef12f1652231ee5e2d98efc29ffe3290a6ef37fbee021b0dcddbfbf11104ca1d9451d3ed455816821e2c089538e7d605e0a380012a07c722f449b863d996f15185efa1fb5b056be6d404c8e793492edb5736372f27a9ee67e7b4998e81cee5f45626984d801b81ef7ebc980cde1959a48b1ad57c70000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdccca9200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000400000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Polygon (5) Standard Relayer,01000000041001f100c23d38d57e97e66009b25adc7ebcaf920f5a1f621d5755d331de61c5f21631a6f0c9fbea8ad75534af4947a4df72cc293944b1aafbbcf0727f31e4071b810003f100618c84ff56ea49f563b432bad076350fae7cfcfb3dec92540803d84ea93b5da4c7fa7bd7ec363b9b612dcda7cfec9fbebdbce517dc30903f13c2ec5cb14e01044a5a94e02266383a11d1c63fdf50b2cf4a4c75fbebf158843865377f01a0cc4710e908e5190abbcabcfef294d7a054eee84a9bb0ead041c09d10f7a9cb2077000105ce71d2e594f36caf27e8b769261e59b91e9e57fa16205c6d375074615088917e05130f24f1bf948431bcb025aecbf24dcf286297a3002c37ebe72acb5c2430c601068445c65befad456f1cc427c80b2243b23700c152afc60b298ccf5d24261bd9ee1627bc40aa527bc67de91de14cc0dfb2d99b9ec08d31a7ae3e1acef1ff22acbf00074569b66d9ee98c4f2ac6f5498c721f3bc66fa9bbb0ec5e783ee381f9f06046ad54042a921a3f7367ddb192ce880ed5794272dedf0a34f791ef4370bc07743ef60008991ec96f347b242770e978a6473da8c82b14dcb9a5ccc05dde4bcf1125e3d9481c25f188d07e1e4e68a916cd79ab21f41a5433d779660d15808e6c172c55accd0009425e5f3f71af0a6ebed1bb037590319bad260e2ebd8b889bc64f782e594792a52874c1973cf69b76f20a33317fa8f16e982afc85fe147ba742be1222d942dcf8000acb1b63f1a4f30702e2b883eecc8048ba91b38a09fffed33299b0e5aeabe09f7809fca5f75fc6a4022b902be7caf793a18d1371aecb3d9bf0d7d27640777b2cd7000bad7121a6512bfe27856dcbd5c1aa96ef1fdb6110b322a0750870b96aed6f06a30678ed78b4e7dc8c57a6171aefc1b9ca7e991ac4a47d2655caf38d22858d0cb6000d2c307443c8329b1c9e456334253c604b5d6c1d7f5dcd4406d9d8c4ed138b72f479ff2f412a41474f3d619a41c8bf216898b8e8a17d3cd7275e6929bcc221b848010e79b575b4795c6d3cccaef379c2f533de626df9a87a52389f38fac3f5d77b57aa317aaefa4386aac86638a9e19cd0dcbd92f9f087fed54c9e28cbb7eb7cc75b84010fa8c983e5931d1276f84540c4005a16d53071e7a65013c5a9812c4e213556739b687a483eb19abb3f1cb73db7d6cd924d212d3c261d4f3018e8dd96c99dc8104500108d63f8802b17d2ae03a138c123b06a3be5fbed3d478672dc5009a6b6cdb13dea467ac4dcb16784cccd9ca9459ee98ceeafa0c9f444cdbd3654f034f288a24fe90111bd3e4eb9455c06c3aff08836f55add7b1bc5d389a1a02d02abcd5d54e5c1df1c31796b93b0b0e85320f8036a38513bc48008b4acc0890936bd46165f2589d69400127f69a920ebe11ad7b73eb13a8b2729d7a2972ef6b86ec2d9b2ca5f4e3b8b9cb70195f59e62b715724ed2221e32c4f537858d12506ec4d4cbf566982bf63bfb5a0100000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccaa200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000500000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Avalanche (6) Standard Relayer,010000000411018a3011f6bab8f816897c708383adf3f5d49be545bb889f4f63133f373c54f02d62237e540224cfc4378bc2e09ff6127a5e2cb8e49bc5d8d96c9d4209ec772bbc0102c09524e6fa41789b556325a4a893546508e5c730ef7f52e4ea7640c381dd476e125708b397751ee2f344b6e123c044ade712f7f83be418c0ced63a2aecae3968010301035d39f88f4d0751269ae4e098bbe47f3591357c1b616b3e34a5c21c4c1f2c6bfd2b19a8078419699405f38d4c30b3d4970c8a7a37729dfc5c319f299883ac01041f645ef4100c53a244d4963a122657e93e8999baa3f6d1ba4f85377fecb9175a31b6e00635e4d06229892e922e79ce817847476e4f3a0be7d83ff59b472610d6000566ec129bfd891f510f4b350743f2ba9c061b0b94d9cc20d0a75c20dd863722d830ad196d3cd9fb5158337e875a7848e8653d50ff7e7e63c41c2995e57e1c0397010604b345098da327b1ce27ee48a6d2bfd26a744090540042dc1d698a458f726b730f39815ab1254cc9b45bf1fb12ca62ea9b5f9f3285974c350fa7e23fe4a9c8bf0107c9f099ea1e931af596d0def924eccb4b2e64fb77b0afca8b112c1b30ab3aa26e765d0ad8ed0128a31c0fc4048f1cdcefcd4c7678c259d06ea7dabbd720fbc8a8000881a52213d65d8fcca6c99cea3b2d134518a451a277a0b92fcf0dba0684fc52c37254b8a2ffb450a1e0777bad5097d907cf5a48c7d70c037b3a362f1973b143d2010928b25ec1394bf9caaf9c95ef074babef722c15b0a4edccedac3fdbd6a6bd87d36ac2fb490e4605eb0d53db3eda85527fe5f00171a5a5a81b283c401ef0369794010ab5470061217ac4b94fcc45fc23292d51c04719493a2785a0caf76eb3497a402e13890bde914f07b680b84079f87bd1448ed8e4f2b1d6a60661986a6f51593d66000ba84a3b14fd2843dfdc408190f1330539d7db5204cada959b82c9a118ff9c633a1c3ff7abf7b2a0bfd7003fec72303a0f39dacd6bb905b2c721bef7f9250b3f1e000d5fa87309ca8cb8ac33c516a3c3ce860c2c69411c4f5abfec0d8ee7f08a917718371fc2e5445d27f9915cfd72396ab0b0f76fdc820f87dedfa6a129a376d39671000e028b814eb1f74fbf10a5fb2c465a254b0002830aad9201555d7f9b5061bf99f41cbeca0fbb2b6dda51fda40dfcf88be08b3c9a9ee1410347a0dff0f70a76fd56000f1cc4a10a0875fad35c42b795c9357be35a67acace09706af13b4009bc72cfc8d3957a2baeb28bbbf0d22256f0896ed0f6fcd098f688b64b53dd111c4cc3c2ac10010fa217241fb64df96812ba7adea8ff477b4c03a76c25ebb3f8bc817afca2a735c7c8d0c57e02ced4c522dc5c5c02758eee91fd3bbf8f69057e93cce6ed177c9d500115cd9c43d6c791a3ad05cea7cfd97f76a1eefa267e134f0d8144b9fc527f93d2e017c44c427670248954d1d119b712412e032ace9f4879b8c36439c100318d0f000127cb2e52609a2ef2838b24744233ba084f76748d2b553abefc70cef8f05eb16731e013081b28eae042ef40f73104ba2b91760e9369168ed91bb98d985edc025f10100000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccab200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000600000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Fantom (10) Standard Relayer,010000000412015298eba9662833bebf84896d4950977e2b3a798843724b0f94e6cc593104ad0f3da6a81c3cc2a5de08913eb26290c66fa618e6fac82b6ca253c423994d7d17190002477859073938199baa195303f6c2ba8cae0c858f61bf459a833114e84ab2c6762e798b91db2623a67704c58656caea49c7459afc820f910742125fdef6b6cc270103d3cf95aa84035358f41d4b0f5dd0c59c2de8b69af4db84e29b5df51781d4a4437cb885054e625a4ad03324573e033bee6e4169fa7fa169c2fb4a5c4c7e69bee001042e63b87f925d6d9b48f8b6df815593f8cc41d12af45ca58cef567a2dee37236c734a714cf2ef110dced59b0b019b89fc06b16328d4331e905db3934f21874dbf00051f843a340ffd3a605fd84480ef14d8595b1fffdd45a7e1c919c686ac1bd234bb4255d6ff88990e33dbeb751c06ff6ba5c63469fef50fb9924c135a2e81db0f91000678e5e902519def669dc1b03d3c9be4b84589a6322bcdf3c8cb056192a13774487a49709566d0cc68fdd9c6d1f368152f1c0728bba71031a867dbf8a170cf694e0007738f6d2e42d49ab86137f8e0f1c1bc2b2b95b9f0f28f3698afb11ac5024261ae1b41b5d705a29ee77abbd7ac27d237fa4e37ae1b40df56b9a067024c90ca6d860008b25df04e7b4147bd3ae3960fe7f181968c084b63a89ca11c28e557d516e6ac3b623b56e9472041a8ce9fab0be14e9f6593caf203242f5a1a8c00c8a23f947183000919c402479e75615c767de34eb463099fc752c82aa9def7bb5dca812dc5d1a14c268f8c8a4c659be8fae0e51d2f0ed120cccac58344ca9b3df9a9cd21fe1919f9000a7c96e0c21eb74310637c8bccfac24bf91190dfca3a7499bae885a4dec541c58f241933b0d567854b6d8c2fcc284e9077ffab16d6c9c0f9b24cdc2f7875e0a8fc010b0aa4e824c96cab81bcb799c62076cbcc8c88d81dd8760d2999188704fc18251e35936882eb00ed58656432be6f60fbf144bc337d1aeb146e19d80359764f72dd000ccdad41a3722e94317d99ec9542e3aa59ea9cf0297f450edc57c037408bdc5d5770df000375a79ae231aff1eb128c657d0965fe8e4fb5efef26720848b6e68a14010d419a91a2299ba3d983171250bfcda19b462c6cecd6c689ab44cd06d77b3c9bc71f532521b1334308bfed01640ab3c8d212f2e69f349c7697fabcf95f43afdce7010e2238dd50fac23d82778680768dc5cf4ffd02bbb351483dd625e034c9dd0be00a1a2c49f95238a7cfd7ec45038b4478a457e9b9c217fff574b7dd9d5663c65346000feb07dee3c5ec9c0a74f181f76f2356d34adccd09cc889758fb1afbc180ff52ee6a6d6c04afcfb4b92afdbb79eed5f8c7e67c7c90bc9c7cf289887eacad42c9a601100fafc125ed044c06597a7563f22a5ed5071cda2e928bf401a71592af7abd6cf45b114d1d69ab5c784cd4adddbbf51b461e85c41f5792c5e309f86787196f9f560011141a93514e4236da671151dfce33f1fd24dd6e9cc88d16ba2fb8e04c664576b122cf795666f5b5df601b2243382b99852cd23840d91c6fd7dfbb33e27753794a0012880041feece8698f81bb66e9817ffeaa30eb58b5ee4f667a24fb05030fa2ffbc347cfc3f30bd9a18ae8e5e9c01ed40d46459d25e96c486cf849d5f4dbea188480000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccac200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000a00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Klaytn (13) Standard Relayer,01000000041201202b6807f3b8bf18ad8d3097829f84c89430a2c342e71f839bb426b8285aa0bd2cc96c07baf96a4e72c90d4c00e402847482d2bd1829e8fe6ce70a9cd2a2583301028e48df820ca4eab9737aa1d5efe784d061e11062944b5035f9c24500e644b1b747752dcdb2d58dd9ffb4b08db098121c884897df42b704fc9914f79e11072fde0103a73bdd6b228644bdc483bc8910c39f120b83c315c33764c308d9f73bc2b30c4f26ce6b93e3de1cceab441db14445318075bde8e15e9aa77fa6c311e40bdc0680000426c3fe6bd835c32b64c567d246b7efe5b4b76319beb8bdc8e02583d921dca6105ed671393ab77a71aa0bae34cc3873a747eac3baf004b2e77a571220d3329b0301053e88ee079e28c6ebd2cdd47cee327b7ba9cd985c5b01352efc25689ebeca85844f7bc66da3266dbe5d5bba69ce0f3c217e87a051fb2de74c253c1193e52b171c01064a46327c3abc0f34caa2cef14341903e14a3b84e67d594f45d0105e2e3b4ebac3793967c20da12aa3f38101fae3f071fe870fbe574657c021949d3df3003a6a70107e61150b95b83e7d8a86f817751fd75e9c8b1c3819cedce83ffe95b656f2a46605aad1a5d78ebb394ede8fd56df0caea9ca865de55205caa35e85b63f60a5fa4801082d5c3b48bd744256c9eeab8845402e5a937481c8ae1fc525da22c9987953e3467e19a6a31c66ba8bff7dcd24d7d23b02d44c79a09da9efacb5d9be8f0dce269d0109bc3c217eb4557cbd5b486ce13e577322808eddad286ff56f8c6403de7217a32a102e634be26acadd332b24a05a04068f823a74a6a41c4e2f91ab23f6217d8ac8010a823b3773e8a5c222bf5a28b95d2ebaa992ba4f8522337e8d2aba19bbe1ad72b4222e6a86a97e346ca937464098bf5f649f5f7e6e18e71d5b4aabdc0c19bb5130000bf67da3d9002c91e9aa913687980a22692ce1ade3995eaad46525928990bef07f0e87ef7709fc2fa77437978b105cc7be084f134ff992f69002f4165e0a60cbfa010cc6d232cfefef4ec108fbef959aa294074eacb83b6c7a8fe5f6b3e76b6d4b3c4679e1e6acb3186651d7fe984c1fa895c4afbb421b18074f917e3224b684d9006e000dd4936f7cbe9cbc64a98a654d4673e66dde3a5ccd52f8f3e16fa69c01f1e63b80362aa8f70c771b04a080bf847b5015914e189c9053e659c996dfb4e1275bd4ea000e8ab19b52ecc453b221bd23b3b437243da76ac0ad88e49e71baeaae300654d8344687f7cb1d69df24426e3d18e90ba39c1267c63725712ab125749642f8742c53010f0e201b577e11fa0c0f85642a40352951615226295e7c9ad18218e00d3994d31d67632a6bd6445a6ba2eb02172c09ff293e4f06ba8498a9e360281de535cbd0760110ab99b0e5b37c20f786b296923131c5df829498559e46f1e5c2971fed93ceab1700a61354b60fb640e369755a9978bc57df01a55391cb5fc7400c6caed0121a890111c844b51223b2fe13448366c8cd00edc91e688ec419aeec97bd41ae9776f317f1770c1742825c3cc1bde2c0f8928edc24874abf23d94d3d12f121b661d313913b0012f46057fb23e8b994dfd0168f8dce2f661ee24fb9ffa0be22a8b0ab4424f3ffc6567d9e5c124d2dcee0d3dae8eb786f0c1d4b38fa857e17310bd25e4092c371c20000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccaf200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000d00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Celo (14) Standard Relayer,0100000004120121285f733587727520973bf05a22418d34f6b5aa27504c4053d5ee5ce23a02c31153495f3c533ca16f71107af7a54b88bb8fc7d64d20206ed0eb26ffc6cfe5a70002d17c60f1fa5a84d2ae69fba2cf46edd03e3283ae74991abaaaa017ddb3d9fb4e239a82eebe14e89f794ca32a421f2516d9fe57c97133f20bd4a34da78a50102e00032085d87ad27eaa019d14cdeeea575f926ec1db44180cb1932b6ff54b56f0a9d73bab0e952fabcba8135fad9f187db120ea6fdf260cfb3869d973d3eb725c457a0104c7af4c135eee9cfb346bb97350f4c0ca5832cc36485d3fa11603f05d42cf9c9f65e4518bc5483dbde664518abc30d2e4741d18649689fb5c9f47dc288a22b1c101050c37eebf1a94032b3fb7f53ffabeee25610a804c7f58c7ab7e82b8d103adbe1f3af1ae9967f1045c040aa5f3a4c8e4d8d5a3802ca826483e9a1a15f8e42399050106f88d72d019b83cb9b10309c8146e19769da72bb59a26369249fe39b51d475d570e57f5e19cd864af9835c4809b2668afb6690b24f271d37d9caf7089402a67140107ad463df69a2591bbb892fdd1b28009802ce29b3d8c98c58248178c927ef514245e2c4d99968a30bf642e750d5345aeb85bcc2f23fca01e0cbeff8e2b3be32a930108e7ec94efd6c6c06e792c3a7e8885bf305cd652a76876d49697c99ddfc9a98b786bc215521a03151718cd81fc4619c72ffeeb29e6cd968dab9d512f7d2d0eba8800095b6f138e529675fe335e5a72f6bc1a35d20cf518786519c24ab014ceef61eb7133adcb701a7f75ccbacc12ab5e74dbc7c083ea8318d0eede51f486292c901e74010a538c2fbf35b4630f13e694da19fd3e2fa57438622af490fd3bb19a620f88be3678b5d6408c7177575d04a6559bc0bd19538f93e6dd5288d9931511ab8c512d31000b4b193a05edc48b51eeaa302473168dba70821a22541a0ef2cfad161b2aa3bc82066a56f9f0f222116f2904701b05201d619fb3f486fefd08876c7a5bebd67c09000c6563e95259a53f854c5441759804111e52ce42e5332df7ca601cb14091d3c6d81a37ffb91829cafc053e14af24a59ffcabc3fd774e1399901154d52d634057fa000dd639c68822ed4f29afbdfe349fb31cc367b065f5a3bfb73587e0aaf8dd0ad5161be5fd99d78628a7bdfa8c07ffaa47d6c4b58e6b470dabecfbe95db39a96496a010eb85a203b18444f5d26beac38279081d618a50a77f0fcb7d7ff3f51fb2705d9a167bf7c7a2506dc4ac90b946ee63d8a9ea6bfad8aa8494f99f2af5d15d190801b010fc87ba5e8a9caff6cfd7e83376dfd97a6840906ebec31e299d2fd0940f936061d605b244bf2427cb36114d39cff7fba122d6baa6d6207257d42e4fa43473f0887001018d5a390d01b98d9762222d97d3cb988573f256a7a3d512bb26db78f2e1284be020a6d5a9660a869dceba199308db403e0708c785e1c2715821f69a091f39d8b01110767d6f4f27f9db7ae9e4256b9a857e78571e92197cbc8218551da332fb4110e07dfcc73438b8473b91f3a93a4bd96be9dbaff86b524eb8dc1639da33f1f79a00012b00387cd213e2e6ec3973bd90d98eb4c500c9c6aa893cb1d607d9842a326b6e75a5644785dd5ff7c2eef012e938b6df215ed4e97b8223c078fc8a8dba92787770100000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccb0200000000000000000000000000000000000576f726d686f6c6552656c61796572010000000e00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Moonbeam (16) Standard Relayer,0100000004120179716c0fb88b8859d07f660f1732af0f8e239dc21a69958235d1dbef7572588c6ad3669b231555bfae49e6a81dc27160026b1a86f2ec813a650967741475b9a2010211fa62ed1fb2e4ac5762da890ae39f0542522987555ce69ce8336a189f138f7100ff0999d9cc68dbcb74078e8b2e64e32513414dadf6873018a5e0245795acc70003aea201f953a34c7b5cbbccbec6c42d474107efa3c1f5f25137f0f7f1f8f3446f53fbf9b1d475f396cd04878e0bf9ef58014beec38c3fb698d38602fbdfb5f18b0104e355004e39c7042982a07a50d0e7995180f3336f6c72fe0edb17f1d0acefb13302799ad1b84d4bd4d5f11b2633a02b3ad7f955cd30387ba46d20546dc109ac010105fb93126334289857302eaf327690a0d8457098fac094a6817b49f38841c385295998dfc8d50071f296053d8fc472685fee36dd8990c8230f3e276e1b873a75be0006241945f86c1abef3ee1286b1422c92bafed7b38c3daec22ba602526675b4d35e1938ab844b416b6a803bde5b12648d66e9bae68e34dc87450a69a64bbd2034ba000728253f463ea16bf1c509575955a47d2a88020fec9db1f5e779a66875be054176795bdad1c04ba3b7ca6aee98d2fd05cacb06aeef0d6bf693c59f14da5d60c0df01084ee90ad3baa0ee4ccb987f686246958634fd8834790f8b664f8ff60bf1d83e25636b9e9ccf6323234cdbd8e52c138c98f85d4ad2c40a15b136520adcf36180010109a76104932e8c3a7336ca6cdd33b1b69cbf750eb724e368fae15334ec880921963c9f5e317de2b6d7bfc634c1cf6d26567662dbe90a0f78989c2e09d8671ee004000a4b57433c1f5608e4c0e78fbb597271bdb79060a01126d555db0a00e4160e2a0e6194e6a2c815109b3ca69b14b8995fb8b5123c11e769b65865c0c48d547c15b0000b76add1069fd8d6ac522acec5153b0aefcad592d9e7a5fcaa8b0b1c42306fb18e746cf5eedb4e9279f4021aa0c6e189447d4e1d6529fdabe5659ed348a98dc64c010c7be055a164a254ef1a8d423fb8a740f365e384dbfb1df6279ec1aa2f8e8ec33f5359e3dbc50ed0b6a6f81cc28a8df550e0b22f4039197c939fb08bf9af6207a2000dffa23f41b9167fbbcbff97425f015f62d68d4f469f0973bdecb8fab41a44c1f131ac820ee22318ea239a7455e1611c77aa7d26783aa1a11203b72f447519520c010e3ef1157fe2d4df059a0d4d3796783bcd9acbd30b9ba81273841a6f82c56b710417dbe60447e5c1bc362bdae2eb15cdcf2af4d0b76577b1b13925e0ab105b4334000f9a5bab2b554ce1cbb63d47a3be885fde9b7d5afc82ef3abc6341b79f182de5b65170b70ef3b015ea5f18aea87546f1abbb35f8fb6a2748d1e6f5bf55907d03fa0010443e60d8ca17b58f77996ddac9525cfaeaf5092ebea04f13fdf0aab8204bbaa23c04b1987b95836d36d706597b2439acddd2539d9f6c0bbeea970de801f9eaa500114a111aeaf1f695515f01fb174e606835292a99a2d953db84753369b7f6aec89a4e9e12db15b76a880b92983f28937e8e2569bd3a7eeddfe710c8fc4fce011ed80112433a42154cbdb6f1b1bdbccff6fdcb90e8b174540e63825af039b8fc43c1bd6211c1cb4849d6ca8cb2aaefedc684717faebe50b111a44f8224debf9aa0bbe5b00100000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccb1200000000000000000000000000000000000576f726d686f6c6552656c61796572010000001000000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Arbitrum (23) Standard Relayer,010000000412010ec78f0da9032eda3bf39f793f612a1f91a40ba7b2791726b5d78b8669d63c2d53ced3e8daf9ad7c7a9eed68b9e4fc7c418403c0e76bade1cefa5d08e9ded7a60102254161d961c9f8e4f84cb48c12e45cb40dddd43a3c7215c480e3d295d7018e5163cf27ad2d53f692eaf5461fe60ff0b0edd33e6989f313df802ed5ffa0a664780003d60b1a8ec2b4ce27e2b7298bb3cb503008b945480d537546dba2a0b1afdc80e26bc0b07d9ee4f3ef40048e25d72d23de26d22dbbc7c23df6eef0367111ea466d0004990843481a1f07312418d822eb817d24ca80d7a53464af9b1f4bf81772dca47e33eb46dd579703c4ae31fb9164e5508f474b4055aa703b0a7c8eebe6f60be04b00053542fa8dba6b62072372bf92ef566f1ade2a95f7abe97692d20bec89c9ad220e49718ebccd0697ca592458d79a73c3f489ba7b5bfc51d9cafc9fd3b54e5d82fa0006b1f4dfb7ee4bb3059c0f9fb81c6afd5b7703d7e0b54720067d7ff7c62755aa3f0e806c426c5a7238917f89cfda30b80e7633cff6005a5965cf61356f551964a500075883d0f908800f54a9feb4211810e14a0a0d65827c051f3793d1511048deef8b7b687003455f2ff07a3395f1297936de1785fea7568fdb62d347ef1b6a1502d30108ebe7c99a2e83a7515927246ac0accad976a388245acce1f41ab198d37b32dcd72717e17dd7339e04d0b97a89356fa994e5b1a036ec80eb681a9c3472c26dfa1400090e98acccf12cba83b7bb65b88f532afa0f86bc068e1313e186b49e9850650c7c6ebaccc02e627b5d7470ef9035c08cae8d874dc4b371945b289706deac7d9008010aa0f27bcfc63715902446fdf352554ea699e361b8e3dcbc57b840f8b5f7dc745e02847d83317d2029b73d47daca88852f1beb2a49004c1c1e9ef4b501f417dcc6010b08ca6babf828e69e3b5fdd0db9c34dca35ff6fd2a2bb261a01216abfd31cb95239af719cf2ba294a2c1b45dfd3d901f68bca3a44d1cc71a180ec6ddc6172282f010c724aa60c084bcc159af35a9d58078d667534cb67bcfca5f959e05eb1b0956d4a02ef98abc9ac677b779b1fbd7505b1621b0935d1a58d7373c36b96b99f8cc0fb000d3139b25069520a4bd9c61905e7fd83ce21eb5786b26b1e5b96772e4933a6eb163dd4031a1bed0cc65e39e00d0a000c917b69015696cb1eed816be864b65abfb2000e794260e5d734ae20e53ff34799b2a9a39f0f792371f8f27e70cd5c14a3d781816b7dc8a3da6ba886f2c21b304648c51c16892da6bacd10776182cb65c9c46b01010ff9bd86279193140979c846052ba99d6f9e8411da7f7004a8e02728579f2283a9510c090466ef71922a58184b5be558a790866125bd76211f308aaa70f080becb00100efc7a08cb812ab047bd67e624197e8244adc6a1ce0d9ef30c469bb5918606e55e3aca65054e0f46e6e7eca8f20b9c4128791ba04496ae9713c5242883777a67011137416a6f4a919b2b4dfafb55c38669b93d66810ab0c77cd9285c71fe3a3e38a36b18c4fb1f6e0700b89afb8f74f056dd58846fb8d0444c3b405afb7755faa3990012747f08fba62aa374373a5c36b6fb29a36d4e382efb2b0a54b039aeb8f76fc764683b02c529802297429d0fb5320b1e6e5c63acf309e03e0f15f7a1fe74eff30f0000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccb2200000000000000000000000000000000000576f726d686f6c6552656c61796572010000001700000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Optimism (24) Standard Relayer,0100000004110188474b81330c0fa2db74ea40139146de4c3f62fa3eb23df25125a26142845d011de1aa9d844605a8d113bd1142e45434f1690812686d7161aade3588e94ac698010311e848aaea7323cddfe9d1f45189acf490d3130b9961855aa00c20e7149395a17f133ce44cd4a16078f2f884806d901eb3c56c7fa11a6c628ae659ba602913ea01046a87b3416c3569a2c41fcab24fff66b07701a5fd6df72a3e6d044398054e048742febab5b5f8903703c6c73ea32902dc94c7ee1c4f31dcfb04c52e0f27d93b2100059d830b8110639295a06447b4f54ed72585a30256bf600b7f0fca48f71b30b74f02a4e64c1f2c4152a2f3b7e8ac28e8029c0f60fe4c92f00f5cff8e5daf2395210006dd08a89b93920292bafca3ab963d171e884cd3bbb9b857bf6f87ab27ad2792150ed5bf038693e6ccb855d2376fc0a4087747fd1154dcc4c20b75df05a758196f010771a162500b2783c74223ab5d28e04f1269e49254630a440bb9f0eacd8b59586f01adf5ecbc7c9abe0bd83235a813b41026b19f571e0af31bbf799fc54e54bd3f010809d6a0821706b2fda0e73c4ddb551981dad9dc1c2c8e85a902195cebd1d8565e528fd078005dfed95fdb92dcad5971ce68f7b5f897f72544a346a073129ac6a700098f24b7e0e5a26410c66b1b1945494d36b9fff6dacf16c5a6a22f01a9ecc021951fd6f992c0ba7ab688b5a90fcd9f96a7fd28bf044a576d58b1a9b85f6964d430000a0323d4671721c0262265a37ff9e3459196ebb928c3568ef4b15f5812ae411f1e4cf9acf02be0f66d380abdcbd1cede4c35483e680a0c330d4fa04551e7b39a63000bd03df44627e6cc431261553953511106c1d451b12cf50c977e0280117a75067340a671de2b755cc23dd6097e5f7f922bc2cbc2b78c499256e04ec75e8f6bcc3e000c4d0e32decb9285203ec763ed6cab15a1fd91fa8bfaf3bfaf449a08e52b79bdb76a10fe2a67974ca57549811cea6b51f39d8abc47b7cd9969e7d6f3b86c3949a6000df8b8844a14ed09439311cf4588760e80ad2a6c460759a85145ded663c503882a367a8ea4727e147822bb6396102d0ce6b90d1e6b87b6ce727d5fdc202b83579f000eea060f748330d8c31e520b8c3b68873e47a6dabe9bd0889dcd7525700b90134b4892bb973ed3aca95343644e5e87b3615409f2a872be97b9a8aaa35661354650000fd64d914031f191e0d748817eb8f682daf8157c46c101d65edb6cda8a23bcc13d10118200042b3335834a02e0c265422d2cffe6ad430d16b12016aa82266f92e001105f7c654722a67c678528e8d6a64a26f5999c70cf33adacd1cfb64d0f8b0c26f81810ba862ac88aafaa90ab5a0669aad2610dd7ad16b1133f4c0dcd4d491a462f0111b698f2fe7cd834d2bdff5d4e2f0289d9631bb910db3e64b91689b7aee09b273679c4cc40da83f0a579a06c756abb9ad9d2ba150a4d18be34c5e88010c46dce6700120ff19d84f49d84cadf0c27f91955b36980271a571c17ac85daf121bb6d0490857cd79a89eb5e1532b74439887ea0f66a5f9ae804ff063b896b24d5014b8e95ff0000000000fded29f600010000000000000000000000000000000000000000000000000000000000000004338004a37fdcccb3200000000000000000000000000000000000576f726d686f6c6552656c61796572010000001800000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911
|
||||
Base (30) Standard Relayer,01000000040f0247e8f4a5a1e5a4f858444a50f419a477866f7ad10af94d62251ff5a7f4a42a9215002d6b5a7939224d6221d743a0107792b4a1efd42619732a34c7c2cdc4401100036fb6ef9f9c50657d7791bb344b948d6c812f1b4070381003a942419b174c4fc94cb8d63cec79e13982a2642d789054d0746498807da03d3c59a39efa29232dbf0104bbf027b263137578ea240576f12e3dc1470ceda63391dfeaaf0f71af0adfa764772a206847aa10646aef2ebdba8ca21b6c08088cb58942f2145c5120e0f94b86000674719843c99e12cd2b9b37f98431f8dd8bd2d74b0794291fd8d7b8b575bcc8964ee2c7982fb4932621996d587eb4ff4861e1d0e6d873ee1ee8b9f684f084262501071243774552bd7af6f1325b86965546b960955e2c594b225ab2df51bd58b7ec5331f17d71b00298536281977290ed6d5d1534cc6693137988aba25c19be3295020008f33ed961639ec82c1be05528b8a75f6657bcebec68827e8f295899e41423e22205312e5e7bb6453004df0eadbe11eb79588ee16f5b35fc8db2f7dc7d457bfaa20009e439e5b37dacdec25d12cba1531efceb2f130a812d2d99fcb728282bce06dbe91fab11228716ea1d430ae8a08ecc2482e30b439b912b7b0dcc95cc80e98fe6da010a5224519f03cf83b67ed6d31a5495edcf66ac10da2d94bac542109be2d075f7230b63c1576641ad6d9a54b1fbd5fa7fbe3c08cd08f673318476aaf9fcef48c6e5010ba277e69a71938f8b1197cb6975968f7e4780fda8e6136d23d2c9f5cbbb15d2ae682321eb8b5f683c5825b74492e7a2a4d18ac20cd8c30fe3fa712bd71c8b6033010d06fba68375dfdf6d76c97d3a2e0ea1c9b243d8f7a37114406fc67cb7545c717402faf5175907d1ccd943f20d539b815eb936d430fc3dfb35c3316a2342dba38d010e4ca329b5c61f7faa4223595fe3dd4d14d77506c36013c6ce8e34834d48380f75536d12e3a9cef5446a33766a500a676c3d59b09e984e0f31be780bd736a8150b000f151a6b2de331631ccdda12cf215868b93b12d6bca992832ce5531d2c57b290b72c323c3bff1150f1606e738a0c5165aefff6489d8d1c6194566ca91fdc882bf30010788d6362177378258f98c0a1a5a85b229b2316e43b28a08c68e0303fe2bae4a27cf109f07ed6efa6be02379b07b4ba02c9d81c478263eda7a3c279af2d4987fa01119031dcaf73436185f8853ae273ba23e44f8fbb6ed31b750684ffe45dac34f11813c37916f0bd6c7282b1caf49206e6df9004e0450010f9f93c9e0e20107c235f0012d5b4f5a87674f8c4a686ac67806a45440d30861a43191ec72e5f75a733a8b51c189659e8ed8ff7be73d3a14780a46cb34a58a5308f7381d668e8db58198f185501000000006b45a1a900010000000000000000000000000000000000000000000000000000000000000004555704dcd5046cc4200000000000000000000000000000000000576f726d686f6c6552656c61796572010000001e000000000000000000000000706f82e9bb5b0813501714ab5974216704980e31
|
||||
|
|
|
|
@ -0,0 +1,19 @@
|
|||
# Blast mainnet env
|
||||
# Rename to .env to use with truffle migrations
|
||||
# Common config for forge deployment
|
||||
RPC_URL=https://rpc.ankr.com/blast
|
||||
FORGE_ARGS="--slow --priority-gas-price 1 --gas-estimate-multiplier 130"
|
||||
# Wormhole Core Migrations
|
||||
INIT_SIGNERS=["0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5"]
|
||||
INIT_CHAIN_ID=36
|
||||
INIT_GOV_CHAIN_ID=0x1
|
||||
INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
|
||||
INIT_EVM_CHAIN_ID=81457
|
||||
# Bridge Migrations
|
||||
BRIDGE_INIT_CHAIN_ID=36
|
||||
BRIDGE_INIT_GOV_CHAIN_ID=0x1
|
||||
BRIDGE_INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
|
||||
# Using "Non-rebasing WETH"
|
||||
# See https://docs.blast.io/building/contracts#l2-contract-addresses
|
||||
BRIDGE_INIT_WETH=0x9D020B1697035d9d54f115194c9e04a1e4Eb9aF7
|
||||
BRIDGE_INIT_FINALITY=1
|
|
@ -0,0 +1,18 @@
|
|||
# Scroll mainnet env
|
||||
# Rename to .env to use with truffle migrations
|
||||
# Common config for forge deployment
|
||||
RPC_URL=https://rpc.ankr.com/scroll
|
||||
FORGE_ARGS="--slow --priority-gas-price 0 --gas-estimate-multiplier 130"
|
||||
# Wormhole Core Migrations
|
||||
INIT_SIGNERS=["0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5"]
|
||||
INIT_CHAIN_ID=34
|
||||
INIT_GOV_CHAIN_ID=0x1
|
||||
INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
|
||||
INIT_EVM_CHAIN_ID=534352
|
||||
# Bridge Migrations
|
||||
BRIDGE_INIT_CHAIN_ID=34
|
||||
BRIDGE_INIT_GOV_CHAIN_ID=0x1
|
||||
BRIDGE_INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
|
||||
# See https://docs.scroll.io/en/developers/scroll-contracts/#l2-predeploys
|
||||
BRIDGE_INIT_WETH=0x5300000000000000000000000000000000000004
|
||||
BRIDGE_INIT_FINALITY=1
|
|
@ -60,6 +60,11 @@ var ibcUpdateChannelChainChainId *string
|
|||
var recoverChainIdEvmChainId *string
|
||||
var recoverChainIdNewChainId *string
|
||||
|
||||
var governanceContractAddress *string
|
||||
var governanceTargetAddress *string
|
||||
var governanceTargetChain *string
|
||||
var governanceCallData *string
|
||||
|
||||
func init() {
|
||||
governanceFlagSet := pflag.NewFlagSet("governance", pflag.ExitOnError)
|
||||
chainID = governanceFlagSet.String("chain-id", "", "Chain ID")
|
||||
|
@ -171,6 +176,19 @@ func init() {
|
|||
AdminClientRecoverChainIdCmd.Flags().AddFlagSet(recoverChainIdFlagSet)
|
||||
AdminClientRecoverChainIdCmd.Flags().AddFlagSet(moduleFlagSet)
|
||||
TemplateCmd.AddCommand(AdminClientRecoverChainIdCmd)
|
||||
|
||||
// flags for general-purpose governance call command
|
||||
generalPurposeGovernanceFlagSet := pflag.NewFlagSet("general-purpose-governance", pflag.ExitOnError)
|
||||
governanceContractAddress = generalPurposeGovernanceFlagSet.String("governance-contract", "", "Governance contract address")
|
||||
governanceTargetAddress = generalPurposeGovernanceFlagSet.String("target-address", "", "Address of the governed contract")
|
||||
governanceCallData = generalPurposeGovernanceFlagSet.String("call-data", "", "calldata")
|
||||
governanceTargetChain = generalPurposeGovernanceFlagSet.String("chain-id", "", "Chain ID")
|
||||
// evm call command
|
||||
AdminClientGeneralPurposeGovernanceEvmCallCmd.Flags().AddFlagSet(generalPurposeGovernanceFlagSet)
|
||||
TemplateCmd.AddCommand(AdminClientGeneralPurposeGovernanceEvmCallCmd)
|
||||
// solana call command
|
||||
AdminClientGeneralPurposeGovernanceSolanaCallCmd.Flags().AddFlagSet(generalPurposeGovernanceFlagSet)
|
||||
TemplateCmd.AddCommand(AdminClientGeneralPurposeGovernanceSolanaCallCmd)
|
||||
}
|
||||
|
||||
var TemplateCmd = &cobra.Command{
|
||||
|
@ -292,6 +310,18 @@ var AdminClientWormholeRelayerSetDefaultDeliveryProviderCmd = &cobra.Command{
|
|||
Run: runWormholeRelayerSetDefaultDeliveryProviderTemplate,
|
||||
}
|
||||
|
||||
var AdminClientGeneralPurposeGovernanceEvmCallCmd = &cobra.Command{
|
||||
Use: "governance-evm-call",
|
||||
Short: "Generate a 'general purpose evm governance call' template for specified chain and address",
|
||||
Run: runGeneralPurposeGovernanceEvmCallTemplate,
|
||||
}
|
||||
|
||||
var AdminClientGeneralPurposeGovernanceSolanaCallCmd = &cobra.Command{
|
||||
Use: "governance-solana-call",
|
||||
Short: "Generate a 'general purpose solana governance call' template for specified chain and address",
|
||||
Run: runGeneralPurposeGovernanceSolanaCallTemplate,
|
||||
}
|
||||
|
||||
func runGuardianSetTemplate(cmd *cobra.Command, args []string) {
|
||||
// Use deterministic devnet addresses as examples in the template, such that this doubles as a test fixture.
|
||||
guardians := make([]*nodev1.GuardianSetUpdate_Guardian, *setUpdateNumGuardians)
|
||||
|
@ -932,6 +962,100 @@ func runWormholeRelayerSetDefaultDeliveryProviderTemplate(cmd *cobra.Command, ar
|
|||
fmt.Print(string(b))
|
||||
}
|
||||
|
||||
func runGeneralPurposeGovernanceEvmCallTemplate(cmd *cobra.Command, args []string) {
|
||||
if *governanceTargetAddress == "" {
|
||||
log.Fatal("--target-address must be specified")
|
||||
}
|
||||
if !common.IsHexAddress(*governanceTargetAddress) {
|
||||
log.Fatal("invalid target address")
|
||||
}
|
||||
governanceTargetAddress := common.HexToAddress(*governanceTargetAddress).Hex()
|
||||
if *governanceCallData == "" {
|
||||
log.Fatal("--call-data must be specified")
|
||||
}
|
||||
if *governanceContractAddress == "" {
|
||||
log.Fatal("--governance-contract must be specified")
|
||||
}
|
||||
if !common.IsHexAddress(*governanceContractAddress) {
|
||||
log.Fatal("invalid governance contract address")
|
||||
}
|
||||
governanceContractAddress := common.HexToAddress(*governanceContractAddress).Hex()
|
||||
if *governanceTargetChain == "" {
|
||||
log.Fatal("--chain-id must be specified")
|
||||
}
|
||||
chainID, err := parseChainID(*governanceTargetChain)
|
||||
if err != nil {
|
||||
log.Fatal("failed to parse chain id: ", err)
|
||||
}
|
||||
|
||||
m := &nodev1.InjectGovernanceVAARequest{
|
||||
CurrentSetIndex: uint32(*templateGuardianIndex),
|
||||
Messages: []*nodev1.GovernanceMessage{
|
||||
{
|
||||
Sequence: rand.Uint64(),
|
||||
Nonce: rand.Uint32(),
|
||||
Payload: &nodev1.GovernanceMessage_EvmCall{
|
||||
EvmCall: &nodev1.EvmCall{
|
||||
ChainId: uint32(chainID),
|
||||
GovernanceContract: governanceContractAddress,
|
||||
TargetContract: governanceTargetAddress,
|
||||
AbiEncodedCall: *governanceCallData,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Print(string(b))
|
||||
}
|
||||
|
||||
func runGeneralPurposeGovernanceSolanaCallTemplate(cmd *cobra.Command, args []string) {
|
||||
if *governanceCallData == "" {
|
||||
log.Fatal("--call-data must be specified")
|
||||
}
|
||||
if *governanceContractAddress == "" {
|
||||
log.Fatal("--governance-contract must be specified")
|
||||
}
|
||||
_, err := base58.Decode(*governanceContractAddress)
|
||||
if err != nil {
|
||||
log.Fatal("invalid base58 governance contract address")
|
||||
}
|
||||
if *governanceTargetChain == "" {
|
||||
log.Fatal("--chain-id must be specified")
|
||||
}
|
||||
chainID, err := parseChainID(*governanceTargetChain)
|
||||
if err != nil {
|
||||
log.Fatal("failed to parse chain id: ", err)
|
||||
}
|
||||
|
||||
m := &nodev1.InjectGovernanceVAARequest{
|
||||
CurrentSetIndex: uint32(*templateGuardianIndex),
|
||||
Messages: []*nodev1.GovernanceMessage{
|
||||
{
|
||||
Sequence: rand.Uint64(),
|
||||
Nonce: rand.Uint32(),
|
||||
Payload: &nodev1.GovernanceMessage_SolanaCall{
|
||||
SolanaCall: &nodev1.SolanaCall{
|
||||
ChainId: uint32(chainID),
|
||||
GovernanceContract: *governanceContractAddress,
|
||||
EncodedInstruction: *governanceCallData,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Print(string(b))
|
||||
}
|
||||
|
||||
// parseAddress parses either a hex-encoded address and returns
|
||||
// a left-padded 32 byte hex string.
|
||||
func parseAddress(s string) (string, error) {
|
||||
|
|
|
@ -182,8 +182,10 @@ var (
|
|||
xlayerRPC *string
|
||||
xlayerContract *string
|
||||
|
||||
lineaRPC *string
|
||||
lineaContract *string
|
||||
lineaRPC *string
|
||||
lineaContract *string
|
||||
lineaRollUpUrl *string
|
||||
lineaRollUpContract *string
|
||||
|
||||
berachainRPC *string
|
||||
berachainContract *string
|
||||
|
@ -386,6 +388,8 @@ func init() {
|
|||
|
||||
lineaRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "lineaRPC", "Linea RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"})
|
||||
lineaContract = NodeCmd.Flags().String("lineaContract", "", "Linea contract address")
|
||||
lineaRollUpUrl = NodeCmd.Flags().String("lineaRollUpUrl", "", "Linea roll up URL")
|
||||
lineaRollUpContract = NodeCmd.Flags().String("lineaRollUpContract", "", "Linea roll up contract address")
|
||||
|
||||
berachainRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "berachainRPC", "Berachain RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"})
|
||||
berachainContract = NodeCmd.Flags().String("berachainContract", "", "Berachain contract address")
|
||||
|
@ -762,11 +766,6 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
logger.Fatal("Both --baseContract and --baseRPC must be set together or both unset")
|
||||
}
|
||||
|
||||
// Scroll should not be allowed in mainnet until its finality policy is understood and implemented in the watcher.
|
||||
if *scrollRPC != "" && !*testnetMode && !*unsafeDevMode {
|
||||
logger.Fatal("scroll is currently only supported in devnet and testnet")
|
||||
}
|
||||
|
||||
if (*scrollRPC == "") != (*scrollContract == "") {
|
||||
logger.Fatal("Both --scrollContract and --scrollRPC must be set together or both unset")
|
||||
}
|
||||
|
@ -779,10 +778,6 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
logger.Fatal("Both --mantleContract and --mantleRPC must be set together or both unset")
|
||||
}
|
||||
|
||||
if *blastRPC != "" && !*testnetMode && !*unsafeDevMode {
|
||||
logger.Fatal("blast is currently only supported in devnet and testnet")
|
||||
}
|
||||
|
||||
if (*blastRPC == "") != (*blastContract == "") {
|
||||
logger.Fatal("Both --blastContract and --blastRPC must be set together or both unset")
|
||||
}
|
||||
|
@ -802,6 +797,9 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
if (*lineaRPC == "") != (*lineaContract == "") {
|
||||
logger.Fatal("Both --lineaContract and --lineaRPC must be set together or both unset")
|
||||
}
|
||||
if (*lineaRPC != "") && (*lineaRollUpUrl == "" || *lineaRollUpContract == "") && !*unsafeDevMode {
|
||||
logger.Fatal("If --lineaRPC is specified, --lineaRollUpUrl and --lineaRollUpContract must also be specified")
|
||||
}
|
||||
|
||||
if *berachainRPC != "" && !*testnetMode && !*unsafeDevMode {
|
||||
logger.Fatal("berachain is currently only supported in devnet and testnet")
|
||||
|
@ -996,10 +994,16 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
if idx != 0 {
|
||||
// try to connect to guardian-0
|
||||
for {
|
||||
// tilt uses this hostname format
|
||||
_, err := net.LookupIP("guardian-0.guardian")
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
// load tests use this hostname format
|
||||
_, err = net.LookupIP("guardian-0")
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
logger.Info("Error resolving guardian-0.guardian. Trying again...")
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
@ -1144,6 +1148,10 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
|
||||
var accountantWormchainConn, accountantNttWormchainConn *wormconn.ClientConn
|
||||
if *accountantContract != "" {
|
||||
if *wormchainURL == "" {
|
||||
logger.Fatal("if accountantContract is specified, wormchainURL is required", zap.String("component", "gacct"))
|
||||
}
|
||||
|
||||
if *accountantKeyPath == "" {
|
||||
logger.Fatal("if accountantContract is specified, accountantKeyPath is required", zap.String("component", "gacct"))
|
||||
}
|
||||
|
@ -1176,6 +1184,10 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
|
||||
// If the NTT accountant is enabled, create a wormchain connection for it.
|
||||
if *accountantNttContract != "" {
|
||||
if *wormchainURL == "" {
|
||||
logger.Fatal("if accountantNttContract is specified, wormchainURL is required", zap.String("component", "gacct"))
|
||||
}
|
||||
|
||||
if *accountantNttKeyPath == "" {
|
||||
logger.Fatal("if accountantNttContract is specified, accountantNttKeyPath is required", zap.String("component", "gacct"))
|
||||
}
|
||||
|
@ -1506,11 +1518,13 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
|
||||
if shouldStart(lineaRPC) {
|
||||
wc := &evm.WatcherConfig{
|
||||
NetworkID: "linea",
|
||||
ChainID: vaa.ChainIDLinea,
|
||||
Rpc: *lineaRPC,
|
||||
Contract: *lineaContract,
|
||||
CcqBackfillCache: *ccqBackfillCache,
|
||||
NetworkID: "linea",
|
||||
ChainID: vaa.ChainIDLinea,
|
||||
Rpc: *lineaRPC,
|
||||
Contract: *lineaContract,
|
||||
CcqBackfillCache: *ccqBackfillCache,
|
||||
LineaRollUpUrl: *lineaRollUpUrl,
|
||||
LineaRollUpContract: *lineaRollUpContract,
|
||||
}
|
||||
|
||||
watcherConfigs = append(watcherConfigs, wc)
|
||||
|
|
|
@ -106,7 +106,7 @@ require (
|
|||
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v0.19.4 // indirect
|
||||
github.com/cosmos/ibc-go/v4 v4.2.2 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect
|
||||
github.com/creachadair/taskgroup v0.3.2 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
|
||||
|
@ -314,8 +314,8 @@ require (
|
|||
github.com/weaveworks/common v0.0.0-20230531151736-e2613bee6b73 // indirect
|
||||
github.com/weaveworks/promrus v1.2.0 // indirect
|
||||
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
|
||||
github.com/zondax/hid v0.9.1 // indirect
|
||||
github.com/zondax/ledger-go v0.14.0 // indirect
|
||||
github.com/zondax/hid v0.9.2 // indirect
|
||||
github.com/zondax/ledger-go v0.14.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.5 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect
|
||||
|
|
12
node/go.sum
12
node/go.sum
|
@ -1036,8 +1036,8 @@ github.com/cosmos/ibc-go/v4 v4.2.2/go.mod h1:EFFqkrJHQPHWUlw155QUxGuis4Ett4lvewA
|
|||
github.com/cosmos/interchain-accounts v0.2.4 h1:7UrroFQsCRSp17980mk6anx4YteveIJVkU+a0wlsHQI=
|
||||
github.com/cosmos/interchain-accounts v0.2.4/go.mod h1:jeiJEb0zg609G0oCrCG0r6Guhb7YbA1uFiwww/1YgZE=
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M=
|
||||
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
|
@ -3153,10 +3153,10 @@ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX
|
|||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo=
|
||||
github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/ledger-go v0.14.0 h1:dlMC7aO8Wss1CxBq2I96kZ69Nh1ligzbs8UWOtq/AsA=
|
||||
github.com/zondax/ledger-go v0.14.0/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320=
|
||||
github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U=
|
||||
github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw=
|
||||
github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI=
|
||||
gitlab.com/bosi/decorder v0.2.1/go.mod h1:6C/nhLSbF6qZbYD8bRmISBwc6vcWdNsiIBkRvjJFrH0=
|
||||
gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
|
|
|
@ -46,6 +46,8 @@ var etherscanAPIMap = map[vaa.ChainID]string{
|
|||
vaa.ChainIDArbitrum: "https://api.arbiscan.io",
|
||||
vaa.ChainIDOptimism: "https://api-optimistic.etherscan.io",
|
||||
vaa.ChainIDBase: "https://api.basescan.org",
|
||||
vaa.ChainIDScroll: "https://api.scrollscan.com",
|
||||
vaa.ChainIDBlast: "https://api.blastscan.io",
|
||||
}
|
||||
|
||||
var coreContractMap = map[vaa.ChainID]string{
|
||||
|
@ -64,6 +66,8 @@ var coreContractMap = map[vaa.ChainID]string{
|
|||
vaa.ChainIDArbitrum: strings.ToLower("0xa5f208e072434bC67592E4C49C1B991BA79BCA46"),
|
||||
vaa.ChainIDOptimism: strings.ToLower("0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722"),
|
||||
vaa.ChainIDBase: strings.ToLower("0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6"),
|
||||
vaa.ChainIDScroll: strings.ToLower("0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6"),
|
||||
vaa.ChainIDBlast: strings.ToLower("0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6 "),
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -577,6 +577,58 @@ func wormholeRelayerSetDefaultDeliveryProvider(req *nodev1.WormholeRelayerSetDef
|
|||
return v, nil
|
||||
}
|
||||
|
||||
func evmCallToVaa(evmCall *nodev1.EvmCall, timestamp time.Time, guardianSetIndex, nonce uint32, sequence uint64) (*vaa.VAA, error) {
|
||||
governanceContract := ethcommon.HexToAddress(evmCall.GovernanceContract)
|
||||
targetContract := ethcommon.HexToAddress(evmCall.TargetContract)
|
||||
|
||||
payload, err := hex.DecodeString(evmCall.AbiEncodedCall)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode ABI encoded call: %w", err)
|
||||
}
|
||||
|
||||
body, err := vaa.BodyGeneralPurposeGovernanceEvm{
|
||||
ChainID: vaa.ChainID(evmCall.ChainId),
|
||||
GovernanceContract: governanceContract,
|
||||
TargetContract: targetContract,
|
||||
Payload: payload,
|
||||
}.Serialize()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize governance body: %w", err)
|
||||
}
|
||||
|
||||
v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func solanaCallToVaa(solanaCall *nodev1.SolanaCall, timestamp time.Time, guardianSetIndex, nonce uint32, sequence uint64) (*vaa.VAA, error) {
|
||||
address, err := base58.Decode(solanaCall.GovernanceContract)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode base58 governance contract address: %w", err)
|
||||
}
|
||||
if len(address) != 32 {
|
||||
return nil, errors.New("invalid governance contract address length (expected 32 bytes)")
|
||||
}
|
||||
|
||||
var governanceContract [32]byte
|
||||
copy(governanceContract[:], address)
|
||||
|
||||
instruction, err := hex.DecodeString(solanaCall.EncodedInstruction)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode instruction: %w", err)
|
||||
}
|
||||
|
||||
v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
|
||||
vaa.BodyGeneralPurposeGovernanceSolana{
|
||||
ChainID: vaa.ChainID(solanaCall.ChainId),
|
||||
GovernanceContract: governanceContract,
|
||||
Instruction: instruction,
|
||||
}.Serialize())
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, timestamp time.Time) (*vaa.VAA, error) {
|
||||
var (
|
||||
v *vaa.VAA
|
||||
|
@ -620,6 +672,10 @@ func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, time
|
|||
v, err = ibcUpdateChannelChain(payload.IbcUpdateChannelChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
|
||||
case *nodev1.GovernanceMessage_WormholeRelayerSetDefaultDeliveryProvider:
|
||||
v, err = wormholeRelayerSetDefaultDeliveryProvider(payload.WormholeRelayerSetDefaultDeliveryProvider, timestamp, currentSetIndex, message.Nonce, message.Sequence)
|
||||
case *nodev1.GovernanceMessage_EvmCall:
|
||||
v, err = evmCallToVaa(payload.EvmCall, timestamp, currentSetIndex, message.Nonce, message.Sequence)
|
||||
case *nodev1.GovernanceMessage_SolanaCall:
|
||||
v, err = solanaCallToVaa(payload.SolanaCall, timestamp, currentSetIndex, message.Nonce, message.Sequence)
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported VAA type: %T", payload))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package governor
|
||||
|
||||
// FlowCancelTokenList Returns a list of `tokenConfigEntry`s representing tokens that can 'Flow Cancel'. This means that incoming transfers
|
||||
// that use these tokens can reduce the 'daily limit' of the Governor configured for the destination chain.
|
||||
// The list of tokens was generated by grepping the file `generated_mainnet_tokens.go` for "USDC", "USDT", and "DAI".
|
||||
//
|
||||
// Note that the field `symbol` is unused. It is retained in this file only for convenience.
|
||||
func FlowCancelTokenList() []tokenConfigEntry {
|
||||
return []tokenConfigEntry{
|
||||
// USDC variants
|
||||
{chain: 2, addr: "000000000000000000000000bcca60bb61934080951369a648fb03df4f96263c", symbol: "aUSDC"},
|
||||
{chain: 4, addr: "0000000000000000000000004268b8f0b87b6eae5d897996e6b845ddbd99adf3", symbol: "axlUSDC"},
|
||||
{chain: 5, addr: "0000000000000000000000001a13f4ca1d028320a707d99520abfefca3998b7f", symbol: "amUSDC"},
|
||||
{chain: 5, addr: "000000000000000000000000750e4c4984a9e0f12978ea6742bc1c5d248f40ed", symbol: "axlUSDC"},
|
||||
{chain: 6, addr: "000000000000000000000000fab550568c688d5d8a52c7d794cb93edc26ec0ec", symbol: "axlUSDC"},
|
||||
{chain: 6, addr: "000000000000000000000000a7d7079b0fead91f3e65f86e8915cb59c1a4c664", symbol: "USDC.e"},
|
||||
{chain: 10, addr: "0000000000000000000000001b6382dbdea11d97f24495c9a90b7c88469134a4", symbol: "axlUSDC"},
|
||||
{chain: 10, addr: "00000000000000000000000028a92dde19d9989f39a49905d7c9c2fac7799bdf", symbol: "USDC"},
|
||||
{chain: 10, addr: "00000000000000000000000027e611fd27b276acbd5ffd632e5eaebec9761e40", symbol: "DAI+USDC"},
|
||||
{chain: 13, addr: "000000000000000000000000754288077d0ff82af7a5317c7cb8c444d421d103", symbol: "oUSDC"},
|
||||
{chain: 14, addr: "000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215", symbol: "axlUSDC"},
|
||||
{chain: 16, addr: "000000000000000000000000ca01a1d0993565291051daff390892518acfad3a", symbol: "axlUSDC"},
|
||||
{chain: 23, addr: "000000000000000000000000625e7708f30ca75bfd92586e17077590c60eb4cd", symbol: "aArbUSDC"},
|
||||
{chain: 24, addr: "000000000000000000000000625e7708f30ca75bfd92586e17077590c60eb4cd", symbol: "aOptUSDC"},
|
||||
{chain: 30, addr: "000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215", symbol: "axlUSDC"},
|
||||
|
||||
// USDT variants
|
||||
{chain: 1, addr: "b7db4e83eb727f1187bd7a50303f5b4e4e943503da8571ad6564a51131504792", symbol: ""},
|
||||
{chain: 1, addr: "ce010e60afedb22717bd63192f54145a3f965a33bb82d2c7029eb2ce1e208264", symbol: "USDT"},
|
||||
{chain: 2, addr: "000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7", symbol: "USDT"},
|
||||
{chain: 4, addr: "00000000000000000000000055d398326f99059ff775485246999027b3197955", symbol: "USDT"},
|
||||
{chain: 5, addr: "000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f", symbol: "USDT"},
|
||||
{chain: 6, addr: "0000000000000000000000009702230a8ea53601f5cd2dc00fdbc13d4df4a8c7", symbol: "USDt"},
|
||||
{chain: 6, addr: "000000000000000000000000c7198437980c041c805a1edcba50c1ce5db95118", symbol: "USDT.e"},
|
||||
{chain: 8, addr: "000000000000000000000000000000000000000000000000000000000004c5c1", symbol: "USDt"},
|
||||
{chain: 9, addr: "0000000000000000000000004988a896b1227218e4a686fde5eabdcabd91571f", symbol: "USDT"},
|
||||
{chain: 10, addr: "000000000000000000000000cc1b99ddac1a33c201a742a1851662e87bc7f22c", symbol: "USDT"},
|
||||
{chain: 10, addr: "000000000000000000000000049d68029688eabf473097a2fc38ef61633a3c7a", symbol: "fUSDT"},
|
||||
{chain: 13, addr: "000000000000000000000000cee8faf64bb97a73bb51e115aa89c17ffa8dd167", symbol: "oUSDT"},
|
||||
{chain: 16, addr: "000000000000000000000000efaeee334f0fd1712f9a8cc375f427d9cdd40d73", symbol: "USDT"},
|
||||
{chain: 16, addr: "000000000000000000000000ffffffffea09fb06d082fd1275cd48b191cbcd1d", symbol: "xcUSDT"},
|
||||
{chain: 23, addr: "000000000000000000000000fd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9", symbol: "USDT"},
|
||||
{chain: 24, addr: "00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58", symbol: "USDT"},
|
||||
|
||||
// DAI variants (DAI+USDC is included under the USDC list above)
|
||||
{chain: 2, addr: "0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f", symbol: "DAI"},
|
||||
{chain: 4, addr: "0000000000000000000000001af3f329e8be154074d8769d1ffa4ee058b1dbc3", symbol: "DAI"},
|
||||
{chain: 5, addr: "0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063", symbol: "DAI"},
|
||||
{chain: 6, addr: "000000000000000000000000d586e7f844cea2f87f50152665bcbc2c279d8d70", symbol: "DAI.e"},
|
||||
{chain: 10, addr: "0000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e", symbol: "DAI"},
|
||||
{chain: 13, addr: "0000000000000000000000005c74070fdea071359b86082bd9f9b3deaafbe32b", symbol: "KDAI"},
|
||||
{chain: 16, addr: "000000000000000000000000765277eebeca2e31912c9946eae1021199b39c61", symbol: "DAI"},
|
||||
{chain: 23, addr: "000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1", symbol: "DAI"},
|
||||
{chain: 24, addr: "000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1", symbol: "DAI"},
|
||||
{chain: 30, addr: "00000000000000000000000050c5725949a6f0c72e6c4a641f24049a917db0cb", symbol: "DAI"},
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
package governor
|
||||
|
||||
// The purpose of the Chain Governor is to limit the notional TVL that can leave a chain in a single day.
|
||||
// It works by tracking transfers (types one and three) for a configured set of tokens from a configured set of emitters (chains).
|
||||
//
|
||||
|
@ -23,11 +25,10 @@
|
|||
//
|
||||
// To enable the chain governor, you must specified the --chainGovernorEnabled guardiand command line argument.
|
||||
|
||||
package governor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
@ -204,7 +205,14 @@ func (gov *ChainGovernor) initConfig() error {
|
|||
}
|
||||
|
||||
key := tokenKey{chain: vaa.ChainID(ct.chain), addr: addr}
|
||||
te := &tokenEntry{cfgPrice: cfgPrice, price: initialPrice, decimals: decimals, symbol: symbol, coinGeckoId: ct.coinGeckoId, token: key}
|
||||
te := &tokenEntry{
|
||||
cfgPrice: cfgPrice,
|
||||
price: initialPrice,
|
||||
decimals: decimals,
|
||||
symbol: symbol,
|
||||
coinGeckoId: ct.coinGeckoId,
|
||||
token: key,
|
||||
}
|
||||
te.updatePrice()
|
||||
|
||||
gov.tokens[key] = te
|
||||
|
@ -294,6 +302,10 @@ func (gov *ChainGovernor) ProcessMsg(msg *common.MessagePublication) bool {
|
|||
}
|
||||
|
||||
func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now time.Time) (bool, error) {
|
||||
// Validation:
|
||||
// - ensure MessagePublication is not nil
|
||||
// - check that the MessagePublication is governed
|
||||
// - check that the message is not a duplicate
|
||||
if msg == nil {
|
||||
return false, fmt.Errorf("msg is nil")
|
||||
}
|
||||
|
@ -301,7 +313,7 @@ func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now
|
|||
gov.mutex.Lock()
|
||||
defer gov.mutex.Unlock()
|
||||
|
||||
msgIsGoverned, ce, token, payload, err := gov.parseMsgAlreadyLocked(msg)
|
||||
msgIsGoverned, emitterChainEntry, token, payload, err := gov.parseMsgAlreadyLocked(msg)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -330,10 +342,11 @@ func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// Get all outgoing transfers for `emitterChainEntry` that happened within the last 24 hours
|
||||
startTime := now.Add(-time.Minute * time.Duration(gov.dayLengthInMinutes))
|
||||
prevTotalValue, err := gov.TrimAndSumValueForChain(ce, startTime)
|
||||
prevTotalValue, err := gov.TrimAndSumValueForChain(emitterChainEntry, startTime)
|
||||
if err != nil {
|
||||
gov.logger.Error("failed to trim transfers",
|
||||
gov.logger.Error("Error when attempting to trim and sum transfers",
|
||||
zap.String("msgID", msg.MessageIDString()),
|
||||
zap.String("hash", hash),
|
||||
zap.Stringer("txHash", msg.TxHash),
|
||||
|
@ -342,6 +355,7 @@ func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now
|
|||
return false, err
|
||||
}
|
||||
|
||||
// Compute the notional USD value of the transfers
|
||||
value, err := computeValue(payload.Amount, token)
|
||||
if err != nil {
|
||||
gov.logger.Error("failed to compute value of transfer",
|
||||
|
@ -367,7 +381,7 @@ func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now
|
|||
|
||||
enqueueIt := false
|
||||
var releaseTime time.Time
|
||||
if ce.isBigTransfer(value) {
|
||||
if emitterChainEntry.isBigTransfer(value) {
|
||||
enqueueIt = true
|
||||
releaseTime = now.Add(maxEnqueuedTime)
|
||||
gov.logger.Error("enqueuing vaa because it is a big transaction",
|
||||
|
@ -376,11 +390,11 @@ func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now
|
|||
zap.Uint64("newTotalValue", newTotalValue),
|
||||
zap.String("msgID", msg.MessageIDString()),
|
||||
zap.Stringer("releaseTime", releaseTime),
|
||||
zap.Uint64("bigTransactionSize", ce.bigTransactionSize),
|
||||
zap.Uint64("bigTransactionSize", emitterChainEntry.bigTransactionSize),
|
||||
zap.String("hash", hash),
|
||||
zap.Stringer("txHash", msg.TxHash),
|
||||
)
|
||||
} else if newTotalValue > ce.dailyLimit {
|
||||
} else if newTotalValue > emitterChainEntry.dailyLimit {
|
||||
enqueueIt = true
|
||||
releaseTime = now.Add(maxEnqueuedTime)
|
||||
gov.logger.Error("enqueuing vaa because it would exceed the daily limit",
|
||||
|
@ -407,7 +421,10 @@ func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now
|
|||
return false, err
|
||||
}
|
||||
|
||||
ce.pending = append(ce.pending, &pendingEntry{token: token, amount: payload.Amount, hash: hash, dbData: dbData})
|
||||
emitterChainEntry.pending = append(
|
||||
emitterChainEntry.pending,
|
||||
&pendingEntry{token: token, amount: payload.Amount, hash: hash, dbData: dbData},
|
||||
)
|
||||
gov.msgsSeen[hash] = transferEnqueued
|
||||
return false, nil
|
||||
}
|
||||
|
@ -421,7 +438,8 @@ func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now
|
|||
zap.Stringer("txHash", msg.TxHash),
|
||||
)
|
||||
|
||||
xfer := db.Transfer{Timestamp: now,
|
||||
xfer := db.Transfer{
|
||||
Timestamp: now,
|
||||
Value: value,
|
||||
OriginChain: token.token.chain,
|
||||
OriginAddress: token.token.addr,
|
||||
|
@ -442,7 +460,7 @@ func (gov *ChainGovernor) ProcessMsgForTime(msg *common.MessagePublication, now
|
|||
return false, err
|
||||
}
|
||||
|
||||
ce.transfers = append(ce.transfers, &xfer)
|
||||
emitterChainEntry.transfers = append(emitterChainEntry.transfers, &xfer)
|
||||
gov.msgsSeen[hash] = transferComplete
|
||||
return true, nil
|
||||
}
|
||||
|
@ -456,19 +474,27 @@ func (gov *ChainGovernor) IsGovernedMsg(msg *common.MessagePublication) (msgIsGo
|
|||
}
|
||||
|
||||
// parseMsgAlreadyLocked determines if the message applies to the governor and also returns data useful to the governor. It assumes the caller holds the lock.
|
||||
func (gov *ChainGovernor) parseMsgAlreadyLocked(msg *common.MessagePublication) (bool, *chainEntry, *tokenEntry, *vaa.TransferPayloadHdr, error) {
|
||||
func (gov *ChainGovernor) parseMsgAlreadyLocked(
|
||||
msg *common.MessagePublication,
|
||||
) (bool, *chainEntry, *tokenEntry, *vaa.TransferPayloadHdr, error) {
|
||||
// If we don't care about this chain, the VAA can be published.
|
||||
ce, exists := gov.chains[msg.EmitterChain]
|
||||
if !exists {
|
||||
if msg.EmitterChain != vaa.ChainIDPythNet {
|
||||
gov.logger.Info("ignoring vaa because the emitter chain is not configured", zap.String("msgID", msg.MessageIDString()))
|
||||
gov.logger.Info(
|
||||
"ignoring vaa because the emitter chain is not configured",
|
||||
zap.String("msgID", msg.MessageIDString()),
|
||||
)
|
||||
}
|
||||
return false, nil, nil, nil, nil
|
||||
}
|
||||
|
||||
// If we don't care about this emitter, the VAA can be published.
|
||||
if msg.EmitterAddress != ce.emitterAddr {
|
||||
gov.logger.Info("ignoring vaa because the emitter address is not configured", zap.String("msgID", msg.MessageIDString()))
|
||||
gov.logger.Info(
|
||||
"ignoring vaa because the emitter address is not configured",
|
||||
zap.String("msgID", msg.MessageIDString()),
|
||||
)
|
||||
return false, nil, nil, nil, nil
|
||||
}
|
||||
|
||||
|
@ -519,7 +545,7 @@ func (gov *ChainGovernor) CheckPendingForTime(now time.Time) ([]*common.MessageP
|
|||
foundOne := false
|
||||
prevTotalValue, err := gov.TrimAndSumValueForChain(ce, startTime)
|
||||
if err != nil {
|
||||
gov.logger.Error("failed to trim transfers", zap.Error(err))
|
||||
gov.logger.Error("Error when attempting to trim and sum transfers", zap.Error(err))
|
||||
gov.msgsToPublish = msgsToPublish
|
||||
return nil, err
|
||||
}
|
||||
|
@ -656,11 +682,110 @@ func computeValue(amount *big.Int, token *tokenEntry) (uint64, error) {
|
|||
return value, nil
|
||||
}
|
||||
|
||||
func (gov *ChainGovernor) TrimAndSumValueForChain(ce *chainEntry, startTime time.Time) (sum uint64, err error) {
|
||||
sum, ce.transfers, err = gov.TrimAndSumValue(ce.transfers, startTime)
|
||||
return sum, err
|
||||
// TrimAndSumValueForChain calculates the `sum` of `Transfer`s for a given chain `emitter`. In effect, it represents a
|
||||
// chain's "Governor Usage" for a given 24 hour period.
|
||||
// This sum may be reduced by the sum of 'flow cancelling' transfers: that is, transfers of an allow-listed token
|
||||
// that have the `emitter` as their destination chain.
|
||||
// The resulting `sum` return value therefore represents the net flow across a chain when taking flow-cancelling tokens
|
||||
// into account. Therefore, this value should never be less than 0 and should never exceed the "Governor limit" for the chain.
|
||||
//
|
||||
// As a side-effect, this function modifies the parameter `emitter`, upating its `transfers` field so that it only includes
|
||||
// filtered `Transfer`s (i.e. outgoing `Transfer`s newer than `startTime`).
|
||||
//
|
||||
// SECURITY Invariant: The `sum` return value should never be less than 0
|
||||
// SECURITY Invariant: The `sum` return value should never exceed the "Governor limit" for the chain
|
||||
func (gov *ChainGovernor) TrimAndSumValueForChain(emitter *chainEntry, startTime time.Time) (sum uint64, err error) {
|
||||
// Sum the value of all outgoing transfers
|
||||
var sumOutgoing uint64
|
||||
sumOutgoing, emitter.transfers, err = gov.TrimAndSumValue(emitter.transfers, startTime)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// Subtract the sum of all flow cancelling transfers. Here the emitter's chainID is actually used as the destination
|
||||
// chain in in the context of FlowCancellingTransfersForChain.
|
||||
flowCancelSum, err := gov.SumTransferValues(gov.FlowCancellingTransfersForChain(emitter.emitterChainId, startTime))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// If flowCancelSum is larger than or equal to sumOutgoing, simply return 0 as this means that all outgoing
|
||||
// transfers have been cancelled by incoming transfers.
|
||||
// This also avoids integer underflow.
|
||||
if flowCancelSum >= sumOutgoing {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
sum = sumOutgoing - flowCancelSum
|
||||
if sum > emitter.dailyLimit {
|
||||
return 0, fmt.Errorf(
|
||||
"invariant violation: calculated sum %d exceeds Governor limit %d",
|
||||
sum,
|
||||
emitter.dailyLimit,
|
||||
)
|
||||
}
|
||||
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
// SumTransferValues iterates over a slice of transfers and sums their value.
|
||||
func (gov *ChainGovernor) SumTransferValues(transfers []*db.Transfer) (sum uint64, err error) {
|
||||
sum = 0
|
||||
// Iterate over all transfers usin tokens that have flow cancelling enabled.
|
||||
// If the destination chain of the transfer is equal to the `ce` parameter, add the value
|
||||
// of the transfer to the flow cancelling sum.
|
||||
for _, transfer := range transfers {
|
||||
// Overflow check. Note that transfer.Value cannot be negative
|
||||
if (sum + transfer.Value) < sum {
|
||||
return 0, errors.New("overflow when calculating flow cancelling sum")
|
||||
}
|
||||
sum += transfer.Value
|
||||
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
// FlowCancellingTransfersForChain builds a list of Transfers that contain assets that can 'flow cancel'
|
||||
// (reduce the Governor usage of) a governed chain represented by `destinationChainID`.
|
||||
func (gov *ChainGovernor) FlowCancellingTransfersForChain(
|
||||
destinationChainID vaa.ChainID,
|
||||
startTime time.Time,
|
||||
) (transfers []*db.Transfer) {
|
||||
flowCancelTokens := FlowCancelTokenList()
|
||||
// transfers = make([]*db.Transfer, 0)
|
||||
// Iterate over all transfers for all governed chains
|
||||
for _, emitterChainEntry := range gov.chains {
|
||||
for _, transfer := range emitterChainEntry.transfers {
|
||||
// We care about the transfer if:
|
||||
// - Its target chain is equal to the `destinationChainID` parameter
|
||||
// - It happened after `startTime`
|
||||
// - It is a flow cancelling token (The transfer's origin chain and
|
||||
// origin address match a hard-coded flow cancelling asset)
|
||||
if transfer.TargetChain != destinationChainID {
|
||||
continue
|
||||
}
|
||||
|
||||
if transfer.Timestamp.Before(startTime) {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, flowCancelToken := range flowCancelTokens {
|
||||
// Compare flow cancel fields with transfer fields. This requires conversions:
|
||||
// - vaa.ChainID to uint16
|
||||
// - vaa.Address to String
|
||||
if uint16(transfer.OriginChain) == flowCancelToken.chain &&
|
||||
transfer.OriginAddress.String() == flowCancelToken.addr {
|
||||
transfers = append(transfers, transfer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return transfers
|
||||
}
|
||||
|
||||
// TrimAndSumValue iterates over a slice of db.Transfer structs. It filters out transfers that have a Timestamp value that
|
||||
// is earlier than the parameter `startTime`. The function then iterates over the remaining transfers, sums their Value,
|
||||
// and returns the sum and the filtered transfers.
|
||||
func (gov *ChainGovernor) TrimAndSumValue(transfers []*db.Transfer, startTime time.Time) (uint64, []*db.Transfer, error) {
|
||||
if len(transfers) == 0 {
|
||||
return 0, transfers, nil
|
||||
|
|
|
@ -49,7 +49,12 @@ func (gov *ChainGovernor) setDayLengthInMinutes(min int) {
|
|||
gov.dayLengthInMinutes = min
|
||||
}
|
||||
|
||||
func (gov *ChainGovernor) setChainForTesting(emitterChainId vaa.ChainID, emitterAddrStr string, dailyLimit uint64, bigTransactionSize uint64) error {
|
||||
func (gov *ChainGovernor) setChainForTesting(
|
||||
emitterChainId vaa.ChainID,
|
||||
emitterAddrStr string,
|
||||
dailyLimit uint64,
|
||||
bigTransactionSize uint64,
|
||||
) error {
|
||||
gov.mutex.Lock()
|
||||
defer gov.mutex.Unlock()
|
||||
|
||||
|
@ -70,7 +75,12 @@ func (gov *ChainGovernor) setChainForTesting(emitterChainId vaa.ChainID, emitter
|
|||
return nil
|
||||
}
|
||||
|
||||
func (gov *ChainGovernor) setTokenForTesting(tokenChainID vaa.ChainID, tokenAddrStr string, symbol string, price float64) error {
|
||||
func (gov *ChainGovernor) setTokenForTesting(
|
||||
tokenChainID vaa.ChainID,
|
||||
tokenAddrStr string,
|
||||
symbol string,
|
||||
price float64,
|
||||
) error {
|
||||
gov.mutex.Lock()
|
||||
defer gov.mutex.Unlock()
|
||||
|
||||
|
@ -163,6 +173,214 @@ func TestSumAllFromToday(t *testing.T) {
|
|||
assert.Equal(t, 1, len(updatedTransfers))
|
||||
}
|
||||
|
||||
func TestSumWithFlowCancelling(t *testing.T) {
|
||||
// NOTE: Replace this Chain:Address pair if the Flow Cancel Token List is modified
|
||||
var originChain vaa.ChainID = 2
|
||||
var originAddress vaa.Address
|
||||
originAddress, err := vaa.StringToAddress("000000000000000000000000bcca60bb61934080951369a648fb03df4f96263c")
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
gov, err := newChainGovernorForTest(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, gov)
|
||||
|
||||
now, err := time.Parse("2006-Jan-02", "2024-Feb-19")
|
||||
require.NoError(t, err)
|
||||
|
||||
var transfers_from_emitter []*db.Transfer
|
||||
var transfers_that_flow_cancel []*db.Transfer
|
||||
transferTime, err := time.Parse("2006-Jan-02", "2024-Feb-19")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Set up values and governor limit
|
||||
emitterTransferValue := uint64(125000)
|
||||
flowCancelValue := uint64(100000)
|
||||
|
||||
emitterLimit := emitterTransferValue * 2 // make sure the limit always exceeds the transfer value
|
||||
emitterChainId := 1
|
||||
|
||||
// Setup transfers
|
||||
// - Transfer from emitter: we only care about Value
|
||||
// - Transfer that flow cancels: Transfer must be a valid entry from FlowCancelTokenList() (based on origin chain and origin address)
|
||||
// and the desintation chain must be the same as the emitter chain
|
||||
transfers_from_emitter = append(transfers_from_emitter, &db.Transfer{Value: emitterTransferValue, Timestamp: transferTime})
|
||||
transfers_that_flow_cancel = append(
|
||||
transfers_that_flow_cancel,
|
||||
&db.Transfer{
|
||||
OriginChain: originChain,
|
||||
OriginAddress: originAddress,
|
||||
TargetChain: vaa.ChainID(emitterChainId),
|
||||
Value: flowCancelValue,
|
||||
Timestamp: transferTime,
|
||||
},
|
||||
)
|
||||
|
||||
// Populate chainEntrys and ChainGovernor
|
||||
emitter := &chainEntry{
|
||||
transfers: transfers_from_emitter,
|
||||
emitterChainId: vaa.ChainID(emitterChainId),
|
||||
dailyLimit: emitterLimit,
|
||||
}
|
||||
chain_with_flow_cancel_transfers := &chainEntry{transfers: transfers_that_flow_cancel, emitterChainId: 2}
|
||||
gov.chains[emitter.emitterChainId] = emitter
|
||||
gov.chains[chain_with_flow_cancel_transfers.emitterChainId] = chain_with_flow_cancel_transfers
|
||||
|
||||
// XXX: sanity check
|
||||
expectedNumTransfers := 1
|
||||
sum, transfers, err := gov.TrimAndSumValue(emitter.transfers, now)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedNumTransfers, len(transfers))
|
||||
assert.NotZero(t, sum)
|
||||
|
||||
// Calculate Governor Usage for emitter, including flow cancelling
|
||||
sum, err = gov.TrimAndSumValueForChain(emitter, now.Add(-time.Hour*24))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, emitterTransferValue-flowCancelValue, sum)
|
||||
}
|
||||
|
||||
// Flow cancelling transfers are subtracted from the overall sum of all transfers from a given
|
||||
// emitter chain. Since we are working with uint64 values, ensure that there is no underflow.
|
||||
// When the sum of all flow cancelling transfers is greater than emitted transfers for a chain,
|
||||
// the expected result is that the resulting Governor Usage equals 0 (and not a negative number
|
||||
// or a very large underflow result).
|
||||
// Also, the function should not return an error in this case.
|
||||
func TestFlowCancelCannotUnderflow(t *testing.T) {
|
||||
// NOTE: Replace this Chain:Address pair if the Flow Cancel Token List is modified
|
||||
var originChain vaa.ChainID = 2
|
||||
var originAddress vaa.Address
|
||||
originAddress, err := vaa.StringToAddress("000000000000000000000000bcca60bb61934080951369a648fb03df4f96263c")
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
gov, err := newChainGovernorForTest(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, gov)
|
||||
|
||||
now, err := time.Parse("2006-Jan-02", "2024-Feb-19")
|
||||
require.NoError(t, err)
|
||||
|
||||
var transfers_from_emitter []*db.Transfer
|
||||
var transfers_that_flow_cancel []*db.Transfer
|
||||
transferTime, err := time.Parse("2006-Jan-02", "2024-Feb-19")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Set up values and governor limit
|
||||
emitterTransferValue := uint64(100000)
|
||||
flowCancelValue := emitterTransferValue + 25000 // make sure this value is higher than `emitterTransferValue`
|
||||
|
||||
emitterLimit := emitterTransferValue * 2 // make sure the limit always exceeds the transfer value
|
||||
emitterChainId := 1
|
||||
|
||||
// Setup transfers
|
||||
// - Transfer from emitter: we only care about Value
|
||||
// - Transfer that flow cancels: Transfer must be a valid entry from FlowCancelTokenList() (based on origin chain and origin address)
|
||||
// and the destination chain must be the same as the emitter chain
|
||||
transfers_from_emitter = append(transfers_from_emitter, &db.Transfer{Value: emitterTransferValue, Timestamp: transferTime})
|
||||
transfers_that_flow_cancel = append(
|
||||
transfers_that_flow_cancel,
|
||||
&db.Transfer{
|
||||
OriginChain: originChain,
|
||||
OriginAddress: originAddress,
|
||||
TargetChain: vaa.ChainID(emitterChainId),
|
||||
Value: flowCancelValue,
|
||||
Timestamp: transferTime,
|
||||
},
|
||||
)
|
||||
|
||||
// Populate chainEntrys and ChainGovernor
|
||||
emitter := &chainEntry{
|
||||
transfers: transfers_from_emitter,
|
||||
emitterChainId: vaa.ChainID(emitterChainId),
|
||||
dailyLimit: emitterLimit,
|
||||
}
|
||||
chain_with_flow_cancel_transfers := &chainEntry{transfers: transfers_that_flow_cancel, emitterChainId: 2}
|
||||
gov.chains[emitter.emitterChainId] = emitter
|
||||
gov.chains[chain_with_flow_cancel_transfers.emitterChainId] = chain_with_flow_cancel_transfers
|
||||
|
||||
// XXX: sanity check: Sum of transfers without flow cancelling should be positive.
|
||||
expectedNumTransfers := 1
|
||||
sum, transfers, err := gov.TrimAndSumValue(emitter.transfers, now)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedNumTransfers, len(transfers))
|
||||
assert.Greater(t, sum, uint64(0))
|
||||
|
||||
// Calculate Governor Usage for emitter, including flow cancelling
|
||||
sum, err = gov.TrimAndSumValueForChain(emitter, now.Add(-time.Hour*24))
|
||||
require.NoError(t, err)
|
||||
assert.Zero(t, sum)
|
||||
}
|
||||
|
||||
// Simulate a case where the total sum of transfers for a chain in a 24 hour period exceeds
|
||||
// the configured Governor limit. This should never happen, so we make sure that an error
|
||||
// is returned if the system is in this state
|
||||
func TestInvariantGovernorLimit(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
gov, err := newChainGovernorForTest(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, gov)
|
||||
|
||||
now, err := time.Parse("2006-Jan-02", "2024-Feb-19")
|
||||
require.NoError(t, err)
|
||||
|
||||
var transfers_from_emitter []*db.Transfer
|
||||
transferTime, err := time.Parse("2006-Jan-02", "2024-Feb-19")
|
||||
require.NoError(t, err)
|
||||
|
||||
emitterTransferValue := uint64(125000)
|
||||
|
||||
emitterLimit := emitterTransferValue * 20
|
||||
emitterChainId := 1
|
||||
|
||||
// Create a lot of transfers. Their total value should exceed `emitterLimit`
|
||||
for i := 0; i < 25; i++ {
|
||||
transfers_from_emitter = append(
|
||||
transfers_from_emitter,
|
||||
&db.Transfer{Value: emitterTransferValue, Timestamp: transferTime},
|
||||
)
|
||||
}
|
||||
|
||||
// Populate chainEntry and ChainGovernor
|
||||
emitter := &chainEntry{
|
||||
transfers: transfers_from_emitter,
|
||||
emitterChainId: vaa.ChainID(emitterChainId),
|
||||
dailyLimit: emitterLimit,
|
||||
}
|
||||
gov.chains[emitter.emitterChainId] = emitter
|
||||
|
||||
// XXX: sanity check
|
||||
expectedNumTransfers := 25
|
||||
sum, transfers, err := gov.TrimAndSumValue(emitter.transfers, now)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedNumTransfers, len(transfers))
|
||||
assert.NotZero(t, sum)
|
||||
|
||||
// Make sure we trigger the Invariant
|
||||
sum, err = gov.TrimAndSumValueForChain(emitter, now.Add(-time.Hour*24))
|
||||
require.ErrorContains(t, err, "invariant violation: calculated sum")
|
||||
assert.Zero(t, sum)
|
||||
}
|
||||
|
||||
func TestInvariantSumOverflow(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
gov, err := newChainGovernorForTest(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, gov)
|
||||
|
||||
transferTime, err := time.Parse("2006-Jan-02", "2024-Feb-19")
|
||||
require.NoError(t, err)
|
||||
|
||||
var transfers []*db.Transfer
|
||||
|
||||
// Add two transfers. When summed, they should trigger an overflow
|
||||
transfers = append(transfers, &db.Transfer{Value: math.MaxUint64, Timestamp: transferTime})
|
||||
transfers = append(transfers, &db.Transfer{Value: 1, Timestamp: transferTime})
|
||||
|
||||
sum, err := gov.SumTransferValues(transfers)
|
||||
require.ErrorContains(t, err, "overflow when calculating flow cancelling sum")
|
||||
assert.Zero(t, sum)
|
||||
}
|
||||
|
||||
func TestTrimOneOfTwoTransfers(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
gov, err := newChainGovernorForTest(ctx)
|
||||
|
@ -316,7 +534,7 @@ func TestVaaForUninterestingEmitterChain(t *testing.T) {
|
|||
assert.NotNil(t, gov)
|
||||
|
||||
emitterAddr, _ := vaa.StringToAddress("0x00")
|
||||
var payload = []byte{1, 97, 97, 97, 97, 97}
|
||||
payload := []byte{1, 97, 97, 97, 97, 97}
|
||||
|
||||
msg := common.MessagePublication{
|
||||
TxHash: hashFromString("0x06f541f5ecfc43407c31587aa6ac3a689e8960f36dc23c332db5510dfc6a4063"),
|
||||
|
@ -348,7 +566,7 @@ func TestVaaForUninterestingEmitterAddress(t *testing.T) {
|
|||
assert.NotNil(t, gov)
|
||||
|
||||
emitterAddr, _ := vaa.StringToAddress("0x00")
|
||||
var payload = []byte{1, 97, 97, 97, 97, 97}
|
||||
payload := []byte{1, 97, 97, 97, 97, 97}
|
||||
|
||||
msg := common.MessagePublication{
|
||||
TxHash: hashFromString("0x06f541f5ecfc43407c31587aa6ac3a689e8960f36dc23c332db5510dfc6a4063"),
|
||||
|
@ -381,7 +599,7 @@ func TestVaaForUninterestingPayloadType(t *testing.T) {
|
|||
assert.NotNil(t, gov)
|
||||
|
||||
emitterAddr, _ := vaa.StringToAddress("0x0290fb167208af455bb137780163b7b7a9a10c16")
|
||||
var payload = []byte{2, 97, 97, 97, 97, 97}
|
||||
payload := []byte{2, 97, 97, 97, 97, 97}
|
||||
|
||||
msg := common.MessagePublication{
|
||||
TxHash: hashFromString("0x06f541f5ecfc43407c31587aa6ac3a689e8960f36dc23c332db5510dfc6a4063"),
|
||||
|
|
|
@ -35,6 +35,8 @@ func chainList() []chainConfigEntry {
|
|||
{emitterChainID: vaa.ChainIDXpla, dailyLimit: 500_000, bigTransactionSize: 50_000},
|
||||
{emitterChainID: vaa.ChainIDBase, dailyLimit: 2_000_000, bigTransactionSize: 200_000},
|
||||
{emitterChainID: vaa.ChainIDSei, dailyLimit: 5_000_000, bigTransactionSize: 500_000},
|
||||
{emitterChainID: vaa.ChainIDScroll, dailyLimit: 500_000, bigTransactionSize: 50_000},
|
||||
{emitterChainID: vaa.ChainIDBlast, dailyLimit: 500_000, bigTransactionSize: 50_000},
|
||||
{emitterChainID: vaa.ChainIDWormchain, dailyLimit: 500_000, bigTransactionSize: 50_000},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,5 +14,37 @@ func manualTokenList() []tokenConfigEntry {
|
|||
{chain: 13, addr: "0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd", symbol: "WEMIX", coinGeckoId: "wemix-token", decimals: 8, price: 1.74},
|
||||
{chain: 15, addr: "0000000000000000000000000000000000000000000000000000000000000000", symbol: "NEAR", coinGeckoId: "near", decimals: 8, price: 3.85},
|
||||
{chain: 32, addr: "00881043998ff2b738519d444d2dd0da3da4545de08290c1076746538d5333df", symbol: "Sei", coinGeckoId: "sei-network", decimals: 6, price: 0.0},
|
||||
// BLAST (tokens over $50,000 24h volume)
|
||||
{chain: 36, addr: "0000000000000000000000004300000000000000000000000000000000000003", symbol: "USDB", coinGeckoId: "usdb", decimals: 18, price: 1.00},
|
||||
{chain: 36, addr: "0000000000000000000000004300000000000000000000000000000000000004", symbol: "WETH", coinGeckoId: "weth", decimals: 18, price: 3157.42},
|
||||
{chain: 36, addr: "0000000000000000000000002416092f143378750bb29b79ed961ab195cceea5", symbol: "EZETH", coinGeckoId: "renzo-restaked-eth", decimals: 18, price: 3092.32},
|
||||
{chain: 36, addr: "0000000000000000000000004fee793d435c6d2c10c135983bb9d6d4fc7b9bbd", symbol: "USD+", coinGeckoId: "usd", decimals: 18, price: 1.00},
|
||||
{chain: 36, addr: "000000000000000000000000818a92bc81aad0053d72ba753fb5bc3d0c5c0923", symbol: "JUICE", coinGeckoId: "juice-finance", decimals: 18, price: 0.1051},
|
||||
{chain: 36, addr: "0000000000000000000000009e20461bc2c4c980f62f1b279d71734207a6a356", symbol: "OMNI", coinGeckoId: "omnicat", decimals: 18, price: 0.0004575},
|
||||
{chain: 36, addr: "000000000000000000000000764933fbad8f5d04ccd088602096655c2ed9879f", symbol: "AI", coinGeckoId: "any-inu", decimals: 18, price: 0.00002742},
|
||||
{chain: 36, addr: "0000000000000000000000005ffd9ebd27f2fcab044c0f0a26a45cb62fa29c06", symbol: "PAC", coinGeckoId: "pacmoon", decimals: 18, price: 0.05459},
|
||||
{chain: 36, addr: "00000000000000000000000020fe91f17ec9080e3cac2d688b4ecb48c5ac3a9c", symbol: "YES", coinGeckoId: "yes-money", decimals: 18, price: 3.96},
|
||||
{chain: 36, addr: "00000000000000000000000076da31d7c9cbeae102aff34d3398bc450c8374c1", symbol: "MIM", coinGeckoId: "magic-internet-money", decimals: 18, price: 0.9935},
|
||||
{chain: 36, addr: "00000000000000000000000015d24de366f69b835be19f7cf9447e770315dd80", symbol: "KAP", coinGeckoId: "kapital-dao", decimals: 18, price: 0.1143},
|
||||
{chain: 36, addr: "000000000000000000000000b9dfcd4cf589bb8090569cb52fac1b88dbe4981f", symbol: "BAG", coinGeckoId: "bag", decimals: 18, price: 0.002972},
|
||||
{chain: 36, addr: "00000000000000000000000068449870eea84453044bd430822827e21fd8f101", symbol: "ZAI", coinGeckoId: "zaibot", decimals: 18, price: 0.2348},
|
||||
{chain: 36, addr: "00000000000000000000000047c337bd5b9344a6f3d6f58c474d9d8cd419d8ca", symbol: "DACKIE", coinGeckoId: "dackieswap", decimals: 18, price: 0.006554},
|
||||
{chain: 36, addr: "000000000000000000000000d43d8adac6a4c7d9aeece7c3151fca8f23752cf8", symbol: "ANDY", coinGeckoId: "andyerc", decimals: 9, price: 0.1165},
|
||||
{chain: 36, addr: "00000000000000000000000087e154e86fb691ab8a27116e93ed8d54e2b8c18c", symbol: "TES", coinGeckoId: "titan-trading-token", decimals: 18, price: 0.867},
|
||||
{chain: 36, addr: "000000000000000000000000870a8f46b62b8bdeda4c02530c1750cddf2ed32e", symbol: "USDC+", coinGeckoId: "usdc-plus-overnight", decimals: 18, price: 1.00},
|
||||
{chain: 36, addr: "00000000000000000000000042e12d42b3d6c4a74a88a61063856756ea2db357", symbol: "ORBIT", coinGeckoId: "orbit-protocol", decimals: 18, price: 0.3074},
|
||||
// SCROLL (tokens over $50,000 24h volume)
|
||||
{chain: 34, addr: "0000000000000000000000000018d96c579121a94307249d47f053e2d687b5e7", symbol: "MVX", coinGeckoId: "metavault-trade", decimals: 18, price: 2.06},
|
||||
{chain: 34, addr: "00000000000000000000000047c337bd5b9344a6f3d6f58c474d9d8cd419d8ca", symbol: "DACKIE", coinGeckoId: "dackieswap", decimals: 18, price: 0.00655},
|
||||
{chain: 34, addr: "0000000000000000000000005300000000000000000000000000000000000004", symbol: "WETH", coinGeckoId: "bridged-wrapped-ether-scroll", decimals: 18, price: 3145.98},
|
||||
{chain: 34, addr: "000000000000000000000000f55bec9cafdbe8730f096aa55dad6d22d44099df", symbol: "USDT", coinGeckoId: "bridged-tether-scroll", decimals: 6, price: 1.00},
|
||||
{chain: 34, addr: "00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a4", symbol: "USDC", coinGeckoId: "bridged-usd-coin-scroll", decimals: 6, price: 1.00},
|
||||
{chain: 34, addr: "000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215", symbol: "AXLUSDC", coinGeckoId: "bridged-axelar-wrapped-usd-coin-scroll", decimals: 6, price: 1.01},
|
||||
{chain: 34, addr: "0000000000000000000000003c1bca5a656e69edcd0d4e36bebb3fcdaca60cf1", symbol: "WBTC", coinGeckoId: "bridged-wrapped-bitcoin-scroll", decimals: 8, price: 64415.17},
|
||||
{chain: 34, addr: "00000000000000000000000060d01ec2d5e98ac51c8b4cf84dfcce98d527c747", symbol: "IZI", coinGeckoId: "izumi-finance", decimals: 18, price: 0.0142},
|
||||
{chain: 34, addr: "0000000000000000000000000a3bb08b3a15a19b4de82f8acfc862606fb69a2d", symbol: "IUSD", coinGeckoId: "izumi-bond-usd", decimals: 18, price: 0.9195},
|
||||
{chain: 34, addr: "000000000000000000000000f610a9dfb7c89644979b4a0f27063e9e7d7cda32", symbol: "WSTETH", coinGeckoId: "bridged-wrapped-lido-staked-ether-scroll", decimals: 18, price: 3659.28},
|
||||
{chain: 34, addr: "000000000000000000000000cA77eB3fEFe3725Dc33bccB54eDEFc3D9f764f97", symbol: "DAI", coinGeckoId: "dai", decimals: 18, price: 1.00},
|
||||
{chain: 34, addr: "00000000000000000000000053878B874283351D26d206FA512aEcE1Bef6C0dD", symbol: "RETH", coinGeckoId: "rocket-pool-eth", decimals: 18, price: 3475.55},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ func GuardianOptionAccountant(
|
|||
}
|
||||
|
||||
if websocket == "" {
|
||||
return errors.New("if accountantContract is specified, accountantWS is required")
|
||||
return errors.New("if either accountantContract or accountantNttContract is specified, accountantWS is required")
|
||||
}
|
||||
if contract != "" {
|
||||
if wormchainConn == nil {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,8 @@
|
|||
package evm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/common"
|
||||
gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
|
||||
"github.com/certusone/wormhole/node/pkg/query"
|
||||
|
@ -20,6 +22,10 @@ type WatcherConfig struct {
|
|||
L1FinalizerRequired watchers.NetworkID // (optional)
|
||||
l1Finalizer interfaces.L1Finalizer
|
||||
CcqBackfillCache bool
|
||||
|
||||
// These parameters are currently only used for Linea and should be set via SetLineaParams()
|
||||
LineaRollUpUrl string
|
||||
LineaRollUpContract string
|
||||
}
|
||||
|
||||
func (wc *WatcherConfig) GetNetworkID() watchers.NetworkID {
|
||||
|
@ -57,5 +63,12 @@ func (wc *WatcherConfig) Create(
|
|||
|
||||
watcher := NewEthWatcher(wc.Rpc, eth_common.HexToAddress(wc.Contract), string(wc.NetworkID), wc.ChainID, msgC, setWriteC, obsvReqC, queryReqC, queryResponseC, devMode, wc.CcqBackfillCache)
|
||||
watcher.SetL1Finalizer(wc.l1Finalizer)
|
||||
if wc.ChainID == vaa.ChainIDLinea {
|
||||
if err := watcher.SetLineaParams(wc.LineaRollUpUrl, wc.LineaRollUpContract); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
} else if wc.LineaRollUpUrl != "" || wc.LineaRollUpContract != "" {
|
||||
return nil, nil, errors.New("LineaRollUpUrl and LineaRollUpContract may only be specified for Linea")
|
||||
}
|
||||
return watcher, watcher.Run, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
// A block is considered finalized on Linea when it is marked finalized by the LineaRollup contract on Ethereum.
|
||||
//
|
||||
// For a discussion of finality on Linea, see here:
|
||||
// https://www.notion.so/wormholefoundation/Testnet-Info-V2-633e4aa64a634d56a7ce07a103789774?pvs=4#03513c2eb3654d33aff2206a562d25b1
|
||||
//
|
||||
// The LineaRollup proxy contract on ethereum is available at the following addresses:
|
||||
// Mainnet: 0xd19d4B5d358258f05D7B411E21A1460D11B0876F
|
||||
// Testnet: 0xB218f8A4Bc926cF1cA7b3423c154a0D627Bdb7E5
|
||||
//
|
||||
// To generate the golang abi for the LineaRollup contract:
|
||||
// - Grab the ABIs from the LineaRollup contract (not the proxy) (0x934Dd4C63E285551CEceF8459103554D0096c179 on Ethereum mainnet) and put it in /tmp/LineaRollup.abi.
|
||||
// - mkdir node/pkg/watchers/evm/connectors/lineaabi
|
||||
// - Install abigen: go install github.com/ethereum/go-ethereum/cmd/abigen@latest
|
||||
// - abigen --abi /tmp/LineaRollup.abi --pkg lineaabi --out node/pkg/watchers/evm/connectors/lineaabi/LineaRollup.go
|
||||
|
||||
package connectors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/common"
|
||||
rollUpAbi "github.com/certusone/wormhole/node/pkg/watchers/evm/connectors/lineaabi"
|
||||
|
||||
ethereum "github.com/ethereum/go-ethereum"
|
||||
ethBind "github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
ethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||
ethClient "github.com/ethereum/go-ethereum/ethclient"
|
||||
ethRpc "github.com/ethereum/go-ethereum/rpc"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// LineaConnector listens for new finalized blocks for Linea by reading the roll up contract on Ethereum.
|
||||
type LineaConnector struct {
|
||||
Connector
|
||||
logger *zap.Logger
|
||||
|
||||
// These are used for querying the roll up contract.
|
||||
rollUpRawClient *ethRpc.Client
|
||||
rollUpClient *ethClient.Client
|
||||
|
||||
// These are used to subscribe for new block finalized events from the roll up contract.
|
||||
rollUpFilterer *rollUpAbi.LineaabiFilterer
|
||||
rollUpCaller *rollUpAbi.LineaabiCaller
|
||||
|
||||
latestBlockNum uint64
|
||||
latestFinalizedBlockNum uint64
|
||||
}
|
||||
|
||||
// NewLineaConnector creates a new Linea poll connector using the specified roll up contract.
|
||||
func NewLineaConnector(
|
||||
ctx context.Context,
|
||||
logger *zap.Logger,
|
||||
baseConnector Connector,
|
||||
rollUpUrl string,
|
||||
rollUpAddress string,
|
||||
) (*LineaConnector, error) {
|
||||
|
||||
rollUpRawClient, err := ethRpc.DialContext(ctx, rollUpUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create roll up raw client for url %s: %w", rollUpUrl, err)
|
||||
}
|
||||
|
||||
rollUpClient := ethClient.NewClient(rollUpRawClient)
|
||||
|
||||
addr := ethCommon.HexToAddress(rollUpAddress)
|
||||
rollUpFilterer, err := rollUpAbi.NewLineaabiFilterer(addr, rollUpClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create roll up filter for url %s: %w", rollUpUrl, err)
|
||||
}
|
||||
|
||||
rollUpCaller, err := rollUpAbi.NewLineaabiCaller(addr, rollUpClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create roll up caller for url %s: %w", rollUpUrl, err)
|
||||
}
|
||||
|
||||
logger.Info("Using roll up for Linea", zap.String("rollUpUrl", rollUpUrl), zap.String("rollUpAddress", rollUpAddress))
|
||||
|
||||
connector := &LineaConnector{
|
||||
Connector: baseConnector,
|
||||
logger: logger,
|
||||
rollUpRawClient: rollUpRawClient,
|
||||
rollUpClient: rollUpClient,
|
||||
rollUpFilterer: rollUpFilterer,
|
||||
rollUpCaller: rollUpCaller,
|
||||
}
|
||||
|
||||
return connector, nil
|
||||
}
|
||||
|
||||
// SubscribeForBlocks starts polling. It implements the standard connector interface.
|
||||
func (c *LineaConnector) SubscribeForBlocks(ctx context.Context, errC chan error, sink chan<- *NewBlock) (ethereum.Subscription, error) {
|
||||
timeout, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Use the standard geth head sink to get latest blocks.
|
||||
headSink := make(chan *ethTypes.Header, 2)
|
||||
headerSubscription, err := c.Connector.Client().SubscribeNewHead(ctx, headSink)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to subscribe for latest blocks: %w", err)
|
||||
}
|
||||
|
||||
// Subscribe to data finalized events from the roll up contract.
|
||||
dataFinalizedChan := make(chan *rollUpAbi.LineaabiDataFinalized, 2)
|
||||
dataFinalizedSub, err := c.rollUpFilterer.WatchDataFinalized(ðBind.WatchOpts{Context: timeout}, dataFinalizedChan, nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to subscribe for events from roll up contract: %w", err)
|
||||
}
|
||||
|
||||
// Get the current latest block on Linea.
|
||||
latestBlock, err := GetBlockByFinality(timeout, c.logger, c.Connector, Latest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get current latest block: %w", err)
|
||||
}
|
||||
c.latestBlockNum = latestBlock.Number.Uint64()
|
||||
|
||||
// Get and publish the current latest finalized block.
|
||||
opts := ðBind.CallOpts{Context: timeout}
|
||||
initialBlock, err := c.rollUpCaller.CurrentL2BlockNumber(opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get initial block: %w", err)
|
||||
}
|
||||
c.latestFinalizedBlockNum = initialBlock.Uint64()
|
||||
|
||||
if c.latestFinalizedBlockNum > c.latestBlockNum {
|
||||
return nil, fmt.Errorf("latest finalized block reported by L1 (%d) is ahead of latest block reported by L2 (%d), L2 node seems to be stuck",
|
||||
c.latestFinalizedBlockNum, c.latestBlockNum)
|
||||
}
|
||||
|
||||
c.logger.Info("queried initial finalized block", zap.Uint64("initialBlock", c.latestFinalizedBlockNum), zap.Uint64("latestBlock", c.latestBlockNum))
|
||||
if err = c.postFinalizedAndSafe(ctx, c.latestFinalizedBlockNum, sink); err != nil {
|
||||
return nil, fmt.Errorf("failed to post initial block: %w", err)
|
||||
}
|
||||
|
||||
common.RunWithScissors(ctx, errC, "linea_block_poller", func(ctx context.Context) error {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
dataFinalizedSub.Unsubscribe()
|
||||
return nil
|
||||
case err := <-dataFinalizedSub.Err():
|
||||
errC <- fmt.Errorf("finalized data watcher posted an error: %w", err)
|
||||
dataFinalizedSub.Unsubscribe()
|
||||
return nil
|
||||
case evt := <-dataFinalizedChan:
|
||||
if err := c.processDataFinalizedEvent(ctx, sink, evt); err != nil {
|
||||
errC <- fmt.Errorf("failed to process block finalized event: %w", err)
|
||||
dataFinalizedSub.Unsubscribe()
|
||||
return nil
|
||||
}
|
||||
case ev := <-headSink:
|
||||
if ev == nil {
|
||||
c.logger.Error("new latest header event is nil")
|
||||
continue
|
||||
}
|
||||
if ev.Number == nil {
|
||||
c.logger.Error("new latest header block number is nil")
|
||||
continue
|
||||
}
|
||||
c.latestBlockNum = ev.Number.Uint64()
|
||||
sink <- &NewBlock{
|
||||
Number: ev.Number,
|
||||
Time: ev.Time,
|
||||
Hash: ev.Hash(),
|
||||
Finality: Latest,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return headerSubscription, nil
|
||||
}
|
||||
|
||||
// processDataFinalizedEvent handles a DataFinalized event published by the roll up contract.
|
||||
func (c *LineaConnector) processDataFinalizedEvent(ctx context.Context, sink chan<- *NewBlock, evt *rollUpAbi.LineaabiDataFinalized) error {
|
||||
latestFinalizedBlockNum := evt.LastBlockFinalized.Uint64()
|
||||
// Leaving this log info in for now because these events come very infrequently.
|
||||
c.logger.Info("processing data finalized event",
|
||||
zap.Uint64("latestFinalizedBlockNum", latestFinalizedBlockNum),
|
||||
zap.Uint64("prevFinalizedBlockNum", c.latestFinalizedBlockNum),
|
||||
)
|
||||
|
||||
if latestFinalizedBlockNum > c.latestBlockNum {
|
||||
return fmt.Errorf("latest finalized block reported by L1 (%d) is ahead of latest block reported by L2 (%d), L2 node seems to be stuck",
|
||||
latestFinalizedBlockNum, c.latestBlockNum)
|
||||
}
|
||||
|
||||
for blockNum := c.latestFinalizedBlockNum + 1; blockNum <= latestFinalizedBlockNum; blockNum++ {
|
||||
if err := c.postFinalizedAndSafe(ctx, blockNum, sink); err != nil {
|
||||
c.latestFinalizedBlockNum = blockNum - 1
|
||||
return fmt.Errorf("failed to post block %d: %w", blockNum, err)
|
||||
}
|
||||
}
|
||||
|
||||
c.latestFinalizedBlockNum = latestFinalizedBlockNum
|
||||
return nil
|
||||
}
|
||||
|
||||
// postFinalizedAndSafe publishes a block as finalized and safe. It takes a block number and looks it up on chain to publish the current values.
|
||||
func (c *LineaConnector) postFinalizedAndSafe(ctx context.Context, blockNum uint64, sink chan<- *NewBlock) error {
|
||||
timeout, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
block, err := GetBlockByNumberUint64(timeout, c.logger, c.Connector, blockNum, Finalized)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get block %d: %w", blockNum, err)
|
||||
}
|
||||
|
||||
// Publish the finalized block.
|
||||
sink <- block
|
||||
|
||||
// Publish same thing for the safe block.
|
||||
sink <- block.Copy(Safe)
|
||||
return nil
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -2,6 +2,7 @@ package evm
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
@ -136,6 +137,10 @@ type (
|
|||
ccqBatchSize int64
|
||||
ccqBackfillCache bool
|
||||
ccqLogger *zap.Logger
|
||||
|
||||
// These parameters are currently only used for Linea and should be set via SetLineaParams()
|
||||
lineaRollUpUrl string
|
||||
lineaRollUpContract string
|
||||
}
|
||||
|
||||
pendingKey struct {
|
||||
|
@ -242,6 +247,19 @@ func (w *Watcher) Run(parentCtx context.Context) error {
|
|||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||
return fmt.Errorf("dialing eth client failed: %w", err)
|
||||
}
|
||||
} else if w.chainID == vaa.ChainIDLinea {
|
||||
baseConnector, err := connectors.NewEthereumBaseConnector(timeout, w.networkName, w.url, w.contract, logger)
|
||||
if err != nil {
|
||||
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
||||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||
return fmt.Errorf("dialing eth client failed: %w", err)
|
||||
}
|
||||
w.ethConn, err = connectors.NewLineaConnector(ctx, logger, baseConnector, w.lineaRollUpUrl, w.lineaRollUpContract)
|
||||
if err != nil {
|
||||
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
|
||||
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
|
||||
return fmt.Errorf("failed to create Linea poller: %w", err)
|
||||
}
|
||||
} else {
|
||||
// Everything else is instant finality.
|
||||
logger.Info("assuming instant finality")
|
||||
|
@ -699,41 +717,61 @@ func fetchCurrentGuardianSet(ctx context.Context, ethConn connectors.Connector)
|
|||
// getFinality determines if the chain supports "finalized" and "safe". This is hard coded so it requires thought to change something. However, it also reads the RPC
|
||||
// to make sure the node actually supports the expected values, and returns an error if it doesn't. Note that we do not support using safe mode but not finalized mode.
|
||||
func (w *Watcher) getFinality(ctx context.Context) (bool, bool, error) {
|
||||
// TODO: Need to handle finality for Linea before it can be deployed in Mainnet.
|
||||
finalized := false
|
||||
safe := false
|
||||
|
||||
// Tilt supports polling for both finalized and safe.
|
||||
if w.unsafeDevMode {
|
||||
finalized = true
|
||||
safe = true
|
||||
|
||||
// The following chains support polling for both finalized and safe.
|
||||
} else if w.chainID == vaa.ChainIDAcala ||
|
||||
w.chainID == vaa.ChainIDArbitrum ||
|
||||
w.chainID == vaa.ChainIDArbitrumSepolia ||
|
||||
w.chainID == vaa.ChainIDBase ||
|
||||
w.chainID == vaa.ChainIDBaseSepolia ||
|
||||
w.chainID == vaa.ChainIDBlast ||
|
||||
w.chainID == vaa.ChainIDBSC ||
|
||||
w.chainID == vaa.ChainIDEthereum ||
|
||||
w.chainID == vaa.ChainIDHolesky ||
|
||||
w.chainID == vaa.ChainIDKarura ||
|
||||
w.chainID == vaa.ChainIDMantle ||
|
||||
w.chainID == vaa.ChainIDMoonbeam ||
|
||||
w.chainID == vaa.ChainIDOptimism ||
|
||||
w.chainID == vaa.ChainIDSepolia ||
|
||||
w.chainID == vaa.ChainIDHolesky ||
|
||||
w.chainID == vaa.ChainIDArbitrumSepolia ||
|
||||
w.chainID == vaa.ChainIDBaseSepolia ||
|
||||
w.chainID == vaa.ChainIDOptimismSepolia ||
|
||||
w.chainID == vaa.ChainIDSepolia ||
|
||||
w.chainID == vaa.ChainIDXLayer {
|
||||
finalized = true
|
||||
safe = true
|
||||
} else if w.chainID == vaa.ChainIDScroll {
|
||||
// As of 11/10/2023 Scroll supports polling for finalized but not safe.
|
||||
finalized = true
|
||||
} else if w.chainID == vaa.ChainIDPolygon ||
|
||||
w.chainID == vaa.ChainIDPolygonSepolia {
|
||||
|
||||
// The following chains have their own specialized finalizers.
|
||||
} else if w.chainID == vaa.ChainIDCelo ||
|
||||
w.chainID == vaa.ChainIDLinea {
|
||||
return false, false, nil
|
||||
|
||||
// Polygon now supports polling for finalized but not safe.
|
||||
// https://forum.polygon.technology/t/optimizing-decentralized-apps-ux-with-milestones-a-significantly-accelerated-finality-solution/13154
|
||||
} else if w.chainID == vaa.ChainIDPolygon ||
|
||||
w.chainID == vaa.ChainIDPolygonSepolia {
|
||||
finalized = true
|
||||
} else if w.chainID == vaa.ChainIDBerachain {
|
||||
// Berachain supports instant finality: https://docs.berachain.com/faq/
|
||||
|
||||
// As of 11/10/2023 Scroll supports polling for finalized but not safe.
|
||||
} else if w.chainID == vaa.ChainIDScroll {
|
||||
finalized = true
|
||||
|
||||
// The following chains support instant finality.
|
||||
} else if w.chainID == vaa.ChainIDAvalanche ||
|
||||
w.chainID == vaa.ChainIDBerachain || // Berachain supports instant finality: https://docs.berachain.com/faq/
|
||||
w.chainID == vaa.ChainIDOasis ||
|
||||
w.chainID == vaa.ChainIDAurora ||
|
||||
w.chainID == vaa.ChainIDFantom ||
|
||||
w.chainID == vaa.ChainIDKlaytn {
|
||||
return false, false, nil
|
||||
|
||||
// Anything else is undefined / not supported.
|
||||
} else {
|
||||
return false, false, fmt.Errorf("unsupported chain: %s", w.chainID.String())
|
||||
}
|
||||
|
||||
// If finalized / safe should be supported, read the RPC to make sure they actually are.
|
||||
|
@ -935,3 +973,22 @@ func (w *Watcher) waitForBlockTime(ctx context.Context, logger *zap.Logger, errC
|
|||
func msgIdFromLogEvent(chainID vaa.ChainID, ev *ethabi.AbiLogMessagePublished) string {
|
||||
return fmt.Sprintf("%v/%v/%v", uint16(chainID), PadAddress(ev.Sender), ev.Sequence)
|
||||
}
|
||||
|
||||
// SetLineaParams is used to enable polling on Linea using the roll up contract on Ethereum.
|
||||
func (w *Watcher) SetLineaParams(lineaRollUpUrl string, lineaRollUpContract string) error {
|
||||
if w.chainID != vaa.ChainIDLinea {
|
||||
return errors.New("function only allowed for Linea")
|
||||
}
|
||||
if w.unsafeDevMode && lineaRollUpUrl == "" && lineaRollUpContract == "" {
|
||||
return nil
|
||||
}
|
||||
if lineaRollUpUrl == "" {
|
||||
return fmt.Errorf("lineaRollUpUrl must be set")
|
||||
}
|
||||
if lineaRollUpContract == "" {
|
||||
return fmt.Errorf("lineaRollUpContract must be set")
|
||||
}
|
||||
w.lineaRollUpUrl = lineaRollUpUrl
|
||||
w.lineaRollUpContract = lineaRollUpContract
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ service NodePrivilegedService {
|
|||
|
||||
// ChainGovernorReleasePendingVAA release a VAA from the chain governor pending list, publishing it immediately.
|
||||
rpc ChainGovernorReleasePendingVAA (ChainGovernorReleasePendingVAARequest) returns (ChainGovernorReleasePendingVAAResponse);
|
||||
|
||||
|
||||
// ChainGovernorResetReleaseTimer resets the release timer for a chain governor pending VAA to the configured maximum.
|
||||
rpc ChainGovernorResetReleaseTimer (ChainGovernorResetReleaseTimerRequest) returns (ChainGovernorResetReleaseTimerResponse);
|
||||
|
||||
|
@ -51,10 +51,10 @@ service NodePrivilegedService {
|
|||
rpc SignExistingVAA (SignExistingVAARequest) returns (SignExistingVAAResponse);
|
||||
|
||||
// DumpRPCs returns the RPCs being used by the guardian
|
||||
rpc DumpRPCs (DumpRPCsRequest) returns (DumpRPCsResponse);
|
||||
rpc DumpRPCs (DumpRPCsRequest) returns (DumpRPCsResponse);
|
||||
|
||||
// GetMissingVAAs returns the VAAs from a cloud function that need to be reobserved.
|
||||
rpc GetAndObserveMissingVAAs (GetAndObserveMissingVAAsRequest) returns (GetAndObserveMissingVAAsResponse);
|
||||
rpc GetAndObserveMissingVAAs (GetAndObserveMissingVAAsRequest) returns (GetAndObserveMissingVAAsResponse);
|
||||
}
|
||||
|
||||
message InjectGovernanceVAARequest {
|
||||
|
@ -85,7 +85,7 @@ message GovernanceMessage {
|
|||
GuardianSetUpdate guardian_set = 10;
|
||||
ContractUpgrade contract_upgrade = 11;
|
||||
|
||||
// Token bridge, NFT module, and Wormhole Relayer module (for the first two)
|
||||
// Token bridge, NFT module, and Wormhole Relayer module (for the first two)
|
||||
|
||||
BridgeRegisterChain bridge_register_chain = 12;
|
||||
BridgeUpgradeContract bridge_contract_upgrade = 13;
|
||||
|
@ -117,6 +117,10 @@ message GovernanceMessage {
|
|||
IbcUpdateChannelChain ibc_update_channel_chain = 21;
|
||||
// Wormhole Relayer module
|
||||
WormholeRelayerSetDefaultDeliveryProvider wormhole_relayer_set_default_delivery_provider = 22;
|
||||
|
||||
// Generic governance
|
||||
EvmCall evm_call = 28;
|
||||
SolanaCall solana_call = 29;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +195,7 @@ message AccountantModifyBalance {
|
|||
|
||||
// ContractUpgrade represents a Wormhole contract update to be submitted to and signed by the node.
|
||||
message ContractUpgrade {
|
||||
// ID of the chain where the Wormhole contract should be updated (uint8).
|
||||
// ID of the chain where the Wormhole contract should be updated (uint16).
|
||||
uint32 chain_id = 1;
|
||||
|
||||
// Hex-encoded address (without leading 0x) address of the new program/contract.
|
||||
|
@ -417,3 +421,30 @@ message GetAndObserveMissingVAAsRequest {
|
|||
message GetAndObserveMissingVAAsResponse {
|
||||
string response =1;
|
||||
}
|
||||
|
||||
// EvmCall represents a generic EVM call that can be executed by the generalized governance contract.
|
||||
message EvmCall {
|
||||
// ID of the chain where the action should be executed (uint16).
|
||||
uint32 chain_id = 1;
|
||||
|
||||
// Address of the governance contract (eth address starting with 0x)
|
||||
string governance_contract = 2;
|
||||
|
||||
// Address of the governed contract (eth address starting with 0x)
|
||||
string target_contract = 3;
|
||||
|
||||
// ABI-encoded calldata to be passed on to the governed contract (hex encoded)
|
||||
string abi_encoded_call = 4;
|
||||
}
|
||||
|
||||
// SolanaCall represents a generic Solana call that can be executed by the generalized governance contract.
|
||||
message SolanaCall {
|
||||
// ID of the chain where the action should be executed (uint16).
|
||||
uint32 chain_id = 1;
|
||||
|
||||
// Address of the governance contract (solana address)
|
||||
string governance_contract = 2;
|
||||
|
||||
// Encoded instruction data to be passed on to the governed contract (hex encoded)
|
||||
string encoded_instruction = 3;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
## 0.10.15
|
||||
|
||||
Add Provenance to cosmwasm chains
|
||||
Add Scroll mainnet support
|
||||
Add Blast mainnet support
|
||||
|
||||
## 0.10.14
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@certusone/wormhole-sdk",
|
||||
"version": "0.10.14",
|
||||
"version": "0.10.15",
|
||||
"description": "SDK for interacting with Wormhole",
|
||||
"homepage": "https://wormhole.com",
|
||||
"main": "./lib/cjs/index.js",
|
||||
|
|
|
@ -309,8 +309,8 @@ const MAINNET = {
|
|||
nft_bridge: undefined,
|
||||
},
|
||||
scroll: {
|
||||
core: undefined,
|
||||
token_bridge: undefined,
|
||||
core: "0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6",
|
||||
token_bridge: "0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d",
|
||||
nft_bridge: undefined,
|
||||
},
|
||||
mantle: {
|
||||
|
@ -319,8 +319,8 @@ const MAINNET = {
|
|||
nft_bridge: undefined,
|
||||
},
|
||||
blast: {
|
||||
core: undefined,
|
||||
token_bridge: undefined,
|
||||
core: "0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6",
|
||||
token_bridge: "0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d",
|
||||
nft_bridge: undefined,
|
||||
},
|
||||
xlayer: {
|
||||
|
|
|
@ -118,6 +118,8 @@ var knownTokenbridgeEmitters = map[vaa.ChainID]string{
|
|||
vaa.ChainIDOptimism: "0000000000000000000000001D68124e65faFC907325e3EDbF8c4d84499DAa8b",
|
||||
vaa.ChainIDBase: "0000000000000000000000008d2de8d2f73F1F4cAB472AC9A881C9b123C79627",
|
||||
vaa.ChainIDXpla: "8f9cf727175353b17a5f574270e370776123d90fd74956ae4277962b4fdee24c",
|
||||
vaa.ChainIDScroll: "00000000000000000000000024850c6f61C438823F01B7A3BF2B89B72174Fa9d",
|
||||
vaa.ChainIDBlast: "00000000000000000000000024850c6f61C438823F01B7A3BF2B89B72174Fa9d",
|
||||
vaa.ChainIDInjective: "00000000000000000000000045dbea4617971d93188eda21530bc6503d153313",
|
||||
vaa.ChainIDSui: "ccceeb29348f71bdd22ffef43a2a19c1f5b5e17c5cca5411529120182672ade5",
|
||||
vaa.ChainIDSei: "86c5fd957e2db8389553e1728f9c27964b22a8154091ccba54d75f4b10c61f5e",
|
||||
|
|
|
@ -4,8 +4,9 @@ import (
|
|||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
@ -55,6 +56,13 @@ var WormholeRelayerModule = [32]byte{
|
|||
}
|
||||
var WormholeRelayerModuleStr = string(WormholeRelayerModule[:])
|
||||
|
||||
var GeneralPurposeGovernanceModule = [32]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x6C,
|
||||
0x50, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x47, 0x6F, 0x76, 0x65, 0x72, 0x6E, 0x61, 0x6E,
|
||||
0x63, 0x65,
|
||||
}
|
||||
var GeneralPurposeGovernanceModuleStr = string(GeneralPurposeGovernanceModule[:])
|
||||
|
||||
type GovernanceAction uint8
|
||||
|
||||
var (
|
||||
|
@ -99,6 +107,10 @@ var (
|
|||
|
||||
// Wormhole relayer governance actions
|
||||
WormholeRelayerSetDefaultDeliveryProvider GovernanceAction = 3
|
||||
|
||||
// General purpose governance
|
||||
GeneralPurposeGovernanceEvmAction GovernanceAction = 1
|
||||
GeneralPurposeGovernanceSolanaAction GovernanceAction = 2
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -110,7 +122,7 @@ type (
|
|||
|
||||
// BodyGuardianSetUpdate is a governance message to set a new guardian set
|
||||
BodyGuardianSetUpdate struct {
|
||||
Keys []common.Address
|
||||
Keys []ethcommon.Address
|
||||
NewIndex uint32
|
||||
}
|
||||
|
||||
|
@ -216,6 +228,24 @@ type (
|
|||
ChainID ChainID
|
||||
NewDefaultDeliveryProviderAddress Address
|
||||
}
|
||||
|
||||
// BodyGeneralPurposeGovernanceEvm is a general purpose governance message for EVM chains
|
||||
BodyGeneralPurposeGovernanceEvm struct {
|
||||
ChainID ChainID
|
||||
GovernanceContract ethcommon.Address
|
||||
TargetContract ethcommon.Address
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
// BodyGeneralPurposeGovernanceSolana is a general purpose governance message for Solana chains
|
||||
BodyGeneralPurposeGovernanceSolana struct {
|
||||
ChainID ChainID
|
||||
GovernanceContract Address
|
||||
// NOTE: unlike in EVM, no target contract in the schema here, the
|
||||
// instruction encodes the target contract address (unlike in EVM, where
|
||||
// an abi encoded calldata doesn't include the target contract address)
|
||||
Instruction []byte
|
||||
}
|
||||
)
|
||||
|
||||
func (b BodyContractUpgrade) Serialize() []byte {
|
||||
|
@ -402,6 +432,31 @@ func (r BodyWormholeRelayerSetDefaultDeliveryProvider) Serialize() []byte {
|
|||
return serializeBridgeGovernanceVaa(WormholeRelayerModuleStr, WormholeRelayerSetDefaultDeliveryProvider, r.ChainID, payload.Bytes())
|
||||
}
|
||||
|
||||
func (r BodyGeneralPurposeGovernanceEvm) Serialize() ([]byte, error) {
|
||||
payload := &bytes.Buffer{}
|
||||
payload.Write(r.GovernanceContract[:])
|
||||
payload.Write(r.TargetContract[:])
|
||||
|
||||
// write payload len as uint16
|
||||
if len(r.Payload) > math.MaxUint16 {
|
||||
return nil, fmt.Errorf("payload too long; expected at most %d bytes", math.MaxUint16)
|
||||
}
|
||||
MustWrite(payload, binary.BigEndian, uint16(len(r.Payload)))
|
||||
payload.Write(r.Payload)
|
||||
return serializeBridgeGovernanceVaa(GeneralPurposeGovernanceModuleStr, GeneralPurposeGovernanceEvmAction, r.ChainID, payload.Bytes()), nil
|
||||
}
|
||||
|
||||
func (r BodyGeneralPurposeGovernanceSolana) Serialize() []byte {
|
||||
payload := &bytes.Buffer{}
|
||||
payload.Write(r.GovernanceContract[:])
|
||||
// NOTE: unlike in EVM, we don't write the payload length here, because we're using
|
||||
// a custom instruction encoding (there is no standard encoding like evm ABI
|
||||
// encoding), generated by an external tool. That tool length-prefixes all
|
||||
// the relevant dynamic fields.
|
||||
payload.Write(r.Instruction)
|
||||
return serializeBridgeGovernanceVaa(GeneralPurposeGovernanceModuleStr, GeneralPurposeGovernanceSolanaAction, r.ChainID, payload.Bytes())
|
||||
}
|
||||
|
||||
func EmptyPayloadVaa(module string, actionId GovernanceAction, chainId ChainID) []byte {
|
||||
return serializeBridgeGovernanceVaa(module, actionId, chainId, []byte{})
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ require (
|
|||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||
github.com/btcsuite/btcd v0.22.1 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect
|
||||
|
@ -49,8 +49,7 @@ require (
|
|||
github.com/cosmos/gogoproto v1.4.3 // indirect
|
||||
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v0.19.4 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
|
||||
github.com/cosmos/ledger-go v0.9.2 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect
|
||||
github.com/creachadair/taskgroup v0.3.2 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
|
@ -122,7 +121,8 @@ require (
|
|||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
|
||||
github.com/tendermint/btcd v0.1.1 // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/zondax/hid v0.9.0 // indirect
|
||||
github.com/zondax/hid v0.9.2 // indirect
|
||||
github.com/zondax/ledger-go v0.14.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/net v0.2.0 // indirect
|
||||
|
|
|
@ -332,6 +332,7 @@ github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c=
|
|||
github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
|
@ -579,6 +580,8 @@ github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ
|
|||
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M=
|
||||
github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI=
|
||||
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
|
@ -2118,6 +2121,10 @@ github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPS
|
|||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
|
||||
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U=
|
||||
github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw=
|
||||
github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI=
|
||||
gitlab.com/bosi/decorder v0.2.1/go.mod h1:6C/nhLSbF6qZbYD8bRmISBwc6vcWdNsiIBkRvjJFrH0=
|
||||
gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
|
|
Loading…
Reference in New Issue