diff --git a/solana/Cargo.lock b/solana/Cargo.lock index 7f34f77a..7fc6b528 100644 --- a/solana/Cargo.lock +++ b/solana/Cargo.lock @@ -386,7 +386,7 @@ dependencies = [ "solana-cli-config", "solana-client", "solana-faucet", - "solana-logger", + "solana-logger 1.3.3", "solana-sdk", "solana-transaction-status", "spl-token 1.0.8 (git+https://github.com/solana-labs/solana-program-library)", @@ -1937,9 +1937,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac94b333ee2aac3284c5b8a1b7fb4dd11cba88c244e3fe33cdbd047af0eb693" +checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" dependencies = [ "base64 0.12.3", "log", @@ -2276,9 +2276,8 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41045abbf3dd7ecb01db9851590cb2951df54d06f5f13667cfbc178497a9683b" +version = "1.4.0" +source = "git+https://github.com/jackcmay/solana?branch=cpi-create-account#d84010e4afe5f79c812ff7da349460dc690a8392" dependencies = [ "backtrace", "bytes 0.4.12", @@ -2313,7 +2312,7 @@ dependencies = [ "serde", "serde_derive", "solana-clap-utils", - "solana-logger", + "solana-logger 1.3.3", "solana-metrics", "solana-sdk", "solana-version", @@ -2332,6 +2331,16 @@ dependencies = [ "log", ] +[[package]] +name = "solana-logger" +version = "1.4.0" +source = "git+https://github.com/jackcmay/solana?branch=cpi-create-account#d84010e4afe5f79c812ff7da349460dc690a8392" +dependencies = [ + "env_logger", + "lazy_static", + "log", +] + [[package]] name = "solana-metrics" version = "1.3.3" @@ -2362,7 +2371,7 @@ dependencies = [ "serde_derive", "socket2", "solana-clap-utils", - "solana-logger", + "solana-logger 1.3.3", "solana-version", "tokio 0.1.22", "tokio-codec", @@ -2391,9 +2400,8 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96fb797cf378f8c85ce4e37f45e2fdc75f3a27793e831b3cccd74b0c66e809d" +version = "1.4.0" +source = "git+https://github.com/jackcmay/solana?branch=cpi-create-account#d84010e4afe5f79c812ff7da349460dc690a8392" dependencies = [ "assert_matches", "bincode", @@ -2422,17 +2430,16 @@ dependencies = [ "serde_json", "sha2", "solana-crate-features", - "solana-logger", + "solana-logger 1.4.0", "solana-sdk-macro", - "solana-sdk-macro-frozen-abi", + "solana-sdk-macro-frozen-abi 1.4.0", "thiserror", ] [[package]] name = "solana-sdk-macro" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aad003e717fc4f1831494de7c5307d667a5c5d2fa22b3dfbedd34a6e61ed4ea" +version = "1.4.0" +source = "git+https://github.com/jackcmay/solana?branch=cpi-create-account#d84010e4afe5f79c812ff7da349460dc690a8392" dependencies = [ "bs58", "proc-macro2 1.0.19", @@ -2454,6 +2461,18 @@ dependencies = [ "syn 1.0.38", ] +[[package]] +name = "solana-sdk-macro-frozen-abi" +version = "1.4.0" +source = "git+https://github.com/jackcmay/solana?branch=cpi-create-account#d84010e4afe5f79c812ff7da349460dc690a8392" +dependencies = [ + "lazy_static", + "proc-macro2 1.0.19", + "quote 1.0.7", + "rustc_version", + "syn 1.0.38", +] + [[package]] name = "solana-stake-program" version = "1.3.3" @@ -2470,7 +2489,7 @@ dependencies = [ "solana-config-program", "solana-metrics", "solana-sdk", - "solana-sdk-macro-frozen-abi", + "solana-sdk-macro-frozen-abi 1.3.3", "solana-vote-program", "thiserror", ] @@ -2507,9 +2526,9 @@ dependencies = [ "rustc_version", "serde", "serde_derive", - "solana-logger", + "solana-logger 1.3.3", "solana-sdk", - "solana-sdk-macro-frozen-abi", + "solana-sdk-macro-frozen-abi 1.3.3", ] [[package]] @@ -2525,10 +2544,10 @@ dependencies = [ "rustc_version", "serde", "serde_derive", - "solana-logger", + "solana-logger 1.3.3", "solana-metrics", "solana-sdk", - "solana-sdk-macro-frozen-abi", + "solana-sdk-macro-frozen-abi 1.3.3", "thiserror", ] @@ -2560,6 +2579,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "spl-token" +version = "1.0.8" +dependencies = [ + "cbindgen", + "num-derive 0.3.1", + "num-traits", + "rand", + "remove_dir_all", + "solana-sdk", + "thiserror", +] + [[package]] name = "spl-token" version = "1.0.8" diff --git a/solana/Cargo.toml b/solana/Cargo.toml index 0a6a3ffd..296cbaf4 100644 --- a/solana/Cargo.toml +++ b/solana/Cargo.toml @@ -1,2 +1,5 @@ [workspace] -members = ["agent", "bridge", "cli"] +members = ["agent", "bridge", "cli", "token"] + +[patch.crates-io] +solana-sdk = { git="https://github.com/jackcmay/solana", branch="cpi-create-account" } diff --git a/solana/bridge/Cargo.toml b/solana/bridge/Cargo.toml index 38a80052..2b34066f 100644 --- a/solana/bridge/Cargo.toml +++ b/solana/bridge/Cargo.toml @@ -19,7 +19,7 @@ default = ["solana-sdk/default", "spl-token/default"] num-derive = "0.2" num-traits = "0.2" remove_dir_all = "=0.5.0" -solana-sdk = { version = "=1.3.3", default-features = false, optional = true } +solana-sdk = { version = "1.3.3", default-features = false, optional = true } spl-token = { package = "spl-token", git = "https://github.com/solana-labs/solana-program-library", default-features = false, optional = true } thiserror = "1.0" byteorder = "1.3.4" diff --git a/solana/bridge/src/error.rs b/solana/bridge/src/error.rs index 03436a1d..d6be9559 100644 --- a/solana/bridge/src/error.rs +++ b/solana/bridge/src/error.rs @@ -97,6 +97,9 @@ pub enum Error { /// VAA is longer than the maximum size #[error("VAATooLong")] VAATooLong, + /// Cannot wrap a solana native asset + #[error("CannotWrapNative")] + CannotWrapNative, } impl From for ProgramError { diff --git a/solana/bridge/src/error_program.rs b/solana/bridge/src/error_program.rs index f76c9152..7ca7dd39 100644 --- a/solana/bridge/src/error_program.rs +++ b/solana/bridge/src/error_program.rs @@ -37,6 +37,7 @@ impl PrintProgramError for Error { Error::VAAProposalMismatch => info!("Error: VAAProposalMismatch"), Error::SameChainTransfer => info!("Error: SameChainTransfer"), Error::VAATooLong => info!("Error: VAATooLong"), + Error::CannotWrapNative => info!("Error: CannotWrapNative"), } } } diff --git a/solana/bridge/src/instruction.rs b/solana/bridge/src/instruction.rs index dce23200..a12e2f72 100644 --- a/solana/bridge/src/instruction.rs +++ b/solana/bridge/src/instruction.rs @@ -241,6 +241,7 @@ pub fn create_wrapped( Bridge::derive_wrapped_meta_id(program_id, &bridge_key, &wrapped_mint_key)?; let accounts = vec![ + AccountMeta::new_readonly(*program_id, false), AccountMeta::new_readonly(solana_sdk::system_program::id(), false), AccountMeta::new_readonly(spl_token::id(), false), AccountMeta::new(bridge_key, false), @@ -279,6 +280,7 @@ pub fn transfer_out( )?; let mut accounts = vec![ + AccountMeta::new_readonly(*program_id, false), AccountMeta::new_readonly(solana_sdk::system_program::id(), false), AccountMeta::new_readonly(spl_token::id(), false), AccountMeta::new(*token_account, false), @@ -331,6 +333,7 @@ pub fn post_vaa( let claim_key = Bridge::derive_claim_id(program_id, &bridge_key, &vaa.body_hash()?)?; let mut accounts = vec![ + AccountMeta::new_readonly(*program_id, false), AccountMeta::new_readonly(solana_sdk::system_program::id(), false), AccountMeta::new_readonly(solana_sdk::sysvar::clock::id(), false), AccountMeta::new(bridge_key, false), diff --git a/solana/bridge/src/processor.rs b/solana/bridge/src/processor.rs index 95ad790e..aade2aa3 100644 --- a/solana/bridge/src/processor.rs +++ b/solana/bridge/src/processor.rs @@ -8,8 +8,6 @@ use num_traits::AsPrimitive; use primitive_types::U256; use solana_sdk::clock::Clock; use solana_sdk::hash::Hasher; -#[cfg(not(target_arch = "bpf"))] -use solana_sdk::instruction::Instruction; #[cfg(target_arch = "bpf")] use solana_sdk::program::invoke_signed; use solana_sdk::rent::Rent; @@ -17,7 +15,7 @@ use solana_sdk::system_instruction::{create_account, SystemInstruction}; use solana_sdk::sysvar::Sysvar; use solana_sdk::{ account_info::next_account_info, account_info::AccountInfo, entrypoint::ProgramResult, info, - program_error::ProgramError, pubkey::Pubkey, + instruction::Instruction, program_error::ProgramError, pubkey::Pubkey, }; use spl_token::state::Mint; @@ -87,11 +85,12 @@ impl Bridge { // Create bridge account let bridge_seed = Bridge::derive_bridge_seeds(); - Bridge::check_and_create_account::( + Bridge::check_and_create_account::( program_id, accounts, new_bridge_info.key, payer_info.key, + program_id, &bridge_seed, )?; @@ -108,6 +107,7 @@ impl Bridge { accounts, new_guardian_info.key, payer_info.key, + program_id, &guardian_seed, )?; @@ -139,6 +139,7 @@ impl Bridge { ) -> ProgramResult { info!("wrapped transfer out"); let account_info_iter = &mut accounts.iter(); + next_account_info(account_info_iter)?; // Bridge program next_account_info(account_info_iter)?; // System program next_account_info(account_info_iter)?; // Token program let sender_account_info = next_account_info(account_info_iter)?; @@ -182,6 +183,7 @@ impl Bridge { accounts, transfer_info.key, payer_info.key, + program_id, &transfer_seed, )?; @@ -192,8 +194,10 @@ impl Bridge { return Err(Error::AlreadyExists.into()); } + info!("burning"); // Burn tokens Bridge::wrapped_burn( + program_id, accounts, &bridge.config.token_program, authority_info.key, @@ -221,6 +225,7 @@ impl Bridge { ) -> ProgramResult { info!("create wrapped"); let account_info_iter = &mut accounts.iter(); + next_account_info(account_info_iter)?; // Bridge program next_account_info(account_info_iter)?; // System program next_account_info(account_info_iter)?; // Token program let bridge_info = next_account_info(account_info_iter)?; @@ -230,6 +235,10 @@ impl Bridge { let bridge = Bridge::bridge_deserialize(bridge_info)?; + if a.chain == CHAIN_ID_SOLANA { + return Err(Error::CannotWrapNative.into()); + } + // Create wrapped mint Self::create_wrapped_mint( program_id, @@ -248,6 +257,7 @@ impl Bridge { accounts, wrapped_meta_info.key, payer_info.key, + program_id, &wrapped_meta_seeds, )?; @@ -269,6 +279,7 @@ impl Bridge { ) -> ProgramResult { info!("native transfer out"); let account_info_iter = &mut accounts.iter(); + next_account_info(account_info_iter)?; // Bridge program next_account_info(account_info_iter)?; // System program next_account_info(account_info_iter)?; // Token program let sender_account_info = next_account_info(account_info_iter)?; @@ -301,6 +312,7 @@ impl Bridge { accounts, transfer_info.key, payer_info.key, + program_id, &transfer_seed, )?; @@ -320,6 +332,7 @@ impl Bridge { // Create the account if it does not exist if custody_info.data_is_empty() { + info!("custody acc"); Bridge::create_custody_account( program_id, accounts, @@ -331,19 +344,23 @@ impl Bridge { )?; } + let bridge_authority = Self::derive_bridge_id(program_id)?; + // Check that the custody token account is owned by the derived key let custody = Self::token_account_deserialize(custody_info)?; - if custody.owner != *bridge_info.key { + if custody.owner != bridge_authority { return Err(Error::WrongTokenAccountOwner.into()); } + info!("transferring"); // Transfer tokens to custody - This also checks that custody mint = mint Bridge::token_transfer_caller( + program_id, accounts, &bridge.config.token_program, sender_account_info.key, custody_info.key, - bridge_info.key, + &bridge_authority, t.amount, )?; @@ -373,6 +390,7 @@ impl Bridge { let account_info_iter = &mut accounts.iter(); // Load VAA processing default accounts + next_account_info(account_info_iter)?; // Bridge program next_account_info(account_info_iter)?; // System program let clock_info = next_account_info(account_info_iter)?; let bridge_info = next_account_info(account_info_iter)?; @@ -398,6 +416,7 @@ impl Bridge { accounts, claim_info.key, payer_info.key, + program_id, &claim_seeds, )?; @@ -507,6 +526,7 @@ impl Bridge { accounts, new_guardian_info.key, payer_info.key, + program_id, &guardian_seed, )?; @@ -562,6 +582,7 @@ impl Bridge { // Native Solana asset, transfer from custody Bridge::token_transfer_custody( + program_id, accounts, &bridge.config.token_program, bridge_info.key, @@ -584,6 +605,7 @@ impl Bridge { // This automatically asserts that the mint was created by this account by using // derivated keys Bridge::wrapped_mint_to( + program_id, accounts, &bridge.config.token_program, mint_info.key, @@ -681,6 +703,7 @@ pub fn invoke_signed<'a>( impl Bridge { /// Burn a wrapped asset from account pub fn wrapped_burn( + program_id: &Pubkey, accounts: &[AccountInfo], token_program_id: &Pubkey, authority: &Pubkey, @@ -698,11 +721,12 @@ impl Bridge { all_signers.as_slice(), amount.as_u64(), )?; - invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]]) + Self::invoke_as_bridge(program_id, &ix, accounts) } /// Mint a wrapped asset to account pub fn wrapped_mint_to( + program_id: &Pubkey, accounts: &[AccountInfo], token_program_id: &Pubkey, mint: &Pubkey, @@ -718,11 +742,12 @@ impl Bridge { &[], amount.as_u64(), )?; - invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]]) + Self::invoke_as_bridge(program_id, &ix, accounts) } /// Transfer tokens from a caller pub fn token_transfer_caller( + program_id: &Pubkey, accounts: &[AccountInfo], token_program_id: &Pubkey, source: &Pubkey, @@ -738,11 +763,12 @@ impl Bridge { &[], amount.as_u64(), )?; - invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]]) + Self::invoke_as_bridge(program_id, &ix, accounts) } /// Transfer tokens from a custody account pub fn token_transfer_custody( + program_id: &Pubkey, accounts: &[AccountInfo], token_program_id: &Pubkey, bridge: &Pubkey, @@ -758,7 +784,7 @@ impl Bridge { &[], amount.as_u64(), )?; - invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]]) + Self::invoke_as_bridge(program_id, &ix, accounts) } /// Create a new account @@ -771,15 +797,23 @@ impl Bridge { mint: &Pubkey, payer: &Pubkey, ) -> Result<(), ProgramError> { - Self::create_account::( - token_program, + Self::check_and_create_account::( + program_id, accounts, - mint, + account, payer, + token_program, &Self::derive_custody_seeds(bridge, mint), )?; - let ix = spl_token::instruction::initialize_account(token_program, account, mint, bridge)?; - invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]]) + info!("bababu"); + info!(token_program.to_string().as_str()); + let ix = spl_token::instruction::initialize_account( + token_program, + account, + mint, + &Self::derive_bridge_id(program_id)?, + )?; + invoke_signed(&ix, accounts, &[]) } /// Create a mint for a wrapped asset @@ -792,16 +826,43 @@ impl Bridge { payer: &Pubkey, asset: &AssetMeta, ) -> Result<(), ProgramError> { - Self::create_account::( - token_program, + Self::check_and_create_account::( + program_id, accounts, mint, payer, + token_program, &Self::derive_wrapped_asset_seeds(bridge, asset.chain, asset.address), )?; - let ix = - spl_token::instruction::initialize_mint(token_program, mint, None, Some(bridge), 0, 8)?; - invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]]) + let ix = spl_token::instruction::initialize_mint( + token_program, + mint, + None, + Some(&Self::derive_bridge_id(program_id)?), + 0, + 8, + )?; + invoke_signed(&ix, accounts, &[]) + } + + pub fn invoke_as_bridge<'a>( + program_id: &Pubkey, + instruction: &Instruction, + account_infos: &[AccountInfo<'a>], + ) -> ProgramResult { + let (_, seeds) = + Self::find_program_address(&vec!["bridge".as_bytes().to_vec()], program_id); + Self::invoke_vec_seed(program_id, instruction, account_infos, &seeds) + } + + pub fn invoke_vec_seed<'a>( + program_id: &Pubkey, + instruction: &Instruction, + account_infos: &[AccountInfo<'a>], + seeds: &Vec>, + ) -> ProgramResult { + let s: Vec<_> = seeds.iter().map(|item| item.as_slice()).collect(); + invoke_signed(instruction, account_infos, &[s.as_slice()]) } /// Check that a key was derived correctly and create account @@ -810,22 +871,35 @@ impl Bridge { accounts: &[AccountInfo], new_account: &Pubkey, payer: &Pubkey, + owner: &Pubkey, seeds: &Vec>, - ) -> Result<(), ProgramError> { - let expected_key = Bridge::derive_key(program_id, seeds)?; + ) -> Result>, ProgramError> { + info!("deriving key"); + let (expected_key, full_seeds) = Bridge::derive_key(program_id, seeds)?; if expected_key != *new_account { return Err(Error::InvalidDerivedAccount.into()); } - Self::create_account::(program_id, accounts, new_account, payer, seeds) + info!("deploying contract"); + Self::create_account_raw::( + program_id, + accounts, + new_account, + payer, + owner, + &full_seeds, + )?; + + Ok(full_seeds) } /// Create a new account - pub fn create_account( + fn create_account_raw( program_id: &Pubkey, accounts: &[AccountInfo], new_account: &Pubkey, payer: &Pubkey, + owner: &Pubkey, seeds: &Vec>, ) -> Result<(), ProgramError> { let size = size_of::(); @@ -834,7 +908,7 @@ impl Bridge { new_account, Rent::default().minimum_balance(size as usize), size as u64, - program_id, + owner, ); let s: Vec<_> = seeds.iter().map(|item| item.as_slice()).collect(); invoke_signed(&ix, accounts, &[s.as_slice()]) diff --git a/solana/bridge/src/state.rs b/solana/bridge/src/state.rs index 9f4c6984..d1f1558b 100644 --- a/solana/bridge/src/state.rs +++ b/solana/bridge/src/state.rs @@ -3,6 +3,8 @@ use std::mem::size_of; use primitive_types::U256; +use solana_sdk::hash::Hasher; +use solana_sdk::pubkey::{PubkeyError, MAX_SEED_LEN}; use solana_sdk::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; use zerocopy::AsBytes; @@ -323,7 +325,7 @@ impl Bridge { /// Calculates a derived address for this program pub fn derive_bridge_id(program_id: &Pubkey) -> Result { - Self::derive_key(program_id, &Self::derive_bridge_seeds()) + Ok(Self::derive_key(program_id, &Self::derive_bridge_seeds())?.0) } /// Calculates a derived address for a custody account @@ -332,7 +334,7 @@ impl Bridge { bridge: &Pubkey, mint: &Pubkey, ) -> Result { - Self::derive_key(program_id, &Self::derive_custody_seeds(bridge, mint)) + Ok(Self::derive_key(program_id, &Self::derive_custody_seeds(bridge, mint))?.0) } /// Calculates a derived address for a claim account @@ -341,7 +343,7 @@ impl Bridge { bridge: &Pubkey, hash: &[u8; 32], ) -> Result { - Self::derive_key(program_id, &Self::derive_claim_seeds(bridge, hash)) + Ok(Self::derive_key(program_id, &Self::derive_claim_seeds(bridge, hash))?.0) } /// Calculates a derived address for a wrapped asset meta entry @@ -350,7 +352,7 @@ impl Bridge { bridge: &Pubkey, mint: &Pubkey, ) -> Result { - Self::derive_key(program_id, &Self::derive_wrapped_meta_seeds(bridge, mint)) + Ok(Self::derive_key(program_id, &Self::derive_wrapped_meta_seeds(bridge, mint))?.0) } /// Calculates a derived address for this program @@ -359,10 +361,11 @@ impl Bridge { bridge_key: &Pubkey, guardian_set_index: u32, ) -> Result { - Self::derive_key( + Ok(Self::derive_key( program_id, &Self::derive_guardian_set_seeds(bridge_key, guardian_set_index), - ) + )? + .0) } /// Calculates a derived seeds for a wrapped asset @@ -372,10 +375,11 @@ impl Bridge { asset_chain: u8, asset: ForeignAddress, ) -> Result { - Self::derive_key( + Ok(Self::derive_key( program_id, &Self::derive_wrapped_asset_seeds(bridge_key, asset_chain, asset), - ) + )? + .0) } /// Calculates a derived address for a transfer out @@ -389,7 +393,7 @@ impl Bridge { user: ForeignAddress, slot: u32, ) -> Result { - Self::derive_key( + Ok(Self::derive_key( program_id, &Self::derive_transfer_id_seeds( bridge_key, @@ -400,22 +404,32 @@ impl Bridge { user, slot, ), - ) + )? + .0) } - pub fn derive_key(program_id: &Pubkey, seeds: &Vec>) -> Result { - let s: Vec<_> = seeds.iter().map(|item| item.as_slice()).collect(); - Ok(Self::find_program_address(s.as_slice(), program_id).0) + pub fn derive_key( + program_id: &Pubkey, + seeds: &Vec>, + ) -> Result<(Pubkey, Vec>), Error> { + Ok(Self::find_program_address(seeds, program_id)) } - pub fn find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> (Pubkey, u8) { - let mut nonce = [255]; + pub fn find_program_address( + seeds: &Vec>, + program_id: &Pubkey, + ) -> (Pubkey, Vec>) { + let mut nonce = [255u8]; for _ in 0..std::u8::MAX { { let mut seeds_with_nonce = seeds.to_vec(); - seeds_with_nonce.push(&nonce); - if let Ok(address) = Pubkey::create_program_address(&seeds_with_nonce, program_id) { - return (address, nonce[0]); + seeds_with_nonce.push(nonce.to_vec()); + let s: Vec<_> = seeds_with_nonce + .iter() + .map(|item| item.as_slice()) + .collect(); + if let Ok(address) = Pubkey::create_program_address(&s, program_id) { + return (address, seeds_with_nonce); } } nonce[0] -= 1; diff --git a/solana/cli/src/main.rs b/solana/cli/src/main.rs index 7f410ec5..60767d97 100644 --- a/solana/cli/src/main.rs +++ b/solana/cli/src/main.rs @@ -8,12 +8,14 @@ use clap::{ }; use hex; use primitive_types::U256; +use solana_account_decoder::{parse_token::TokenAccountType, UiAccountData}; use solana_clap_utils::input_parsers::value_of; use solana_clap_utils::input_validators::is_derivation; use solana_clap_utils::{ input_parsers::{keypair_of, pubkey_of}, input_validators::{is_amount, is_keypair, is_pubkey_or_keypair, is_url}, }; +use solana_client::client_error::ClientError; use solana_client::{rpc_client::RpcClient, rpc_request::TokenAccountsFilter}; use solana_sdk::system_instruction::create_account; use solana_sdk::{ @@ -31,7 +33,6 @@ use spl_token::{ state::{Account, Mint}, }; -use solana_account_decoder::{parse_token::TokenAccountType, UiAccountData}; use spl_bridge::instruction::*; use spl_bridge::state::*; @@ -94,9 +95,20 @@ fn command_lock_tokens( // Check whether we can find wrapped asset meta for the given token let wrapped_key = Bridge::derive_wrapped_meta_id(bridge, &bridge_key, &token)?; - let wrapped_info = config.rpc_client.get_account(&wrapped_key).or_else(Err)?; - let wrapped_meta: &WrappedAssetMeta = - Bridge::unpack_unchecked_immutable(wrapped_info.data.as_slice())?; + let asset_meta = match config.rpc_client.get_account(&wrapped_key) { + Ok(v) => { + let wrapped_meta: &WrappedAssetMeta = + Bridge::unpack_unchecked_immutable(v.data.as_slice())?; + AssetMeta { + address: wrapped_meta.address, + chain: wrapped_meta.chain, + } + } + Err(_) => AssetMeta { + address: token.to_bytes(), + chain: CHAIN_ID_SOLANA, + }, + }; let ix = transfer_out( bridge, @@ -106,37 +118,30 @@ fn command_lock_tokens( &TransferOutPayload { amount: U256::from(amount), chain_id: to_chain, - asset: { - if wrapped_meta.is_initialized() { - AssetMeta { - address: wrapped_meta.address, - chain: wrapped_meta.chain, - } - } else { - AssetMeta { - address: token.to_bytes(), - chain: CHAIN_ID_SOLANA, - } - } - }, + asset: asset_meta, target, nonce, }, )?; println!("custody: {}, ", ix.accounts[7].pubkey.to_string()); + let mut instructions = vec![]; // Approve tokens - let ix_a = approve( - &spl_token::id(), - &account, - &ix.accounts[3].pubkey, - &config.owner.pubkey(), - &[], - amount, - )?; + if asset_meta.chain == CHAIN_ID_SOLANA { + let ix_a = approve( + &spl_token::id(), + &account, + &ix.accounts[4].pubkey, + &config.owner.pubkey(), + &[], + amount, + )?; + instructions.push(ix_a); + } + instructions.push(ix); let mut transaction = - Transaction::new_with_payer(&[ix_a, ix], Some(&config.fee_payer.pubkey())); + Transaction::new_with_payer(&instructions.as_slice(), Some(&config.fee_payer.pubkey())); let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?; check_fee_payer_balance(