Working transfer in

This commit is contained in:
Hendrik Hofstadt 2020-08-17 17:06:09 +02:00
parent 2f526ff136
commit e040449197
9 changed files with 227 additions and 92 deletions

74
solana/Cargo.lock generated
View File

@ -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"

View File

@ -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" }

View File

@ -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"

View File

@ -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<Error> for ProgramError {

View File

@ -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"),
}
}
}

View File

@ -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),

View File

@ -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::<BridgeConfig>(
Bridge::check_and_create_account::<Bridge>(
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::<Mint>(
token_program,
Self::check_and_create_account::<spl_token::state::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::<Mint>(
token_program,
Self::check_and_create_account::<Mint>(
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<Vec<u8>>,
) -> 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<Vec<u8>>,
) -> Result<(), ProgramError> {
let expected_key = Bridge::derive_key(program_id, seeds)?;
) -> Result<Vec<Vec<u8>>, 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::<T>(program_id, accounts, new_account, payer, seeds)
info!("deploying contract");
Self::create_account_raw::<T>(
program_id,
accounts,
new_account,
payer,
owner,
&full_seeds,
)?;
Ok(full_seeds)
}
/// Create a new account
pub fn create_account<T: Sized>(
fn create_account_raw<T: Sized>(
program_id: &Pubkey,
accounts: &[AccountInfo],
new_account: &Pubkey,
payer: &Pubkey,
owner: &Pubkey,
seeds: &Vec<Vec<u8>>,
) -> Result<(), ProgramError> {
let size = size_of::<T>();
@ -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()])

View File

@ -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<Pubkey, Error> {
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<Pubkey, Error> {
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<Pubkey, Error> {
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<Pubkey, Error> {
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<Pubkey, Error> {
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<Pubkey, Error> {
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<Pubkey, Error> {
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<Vec<u8>>) -> Result<Pubkey, Error> {
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<Vec<u8>>,
) -> Result<(Pubkey, Vec<Vec<u8>>), 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<Vec<u8>>,
program_id: &Pubkey,
) -> (Pubkey, Vec<Vec<u8>>) {
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;

View File

@ -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 asset_meta = match config.rpc_client.get_account(&wrapped_key) {
Ok(v) => {
let wrapped_meta: &WrappedAssetMeta =
Bridge::unpack_unchecked_immutable(wrapped_info.data.as_slice())?;
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
if asset_meta.chain == CHAIN_ID_SOLANA {
let ix_a = approve(
&spl_token::id(),
&account,
&ix.accounts[3].pubkey,
&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(