diff --git a/cross-chain/solana/deploy/helpers/consts.ts b/cross-chain/solana/deploy/helpers/consts.ts new file mode 100644 index 000000000..1a6fceed5 --- /dev/null +++ b/cross-chain/solana/deploy/helpers/consts.ts @@ -0,0 +1,38 @@ +import { WRAPPED_TBTC_MINT } from "./../../tests/helpers/consts" +export const WH_ARBITRUM_CHAIN_ID = 23 + +export const WH_OPTIMISM_CHAIN_ID = 24 + +export const WH_POLYGON_CHAIN_ID = 5 + +export const WH_BASE_CHAIN_ID = 30 + +// EVM addresses converted to 32 bytes. 0x is trimmed intentionally as the input +// param requires it without leading 0x. + +export const ARBITRUM_GATEWAY_ADDRESS_TESTNET = + "00000000000000000000000031a15e213b59e230b45e8c5c99dafac3d1236ee2" +export const ARBITRUM_GATEWAY_ADDRESS_MAINNET = + "0000000000000000000000001293a54e160d1cd7075487898d65266081a15458" + +export const OPTIMISM_GATEWAY_ADDRESS_TESTNET = + "0000000000000000000000006449F4381f3d63bDfb36B3bDc375724aD3cD4621" +export const OPTIMISM_GATEWAY_ADDRESS_MAINNET = + "0000000000000000000000001293a54e160D1cd7075487898d65266081A15458" + +export const POLYGON_GATEWAY_ADDRESS_TESTNET = + "00000000000000000000000091Fe7128f74dBd4F031ea3D90FC5Ea4DCfD81818" // testnet +export const POLYGON_GATEWAY_ADDRESS_MAINNET = + "00000000000000000000000009959798B95d00a3183d20FaC298E4594E599eab" + +export const BASE_GATEWAY_ADDRESS_TESTNET = + "000000000000000000000000e3e0511EEbD87F08FbaE4486419cb5dFB06e1343" +export const BASE_GATEWAY_ADDRESS_MAINNET = + "00000000000000000000000009959798B95d00a3183d20FaC298E4594E599eab" + +// deriveWrappedMintKey("DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe", 2, "0x679874fbe6d4e7cc54a59e315ff1eb266686a937") +export const WRAPPED_TBTC_MINT_TESTNET = + "FMYvcyMJJ22whB9m3T5g1oPKwM6jpLnFBXnrY6eXmCrp" +// deriveWrappedMintKey("wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb", 2, "0x18084fbA666a33d37592fA2633fD49a74DD93a88") +export const WRAPPED_TBTC_MINT_MAINNET = + "25rXTx9zDZcHyTav5sRqM6YBvTGu9pPH9yv83uAEqbgG" diff --git a/cross-chain/solana/deploy/init.ts b/cross-chain/solana/deploy/init.ts index 70e1c8a1d..3bf42a760 100644 --- a/cross-chain/solana/deploy/init.ts +++ b/cross-chain/solana/deploy/init.ts @@ -2,55 +2,56 @@ import * as anchor from "@coral-xyz/anchor" import fs from "fs" import { PublicKey, Keypair } from "@solana/web3.js" import dotenv from "dotenv" -import { Program } from "@coral-xyz/anchor"; -import { Tbtc } from "../target/types/tbtc"; -import { WormholeGateway } from "../target/types/wormhole_gateway"; -import { PROGRAM_ID as METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata"; +import { Program } from "@coral-xyz/anchor" +import { Tbtc } from "../target/types/tbtc" +import { WormholeGateway } from "../target/types/wormhole_gateway" +import { PROGRAM_ID as METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata" +import * as consts from "./helpers/consts" async function run(): Promise { dotenv.config({ path: "../solana.env" }) - anchor.setProvider(anchor.AnchorProvider.env()); + anchor.setProvider(anchor.AnchorProvider.env()) - const tbtcProgram = anchor.workspace.Tbtc as Program; - const wormholeGatewayProgram = anchor.workspace.WormholeGateway as Program; + const tbtcProgram = anchor.workspace.Tbtc as Program + const wormholeGatewayProgram = anchor.workspace + .WormholeGateway as Program console.log("tbtcProgram.programId", tbtcProgram.programId) - console.log("wormholeGatewayProgram.programId", wormholeGatewayProgram.programId) + console.log( + "wormholeGatewayProgram.programId", + wormholeGatewayProgram.programId + ) // This wallet deployed the program and is also an authority - const authority = (loadKey(process.env.AUTHORITY)).publicKey + const authority = loadKey(process.env.AUTHORITY).publicKey const mint = PublicKey.findProgramAddressSync( [Buffer.from("tbtc-mint")], tbtcProgram.programId - )[0]; + )[0] const config = PublicKey.findProgramAddressSync( [Buffer.from("config")], tbtcProgram.programId - )[0]; + )[0] const guardians = PublicKey.findProgramAddressSync( [Buffer.from("guardians")], tbtcProgram.programId - )[0]; + )[0] const minters = PublicKey.findProgramAddressSync( [Buffer.from("minters")], tbtcProgram.programId - )[0]; + )[0] const tbtcMetadata = PublicKey.findProgramAddressSync( - [ - Buffer.from("metadata"), - METADATA_PROGRAM_ID.toBuffer(), - mint.toBuffer(), - ], + [Buffer.from("metadata"), METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], METADATA_PROGRAM_ID - )[0]; + )[0] - const mplTokenMetadataProgram = METADATA_PROGRAM_ID; + const mplTokenMetadataProgram = METADATA_PROGRAM_ID // Initalize tbtc program await tbtcProgram.methods @@ -62,9 +63,9 @@ async function run(): Promise { minters, authority, tbtcMetadata, - mplTokenMetadataProgram + mplTokenMetadataProgram, }) - .instruction() + .rpc() const minter = PublicKey.findProgramAddressSync( [Buffer.from("redeemer")], @@ -72,10 +73,11 @@ async function run(): Promise { )[0] const mintingLimit = 10000 // Arbitrary big number of TBTC - // TODO: verify with WH team if the address is correct - const WRAPPED_TBTC_MINT = new PublicKey( - "25rXTx9zDZcHyTav5sRqM6YBvTGu9pPH9yv83uAEqbgG" - ); + let WRAPPED_TBTC = consts.WRAPPED_TBTC_MINT_TESTNET + if (process.env.CLUSTER === "mainnet-beta") { + WRAPPED_TBTC = consts.WRAPPED_TBTC_MINT_MAINNET + } + const WRAPPED_TBTC_MINT = new PublicKey(WRAPPED_TBTC) const gatewayWrappedTbtcToken = PublicKey.findProgramAddressSync( [Buffer.from("wrapped-token")], @@ -87,6 +89,7 @@ async function run(): Promise { wormholeGatewayProgram.programId )[0] + // Initialize wormhole gateway await wormholeGatewayProgram.methods .initialize(new anchor.BN(mintingLimit)) .accounts({ @@ -97,53 +100,129 @@ async function run(): Promise { wrappedTbtcToken: gatewayWrappedTbtcToken, tokenBridgeSender, }) - .rpc(); + .rpc() const minterInfo = PublicKey.findProgramAddressSync( [Buffer.from("minter-info"), minter.toBuffer()], tbtcProgram.programId )[0] - // // Adding a minter (wormholeGateway) - // await tbtcProgram.methods - // .addMinter() - // .accounts({ - // config, - // authority, - // minters, - // minterInfo, - // minter, - // }) - // .instruction(); - - // // update mappings (self?, arbitrum, optimism, polygon, base) - - // // arbitrum chain ID: 23 - // // ETH Goerli address: 0x00000000000000000000000031a15e213b59e230b45e8c5c99dafac3d1236ee2 - // // ETH Mainnet address: 0x0000000000000000000000001293a54e160d1cd7075487898d65266081a15458 - // const arbitrumChain = 23 - // const arbiArgs = { - // chain: arbitrumChain, - // address: Array.from(Buffer.alloc(32, "00000000000000000000000031a15e213b59e230b45e8c5c99dafac3d1236ee2", "hex")) - // } - - // const encodedChain = Buffer.alloc(2); - // encodedChain.writeUInt16LE(arbitrumChain); - // const gatewayInfo = PublicKey.findProgramAddressSync( - // [Buffer.from("gateway-info"), encodedChain], - // wormholeGatewayProgram.programId - // )[0] - - // wormholeGatewayProgram.methods - // .updateGatewayAddress(arbiArgs) - // .accounts({ - // custodian: minter, - // gatewayInfo, - // authority, - // }) - // .instruction(); - - console.log("success") + // Adding a minter (wormholeGateway) + await tbtcProgram.methods + .addMinter() + .accounts({ + config, + authority, + minters, + minterInfo, + minter, + }) + .rpc() + + // Point to devnet addresses by default + let ARBITRUM_GATEWAY = consts.ARBITRUM_GATEWAY_ADDRESS_TESTNET + let OPTIMISM_GATEWAY = consts.ARBITRUM_GATEWAY_ADDRESS_TESTNET + let POLYGON_GATEWAY = consts.ARBITRUM_GATEWAY_ADDRESS_TESTNET + let BASE_GATEWAY = consts.ARBITRUM_GATEWAY_ADDRESS_TESTNET + if (process.env.CLUSTER === "mainnet-beta") { + ARBITRUM_GATEWAY = consts.ARBITRUM_GATEWAY_ADDRESS_MAINNET + OPTIMISM_GATEWAY = consts.OPTIMISM_GATEWAY_ADDRESS_MAINNET + POLYGON_GATEWAY = consts.POLYGON_GATEWAY_ADDRESS_MAINNET + BASE_GATEWAY = consts.BASE_GATEWAY_ADDRESS_MAINNET + } + + // Updating with Arbitrum + const arbiArgs = { + chain: consts.WH_ARBITRUM_CHAIN_ID, + address: Array.from(Buffer.alloc(32, ARBITRUM_GATEWAY, "hex")), + } + + const encodedArbiChain = Buffer.alloc(2) + encodedArbiChain.writeUInt16LE(consts.WH_ARBITRUM_CHAIN_ID) + const gatewayArbiInfo = PublicKey.findProgramAddressSync( + [Buffer.from("gateway-info"), encodedArbiChain], + wormholeGatewayProgram.programId + )[0] + + wormholeGatewayProgram.methods + .updateGatewayAddress(arbiArgs) + .accounts({ + custodian: minter, + gatewayInfo: gatewayArbiInfo, + authority, + }) + .rpc() + + // Updating with Optimism + const optiArgs = { + chain: consts.WH_OPTIMISM_CHAIN_ID, + address: Array.from(Buffer.alloc(32, OPTIMISM_GATEWAY, "hex")), + } + + const encodedOptiChain = Buffer.alloc(2) + encodedOptiChain.writeUInt16LE(consts.WH_OPTIMISM_CHAIN_ID) + const gatewayOptiInfo = PublicKey.findProgramAddressSync( + [Buffer.from("gateway-info"), encodedOptiChain], + wormholeGatewayProgram.programId + )[0] + + wormholeGatewayProgram.methods + .updateGatewayAddress(optiArgs) + .accounts({ + custodian: minter, + gatewayInfo: gatewayOptiInfo, + authority, + }) + .rpc() + + // Updating with Polygon + const polyArgs = { + chain: consts.WH_POLYGON_CHAIN_ID, + address: Array.from(Buffer.alloc(32, POLYGON_GATEWAY, "hex")), + } + + const encodedPolyChain = Buffer.alloc(2) + encodedPolyChain.writeUInt16LE(consts.WH_POLYGON_CHAIN_ID) + const gatewayPolyInfo = PublicKey.findProgramAddressSync( + [Buffer.from("gateway-info"), encodedPolyChain], + wormholeGatewayProgram.programId + )[0] + + wormholeGatewayProgram.methods + .updateGatewayAddress(polyArgs) + .accounts({ + custodian: minter, + gatewayInfo: gatewayPolyInfo, + authority, + }) + .rpc() + + // Updating with BASE + const baseArgs = { + chain: consts.WH_BASE_CHAIN_ID, + address: Array.from(Buffer.alloc(32, BASE_GATEWAY, "hex")), + } + + const encodedBaseChain = Buffer.alloc(2) + encodedBaseChain.writeUInt16LE(consts.WH_BASE_CHAIN_ID) + const gatewayBaseInfo = PublicKey.findProgramAddressSync( + [Buffer.from("gateway-info"), encodedBaseChain], + wormholeGatewayProgram.programId + )[0] + + wormholeGatewayProgram.methods + .updateGatewayAddress(baseArgs) + .accounts({ + custodian: minter, + gatewayInfo: gatewayBaseInfo, + authority, + }) + .rpc() + + // TODO: confirm with the WH team if Solana gateway should be self updated just + // like we do on EVMs, i.e updateGatewayAddress(solanaArgs) + + console.log("Done initializing programs!") } ;(async () => { @@ -163,4 +242,4 @@ function loadKey(filename: string): Keypair { } catch { console.log("Unable to read keypair...", filename) } -} \ No newline at end of file +}