Skip to content

Commit

Permalink
Add test for depositing wrapped tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
eth-r committed Aug 2, 2023
1 parent 97e13f0 commit 79728bc
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 70 deletions.
72 changes: 11 additions & 61 deletions cross-chain/solana/tests/01__tbtc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,7 @@ import { Tbtc } from "../target/types/tbtc";
import { expect } from 'chai';
import { ASSOCIATED_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/utils/token";
import { transferLamports } from "./helpers/utils";
import { getConfigPDA, getTokenPDA, getMinterPDA, getGuardianPDA } from "./helpers/tbtcHelpers";

function maybeAuthorityAnd(
signer,
signers
) {
return signers.concat(signer instanceof (anchor.Wallet as any) ? [] : [signer]);
}
import { maybeAuthorityAnd, getConfigPDA, getTokenPDA, getMinterPDA, getGuardianPDA, checkState, addMinter } from "./helpers/tbtcHelpers";

async function setup(
program: Program<Tbtc>,
Expand All @@ -32,26 +25,6 @@ async function setup(
.rpc();
}

async function checkState(
program: Program<Tbtc>,
expectedAuthority,
expectedMinters,
expectedGuardians,
expectedTokensSupply
) {
const [config,] = getConfigPDA(program);
let configState = await program.account.config.fetch(config);

expect(configState.authority).to.eql(expectedAuthority.publicKey);
expect(configState.numMinters).to.equal(expectedMinters);
expect(configState.numGuardians).to.equal(expectedGuardians);

let tbtcMint = configState.mint;

let mintState = await spl.getMint(program.provider.connection, tbtcMint);

expect(mintState.supply).to.equal(BigInt(expectedTokensSupply));
}

async function changeAuthority(
program: Program<Tbtc>,
Expand Down Expand Up @@ -127,34 +100,11 @@ async function checkPaused(
}




async function addMinter(
program: Program<Tbtc>,
authority,
minter,
payer
): Promise<anchor.web3.PublicKey> {
const [config,] = getConfigPDA(program);
const [minterInfoPDA, _] = getMinterPDA(program, minter);
await program.methods
.addMinter()
.accounts({
config,
authority: authority.publicKey,
minter: minter.publicKey,
minterInfo: minterInfoPDA,
})
.signers(maybeAuthorityAnd(authority, []))
.rpc();
return minterInfoPDA;
}

async function checkMinter(
program: Program<Tbtc>,
minter
) {
const [minterInfoPDA, bump] = getMinterPDA(program, minter);
const [minterInfoPDA, bump] = getMinterPDA(program, minter.publicKey);
let minterInfo = await program.account.minterInfo.fetch(minterInfoPDA);

expect(minterInfo.minter).to.eql(minter.publicKey);
Expand Down Expand Up @@ -397,7 +347,7 @@ describe("tbtc", () => {

it('add minter', async () => {
await checkState(program, authority, 0, 0, 0);
await addMinter(program, authority, minterKeys, authority);
await addMinter(program, authority, minterKeys.publicKey);
await checkMinter(program, minterKeys);
await checkState(program, authority, 1, 0, 0);

Expand All @@ -416,7 +366,7 @@ describe("tbtc", () => {
// );

try {
await addMinter(program, impostorKeys, minter2Keys, authority);
await addMinter(program, impostorKeys, minter2Keys.publicKey);
chai.assert(false, "should've failed but didn't");
} catch (_err) {
expect(_err).to.be.instanceOf(AnchorError);
Expand All @@ -428,7 +378,7 @@ describe("tbtc", () => {

it('mint', async () => {
await checkState(program, authority, 1, 0, 0);
const [minterInfoPDA, _] = getMinterPDA(program, minterKeys);
const [minterInfoPDA, _] = getMinterPDA(program, minterKeys.publicKey);
await checkMinter(program, minterKeys);

// await setupMint(program, authority, recipientKeys);
Expand All @@ -449,7 +399,7 @@ describe("tbtc", () => {

it('won\'t mint', async () => {
await checkState(program, authority, 1, 0, 1000);
const [minterInfoPDA, _] = getMinterPDA(program, minterKeys);
const [minterInfoPDA, _] = getMinterPDA(program, minterKeys.publicKey);
await checkMinter(program, minterKeys);

// await setupMint(program, authority, recipientKeys);
Expand All @@ -467,9 +417,9 @@ describe("tbtc", () => {

it('use two minters', async () => {
await checkState(program, authority, 1, 0, 1000);
const [minterInfoPDA, _] = getMinterPDA(program, minterKeys);
const [minterInfoPDA, _] = getMinterPDA(program, minterKeys.publicKey);
await checkMinter(program, minterKeys);
const minter2InfoPDA = await addMinter(program, authority, minter2Keys, authority);
const minter2InfoPDA = await addMinter(program, authority, minter2Keys.publicKey);
await checkMinter(program, minter2Keys);
await checkState(program, authority, 2, 0, 1000);
// await setupMint(program, authority, recipientKeys);
Expand Down Expand Up @@ -502,15 +452,15 @@ describe("tbtc", () => {

it('remove minter', async () => {
await checkState(program, authority, 2, 0, 1500);
const [minter2InfoPDA, _] = getMinterPDA(program, minter2Keys);
const [minter2InfoPDA, _] = getMinterPDA(program, minter2Keys.publicKey);
await checkMinter(program, minter2Keys);
await removeMinter(program, authority, minter2Keys, minter2InfoPDA);
await checkState(program, authority, 1, 0, 1500);
});

it('won\'t remove minter', async () => {
await checkState(program, authority, 1, 0, 1500);
const [minterInfoPDA, _] = getMinterPDA(program, minterKeys);
const [minterInfoPDA, _] = getMinterPDA(program, minterKeys.publicKey);
await checkMinter(program, minterKeys);

try {
Expand Down Expand Up @@ -611,7 +561,7 @@ describe("tbtc", () => {

it('won\'t mint when paused', async () => {
await checkState(program, authority, 0, 1, 1500);
const minterInfoPDA = await addMinter(program, authority, minterKeys, authority);
const minterInfoPDA = await addMinter(program, authority, minterKeys.publicKey);
await pause(program, guardianKeys);
// await setupMint(program, authority, recipientKeys);

Expand Down
76 changes: 69 additions & 7 deletions cross-chain/solana/tests/02__wormholeGateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { expect } from 'chai';
import { WormholeGateway } from "../target/types/wormhole_gateway";
import { generatePayer, getOrCreateTokenAccount } from "./helpers/utils";
import { getCustodianPDA, getTokenBridgeRedeemerPDA, getTokenBridgeSenderPDA, getWrappedTbtcTokenPDA } from "./helpers/wormholeGatewayHelpers";
import { getConfigPDA, getTokenPDA, getMinterPDA, getGuardianPDA } from "./helpers/tbtcHelpers";
import * as tbtc from "./helpers/tbtcHelpers";
import { web3 } from "@coral-xyz/anchor";
import { Tbtc } from "../target/types/tbtc";

Expand All @@ -24,18 +24,16 @@ const GUARDIAN_SET_INDEX = 3;

async function setup(
program: Program<WormholeGateway>,
tbtc: Program<Tbtc>,
tbtcProgram: Program<Tbtc>,
authority,
mintingLimit: number
) {
const [custodian,] = getCustodianPDA(program);
const [tbtcMint,] = getTokenPDA(tbtc);
const [tbtcMint,] = tbtc.getTokenPDA(tbtcProgram);
const [gatewayWrappedTbtcToken,] = getWrappedTbtcTokenPDA(program);
const [tokenBridgeSender,] = getTokenBridgeSenderPDA(program);
const [tokenBridgeRedeemer,] = getTokenBridgeRedeemerPDA(program);

const connection = program.provider.connection;

const wrappedTbtcMint = tokenBridge.deriveWrappedMintKey(SOLANA_TOKEN_BRIDGE_ADDRESS, 2, ETHEREUM_TBTC_ADDRESS);

await program.methods
Expand Down Expand Up @@ -74,6 +72,13 @@ describe("wormhole-gateway", () => {

const tbtcProgram = anchor.workspace.Tbtc as Program<Tbtc>;

const [custodian,] = getCustodianPDA(program);
const [tbtcMint,] = tbtc.getTokenPDA(tbtcProgram);
const [tbtcConfig,] = tbtc.getConfigPDA(tbtcProgram);
const [gatewayWrappedTbtcToken,] = getWrappedTbtcTokenPDA(program);
const [tokenBridgeSender,] = getTokenBridgeSenderPDA(program);
const [tokenBridgeRedeemer,] = getTokenBridgeRedeemerPDA(program);

const authority = (program.provider as anchor.AnchorProvider).wallet as anchor.Wallet;
const newAuthority = anchor.web3.Keypair.generate();
const minterKeys = anchor.web3.Keypair.generate();
Expand Down Expand Up @@ -127,9 +132,66 @@ describe("wormhole-gateway", () => {
});

it('setup', async () => {
await setup(program, tbtcProgram, authority, 1000);
await checkState(program, authority, 1000);
await setup(program, tbtcProgram, authority, 10000);
await checkState(program, authority, 10000);
await tbtc.checkState(tbtcProgram, authority, 1, 2, 1500);
});

it('deposit wrapped tokens', async () => {
const [custodian,] = getCustodianPDA(program);
const minterInfo = await tbtc.addMinter(tbtcProgram, authority, custodian);

// Set up new wallet
const payer = await generatePayer(connection, authority.payer);

// Check wrapped tBTC mint.
const wrappedTbtcMint = tokenBridge.deriveWrappedMintKey(SOLANA_TOKEN_BRIDGE_ADDRESS, 2, ETHEREUM_TBTC_ADDRESS);
const wrappedTbtcToken = await getOrCreateTokenAccount(connection, payer, wrappedTbtcMint, payer.publicKey);

// Bridge tbtc to token account.
const published = ethereumTokenBridge.publishTransferTokens(
tryNativeToHexString(ETHEREUM_TBTC_ADDRESS, "ethereum"),
2,
BigInt("100000000000"),
1,
wrappedTbtcToken.address.toBuffer().toString("hex"),
BigInt(0),
0,
0
);

const signedVaa = await mockSignAndPostVaa(connection, payer, published);

const tx = await redeemOnSolana(
connection,
SOLANA_CORE_BRIDGE_ADDRESS,
SOLANA_TOKEN_BRIDGE_ADDRESS,
payer.publicKey,
signedVaa,
);
await web3.sendAndConfirmTransaction(connection, tx, [payer]);

const recipientToken = await getOrCreateTokenAccount(connection, payer, tbtcMint, payer.publicKey);

await program.methods
.depositWormholeTbtc(new anchor.BN(500))
.accounts({
custodian,
wrappedTbtcToken: gatewayWrappedTbtcToken,
wrappedTbtcMint,
tbtcMint,
recipientWrappedToken: wrappedTbtcToken.address,
recipientToken: recipientToken.address,
recipient: payer.publicKey,
tbtcConfig,
minterInfo,
tbtcProgram: tbtcProgram.programId,
})
.signers(tbtc.maybeAuthorityAnd(payer, []))
.rpc();

await tbtc.checkState(tbtcProgram, authority, 2, 2, 2000);
})
});

async function mockSignAndPostVaa(connection: web3.Connection, payer: web3.Keypair, published: Buffer) {
Expand Down
53 changes: 51 additions & 2 deletions cross-chain/solana/tests/helpers/tbtcHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import * as spl from "@solana/spl-token";
import * as web3 from '@solana/web3.js';
import { Tbtc } from "../../target/types/tbtc";
import { expect } from 'chai';

export function maybeAuthorityAnd(
signer,
signers
) {
return signers.concat(signer instanceof (anchor.Wallet as any) ? [] : [signer]);
}

export function getConfigPDA(
program: Program<Tbtc>,
Expand Down Expand Up @@ -32,7 +41,7 @@ export function getMinterPDA(
return web3.PublicKey.findProgramAddressSync(
[
Buffer.from('minter-info'),
minter.publicKey.toBuffer(),
minter.toBuffer(),
],
program.programId
);
Expand All @@ -51,4 +60,44 @@ export function getGuardianPDA(
program.programId
);
}


export async function checkState(
program: Program<Tbtc>,
expectedAuthority,
expectedMinters,
expectedGuardians,
expectedTokensSupply
) {
const [config,] = getConfigPDA(program);
let configState = await program.account.config.fetch(config);

expect(configState.authority).to.eql(expectedAuthority.publicKey);
expect(configState.numMinters).to.equal(expectedMinters);
expect(configState.numGuardians).to.equal(expectedGuardians);

let tbtcMint = configState.mint;

let mintState = await spl.getMint(program.provider.connection, tbtcMint);

expect(mintState.supply).to.equal(BigInt(expectedTokensSupply));
}

export async function addMinter(
program: Program<Tbtc>,
authority,
minter
): Promise<anchor.web3.PublicKey> {
const [config,] = getConfigPDA(program);
const [minterInfoPDA, _] = getMinterPDA(program, minter);
await program.methods
.addMinter()
.accounts({
config,
authority: authority.publicKey,
minter,
minterInfo: minterInfoPDA,
})
.signers(maybeAuthorityAnd(authority, []))
.rpc();
return minterInfoPDA;
}

0 comments on commit 79728bc

Please sign in to comment.