Skip to content

Commit

Permalink
solana: consume fill tests
Browse files Browse the repository at this point in the history
  • Loading branch information
a5-pickle committed Apr 4, 2024
1 parent 4027d70 commit 97df0a9
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 75 deletions.
10 changes: 5 additions & 5 deletions solana/ts/src/tokenRouter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ export class TokenRouterProgram {
return splToken.getAssociatedTokenAddressSync(this.mint, this.custodianAddress(), true);
}

preparedCustodyTokenAddress(preparedOrder: PublicKey): PublicKey {
preparedCustodyTokenAddress(preparedAccount: PublicKey): PublicKey {
return PublicKey.findProgramAddressSync(
[Buffer.from("prepared-custody"), preparedOrder.toBuffer()],
[Buffer.from("prepared-custody"), preparedAccount.toBuffer()],
this.ID,
)[0];
}
Expand Down Expand Up @@ -557,9 +557,9 @@ export class TokenRouterProgram {
const msg = CctpTokenBurnMessage.from(cctpMessage);
const cctpMintRecipient = this.cctpMintRecipientAddress();

const vaaAcct = await VaaAccount.fetch(this.program.provider.connection, vaa);
const { chain } = vaaAcct.emitterInfo();
const preparedFill = this.preparedFillAddress(vaaAcct.digest());
const vaaAccount = await VaaAccount.fetch(this.program.provider.connection, vaa);
const { chain } = vaaAccount.emitterInfo();
const preparedFill = this.preparedFillAddress(vaaAccount.digest());

const {
authority: messageTransmitterAuthority,
Expand Down
143 changes: 73 additions & 70 deletions solana/ts/tests/02__tokenRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Keypair,
PublicKey,
SystemProgram,
TransactionInstruction,
} from "@solana/web3.js";
import { use as chaiUse, expect } from "chai";
import chaiAsPromised from "chai-as-promised";
Expand All @@ -27,6 +28,8 @@ import {
expectIxOk,
postLiquidityLayerVaa,
} from "./helpers";
import { token } from "@coral-xyz/anchor/dist/cjs/utils";
import { VaaAccount } from "../src/wormhole";

chaiUse(chaiAsPromised);

Expand Down Expand Up @@ -1492,7 +1495,6 @@ describe("Token Router", function () {
expect(localVariables.delete("args")).is.true;

const vaa = localVariables.get("vaa") as PublicKey;
expect(localVariables.delete("vaa")).is.true;

const ix = await tokenRouter.redeemCctpFillIx(
{
Expand All @@ -1510,89 +1512,90 @@ describe("Token Router", function () {
});

// TODO: check prepared fill account.

// Save for later.
localVariables.set("redeemIx", ix);
});
});

describe("Consume Prepared Fill", function () {
const redeemer = Keypair.generate();
it("Consume Prepared Fill after Redeem Fill", async function () {
const vaa = localVariables.get("vaa") as PublicKey;
expect(localVariables.delete("vaa")).is.true;

const localVariables = new Map<string, any>();
const someone = Keypair.generate();
const dstToken = await splToken.createAssociatedTokenAccount(
connection,
payer,
USDC_MINT_ADDRESS,
someone.publicKey,
);

it.skip("Redeem Fill (CCTP)", async function () {
// TODO
});
const beneficiary = Keypair.generate().publicKey;

it.skip("Consume Prepared Fill after Redeem Fill (CCTP)", async function () {
// TODO
});
const vaaAccount = await VaaAccount.fetch(connection, vaa);
const preparedFill = tokenRouter.preparedFillAddress(vaaAccount.digest());

it.skip("Cannot Redeem Fill Again (CCTP)", async function () {
// TODO
});
const expectedPreparedFillLamports = await connection
.getAccountInfo(preparedFill)
.then((info) => info!.lamports);

async function redeemFillCctp() {
const encodedMintRecipient = Array.from(
tokenRouter.cctpMintRecipientAddress().toBuffer(),
const custodyToken = tokenRouter.preparedCustodyTokenAddress(preparedFill);
const { amount: custodyTokenBalance } = await splToken.getAccount(
connection,
custodyToken,
);
const sourceCctpDomain = 0;
const cctpNonce = testCctpNonce++;
const amount = 69n;

// Concoct a Circle message.
const burnSource = Array.from(Buffer.alloc(32, "beefdead", "hex"));
const { destinationCctpDomain, burnMessage, encodedCctpMessage, cctpAttestation } =
await craftCctpTokenBurnMessage(
tokenRouter,
sourceCctpDomain,
cctpNonce,
encodedMintRecipient,
amount,
burnSource,
);
const expectedCustodyTokenLamports = await connection
.getAccountInfo(custodyToken)
.then((info) => info!.lamports);

const message = new LiquidityLayerMessage({
deposit: new LiquidityLayerDeposit(
{
tokenAddress: burnMessage.burnTokenAddress,
amount,
sourceCctpDomain,
destinationCctpDomain,
cctpNonce,
burnSource,
mintRecipient: encodedMintRecipient,
},
{
fill: {
sourceChain: foreignChain,
orderSender: Array.from(Buffer.alloc(32, "d00d", "hex")),
redeemer: Array.from(redeemer.publicKey.toBuffer()),
redeemerMessage: Buffer.from("Somebody set up us the bomb"),
},
},
),
const ix = await tokenRouter.consumePreparedFillIx({
preparedFill,
redeemer: redeemer.publicKey,
dstToken,
beneficiary,
});

const vaa = await postLiquidityLayerVaa(
connection,
payer,
MOCK_GUARDIANS,
foreignEndpointAddress,
wormholeSequence++,
message,
await expectIxOk(connection, [ix], [payer, redeemer]);

{
const accInfo = await connection.getAccountInfo(preparedFill);
expect(accInfo).is.null;
}
{
const accInfo = await connection.getAccountInfo(custodyToken);
expect(accInfo).is.null;
}

const { amount: dstTokenBalance } = await splToken.getAccount(connection, dstToken);
expect(dstTokenBalance).equals(custodyTokenBalance);

const beneficiaryBalance = await connection.getBalance(beneficiary);
expect(beneficiaryBalance).equals(
expectedPreparedFillLamports + expectedCustodyTokenLamports,
);
const redeemIx = await tokenRouter.redeemCctpFillIx(
{
payer: payer.publicKey,
vaa,
},
{
encodedCctpMessage,
cctpAttestation,
},

// Save for later.
localVariables.set("consumeIx", ix);
});

it("Cannot Consume Fill Again", async function () {
const ix = localVariables.get("consumeIx") as TransactionInstruction;
expect(localVariables.delete("consumeIx")).is.true;

await expectIxErr(
connection,
[ix],
[payer, redeemer],
"prepared_fill. Error Code: AccountNotInitialized",
);
});

return { amount, message, vaa, redeemIx };
}
it("Cannot Redeem Fill Again (CCTP)", async function () {
const ix = localVariables.get("redeemIx") as TransactionInstruction;
expect(localVariables.delete("redeemIx")).is.true;

// NOTE: This is a CCTP message transmitter error.
await expectIxErr(connection, [ix], [payer], "Error Code: NonceAlreadyUsed");
});
});
});
});
Expand Down

0 comments on commit 97df0a9

Please sign in to comment.