The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
hyperlane-monorepo/rust/sealevel/programs/hyperlane-sealevel-token/src/processor.rs

265 lines
9.1 KiB

//! Program processor.
use account_utils::DiscriminatorDecode;
use hyperlane_sealevel_connection_client::{
gas_router::GasRouterConfig, router::RemoteRouterConfig,
};
use hyperlane_sealevel_igp::accounts::InterchainGasPaymasterType;
use hyperlane_sealevel_message_recipient_interface::{
HandleInstruction, MessageRecipientInstruction,
};
use hyperlane_sealevel_token_lib::{
instruction::{Init, Instruction as TokenIxn, TransferRemote},
processor::HyperlaneSealevelToken,
};
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey};
use crate::plugin::SyntheticPlugin;
#[cfg(not(feature = "no-entrypoint"))]
solana_program::entrypoint!(process_instruction);
/// Processes an instruction.
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
// First, check if the instruction has a discriminant relating to
// the message recipient interface.
if let Ok(message_recipient_instruction) = MessageRecipientInstruction::decode(instruction_data)
{
return match message_recipient_instruction {
MessageRecipientInstruction::InterchainSecurityModule => {
interchain_security_module(program_id, accounts)
}
MessageRecipientInstruction::InterchainSecurityModuleAccountMetas => {
interchain_security_module_account_metas(program_id)
}
MessageRecipientInstruction::Handle(handle) => transfer_from_remote(
program_id,
accounts,
HandleInstruction {
origin: handle.origin,
sender: handle.sender,
message: handle.message,
},
),
MessageRecipientInstruction::HandleAccountMetas(handle) => {
transfer_from_remote_account_metas(
program_id,
accounts,
HandleInstruction {
origin: handle.origin,
sender: handle.sender,
message: handle.message,
},
)
}
};
}
// Otherwise, try decoding a "normal" token instruction
match TokenIxn::decode(instruction_data)? {
TokenIxn::Init(init) => initialize(program_id, accounts, init),
TokenIxn::TransferRemote(xfer) => transfer_remote(program_id, accounts, xfer),
TokenIxn::EnrollRemoteRouter(config) => enroll_remote_router(program_id, accounts, config),
TokenIxn::EnrollRemoteRouters(configs) => {
enroll_remote_routers(program_id, accounts, configs)
}
TokenIxn::SetDestinationGasConfigs(configs) => {
set_destination_gas_configs(program_id, accounts, configs)
}
TokenIxn::SetInterchainSecurityModule(new_ism) => {
set_interchain_security_module(program_id, accounts, new_ism)
}
TokenIxn::SetInterchainGasPaymaster(new_igp) => {
set_interchain_gas_paymaster(program_id, accounts, new_igp)
}
TokenIxn::TransferOwnership(new_owner) => {
transfer_ownership(program_id, accounts, new_owner)
}
}
.map_err(|err| {
msg!("{}", err);
err
})
}
/// Initializes the program.
///
/// Accounts:
/// 0. `[executable]` The system program.
/// 1. `[writable]` The token PDA account.
/// 2. `[writable]` The dispatch authority PDA account.
/// 3. `[signer]` The payer.
/// 4. `[writable]` The mint / mint authority PDA account.
/// 5. `[writable]` The ATA payer PDA account.
fn initialize(program_id: &Pubkey, accounts: &[AccountInfo], init: Init) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::initialize(program_id, accounts, init)
}
/// Transfers tokens to a remote.
/// Burns the tokens from the sender's associated token account and
/// then dispatches a message to the remote recipient.
///
/// Accounts:
/// 0. `[executable]` The system program.
/// 1. `[executable]` The spl_noop program.
/// 2. `[]` The token PDA account.
/// 3. `[executable]` The mailbox program.
/// 4. `[writeable]` The mailbox outbox account.
/// 5. `[]` Message dispatch authority.
/// 6. `[signer]` The token sender and mailbox payer.
/// 7. `[signer]` Unique message / gas payment account.
/// 8. `[writeable]` Message storage PDA.
/// ---- If using an IGP ----
/// 9. `[executable]` The IGP program.
/// 10. `[writeable]` The IGP program data.
/// 11. `[writeable]` Gas payment PDA.
/// 12. `[]` OPTIONAL - The Overhead IGP program, if the configured IGP is an Overhead IGP.
/// 13. `[writeable]` The IGP account.
/// ---- End if ----
/// 14. `[signer]` The token sender.
/// 15. `[executable]` The spl_token_2022 program.
/// 16. `[writeable]` The mint / mint authority PDA account.
/// 17. `[writeable]` The token sender's associated token account, from which tokens will be burned.
fn transfer_remote(
program_id: &Pubkey,
accounts: &[AccountInfo],
transfer: TransferRemote,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::transfer_remote(program_id, accounts, transfer)
}
// Accounts:
// 0. `[signer]` Mailbox process authority specific to this program.
// 1. `[executable]` system_program
// 2. `[]` hyperlane_token storage
// 3. `[]` recipient wallet address
// 4. `[executable]` SPL token 2022 program
// 5. `[executable]` SPL associated token account
// 6. `[writeable]` Mint account
// 7. `[writeable]` Recipient associated token account
// 8. `[writeable]` ATA payer PDA account.
fn transfer_from_remote(
program_id: &Pubkey,
accounts: &[AccountInfo],
transfer: HandleInstruction,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::transfer_from_remote(program_id, accounts, transfer)
}
/// Gets the account metas required for the `HandleInstruction` instruction.
fn transfer_from_remote_account_metas(
program_id: &Pubkey,
accounts: &[AccountInfo],
transfer: HandleInstruction,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::transfer_from_remote_account_metas(
program_id, accounts, transfer,
)
}
/// Enrolls a remote router.
///
/// Accounts:
/// 0. `[executable]` The system program.
/// 1. `[writeable]` The token PDA account.
/// 2. `[signer]` The owner.
fn enroll_remote_router(
program_id: &Pubkey,
accounts: &[AccountInfo],
config: RemoteRouterConfig,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::enroll_remote_router(program_id, accounts, config)
}
/// Enrolls remote routers.
///
/// Accounts:
/// 0. `[executable]` The system program.
/// 1. `[writeable]` The token PDA account.
/// 2. `[signer]` The owner.
fn enroll_remote_routers(
program_id: &Pubkey,
accounts: &[AccountInfo],
configs: Vec<RemoteRouterConfig>,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::enroll_remote_routers(program_id, accounts, configs)
}
/// Sets the destination gas configs.
///
/// Accounts:
/// 0. `[executable]` The system program.
/// 1. `[writeable]` The token PDA account.
/// 2. `[signer]` The owner.
fn set_destination_gas_configs(
program_id: &Pubkey,
accounts: &[AccountInfo],
configs: Vec<GasRouterConfig>,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::set_destination_gas_configs(
program_id, accounts, configs,
)
}
/// Transfers ownership.
///
/// Accounts:
/// 0. `[writeable]` The token PDA account.
/// 1. `[signer]` The current owner.
fn transfer_ownership(
program_id: &Pubkey,
accounts: &[AccountInfo],
new_owner: Option<Pubkey>,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::transfer_ownership(program_id, accounts, new_owner)
}
/// Gets the interchain security module, returning it as a serialized Option<Pubkey>.
///
/// Accounts:
/// 0. `[]` The token PDA account.
fn interchain_security_module(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::interchain_security_module(program_id, accounts)
}
/// Gets the account metas for getting the interchain security module.
///
/// Accounts:
/// None
fn interchain_security_module_account_metas(program_id: &Pubkey) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::interchain_security_module_account_metas(program_id)
}
/// Lets the owner set the interchain security module.
///
/// Accounts:
/// 0. `[writeable]` The token PDA account.
/// 1. `[signer]` The access control owner.
fn set_interchain_security_module(
program_id: &Pubkey,
accounts: &[AccountInfo],
new_ism: Option<Pubkey>,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::set_interchain_security_module(
program_id, accounts, new_ism,
)
}
/// Lets the owner set the interchain gas paymaster.
///
/// Accounts:
/// 0. `[writeable]` The token PDA account.
/// 1. `[signer]` The access control owner.
fn set_interchain_gas_paymaster(
program_id: &Pubkey,
accounts: &[AccountInfo],
new_igp: Option<(Pubkey, InterchainGasPaymasterType)>,
) -> ProgramResult {
HyperlaneSealevelToken::<SyntheticPlugin>::set_interchain_gas_paymaster(
program_id, accounts, new_igp,
)
}