Skip to content

Commit

Permalink
solana: transfer before burn/mint to trigger hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
kcsongor authored and johnsaigle committed Jun 6, 2024
1 parent 0138920 commit 5bb6ffb
Show file tree
Hide file tree
Showing 10 changed files with 451 additions and 196 deletions.
79 changes: 55 additions & 24 deletions sdk/solana/src/ntt.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Program } from "@coral-xyz/anchor";
import { associatedAddress } from "@coral-xyz/anchor/dist/cjs/utils/token.js";
import * as splToken from "@solana/spl-token";
import {
createAssociatedTokenAccountInstruction,
Expand All @@ -9,6 +8,7 @@ import {
Connection,
Keypair,
PublicKey,
SystemProgram,
Transaction,
TransactionInstruction,
TransactionMessage,
Expand Down Expand Up @@ -236,16 +236,11 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
);
}

const custodyAddress = associatedAddress({
mint: args.mint,
owner: this.pdas.tokenAuthority(),
});

const tokenProgram = mintInfo.owner;
const limit = new BN(args.outboundLimit.toString());
const ix = await this.program.methods
.initialize({ chainId, limit: limit, mode })
.accounts({
.accountsStrict({
payer: args.payer.publicKey,
deployer: args.owner.publicKey,
programData: programDataAddress(this.program.programId),
Expand All @@ -254,8 +249,10 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
rateLimit: this.pdas.outboxRateLimitAccount(),
tokenProgram,
tokenAuthority: this.pdas.tokenAuthority(),
custody: custodyAddress,
custody: await this.custodyAccountAddress(args.mint, tokenProgram),
bpfLoaderUpgradeableProgram: BPF_LOADER_UPGRADEABLE_PROGRAM_ID,
associatedTokenProgram: splToken.ASSOCIATED_TOKEN_PROGRAM_ID,
systemProgram: SystemProgram.programId,
})
.instruction();

Expand All @@ -278,14 +275,15 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>

const ix = await this.program.methods
.registerTransceiver()
.accounts({
.accountsStrict({
payer: args.payer.publicKey,
owner: args.owner.publicKey,
config: this.pdas.configAccount(),
transceiver: args.transceiver,
registeredTransceiver: this.pdas.registeredTransceiver(
args.transceiver
),
systemProgram: SystemProgram.programId,
})
.instruction();

Expand All @@ -307,6 +305,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
feeCollector: whAccs.wormholeFeeCollector,
sequence: whAccs.wormholeSequence,
program: this.core.address,
systemProgram: SystemProgram.programId,
},
})
.instruction();
Expand Down Expand Up @@ -337,11 +336,12 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
chainId: { id: toChainId(peer.chain) },
address: Array.from(peer.address.toUniversalAddress().toUint8Array()),
})
.accounts({
.accountsStrict({
payer: sender,
owner: sender,
config: this.pdas.configAccount(),
peer: this.pdas.transceiverPeerAccount(peer.chain),
systemProgram: SystemProgram.programId,
})
.instruction(),
this.program.methods
Expand Down Expand Up @@ -390,12 +390,13 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
limit: new BN(inboundLimit.toString()),
tokenDecimals: tokenDecimals,
})
.accounts({
.accountsStrict({
payer: sender,
owner: sender,
config: this.pdas.configAccount(),
peer: this.pdas.peerAccount(peer.chain),
inboxRateLimit: this.pdas.inboxRateLimitAccount(peer.chain),
systemProgram: SystemProgram.programId,
})
.instruction();

Expand Down Expand Up @@ -671,7 +672,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
),
shouldQueue: args.transferArgs.shouldQueue,
})
.accounts({
.accountsStrict({
common: {
payer: args.payer,
config: { config: this.pdas.configAccount() },
Expand All @@ -680,10 +681,11 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
tokenProgram: config.tokenProgram,
outboxItem: args.outboxItem,
outboxRateLimit: this.pdas.outboxRateLimitAccount(),
systemProgram: SystemProgram.programId,
custody: config.custody,
},
peer: this.pdas.peerAccount(recipientChain),
inboxRateLimit: this.pdas.inboxRateLimitAccount(recipientChain),
custody: config.custody,
sessionAuthority: sessionAuthority,
})
.instruction();
Expand Down Expand Up @@ -712,21 +714,25 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
),
shouldQueue: args.transferArgs.shouldQueue,
})
.accounts({
.accountsStrict({
common: {
payer: args.payer,
config: { config: this.pdas.configAccount() },
mint: config.mint,
from: args.from,
outboxItem: args.outboxItem,
outboxRateLimit: this.pdas.outboxRateLimitAccount(),
custody: config.custody,
tokenProgram: config.tokenProgram,
systemProgram: SystemProgram.programId,
},
peer: this.pdas.peerAccount(recipientChain),
inboxRateLimit: this.pdas.inboxRateLimitAccount(recipientChain),
sessionAuthority: this.pdas.sessionAuthority(
args.fromAuthority,
args.transferArgs
),
tokenAuthority: this.pdas.tokenAuthority(),
})
.instruction();
}
Expand Down Expand Up @@ -757,6 +763,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
feeCollector: whAccs.wormholeFeeCollector,
sequence: whAccs.wormholeSequence,
program: this.core.address,
systemProgram: SystemProgram.programId,
},
})
.instruction();
Expand All @@ -773,7 +780,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
const emitterChain = wormholeNTT.emitterChain;
return await this.program.methods
.receiveWormholeMessage()
.accounts({
.accountsStrict({
payer: payer,
config: { config: this.pdas.configAccount() },
peer: this.pdas.transceiverPeerAccount(emitterChain),
Expand All @@ -785,6 +792,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
emitterChain,
nttMessage.id
),
systemProgram: SystemProgram.programId,
})
.instruction();
}
Expand All @@ -805,7 +813,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>

