Working transfer in
This commit is contained in:
parent
2f526ff136
commit
e040449197
|
@ -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"
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()])
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue