Implement fees in the solana token bridge
Change-Id: I0bc29ced7e14c37294d0bde7ada173a90b5fcae4
This commit is contained in:
parent
f42453be45
commit
2437a76ad7
|
@ -50,6 +50,7 @@ pub struct CompleteNative<'b> {
|
|||
pub chain_registration: Endpoint<'b, { AccountState::Initialized }>,
|
||||
|
||||
pub to: Mut<Data<'b, SplAccount, { AccountState::Initialized }>>,
|
||||
pub to_fees: Mut<Data<'b, SplAccount, { AccountState::Initialized }>>,
|
||||
pub custody: Mut<CustodyAccount<'b, { AccountState::Initialized }>>,
|
||||
pub mint: Data<'b, SplMint, { AccountState::Initialized }>,
|
||||
|
||||
|
@ -98,6 +99,9 @@ pub fn complete_native(
|
|||
if *accs.mint.info().key != accs.to.mint {
|
||||
return Err(InvalidMint.into());
|
||||
}
|
||||
if *accs.mint.info().key != accs.to_fees.mint {
|
||||
return Err(InvalidMint.into());
|
||||
}
|
||||
if *accs.mint.info().key != accs.custody.mint {
|
||||
return Err(InvalidMint.into());
|
||||
}
|
||||
|
@ -121,10 +125,12 @@ pub fn complete_native(
|
|||
accs.vaa.claim(ctx, accs.payer.key)?;
|
||||
|
||||
let mut amount = accs.vaa.amount.as_u64();
|
||||
let mut fee = accs.vaa.fee.as_u64();
|
||||
|
||||
// Wormhole always caps transfers at 8 decimals; un-truncate if the local token has more
|
||||
if accs.mint.decimals > 8 {
|
||||
amount *= 10u64.pow((accs.mint.decimals - 8) as u32)
|
||||
amount *= 10u64.pow((accs.mint.decimals - 8) as u32);
|
||||
fee *= 10u64.pow((accs.mint.decimals - 8) as u32);
|
||||
}
|
||||
|
||||
// Transfer tokens
|
||||
|
@ -134,11 +140,20 @@ pub fn complete_native(
|
|||
accs.to.info().key,
|
||||
accs.custody_signer.key,
|
||||
&[],
|
||||
amount,
|
||||
amount - fee,
|
||||
)?;
|
||||
invoke_seeded(&transfer_ix, ctx, &accs.custody_signer, None)?;
|
||||
|
||||
// TODO fee
|
||||
// Transfer fees
|
||||
let transfer_ix = spl_token::instruction::transfer(
|
||||
&spl_token::id(),
|
||||
accs.custody.info().key,
|
||||
accs.to_fees.info().key,
|
||||
accs.custody_signer.key,
|
||||
&[],
|
||||
fee,
|
||||
)?;
|
||||
invoke_seeded(&transfer_ix, ctx, &accs.custody_signer, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -154,6 +169,7 @@ pub struct CompleteWrapped<'b> {
|
|||
pub chain_registration: Endpoint<'b, { AccountState::Initialized }>,
|
||||
|
||||
pub to: Mut<Data<'b, SplAccount, { AccountState::Initialized }>>,
|
||||
pub to_fees: Mut<Data<'b, SplAccount, { AccountState::Initialized }>>,
|
||||
pub mint: Mut<WrappedMint<'b, { AccountState::Initialized }>>,
|
||||
|
||||
pub mint_authority: MintSigner<'b>,
|
||||
|
@ -202,6 +218,9 @@ pub fn complete_wrapped(
|
|||
if *accs.mint.info().key != accs.to.mint {
|
||||
return Err(InvalidMint.into());
|
||||
}
|
||||
if *accs.mint.info().key != accs.to_fees.mint {
|
||||
return Err(InvalidMint.into());
|
||||
}
|
||||
|
||||
// Verify VAA
|
||||
if accs.vaa.to_chain != CHAIN_ID_SOLANA {
|
||||
|
@ -218,11 +237,20 @@ pub fn complete_wrapped(
|
|||
accs.to.info().key,
|
||||
accs.mint_authority.key,
|
||||
&[],
|
||||
accs.vaa.amount.as_u64(),
|
||||
accs.vaa.amount.as_u64() - accs.vaa.fee.as_u64(),
|
||||
)?;
|
||||
invoke_seeded(&mint_ix, ctx, &accs.mint_authority, None)?;
|
||||
|
||||
// TODO fee
|
||||
// Mint fees
|
||||
let mint_ix = spl_token::instruction::mint_to(
|
||||
&spl_token::id(),
|
||||
accs.mint.info().key,
|
||||
accs.to_fees.info().key,
|
||||
accs.mint_authority.key,
|
||||
&[],
|
||||
accs.vaa.fee.as_u64(),
|
||||
)?;
|
||||
invoke_seeded(&mint_ix, ctx, &accs.mint_authority, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -155,6 +155,7 @@ pub fn transfer_native(
|
|||
let trunc_divisor = 10u64.pow(8.max(accs.mint.decimals as u32) - 8);
|
||||
// Truncate to 8 decimals
|
||||
let amount: u64 = data.amount / trunc_divisor;
|
||||
let fee: u64 = data.fee / trunc_divisor;
|
||||
// Untruncate the amount to drop the remainder so we don't "burn" user's funds.
|
||||
let amount_trunc: u64 = amount * trunc_divisor;
|
||||
|
||||
|
@ -181,7 +182,7 @@ pub fn transfer_native(
|
|||
token_chain: 1,
|
||||
to: data.target_address,
|
||||
to_chain: data.target_chain,
|
||||
fee: U256::from(data.fee),
|
||||
fee: U256::from(fee),
|
||||
};
|
||||
let params = (
|
||||
bridge::instruction::Instruction::PostMessage,
|
||||
|
|
|
@ -102,6 +102,7 @@ pub fn complete_native(
|
|||
message_key: Pubkey,
|
||||
vaa: PostVAAData,
|
||||
to: Pubkey,
|
||||
fee_recipient: Option<Pubkey>,
|
||||
mint: Pubkey,
|
||||
data: CompleteNativeData,
|
||||
) -> solitaire::Result<Instruction> {
|
||||
|
@ -129,6 +130,11 @@ pub fn complete_native(
|
|||
claim_acc,
|
||||
AccountMeta::new_readonly(endpoint, false),
|
||||
AccountMeta::new(to, false),
|
||||
if let Some(fee_r) = fee_recipient {
|
||||
AccountMeta::new(fee_r, false)
|
||||
} else {
|
||||
AccountMeta::new(to, false)
|
||||
},
|
||||
AccountMeta::new(custody_key, false),
|
||||
AccountMeta::new_readonly(mint, false),
|
||||
AccountMeta::new_readonly(custody_signer_key, false),
|
||||
|
@ -151,6 +157,7 @@ pub fn complete_wrapped(
|
|||
vaa: PostVAAData,
|
||||
payload: PayloadTransfer,
|
||||
to: Pubkey,
|
||||
fee_recipient: Option<Pubkey>,
|
||||
data: CompleteWrappedData,
|
||||
) -> solitaire::Result<Instruction> {
|
||||
let config_key = ConfigAccount::<'_, { AccountState::Uninitialized }>::key(None, &program_id);
|
||||
|
@ -180,6 +187,11 @@ pub fn complete_wrapped(
|
|||
claim_acc,
|
||||
AccountMeta::new_readonly(endpoint, false),
|
||||
AccountMeta::new(to, false),
|
||||
if let Some(fee_r) = fee_recipient {
|
||||
AccountMeta::new(fee_r, false)
|
||||
} else {
|
||||
AccountMeta::new(to, false)
|
||||
},
|
||||
AccountMeta::new(mint_key, false),
|
||||
AccountMeta::new_readonly(mint_authority_key, false),
|
||||
// Dependencies
|
||||
|
|
|
@ -170,6 +170,7 @@ pub fn complete_transfer_native_ix(
|
|||
bridge_id: String,
|
||||
payer: String,
|
||||
vaa: Vec<u8>,
|
||||
fee_recipient: Option<String>,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
|
@ -201,6 +202,11 @@ pub fn complete_transfer_native_ix(
|
|||
message_key,
|
||||
post_vaa_data,
|
||||
Pubkey::new(&payload.to[..]),
|
||||
if let Some(fee_r) = fee_recipient {
|
||||
Some(Pubkey::from_str(fee_r.as_str()).unwrap())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
Pubkey::new(&payload.token_address),
|
||||
CompleteNativeData {},
|
||||
)
|
||||
|
@ -215,6 +221,7 @@ pub fn complete_transfer_wrapped_ix(
|
|||
bridge_id: String,
|
||||
payer: String,
|
||||
vaa: Vec<u8>,
|
||||
fee_recipient: Option<String>,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
|
@ -247,6 +254,11 @@ pub fn complete_transfer_wrapped_ix(
|
|||
post_vaa_data,
|
||||
payload.clone(),
|
||||
Pubkey::new(&payload.to),
|
||||
if let Some(fee_r) = fee_recipient {
|
||||
Some(Pubkey::from_str(fee_r.as_str()).unwrap())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
CompleteWrappedData {},
|
||||
)
|
||||
.unwrap();
|
||||
|
|
|
@ -434,6 +434,7 @@ mod helpers {
|
|||
*message_acc,
|
||||
vaa,
|
||||
Pubkey::new(&payload.to[..]),
|
||||
None,
|
||||
Pubkey::new(&payload.token_address[..]),
|
||||
CompleteNativeData {},
|
||||
)
|
||||
|
@ -471,6 +472,7 @@ mod helpers {
|
|||
vaa,
|
||||
payload,
|
||||
to,
|
||||
None,
|
||||
CompleteWrappedData {},
|
||||
)
|
||||
.expect("Could not create Complete Wrapped instruction");
|
||||
|
|
Loading…
Reference in New Issue