return await this.program.methods
.redeem({})
.accounts({
.accountsStrict({
payer: payer,
config: this.pdas.configAccount(),
peer: nttManagerPeer,
Expand All @@ -818,6 +826,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
inboxItem,
inboxRateLimit,
outboxRateLimit: this.pdas.outboxRateLimitAccount(),
systemProgram: SystemProgram.programId,
})
.instruction();
}
Expand Down Expand Up @@ -847,7 +856,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
.releaseInboundMint({
revertOnDelay: args.revertOnDelay,
})
.accounts({
.accountsStrict({
common: {
payer: args.payer,
config: { config: this.pdas.configAccount() },
Expand All @@ -858,6 +867,8 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
),
mint: config.mint,
tokenAuthority: this.pdas.tokenAuthority(),
custody: config.custody,
tokenProgram: config.tokenProgram,
},
})
.instruction();
Expand Down Expand Up @@ -888,7 +899,7 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
.releaseInboundUnlock({
revertOnDelay: args.revertOnDelay,
})
.accounts({
.accountsStrict({
common: {
payer: args.payer,
config: { config: this.pdas.configAccount() },
Expand All @@ -899,17 +910,37 @@ export class SolanaNtt<N extends Network, C extends SolanaChains>
),
mint: config.mint,
tokenAuthority: this.pdas.tokenAuthority(),
custody: config.custody,
tokenProgram: config.tokenProgram,
},
custody: config.custody,
})
.instruction();
}

async custodyAccountAddress(mint: PublicKey): Promise<PublicKey> {
return associatedAddress({
mint: mint,
owner: this.pdas.tokenAuthority(),
});
/**
* Returns the address of the custody account. If the config is available
* (i.e. the program is initialised), the mint is derived from the config.
* Otherwise, the mint must be provided.
*/
async custodyAccountAddress(
configOrMint: NttBindings.Config | PublicKey,
tokenProgram = splToken.TOKEN_PROGRAM_ID
): Promise<PublicKey> {
if (configOrMint instanceof PublicKey) {
return splToken.getAssociatedTokenAddress(
configOrMint,
this.pdas.tokenAuthority(),
true,
tokenProgram
);
} else {
return splToken.getAssociatedTokenAddress(
configOrMint.mint,
this.pdas.tokenAuthority(),
true,
configOrMint.tokenProgram
);
}
}

createUnsignedTx(
Expand Down
58 changes: 44 additions & 14 deletions solana/idl/json/example_native_token_transfers.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@
"isMut": true,
"isSigner": false,
"docs": [
"The custody account that holds tokens in locking mode.",
"NOTE: the account is unconditionally initialized, but not used in",
"burning mode.",
"The custody account that holds tokens in locking mode and temporarily",
"holds tokens in burning mode.",
"function if the token account has already been created."
]
},
Expand Down Expand Up @@ -139,6 +138,16 @@
"isMut": true,
"isSigner": false
},
{
"name": "custody",
"isMut": true,
"isSigner": false,
"docs": [
"Tokens are always transferred to the custody account first regardless of",
"the mode.",
"For an explanation, see the note in [`transfer_burn`]."
]
},
{
"name": "systemProgram",
"isMut": false,
Expand All @@ -159,6 +168,14 @@
{
"name": "sessionAuthority",
"isMut": false,
"isSigner": false,
"docs": [
"See [`crate::SESSION_AUTHORITY_SEED`] for an explanation of the flow."
]
},
{
"name": "tokenAuthority",
"isMut": false,
"isSigner": false
}
],
Expand Down Expand Up @@ -220,6 +237,16 @@
"isMut": true,
"isSigner": false
},
{
"name": "custody",
"isMut": true,
"isSigner": false,
"docs": [
"Tokens are always transferred to the custody account first regardless of",
"the mode.",
"For an explanation, see the note in [`transfer_burn`]."
]
},
{
"name": "systemProgram",
"isMut": false,
Expand All @@ -240,12 +267,10 @@
{
"name": "sessionAuthority",
"isMut": false,
"isSigner": false
},
{
"name": "custody",
"isMut": true,
"isSigner": false
"isSigner": false,
"docs": [
"See [`crate::SESSION_AUTHORITY_SEED`] for an explanation of the flow."
]
}
],
"args": [
Expand Down Expand Up @@ -378,6 +403,11 @@
"name": "tokenProgram",
"isMut": false,
"isSigner": false
},
{
"name": "custody",
"isMut": true,
"isSigner": false
}
]
}
Expand Down Expand Up @@ -436,13 +466,13 @@
"name": "tokenProgram",
"isMut": false,
"isSigner": false
},
{
"name": "custody",
"isMut": true,
"isSigner": false
}
]
},
{
"name": "custody",
"isMut": true,
"isSigner": false
}
],
"args": [
Expand Down
Loading

0 comments on commit 5bb6ffb

Please sign in to comment.