Fixes for actual CPI usage and variable VAA size
This commit is contained in:
parent
760d5541b7
commit
f8e70efb0b
|
@ -26,13 +26,14 @@ Parameters:
|
|||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
|
||||
| 0 | sys | SystemProgram | | | ️ | |
|
||||
| 1 | token_program | SplToken | | | ️ | |
|
||||
| 2 | token_account | TokenAccount | | ✅ | | |
|
||||
| 3 | bridge | BridgeConfig | | | | |
|
||||
| 4 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
|
||||
| 5 | token | WrappedAsset | | ✅ | | ✅ |
|
||||
| 6 | payer | Account | ✅ | | | |
|
||||
| 0 | bridge_p | BridgeProgram | | | ️ | |
|
||||
| 1 | sys | SystemProgram | | | ️ | |
|
||||
| 2 | token_program | SplToken | | | ️ | |
|
||||
| 3 | token_account | TokenAccount | | ✅ | | |
|
||||
| 4 | bridge | BridgeConfig | | | | |
|
||||
| 5 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
|
||||
| 6 | token | WrappedAsset | | ✅ | | ✅ |
|
||||
| 7 | payer | Account | ✅ | | | |
|
||||
|
||||
#### TransferOutNative
|
||||
|
||||
|
@ -43,14 +44,15 @@ The transfer proposal will be tracked at a new account `proposal` where a VAA wi
|
|||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | --------------- | ------------------- | ------ | --------- | ----- | ------- |
|
||||
| 0 | sys | SystemProgram | | | ️ | |
|
||||
| 1 | token_program | SplToken | | | ️ | |
|
||||
| 2 | token_account | TokenAccount | | ✅ | | |
|
||||
| 3 | bridge | BridgeConfig | | | | |
|
||||
| 4 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
|
||||
| 5 | token | Mint | | ✅ | | |
|
||||
| 6 | payer | Account | ✅ | | | |
|
||||
| 7 | custody_account | TokenAccount | | ✅ | opt | ✅ |
|
||||
| 0 | bridge_p | BridgeProgram | | | ️ | |
|
||||
| 1 | sys | SystemProgram | | | ️ | |
|
||||
| 2 | token_program | SplToken | | | ️ | |
|
||||
| 3 | token_account | TokenAccount | | ✅ | | |
|
||||
| 4 | bridge | BridgeConfig | | | | |
|
||||
| 5 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
|
||||
| 6 | token | Mint | | ✅ | | |
|
||||
| 7 | payer | Account | ✅ | | | |
|
||||
| 8 | custody_account | TokenAccount | | ✅ | opt | ✅ |
|
||||
|
||||
#### EvictTransferOut
|
||||
|
||||
|
@ -58,10 +60,11 @@ Deletes a `proposal` after the `VAA_EXPIRATION_TIME` to free up space on chain.
|
|||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
|
||||
| 0 | guardian | Account | ✅ | | | |
|
||||
| 1 | clock | Sysvar | | | ️ | ✅ |
|
||||
| 2 | bridge | BridgeConfig | | | | |
|
||||
| 3 | proposal | TransferOutProposal | | ✅ | | ✅ |
|
||||
| 0 | bridge_p | BridgeProgram | | | ️ | |
|
||||
| 1 | guardian | Account | ✅ | | | |
|
||||
| 2 | clock | Sysvar | | | ️ | ✅ |
|
||||
| 3 | bridge | BridgeConfig | | | | |
|
||||
| 4 | proposal | TransferOutProposal | | ✅ | | ✅ |
|
||||
|
||||
#### EvictClaimedVAA
|
||||
|
||||
|
@ -69,10 +72,11 @@ Deletes a `ClaimedVAA` after the `VAA_EXPIRATION_TIME` to free up space on chain
|
|||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
|
||||
| 0 | guardian | Account | ✅ | | | |
|
||||
| 1 | clock | Sysvar | | | ️ | ✅ |
|
||||
| 2 | bridge | BridgeConfig | | | | |
|
||||
| 3 | claim | ClaimedVAA | | ✅ | | ✅ |
|
||||
| 0 | bridge_p | BridgeProgram | | | ️ | |
|
||||
| 1 | guardian | Account | ✅ | | | |
|
||||
| 2 | clock | Sysvar | | | ️ | ✅ |
|
||||
| 3 | bridge | BridgeConfig | | | | |
|
||||
| 4 | claim | ClaimedVAA | | ✅ | | ✅ |
|
||||
|
||||
#### CreateWrappedAsset
|
||||
|
||||
|
@ -80,12 +84,13 @@ Creates a new `WrappedAsset` to be used to create accounts and later receive tra
|
|||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
|
||||
| 0 | sys | SystemProgram | | | ️ | |
|
||||
| 1 | token_program | SplToken | | | ️ | |
|
||||
| 2 | bridge | BridgeConfig | | | | |
|
||||
| 3 | payer | Account | ✅ | | ️ | |
|
||||
| 4 | wrapped_mint | WrappedAsset | | | ✅ | ✅ |
|
||||
| 5 | wrapped_meta_account | WrappedAssetMeta | | ✅ | ✅ | ✅ |
|
||||
| 0 | bridge_p | BridgeProgram | | | ️ | |
|
||||
| 1 | sys | SystemProgram | | | ️ | |
|
||||
| 2 | token_program | SplToken | | | ️ | |
|
||||
| 3 | bridge | BridgeConfig | | | | |
|
||||
| 4 | payer | Account | ✅ | | ️ | |
|
||||
| 5 | wrapped_mint | WrappedAsset | | | ✅ | ✅ |
|
||||
| 6 | wrapped_meta_account | WrappedAssetMeta | | ✅ | ✅ | ✅ |
|
||||
|
||||
#### SubmitVAA
|
||||
|
||||
|
@ -97,12 +102,13 @@ All require:
|
|||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
|
||||
| 0 | sys | SystemProgram | | | ️ | |
|
||||
| 1 | clock | Sysvar | | | ️ | ✅ |
|
||||
| 2 | bridge | BridgeConfig | | | | |
|
||||
| 3 | guardian_set | GuardianSet | | | | |
|
||||
| 4 | claim | ExecutedVAA | | ✅ | ✅ | ✅ |
|
||||
| 5 | payer | Account | ✅ | | | |
|
||||
| 0 | bridge_p | BridgeProgram | | | ️ | |
|
||||
| 1 | sys | SystemProgram | | | ️ | |
|
||||
| 2 | clock | Sysvar | | | ️ | ✅ |
|
||||
| 3 | bridge | BridgeConfig | | | | |
|
||||
| 4 | guardian_set | GuardianSet | | | | |
|
||||
| 5 | claim | ExecutedVAA | | ✅ | ✅ | ✅ |
|
||||
| 6 | payer | Account | ✅ | | | |
|
||||
|
||||
followed by:
|
||||
|
||||
|
@ -110,30 +116,30 @@ followed by:
|
|||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- |
|
||||
| 6 | guardian_set_new | GuardianSet | | ✅ | ✅ | ✅ |
|
||||
| 7 | guardian_set_new | GuardianSet | | ✅ | ✅ | ✅ |
|
||||
|
||||
##### Transfer: Ethereum (native) -> Solana (wrapped)
|
||||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
|
||||
| 6 | token_program | SplToken | | | ️ | |
|
||||
| 7 | token | WrappedAsset | | | | ✅ |
|
||||
| 8 | destination | TokenAccount | | ✅ | | |
|
||||
| 7 | token_program | SplToken | | | ️ | |
|
||||
| 8 | token | WrappedAsset | | | | ✅ |
|
||||
| 9 | destination | TokenAccount | | ✅ | | |
|
||||
|
||||
##### Transfer: Ethereum (wrapped) -> Solana (native)
|
||||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
|
||||
| 6 | token_program | SplToken | | | ️ | |
|
||||
| 7 | token | Mint | | | | ✅ |
|
||||
| 8 | destination | TokenAccount | | ✅ | opt | |
|
||||
| 9 | custody_src | TokenAccount | | ✅ | | ✅ |
|
||||
| 7 | token_program | SplToken | | | ️ | |
|
||||
| 8 | token | Mint | | | | ✅ |
|
||||
| 9 | destination | TokenAccount | | ✅ | opt | |
|
||||
| 10 | custody_src | TokenAccount | | ✅ | | ✅ |
|
||||
|
||||
##### Transfer: Solana (any) -> Ethereum (any)
|
||||
|
||||
| Index | Name | Type | signer | writeable | empty | derived |
|
||||
| ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- |
|
||||
| 6 | out_proposal | TransferOutProposal | | ✅ | | ✅ |
|
||||
| 7 | out_proposal | TransferOutProposal | | ✅ | | ✅ |
|
||||
|
||||
## Accounts
|
||||
|
||||
|
|
|
@ -2579,19 +2579,6 @@ 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"
|
||||
|
|
|
@ -21,14 +21,11 @@ use crate::vaa::{VAABody, VAA};
|
|||
/// chain id of this chain
|
||||
pub const CHAIN_ID_SOLANA: u8 = 1;
|
||||
|
||||
/// size of a VAA in bytes
|
||||
const VAA_SIZE: usize = 200;
|
||||
|
||||
/// size of a foreign address in bytes
|
||||
const FOREIGN_ADDRESS_SIZE: usize = 32;
|
||||
|
||||
/// length-prefixed serialized validator payment approval data
|
||||
pub type VAAData = [u8; VAA_SIZE];
|
||||
pub type VAAData = Vec<u8>;
|
||||
/// X and Y point of P for guardians
|
||||
pub type GuardianKey = [u8; 64];
|
||||
/// address on a foreign chain
|
||||
|
@ -129,9 +126,8 @@ impl BridgeInstruction {
|
|||
TransferOut(*payload)
|
||||
}
|
||||
2 => {
|
||||
let payload: &VAAData = unpack(input)?;
|
||||
|
||||
PostVAA(*payload)
|
||||
let payload: VAAData = input[1..].to_vec();
|
||||
PostVAA(payload)
|
||||
}
|
||||
5 => {
|
||||
let payload: &AssetMeta = unpack(input)?;
|
||||
|
@ -307,22 +303,10 @@ pub fn transfer_out(
|
|||
pub fn post_vaa(
|
||||
program_id: &Pubkey,
|
||||
payer: &Pubkey,
|
||||
v: &[u8],
|
||||
v: VAAData,
|
||||
) -> Result<Instruction, ProgramError> {
|
||||
// VAA must be <= VAA_SIZE-1 to allow for the length prefix
|
||||
if v.len() > VAA_SIZE - 1 {
|
||||
return Err(VAATooLong.into());
|
||||
}
|
||||
// Convert data to length-prefixed on-chain format
|
||||
let mut vaa_data: Vec<u8> = vec![];
|
||||
vaa_data.push(v.len() as u8);
|
||||
vaa_data.append(&mut v.to_vec());
|
||||
vaa_data.resize(200, 0);
|
||||
|
||||
let mut vaa_chain: [u8; 200] = [0; 200];
|
||||
vaa_chain.copy_from_slice(vaa_data.as_slice());
|
||||
|
||||
let data = BridgeInstruction::PostVAA(vaa_chain).serialize()?;
|
||||
let mut data = v.clone();
|
||||
data.insert(0, 2);
|
||||
|
||||
// Parse VAA
|
||||
let vaa = VAA::deserialize(&v[..])?;
|
||||
|
@ -350,6 +334,7 @@ pub fn post_vaa(
|
|||
}
|
||||
VAABody::Transfer(t) => {
|
||||
if t.source_chain == CHAIN_ID_SOLANA {
|
||||
println!("kot");
|
||||
// Solana (any) -> Ethereum (any)
|
||||
let transfer_key = Bridge::derive_transfer_id(
|
||||
program_id,
|
||||
|
@ -363,6 +348,7 @@ pub fn post_vaa(
|
|||
)?;
|
||||
accounts.push(AccountMeta::new(transfer_key, false))
|
||||
} else if t.asset.chain == CHAIN_ID_SOLANA {
|
||||
println!("kat");
|
||||
// Foreign (wrapped) -> Solana (native)
|
||||
let mint_key = Pubkey::new(&t.asset.address);
|
||||
let custody_key = Bridge::derive_custody_id(program_id, &bridge_key, &mint_key)?;
|
||||
|
@ -371,6 +357,7 @@ pub fn post_vaa(
|
|||
accounts.push(AccountMeta::new(Pubkey::new(&t.target_address), false));
|
||||
accounts.push(AccountMeta::new(custody_key, false));
|
||||
} else {
|
||||
println!("kit");
|
||||
// Foreign (native) -> Solana (wrapped)
|
||||
let wrapped_key = Bridge::derive_wrapped_asset_id(
|
||||
program_id,
|
||||
|
|
|
@ -51,9 +51,7 @@ impl Bridge {
|
|||
}
|
||||
PostVAA(vaa_body) => {
|
||||
info!("Instruction: PostVAA");
|
||||
let len = vaa_body[0] as usize;
|
||||
let vaa_data = &vaa_body[..len];
|
||||
let vaa = VAA::deserialize(vaa_data)?;
|
||||
let vaa = VAA::deserialize(&vaa_body)?;
|
||||
|
||||
let hash = vaa.body_hash()?;
|
||||
|
||||
|
@ -147,7 +145,6 @@ impl Bridge {
|
|||
let transfer_info = next_account_info(account_info_iter)?;
|
||||
let mint_info = next_account_info(account_info_iter)?;
|
||||
let payer_info = next_account_info(account_info_iter)?;
|
||||
let authority_info = next_account_info(account_info_iter)?;
|
||||
|
||||
let sender = Bridge::token_account_deserialize(sender_account_info)?;
|
||||
let bridge = Bridge::bridge_deserialize(bridge_info)?;
|
||||
|
@ -175,10 +172,10 @@ impl Bridge {
|
|||
t.asset.address,
|
||||
t.chain_id,
|
||||
t.target,
|
||||
sender.owner.to_bytes(),
|
||||
sender_account_info.key.to_bytes(),
|
||||
t.nonce,
|
||||
);
|
||||
Bridge::check_and_create_account::<TransferOutProposal>(
|
||||
Bridge::check_and_create_account::<[u8; TRANSFER_OUT_PROPOSAL_SIZE]>(
|
||||
program_id,
|
||||
accounts,
|
||||
transfer_info.key,
|
||||
|
@ -188,11 +185,7 @@ impl Bridge {
|
|||
)?;
|
||||
|
||||
// Load transfer account
|
||||
let mut transfer_data = transfer_info.data.borrow_mut();
|
||||
let transfer: &mut TransferOutProposal = Bridge::unpack_unchecked(&mut transfer_data)?;
|
||||
if transfer.is_initialized {
|
||||
return Err(Error::AlreadyExists.into());
|
||||
}
|
||||
let mut transfer: TransferOutProposal = TransferOutProposal::default();
|
||||
|
||||
info!("burning");
|
||||
// Burn tokens
|
||||
|
@ -200,7 +193,6 @@ impl Bridge {
|
|||
program_id,
|
||||
accounts,
|
||||
&bridge.config.token_program,
|
||||
authority_info.key,
|
||||
sender_account_info.key,
|
||||
t.amount,
|
||||
)?;
|
||||
|
@ -213,6 +205,11 @@ impl Bridge {
|
|||
transfer.amount = t.amount;
|
||||
transfer.to_chain_id = t.chain_id;
|
||||
transfer.asset = t.asset;
|
||||
let mut transfer_data = Self::transfer_out_proposal_serialize(&transfer)?;
|
||||
transfer_info
|
||||
.data
|
||||
.borrow_mut()
|
||||
.swap_with_slice(transfer_data.as_mut_slice());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -307,7 +304,7 @@ impl Bridge {
|
|||
sender_account_info.key.to_bytes(),
|
||||
t.nonce,
|
||||
);
|
||||
Bridge::check_and_create_account::<TransferOutProposal>(
|
||||
Bridge::check_and_create_account::<[u8; TRANSFER_OUT_PROPOSAL_SIZE]>(
|
||||
program_id,
|
||||
accounts,
|
||||
transfer_info.key,
|
||||
|
@ -317,11 +314,7 @@ impl Bridge {
|
|||
)?;
|
||||
|
||||
// Load transfer account
|
||||
let mut transfer_data = transfer_info.data.borrow_mut();
|
||||
let transfer: &mut TransferOutProposal = Bridge::unpack_unchecked(&mut transfer_data)?;
|
||||
if transfer.is_initialized {
|
||||
return Err(Error::AlreadyExists.into());
|
||||
}
|
||||
let mut transfer = TransferOutProposal::default();
|
||||
|
||||
// Check that custody account was derived correctly
|
||||
let expected_custody_id =
|
||||
|
@ -376,6 +369,12 @@ impl Bridge {
|
|||
address: mint_info.key.to_bytes(),
|
||||
};
|
||||
|
||||
let mut transfer_data = Self::transfer_out_proposal_serialize(&transfer)?;
|
||||
transfer_info
|
||||
.data
|
||||
.borrow_mut()
|
||||
.swap_with_slice(transfer_data.as_mut_slice());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -585,7 +584,6 @@ impl Bridge {
|
|||
program_id,
|
||||
accounts,
|
||||
&bridge.config.token_program,
|
||||
bridge_info.key,
|
||||
custody_info.key,
|
||||
destination_info.key,
|
||||
b.amount,
|
||||
|
@ -610,7 +608,6 @@ impl Bridge {
|
|||
&bridge.config.token_program,
|
||||
mint_info.key,
|
||||
destination_info.key,
|
||||
bridge_info.key,
|
||||
b.amount,
|
||||
)?;
|
||||
}
|
||||
|
@ -653,6 +650,12 @@ impl Bridge {
|
|||
proposal.vaa = vaa_data;
|
||||
proposal.vaa_time = vaa.timestamp;
|
||||
|
||||
let mut transfer_data = Self::transfer_out_proposal_serialize(&proposal)?;
|
||||
proposal_info
|
||||
.data
|
||||
.borrow_mut()
|
||||
.swap_with_slice(transfer_data.as_mut_slice());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -676,14 +679,7 @@ pub fn invoke_signed<'a>(
|
|||
for account_info in account_infos.iter() {
|
||||
if meta.pubkey == *account_info.key {
|
||||
let mut new_account_info = account_info.clone();
|
||||
for seeds in signers_seeds.iter() {
|
||||
let signer =
|
||||
solana_sdk::program::create_program_address(seeds, &WORMHOLE_PROGRAM_ID)
|
||||
.unwrap();
|
||||
if *account_info.key == signer {
|
||||
new_account_info.is_signer = true;
|
||||
}
|
||||
}
|
||||
for seeds in signers_seeds.iter() {}
|
||||
new_account_infos.push(new_account_info);
|
||||
}
|
||||
}
|
||||
|
@ -706,19 +702,14 @@ impl Bridge {
|
|||
program_id: &Pubkey,
|
||||
accounts: &[AccountInfo],
|
||||
token_program_id: &Pubkey,
|
||||
authority: &Pubkey,
|
||||
token_account: &Pubkey,
|
||||
amount: U256,
|
||||
) -> Result<(), ProgramError> {
|
||||
let all_signers: Vec<&Pubkey> = accounts
|
||||
.iter()
|
||||
.filter_map(|item| if item.is_signer { Some(item.key) } else { None })
|
||||
.collect();
|
||||
let ix = spl_token::instruction::burn(
|
||||
token_program_id,
|
||||
token_account,
|
||||
authority,
|
||||
all_signers.as_slice(),
|
||||
&Self::derive_bridge_id(program_id)?,
|
||||
&[],
|
||||
amount.as_u64(),
|
||||
)?;
|
||||
Self::invoke_as_bridge(program_id, &ix, accounts)
|
||||
|
@ -731,14 +722,13 @@ impl Bridge {
|
|||
token_program_id: &Pubkey,
|
||||
mint: &Pubkey,
|
||||
destination: &Pubkey,
|
||||
bridge: &Pubkey,
|
||||
amount: U256,
|
||||
) -> Result<(), ProgramError> {
|
||||
let ix = spl_token::instruction::mint_to(
|
||||
token_program_id,
|
||||
mint,
|
||||
destination,
|
||||
bridge,
|
||||
&Self::derive_bridge_id(program_id)?,
|
||||
&[],
|
||||
amount.as_u64(),
|
||||
)?;
|
||||
|
@ -771,7 +761,6 @@ impl Bridge {
|
|||
program_id: &Pubkey,
|
||||
accounts: &[AccountInfo],
|
||||
token_program_id: &Pubkey,
|
||||
bridge: &Pubkey,
|
||||
source: &Pubkey,
|
||||
destination: &Pubkey,
|
||||
amount: U256,
|
||||
|
@ -780,7 +769,7 @@ impl Bridge {
|
|||
token_program_id,
|
||||
source,
|
||||
destination,
|
||||
bridge,
|
||||
&Self::derive_bridge_id(program_id)?,
|
||||
&[],
|
||||
amount.as_u64(),
|
||||
)?;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
//! Bridge transition types
|
||||
|
||||
use std::io::{Cursor, Read, Write};
|
||||
use std::mem::size_of;
|
||||
use std::ops::Deref;
|
||||
|
||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
use primitive_types::U256;
|
||||
use solana_sdk::hash::Hasher;
|
||||
use solana_sdk::pubkey::{PubkeyError, MAX_SEED_LEN};
|
||||
|
@ -46,8 +49,7 @@ impl IsInitialized for GuardianSet {
|
|||
}
|
||||
|
||||
/// proposal to transfer tokens to a foreign chain
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Default)]
|
||||
pub struct TransferOutProposal {
|
||||
/// amount to transfer
|
||||
pub amount: U256,
|
||||
|
@ -62,7 +64,7 @@ pub struct TransferOutProposal {
|
|||
/// nonce of the transfer
|
||||
pub nonce: u32,
|
||||
/// vaa to unlock the tokens on the foreign chain
|
||||
pub vaa: VAAData,
|
||||
pub vaa: Vec<u8>,
|
||||
/// time the vaa was submitted
|
||||
pub vaa_time: u32,
|
||||
|
||||
|
@ -76,6 +78,7 @@ impl IsInitialized for TransferOutProposal {
|
|||
}
|
||||
}
|
||||
|
||||
pub const TRANSFER_OUT_PROPOSAL_SIZE: usize = 1139;
|
||||
impl TransferOutProposal {
|
||||
pub fn matches_vaa(&self, b: &BodyTransfer) -> bool {
|
||||
return b.amount == self.amount
|
||||
|
@ -203,8 +206,55 @@ impl Bridge {
|
|||
pub fn transfer_out_proposal_deserialize(
|
||||
info: &AccountInfo,
|
||||
) -> Result<TransferOutProposal, Error> {
|
||||
Ok(*Bridge::unpack(&mut info.data.borrow_mut())
|
||||
.map_err(|_| Error::ExpectedTransferOutProposal)?)
|
||||
let raw_data = info.data.borrow();
|
||||
let mut rdr = Cursor::new(raw_data.as_ref());
|
||||
let mut proposal = TransferOutProposal::default();
|
||||
proposal.is_initialized = rdr.read_u8()? == 1;
|
||||
|
||||
let mut amount_data = [0u8; 32];
|
||||
rdr.read_exact(&mut amount_data)?;
|
||||
let amount = U256::from_big_endian(&amount_data[..]);
|
||||
proposal.amount = amount;
|
||||
|
||||
proposal.nonce = rdr.read_u32::<BigEndian>()?;
|
||||
proposal.vaa_time = rdr.read_u32::<BigEndian>()?;
|
||||
proposal.to_chain_id = rdr.read_u8()?;
|
||||
rdr.read_exact(&mut proposal.source_address)?;
|
||||
rdr.read_exact(&mut proposal.foreign_address)?;
|
||||
proposal.asset.chain = rdr.read_u8()?;
|
||||
rdr.read_exact(&mut proposal.asset.address)?;
|
||||
|
||||
rdr.read_to_end(&mut proposal.vaa)?;
|
||||
|
||||
return Ok(proposal);
|
||||
}
|
||||
|
||||
/// Deserializes a `TransferOutProposal`.
|
||||
pub fn transfer_out_proposal_serialize(data: &TransferOutProposal) -> Result<Vec<u8>, Error> {
|
||||
let mut out_data = Vec::new();
|
||||
out_data.write_u8({
|
||||
if data.is_initialized {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
})?;
|
||||
let mut amount_data = [0u8; 32];
|
||||
data.amount.to_big_endian(&mut amount_data);
|
||||
out_data.write(&amount_data)?;
|
||||
|
||||
out_data.write_u32::<BigEndian>(data.nonce)?;
|
||||
out_data.write_u32::<BigEndian>(data.vaa_time)?;
|
||||
out_data.write_u8(data.to_chain_id)?;
|
||||
out_data.write(&data.source_address)?;
|
||||
out_data.write(&data.foreign_address)?;
|
||||
out_data.write_u8(data.asset.chain)?;
|
||||
out_data.write(&data.asset.address)?;
|
||||
let mut vaa_res = data.vaa.clone();
|
||||
vaa_res.resize(1000, 0u8);
|
||||
out_data.write(&vaa_res)?;
|
||||
|
||||
return Ok(out_data);
|
||||
}
|
||||
|
||||
/// Unpacks a state from a bytes buffer while assuring that the state is initialized.
|
||||
|
|
|
@ -46,7 +46,11 @@ struct Config {
|
|||
type Error = Box<dyn std::error::Error>;
|
||||
type CommmandResult = Result<Option<Transaction>, Error>;
|
||||
|
||||
fn command_deploy_bridge(config: &Config, bridge: &Pubkey) -> CommmandResult {
|
||||
fn command_deploy_bridge(
|
||||
config: &Config,
|
||||
bridge: &Pubkey,
|
||||
initial_guardian: Vec<[u8; 20]>,
|
||||
) -> CommmandResult {
|
||||
println!("Deploying bridge program");
|
||||
|
||||
let minimum_balance_for_rent_exemption = config
|
||||
|
@ -56,7 +60,7 @@ fn command_deploy_bridge(config: &Config, bridge: &Pubkey) -> CommmandResult {
|
|||
let ix = initialize(
|
||||
bridge,
|
||||
&config.owner.pubkey(),
|
||||
vec![[0u8; 20]],
|
||||
initial_guardian,
|
||||
&BridgeConfig {
|
||||
vaa_expiration_time: 200000000,
|
||||
token_program: spl_token::id(),
|
||||
|
@ -104,7 +108,7 @@ fn command_lock_tokens(
|
|||
chain: wrapped_meta.chain,
|
||||
}
|
||||
}
|
||||
Err(_) => AssetMeta {
|
||||
Err(e) => AssetMeta {
|
||||
address: token.to_bytes(),
|
||||
chain: CHAIN_ID_SOLANA,
|
||||
},
|
||||
|
@ -152,6 +156,30 @@ fn command_lock_tokens(
|
|||
Ok(Some(transaction))
|
||||
}
|
||||
|
||||
fn command_create_wrapped_asset(
|
||||
config: &Config,
|
||||
bridge: &Pubkey,
|
||||
meta: AssetMeta,
|
||||
) -> CommmandResult {
|
||||
println!("Creating wrapped asset");
|
||||
|
||||
let minimum_balance_for_rent_exemption = config
|
||||
.rpc_client
|
||||
.get_minimum_balance_for_rent_exemption(size_of::<Mint>())?;
|
||||
|
||||
let ix = create_wrapped(bridge, &config.owner.pubkey(), meta)?;
|
||||
|
||||
let mut transaction = Transaction::new_with_payer(&[ix], Some(&config.fee_payer.pubkey()));
|
||||
|
||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
||||
check_fee_payer_balance(
|
||||
config,
|
||||
minimum_balance_for_rent_exemption + fee_calculator.calculate_fee(&transaction.message()),
|
||||
)?;
|
||||
transaction.sign(&[&config.fee_payer, &config.owner], recent_blockhash);
|
||||
Ok(Some(transaction))
|
||||
}
|
||||
|
||||
fn command_submit_vaa(config: &Config, bridge: &Pubkey, vaa: &[u8]) -> CommmandResult {
|
||||
println!("Submitting VAA");
|
||||
|
||||
|
@ -159,7 +187,7 @@ fn command_submit_vaa(config: &Config, bridge: &Pubkey, vaa: &[u8]) -> CommmandR
|
|||
.rpc_client
|
||||
.get_minimum_balance_for_rent_exemption(size_of::<Mint>())?;
|
||||
|
||||
let ix = post_vaa(bridge, &config.owner.pubkey(), vaa)?;
|
||||
let ix = post_vaa(bridge, &config.owner.pubkey(), vaa.to_vec())?;
|
||||
|
||||
let mut transaction = Transaction::new_with_payer(&[ix], Some(&config.fee_payer.pubkey()));
|
||||
|
||||
|
@ -828,6 +856,16 @@ fn main() {
|
|||
.help(
|
||||
"Specify the bridge program public key"
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("guardian")
|
||||
.validator(is_hex)
|
||||
.value_name("GUADIAN_ADDRESS")
|
||||
.takes_value(true)
|
||||
.index(2)
|
||||
.required(true)
|
||||
.help("Address of the initial guardian"),
|
||||
|
||||
))
|
||||
.subcommand(
|
||||
SubCommand::with_name("lock")
|
||||
|
@ -915,6 +953,74 @@ fn main() {
|
|||
.help("The vaa to be posted"),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("create-wrapped")
|
||||
.about("Create new wrapped asset and token account")
|
||||
.arg(
|
||||
Arg::with_name("bridge")
|
||||
.long("bridge")
|
||||
.value_name("BRIDGE_KEY")
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.takes_value(true)
|
||||
.index(1)
|
||||
.required(true)
|
||||
.help(
|
||||
"Specify the bridge program public key"
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("chain")
|
||||
.validator(is_u8)
|
||||
.value_name("CHAIN")
|
||||
.takes_value(true)
|
||||
.index(2)
|
||||
.required(true)
|
||||
.help("Chain ID of the asset"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("token")
|
||||
.validator(is_hex)
|
||||
.value_name("TOKEN_ADDRESS")
|
||||
.takes_value(true)
|
||||
.index(3)
|
||||
.required(true)
|
||||
.help("Token address of the asset"),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("wrapped-address")
|
||||
.about("Derive wrapped asset address")
|
||||
.arg(
|
||||
Arg::with_name("bridge")
|
||||
.long("bridge")
|
||||
.value_name("BRIDGE_KEY")
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.takes_value(true)
|
||||
.index(1)
|
||||
.required(true)
|
||||
.help(
|
||||
"Specify the bridge program public key"
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("chain")
|
||||
.validator(is_u8)
|
||||
.value_name("CHAIN")
|
||||
.takes_value(true)
|
||||
.index(2)
|
||||
.required(true)
|
||||
.help("Chain ID of the asset"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("token")
|
||||
.validator(is_hex)
|
||||
.value_name("TOKEN_ADDRESS")
|
||||
.takes_value(true)
|
||||
.index(3)
|
||||
.required(true)
|
||||
.help("Token address of the asset"),
|
||||
)
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let config = {
|
||||
|
@ -999,7 +1105,12 @@ fn main() {
|
|||
}
|
||||
("create-bridge", Some(arg_matches)) => {
|
||||
let bridge = pubkey_of(arg_matches, "bridge").unwrap();
|
||||
command_deploy_bridge(&config, &bridge)
|
||||
let initial_guardian: String = value_of(arg_matches, "guardian").unwrap();
|
||||
let initial_data = hex::decode(initial_guardian).unwrap();
|
||||
|
||||
let mut guardian = [0u8; 20];
|
||||
guardian.copy_from_slice(&initial_data);
|
||||
command_deploy_bridge(&config, &bridge, vec![guardian])
|
||||
}
|
||||
("lock", Some(arg_matches)) => {
|
||||
let bridge = pubkey_of(arg_matches, "bridge").unwrap();
|
||||
|
@ -1018,6 +1129,39 @@ fn main() {
|
|||
let vaa = hex::decode(vaa_string).unwrap();
|
||||
command_submit_vaa(&config, &bridge, vaa.as_slice())
|
||||
}
|
||||
("create-wrapped", Some(arg_matches)) => {
|
||||
let bridge = pubkey_of(arg_matches, "bridge").unwrap();
|
||||
let chain = value_t_or_exit!(arg_matches, "chain", u8);
|
||||
let addr_string: String = value_of(arg_matches, "token").unwrap();
|
||||
let addr_data = hex::decode(addr_string).unwrap();
|
||||
|
||||
let mut token_addr = [0u8; 32];
|
||||
token_addr.copy_from_slice(addr_data.as_slice());
|
||||
|
||||
command_create_wrapped_asset(
|
||||
&config,
|
||||
&bridge,
|
||||
AssetMeta {
|
||||
chain,
|
||||
address: token_addr,
|
||||
},
|
||||
)
|
||||
}
|
||||
("wrapped-address", Some(arg_matches)) => {
|
||||
let bridge = pubkey_of(arg_matches, "bridge").unwrap();
|
||||
let chain = value_t_or_exit!(arg_matches, "chain", u8);
|
||||
let addr_string: String = value_of(arg_matches, "token").unwrap();
|
||||
let addr_data = hex::decode(addr_string).unwrap();
|
||||
|
||||
let mut token_addr = [0u8; 32];
|
||||
token_addr.copy_from_slice(addr_data.as_slice());
|
||||
|
||||
let bridge_key = Bridge::derive_bridge_id(&bridge).unwrap();
|
||||
let wrapped_key =
|
||||
Bridge::derive_wrapped_asset_id(&bridge, &bridge_key, chain, token_addr).unwrap();
|
||||
println!("Wrapped address: {}", wrapped_key);
|
||||
return;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
.and_then(|transaction| {
|
||||
|
|
Loading…
Reference in New Issue