diff --git a/contract_manager/scripts/common.ts b/contract_manager/scripts/common.ts index e4d5d9abb6..9b6f099251 100644 --- a/contract_manager/scripts/common.ts +++ b/contract_manager/scripts/common.ts @@ -107,7 +107,7 @@ export const COMMON_DEPLOY_OPTIONS = { desc: "Save the contract to the store", }, } as const; -export const COMMON_UPGRADE_OPTIONS = { +export const CHAIN_SELECTION_OPTIONS = { testnet: { type: "boolean", default: false, @@ -123,6 +123,9 @@ export const COMMON_UPGRADE_OPTIONS = { string: true, desc: "Chains to upgrade the contract on", }, +} as const; +export const COMMON_UPGRADE_OPTIONS = { + ...CHAIN_SELECTION_OPTIONS, "private-key": COMMON_DEPLOY_OPTIONS["private-key"], "ops-key-path": { type: "string", diff --git a/contract_manager/src/chains.ts b/contract_manager/src/chains.ts index b4264e3764..c922b822a8 100644 --- a/contract_manager/src/chains.ts +++ b/contract_manager/src/chains.ts @@ -10,6 +10,7 @@ import { DataSource, EvmSetWormholeAddress, UpgradeContract256Bit, + EvmExecute, } from "@pythnetwork/xc-admin-common"; import { AptosClient, AptosAccount, CoinClient, TxnBuilderTypes } from "aptos"; import Web3 from "web3"; @@ -371,6 +372,27 @@ export class EvmChain extends Chain { return new EvmUpgradeContract(this.wormholeChainName, address).encode(); } + /** + * Returns the payload for a governance action from the executor contract + * @param executor the address of the executor contract live on this chain + * @param callAddress the address of the contract to call + * @param calldata the calldata to pass to the contract + * @returns the payload for the governance action + */ + generateExecutorPayload( + executor: string, + callAddress: string, + calldata: string + ): Buffer { + return new EvmExecute( + this.wormholeChainName, + executor.replace("0x", ""), + callAddress.replace("0x", ""), + 0n, + Buffer.from(calldata.replace("0x", ""), "hex") + ).encode(); + } + generateGovernanceSetWormholeAddressPayload(address: string): Buffer { return new EvmSetWormholeAddress(this.wormholeChainName, address).encode(); } diff --git a/contract_manager/src/contracts/evm.ts b/contract_manager/src/contracts/evm.ts index 57101d9b6e..6b56b5a9c4 100644 --- a/contract_manager/src/contracts/evm.ts +++ b/contract_manager/src/contracts/evm.ts @@ -1,373 +1,17 @@ import Web3 from "web3"; import type { Contract } from "web3-eth-contract"; -import PythInterfaceAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json"; -import EntropyAbi from "@pythnetwork/entropy-sdk-solidity/abis/IEntropy.json"; import { PriceFeedContract, PrivateKey, Storable } from "../base"; import { Chain, EvmChain } from "../chains"; import { DataSource, EvmExecute } from "@pythnetwork/xc-admin-common"; import { WormholeContract } from "./wormhole"; import { TokenQty } from "../token"; - -// Just to make sure tx gas limit is enough -const EXTENDED_ENTROPY_ABI = [ - { - inputs: [], - name: "acceptOwnership", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "acceptAdmin", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "owner", - outputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "pendingOwner", - outputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "version", - outputs: [ - { - internalType: "string", - name: "", - type: "string", - }, - ], - stateMutability: "pure", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "newImplementation", - type: "address", - }, - ], - name: "upgradeTo", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - ...EntropyAbi, -] as any; // eslint-disable-line @typescript-eslint/no-explicit-any -const EXTENDED_PYTH_ABI = [ - { - inputs: [], - name: "wormhole", - outputs: [ - { - internalType: "contract IWormhole", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "governanceDataSource", - outputs: [ - { - components: [ - { - internalType: "uint16", - name: "chainId", - type: "uint16", - }, - { - internalType: "bytes32", - name: "emitterAddress", - type: "bytes32", - }, - ], - internalType: "struct PythInternalStructs.DataSource", - name: "", - type: "tuple", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "bytes", - name: "encodedVM", - type: "bytes", - }, - ], - name: "executeGovernanceInstruction", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "version", - outputs: [{ internalType: "string", name: "", type: "string" }], - stateMutability: "pure", - type: "function", - }, - { - inputs: [], - name: "singleUpdateFeeInWei", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "validDataSources", - outputs: [ - { - components: [ - { - internalType: "uint16", - name: "chainId", - type: "uint16", - }, - { - internalType: "bytes32", - name: "emitterAddress", - type: "bytes32", - }, - ], - internalType: "struct PythInternalStructs.DataSource[]", - name: "", - type: "tuple[]", - }, - ], - stateMutability: "view", - type: "function", - constant: true, - }, - { - inputs: [], - name: "lastExecutedGovernanceSequence", - outputs: [ - { - internalType: "uint64", - name: "", - type: "uint64", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "bytes32", - name: "id", - type: "bytes32", - }, - ], - name: "priceFeedExists", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "view", - type: "function", - }, - ...PythInterfaceAbi, -] as any; // eslint-disable-line @typescript-eslint/no-explicit-any -const WORMHOLE_ABI = [ - { - inputs: [], - name: "getCurrentGuardianSetIndex", - outputs: [ - { - internalType: "uint32", - name: "", - type: "uint32", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "chainId", - outputs: [ - { - internalType: "uint16", - name: "", - type: "uint16", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "uint32", - name: "index", - type: "uint32", - }, - ], - name: "getGuardianSet", - outputs: [ - { - components: [ - { - internalType: "address[]", - name: "keys", - type: "address[]", - }, - { - internalType: "uint32", - name: "expirationTime", - type: "uint32", - }, - ], - internalType: "struct Structs.GuardianSet", - name: "", - type: "tuple", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "bytes", - name: "_vm", - type: "bytes", - }, - ], - name: "submitNewGuardianSet", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "messageFee", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, -] as any; // eslint-disable-line @typescript-eslint/no-explicit-any -const EXECUTOR_ABI = [ - { - inputs: [ - { - internalType: "bytes", - name: "encodedVm", - type: "bytes", - }, - ], - name: "execute", - outputs: [ - { - internalType: "bytes", - name: "response", - type: "bytes", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "getOwnerChainId", - outputs: [ - { - internalType: "uint64", - name: "", - type: "uint64", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "getOwnerEmitterAddress", - outputs: [ - { - internalType: "bytes32", - name: "", - type: "bytes32", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "getLastExecutedSequence", - outputs: [ - { - internalType: "uint64", - name: "", - type: "uint64", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "owner", - outputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, -] as any; // eslint-disable-line @typescript-eslint/no-explicit-any +import { + EXECUTOR_ABI, + EXPRESS_RELAY_ABI, + EXTENDED_ENTROPY_ABI, + EXTENDED_PYTH_ABI, + WORMHOLE_ABI, +} from "./evm_abis"; /** * Returns the keccak256 digest of the contract bytecode at the given address after replacing @@ -546,34 +190,18 @@ export class EvmEntropyContract extends Storable { return new EvmEntropyContract(chain, parsed.address); } - // Generate a payload for the given executor address and calldata. - // `executor` and `calldata` should be hex strings. - generateExecutorPayload( - executor: string, - callAddress: string, - calldata: string - ) { - return new EvmExecute( - this.chain.wormholeChainName, - executor.replace("0x", ""), - callAddress.replace("0x", ""), - 0n, - Buffer.from(calldata.replace("0x", ""), "hex") - ).encode(); - } - // Generates a payload for the newAdmin to call acceptAdmin on the entropy contracts generateAcceptAdminPayload(newAdmin: string): Buffer { const contract = this.getContract(); const data = contract.methods.acceptAdmin().encodeABI(); - return this.generateExecutorPayload(newAdmin, this.address, data); + return this.chain.generateExecutorPayload(newAdmin, this.address, data); } // Generates a payload for newOwner to call acceptOwnership on the entropy contracts generateAcceptOwnershipPayload(newOwner: string): Buffer { const contract = this.getContract(); const data = contract.methods.acceptOwnership().encodeABI(); - return this.generateExecutorPayload(newOwner, this.address, data); + return this.chain.generateExecutorPayload(newOwner, this.address, data); } async generateUpgradeEntropyContractPayload( @@ -581,7 +209,7 @@ export class EvmEntropyContract extends Storable { ): Promise { const contract = this.getContract(); const data = contract.methods.upgradeTo(newImplementation).encodeABI(); - return this.generateExecutorPayload( + return this.chain.generateExecutorPayload( await this.getOwner(), this.address, data @@ -597,7 +225,7 @@ export class EvmEntropyContract extends Storable { const web3 = new Web3(this.chain.getRpcUrl()); const executor = new web3.eth.Contract(EXECUTOR_ABI, executorAddr); const data = executor.methods.upgradeTo(newImplementation).encodeABI(); - return this.generateExecutorPayload(executorAddr, executorAddr, data); + return this.chain.generateExecutorPayload(executorAddr, executorAddr, data); } async getOwner(): Promise { @@ -779,6 +407,90 @@ export class EvmEntropyContract extends Storable { } } +export class EvmExpressRelayContract extends Storable { + static type = "EvmExpressRelayContract"; + + constructor(public chain: EvmChain, public address: string) { + super(); + } + + getId(): string { + return `${this.chain.getId()}_${this.address}`; + } + + getChain(): EvmChain { + return this.chain; + } + + getType(): string { + return EvmExpressRelayContract.type; + } + + async getVersion(): Promise { + const contract = this.getContract(); + return contract.methods.version().call(); + } + + static fromJson( + chain: Chain, + parsed: { type: string; address: string } + ): EvmExpressRelayContract { + if (parsed.type !== EvmExpressRelayContract.type) + throw new Error("Invalid type"); + if (!(chain instanceof EvmChain)) + throw new Error(`Wrong chain type ${chain}`); + return new EvmExpressRelayContract(chain, parsed.address); + } + + async generateSetRelayerPayload(relayer: string): Promise { + const contract = this.getContract(); + const data = contract.methods.setRelayer(relayer).encodeABI(); + return this.chain.generateExecutorPayload( + await this.getOwner(), + this.address, + data + ); + } + + async getOwner(): Promise { + const contract = this.getContract(); + return contract.methods.owner().call(); + } + + async getExecutorContract(): Promise { + const owner = await this.getOwner(); + return new EvmExecutorContract(this.chain, owner); + } + + async getPendingOwner(): Promise { + const contract = this.getContract(); + return contract.methods.pendingOwner().call(); + } + + async getRelayer(): Promise { + const contract = this.getContract(); + return contract.methods.getRelayer().call(); + } + + async getRelayerSubwallets(): Promise { + const contract = this.getContract(); + return contract.methods.getRelayerSubwallets().call(); + } + + toJson() { + return { + chain: this.chain.getId(), + address: this.address, + type: EvmExpressRelayContract.type, + }; + } + + getContract() { + const web3 = new Web3(this.chain.getRpcUrl()); + return new web3.eth.Contract(EXPRESS_RELAY_ABI, this.address); + } +} + export class EvmExecutorContract { constructor(public chain: EvmChain, public address: string) {} diff --git a/contract_manager/src/contracts/evm_abis.ts b/contract_manager/src/contracts/evm_abis.ts new file mode 100644 index 0000000000..41dbe1db55 --- /dev/null +++ b/contract_manager/src/contracts/evm_abis.ts @@ -0,0 +1,524 @@ +import PythInterfaceAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json"; +import EntropyAbi from "@pythnetwork/entropy-sdk-solidity/abis/IEntropy.json"; + +export const OWNABLE_ABI = [ + { + inputs: [], + name: "acceptOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pendingOwner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newImplementation", + type: "address", + }, + ], + name: "upgradeTo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as any; // eslint-disable-line @typescript-eslint/no-explicit-any + +export const EXPRESS_RELAY_ABI = [ + { + type: "function", + name: "getAdmin", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "address", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getFeeProtocol", + inputs: [ + { + name: "feeRecipient", + type: "address", + internalType: "address", + }, + ], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getFeeProtocolDefault", + inputs: [], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getFeeRelayer", + inputs: [], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getFeeSplitPrecision", + inputs: [], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getRelayer", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "address", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "getRelayerSubwallets", + inputs: [], + outputs: [ + { + name: "", + type: "address[]", + internalType: "address[]", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "setFeeProtocol", + inputs: [ + { + name: "feeRecipient", + type: "address", + internalType: "address", + }, + { + name: "feeSplit", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setFeeProtocolDefault", + inputs: [ + { + name: "feeSplit", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setFeeRelayer", + inputs: [ + { + name: "feeSplit", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "setRelayer", + inputs: [ + { + name: "relayer", + type: "address", + internalType: "address", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + ...OWNABLE_ABI, +] as any; // eslint-disable-line @typescript-eslint/no-explicit-any + +export const EXTENDED_ENTROPY_ABI = [ + { + inputs: [], + name: "acceptAdmin", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + ...OWNABLE_ABI, + ...EntropyAbi, +] as any; // eslint-disable-line @typescript-eslint/no-explicit-any +export const EXTENDED_PYTH_ABI = [ + { + inputs: [], + name: "wormhole", + outputs: [ + { + internalType: "contract IWormhole", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "governanceDataSource", + outputs: [ + { + components: [ + { + internalType: "uint16", + name: "chainId", + type: "uint16", + }, + { + internalType: "bytes32", + name: "emitterAddress", + type: "bytes32", + }, + ], + internalType: "struct PythInternalStructs.DataSource", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes", + name: "encodedVM", + type: "bytes", + }, + ], + name: "executeGovernanceInstruction", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "singleUpdateFeeInWei", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "validDataSources", + outputs: [ + { + components: [ + { + internalType: "uint16", + name: "chainId", + type: "uint16", + }, + { + internalType: "bytes32", + name: "emitterAddress", + type: "bytes32", + }, + ], + internalType: "struct PythInternalStructs.DataSource[]", + name: "", + type: "tuple[]", + }, + ], + stateMutability: "view", + type: "function", + constant: true, + }, + { + inputs: [], + name: "lastExecutedGovernanceSequence", + outputs: [ + { + internalType: "uint64", + name: "", + type: "uint64", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "id", + type: "bytes32", + }, + ], + name: "priceFeedExists", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + ...PythInterfaceAbi, +] as any; // eslint-disable-line @typescript-eslint/no-explicit-any +export const WORMHOLE_ABI = [ + { + inputs: [], + name: "getCurrentGuardianSetIndex", + outputs: [ + { + internalType: "uint32", + name: "", + type: "uint32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "chainId", + outputs: [ + { + internalType: "uint16", + name: "", + type: "uint16", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint32", + name: "index", + type: "uint32", + }, + ], + name: "getGuardianSet", + outputs: [ + { + components: [ + { + internalType: "address[]", + name: "keys", + type: "address[]", + }, + { + internalType: "uint32", + name: "expirationTime", + type: "uint32", + }, + ], + internalType: "struct Structs.GuardianSet", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes", + name: "_vm", + type: "bytes", + }, + ], + name: "submitNewGuardianSet", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "messageFee", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, +] as any; // eslint-disable-line @typescript-eslint/no-explicit-any +export const EXECUTOR_ABI = [ + { + inputs: [ + { + internalType: "bytes", + name: "encodedVm", + type: "bytes", + }, + ], + name: "execute", + outputs: [ + { + internalType: "bytes", + name: "response", + type: "bytes", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "getOwnerChainId", + outputs: [ + { + internalType: "uint64", + name: "", + type: "uint64", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getOwnerEmitterAddress", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getLastExecutedSequence", + outputs: [ + { + internalType: "uint64", + name: "", + type: "uint64", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, +] as any; // eslint-disable-line @typescript-eslint/no-explicit-any diff --git a/contract_manager/src/contracts/index.ts b/contract_manager/src/contracts/index.ts index 32c635367d..ea7145c336 100644 --- a/contract_manager/src/contracts/index.ts +++ b/contract_manager/src/contracts/index.ts @@ -4,3 +4,4 @@ export * from "./evm"; export * from "./fuel"; export * from "./sui"; export * from "./wormhole"; +export * from "./evm_abis"; diff --git a/contract_manager/src/shell.ts b/contract_manager/src/shell.ts index 1462552495..1667d2d803 100644 --- a/contract_manager/src/shell.ts +++ b/contract_manager/src/shell.ts @@ -9,7 +9,7 @@ repl.evalCode( "import { SuiChain, CosmWasmChain, AptosChain, EvmChain, StarknetChain } from './src/chains';" + "import { SuiPriceFeedContract } from './src/contracts/sui';" + "import { CosmWasmWormholeContract, CosmWasmPriceFeedContract } from './src/contracts/cosmwasm';" + - "import { EvmWormholeContract, EvmPriceFeedContract } from './src/contracts/evm';" + + "import { EvmWormholeContract, EvmPriceFeedContract, EvmEntropyContract, EvmExpressRelayContract } from './src/contracts/evm';" + "import { AptosWormholeContract, AptosPriceFeedContract } from './src/contracts/aptos';" + "import { StarknetPriceFeedContract } from './src/contracts/starknet';" + "import { DefaultStore } from './src/store';" + diff --git a/contract_manager/src/store.ts b/contract_manager/src/store.ts index c611b51df8..9687f0fbba 100644 --- a/contract_manager/src/store.ts +++ b/contract_manager/src/store.ts @@ -21,6 +21,7 @@ import { FuelWormholeContract, WormholeContract, FuelPriceFeedContract, + EvmExpressRelayContract, } from "./contracts"; import { Token } from "./token"; import { PriceFeedContract, Storable } from "./base"; @@ -37,6 +38,7 @@ export class Store { public contracts: Record = {}; public entropy_contracts: Record = {}; public wormhole_contracts: Record = {}; + public express_relay_contracts: Record = {}; public tokens: Record = {}; public vaults: Record = {}; @@ -138,6 +140,7 @@ export class Store { [AptosPriceFeedContract.type]: AptosPriceFeedContract, [AptosWormholeContract.type]: AptosWormholeContract, [EvmEntropyContract.type]: EvmEntropyContract, + [EvmExpressRelayContract.type]: EvmExpressRelayContract, [EvmWormholeContract.type]: EvmWormholeContract, [FuelPriceFeedContract.type]: FuelPriceFeedContract, [FuelWormholeContract.type]: FuelWormholeContract, @@ -165,6 +168,8 @@ export class Store { ); if (chainContract instanceof EvmEntropyContract) { this.entropy_contracts[chainContract.getId()] = chainContract; + } else if (chainContract instanceof EvmExpressRelayContract) { + this.express_relay_contracts[chainContract.getId()] = chainContract; } else if (chainContract instanceof WormholeContract) { this.wormhole_contracts[chainContract.getId()] = chainContract; } else { diff --git a/contract_manager/store/contracts/EvmExpressRelayContracts.yaml b/contract_manager/store/contracts/EvmExpressRelayContracts.yaml new file mode 100644 index 0000000000..d9d952986c --- /dev/null +++ b/contract_manager/store/contracts/EvmExpressRelayContracts.yaml @@ -0,0 +1,3 @@ +- chain: mode + address: "0x5Cc070844E98F4ceC5f2fBE1592fB1ed73aB7b48" + type: EvmExpressRelayContract diff --git a/governance/xc_admin/packages/xc_admin_frontend/utils/parseEvmExecuteCallData.ts b/governance/xc_admin/packages/xc_admin_frontend/utils/parseEvmExecuteCallData.ts index 4edb9bc207..ab6937633a 100644 --- a/governance/xc_admin/packages/xc_admin_frontend/utils/parseEvmExecuteCallData.ts +++ b/governance/xc_admin/packages/xc_admin_frontend/utils/parseEvmExecuteCallData.ts @@ -33,6 +33,19 @@ const ABI = [ stateMutability: 'nonpayable', type: 'function', }, + { + type: 'function', + name: 'setRelayer', + inputs: [ + { + name: 'relayer', + type: 'address', + internalType: 'address', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, ] type Input = {