Skip to content

Commit

Permalink
Merge branch 'solana/multi-transceiver-sdk' of https://github.com/wor…
Browse files Browse the repository at this point in the history
…mhole-foundation/example-native-token-transfers into solana/multi-transceiver-sdk
  • Loading branch information
nvsriram committed Oct 17, 2024
2 parents 2586e9e + c762433 commit 75b1af6
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::{
config::*, error::NTTError, queue::outbox::OutboxItem,
registered_transceiver::RegisteredTransceiver,
};
use anchor_lang::prelude::*;

pub const OUTBOX_ITEM_SIGNER_SEED: &'static [u8] = b"outbox_item_signer";

#[derive(Accounts)]
pub struct MarkOutboxItemAsReleased<'info> {
#[account(
seeds = [OUTBOX_ITEM_SIGNER_SEED],
seeds::program = transceiver.transceiver_address,
bump
)]
pub signer: Signer<'info>,

pub config: NotPausedConfig<'info>,

#[account(
mut,
constraint = !outbox_item.released.get(transceiver.id)? @ NTTError::MessageAlreadySent,
)]
pub outbox_item: Account<'info, OutboxItem>,

#[account(
constraint = config.enabled_transceivers.get(transceiver.id)? @ NTTError::DisabledTransceiver
)]
pub transceiver: Account<'info, RegisteredTransceiver>,
}

pub fn mark_outbox_item_as_released(ctx: Context<MarkOutboxItemAsReleased>) -> Result<bool> {
let accs = ctx.accounts;
let released = accs.outbox_item.try_release(accs.transceiver.id)?;
Ok(released)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
pub mod admin;
pub mod initialize;
pub mod luts;
pub mod mark_outbox_item_as_released;
pub mod redeem;
pub mod release_inbound;
pub mod transfer;

pub use admin::*;
pub use initialize::*;
pub use luts::*;
pub use mark_outbox_item_as_released::*;
pub use redeem::*;
pub use release_inbound::*;
pub use transfer::*;
4 changes: 4 additions & 0 deletions solana/programs/example-native-token-transfers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ pub mod example_native_token_transfers {
instructions::set_inbound_limit(ctx, args)
}

pub fn mark_outbox_item_as_released(ctx: Context<MarkOutboxItemAsReleased>) -> Result<bool> {
instructions::mark_outbox_item_as_released(ctx)
}

// standalone transceiver stuff

pub fn set_wormhole_peer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@ use anchor_lang::prelude::*;
use example_native_token_transfers::{
config::{anchor_reexports::*, *},
error::NTTError,
instructions::OUTBOX_ITEM_SIGNER_SEED,
program::ExampleNativeTokenTransfers,
queue::outbox::OutboxItem,
registered_transceiver::*,
registered_transceiver::RegisteredTransceiver,
transfer::Payload,
};
use ntt_messages::{
ntt::NativeTokenTransfer, ntt_manager::NttManagerMessage, transceiver::TransceiverMessage,
transceivers::wormhole::WormholeTransceiver,
};
use solana_program::{
hash,
instruction::Instruction,
program::{get_return_data, invoke_signed},
};

#[derive(Accounts)]
pub struct ReleaseOutbound<'info> {
Expand Down Expand Up @@ -48,16 +55,67 @@ pub struct ReleaseOutbound<'info> {
pub emitter: UncheckedAccount<'info>,

pub wormhole: WormholeAccounts<'info>,

// NOTE: we put `manager` and `outbox_item_signer` at the end so that the generated
// IDL does not clash with the baked-in transceiver IDL in the manager
pub manager: Program<'info, ExampleNativeTokenTransfers>,

#[account(
seeds = [OUTBOX_ITEM_SIGNER_SEED],
bump
)]
/// CHECK: this PDA is used to sign the CPI into NTT manager program
pub outbox_item_signer: UncheckedAccount<'info>,
}

impl<'info> ReleaseOutbound<'info> {
pub fn mark_outbox_item_as_released(&self, bump_seed: u8) -> Result<bool> {
// calculate signhash of mark_outbox_item_as_released function
let ix_data = {
let preimage = format!("{}:{}", "global", "mark_outbox_item_as_released");
let mut sighash = [0u8; 8];
sighash.copy_from_slice(&hash::hash(preimage.as_bytes()).to_bytes()[..8]);
sighash
};
// deref config account info from NotPausedConfig
assert!(self.config.to_account_infos().len() == 1);
let config_info = &self.config.to_account_infos()[0];
// construct CPI call
let account_metas = vec![
AccountMeta::new_readonly(self.outbox_item_signer.key(), true),
AccountMeta::new_readonly(config_info.key(), false),
AccountMeta::new(self.outbox_item.key(), false),
AccountMeta::new_readonly(self.transceiver.key(), false),
];
let instruction = Instruction::new_with_borsh(self.manager.key(), &ix_data, account_metas);
let account_infos = vec![
self.outbox_item_signer.to_account_info(),
config_info.clone(),
self.outbox_item.to_account_info(),
self.transceiver.to_account_info(),
];
invoke_signed(
&instruction,
&account_infos,
&[&[OUTBOX_ITEM_SIGNER_SEED, &[bump_seed]]],
)?;
// get return value
let (_key, data) = get_return_data().unwrap();
Ok(data.len() == 1 && data[0] == 1)
}
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct ReleaseOutboundArgs {
pub revert_on_delay: bool,
}

pub fn release_outbound(ctx: Context<ReleaseOutbound>, args: ReleaseOutboundArgs) -> Result<()> {
pub fn release_outbound<'info>(
ctx: Context<'_, '_, '_, 'info, ReleaseOutbound>,
args: ReleaseOutboundArgs,
) -> Result<()> {
let accs = ctx.accounts;
let released = accs.outbox_item.try_release(accs.transceiver.id)?;
let released = accs.mark_outbox_item_as_released(ctx.bumps.outbox_item_signer)?;

if !released {
if args.revert_on_delay {
Expand All @@ -67,7 +125,9 @@ pub fn release_outbound(ctx: Context<ReleaseOutbound>, args: ReleaseOutboundArgs
}
}

accs.outbox_item.reload()?;
assert!(accs.outbox_item.released.get(accs.transceiver.id)?);

let message: TransceiverMessage<WormholeTransceiver, NativeTokenTransfer<Payload>> =
TransceiverMessage::new(
// TODO: should we just put the ntt id here statically?
Expand Down

0 comments on commit 75b1af6

Please sign in to comment.