Derive Wrapped Mint/Tokens
Change-Id: Ic530013e1932daef382cd89b9f14d1069c4006b0
This commit is contained in:
parent
108a4a2ff9
commit
0a669111dd
|
@ -2,6 +2,7 @@ use solitaire::*;
|
||||||
|
|
||||||
use solana_program::{
|
use solana_program::{
|
||||||
program::invoke_signed,
|
program::invoke_signed,
|
||||||
|
pubkey::Pubkey,
|
||||||
sysvar::{
|
sysvar::{
|
||||||
clock::Clock,
|
clock::Clock,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
|
@ -20,6 +21,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
error::Error::{
|
error::Error::{
|
||||||
InvalidFeeRecipient,
|
InvalidFeeRecipient,
|
||||||
|
InvalidGovernanceKey,
|
||||||
InvalidGovernanceWithdrawal,
|
InvalidGovernanceWithdrawal,
|
||||||
InvalidGuardianSetUpgrade,
|
InvalidGuardianSetUpgrade,
|
||||||
},
|
},
|
||||||
|
@ -30,8 +32,27 @@ use crate::{
|
||||||
GovernancePayloadUpgrade,
|
GovernancePayloadUpgrade,
|
||||||
},
|
},
|
||||||
vaa::ClaimableVAA,
|
vaa::ClaimableVAA,
|
||||||
|
DeserializePayload,
|
||||||
|
CHAIN_ID_SOLANA,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn verify_governance<'a, T>(vaa: &ClaimableVAA<'a, T>) -> Result<()>
|
||||||
|
where
|
||||||
|
T: DeserializePayload,
|
||||||
|
{
|
||||||
|
let expected_emitter = std::env!("EMITTER_ADDRESS");
|
||||||
|
let current_emitter = format!(
|
||||||
|
"{}",
|
||||||
|
Pubkey::new_from_array(vaa.message.meta().emitter_address)
|
||||||
|
);
|
||||||
|
// Fail if the emitter is not the known governance key, or the emitting chain is not Solana.
|
||||||
|
if expected_emitter != current_emitter || vaa.message.meta().emitter_chain != CHAIN_ID_SOLANA {
|
||||||
|
Err(InvalidGovernanceKey.into())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(FromAccounts)]
|
#[derive(FromAccounts)]
|
||||||
pub struct UpgradeContract<'b> {
|
pub struct UpgradeContract<'b> {
|
||||||
/// Payer for account creation (vaa-claim)
|
/// Payer for account creation (vaa-claim)
|
||||||
|
@ -76,6 +97,7 @@ pub fn upgrade_contract(
|
||||||
accs: &mut UpgradeContract,
|
accs: &mut UpgradeContract,
|
||||||
_data: UpgradeContractData,
|
_data: UpgradeContractData,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
verify_governance(&accs.vaa)?;
|
||||||
accs.vaa.verify(ctx.program_id)?;
|
accs.vaa.verify(ctx.program_id)?;
|
||||||
accs.vaa.claim(ctx, accs.payer.key)?;
|
accs.vaa.claim(ctx, accs.payer.key)?;
|
||||||
|
|
||||||
|
@ -135,6 +157,7 @@ pub fn upgrade_guardian_set(
|
||||||
return Err(InvalidGuardianSetUpgrade.into());
|
return Err(InvalidGuardianSetUpgrade.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verify_governance(&accs.vaa)?;
|
||||||
accs.vaa.verify(ctx.program_id)?;
|
accs.vaa.verify(ctx.program_id)?;
|
||||||
accs.guardian_set_old.verify_derivation(
|
accs.guardian_set_old.verify_derivation(
|
||||||
ctx.program_id,
|
ctx.program_id,
|
||||||
|
@ -196,6 +219,7 @@ impl<'b> InstructionContext<'b> for SetFees<'b> {
|
||||||
pub struct SetFeesData {}
|
pub struct SetFeesData {}
|
||||||
|
|
||||||
pub fn set_fees(ctx: &ExecutionContext, accs: &mut SetFees, _data: SetFeesData) -> Result<()> {
|
pub fn set_fees(ctx: &ExecutionContext, accs: &mut SetFees, _data: SetFeesData) -> Result<()> {
|
||||||
|
verify_governance(&accs.vaa)?;
|
||||||
accs.vaa.verify(ctx.program_id)?;
|
accs.vaa.verify(ctx.program_id)?;
|
||||||
accs.vaa.claim(ctx, accs.payer.key)?;
|
accs.vaa.claim(ctx, accs.payer.key)?;
|
||||||
accs.bridge.config.fee = accs.vaa.fee.as_u64();
|
accs.bridge.config.fee = accs.vaa.fee.as_u64();
|
||||||
|
@ -240,6 +264,7 @@ pub fn transfer_fees(
|
||||||
return Err(InvalidFeeRecipient.into());
|
return Err(InvalidFeeRecipient.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verify_governance(&accs.vaa)?;
|
||||||
accs.vaa.verify(ctx.program_id)?;
|
accs.vaa.verify(ctx.program_id)?;
|
||||||
|
|
||||||
if accs
|
if accs
|
||||||
|
|
|
@ -6,7 +6,6 @@ use crate::{
|
||||||
error::Error::{
|
error::Error::{
|
||||||
InvalidGovernanceAction,
|
InvalidGovernanceAction,
|
||||||
InvalidGovernanceChain,
|
InvalidGovernanceChain,
|
||||||
InvalidGovernanceKey,
|
|
||||||
InvalidGovernanceModule,
|
InvalidGovernanceModule,
|
||||||
VAAAlreadyExecuted,
|
VAAAlreadyExecuted,
|
||||||
},
|
},
|
||||||
|
@ -162,20 +161,6 @@ impl<'b, T: DeserializePayload> ClaimableVAA<'b, T> {
|
||||||
pub fn verify(&self, program_id: &Pubkey) -> Result<()> {
|
pub fn verify(&self, program_id: &Pubkey) -> Result<()> {
|
||||||
trace!("Seq: {}", self.message.meta().sequence);
|
trace!("Seq: {}", self.message.meta().sequence);
|
||||||
|
|
||||||
// Do the Posted Message verification
|
|
||||||
let (expected_emitter, current_emitter) = (
|
|
||||||
std::env!("EMITTER_ADDRESS"),
|
|
||||||
format!(
|
|
||||||
"{}",
|
|
||||||
Pubkey::new_from_array(self.message.meta().emitter_address)
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fail if the emitter is not the known governance key, or the emitting chain is not Solana.
|
|
||||||
if expected_emitter != current_emitter || self.message.meta().emitter_chain != CHAIN_ID_SOLANA {
|
|
||||||
return Err(InvalidGovernanceKey.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the claim account is derived correctly
|
// Verify that the claim account is derived correctly
|
||||||
self.claim.verify_derivation(
|
self.claim.verify_derivation(
|
||||||
program_id,
|
program_id,
|
||||||
|
|
|
@ -54,14 +54,17 @@ impl<'b, const State: AccountState> Seeded<&WrappedDerivationData> for WrappedMi
|
||||||
|
|
||||||
pub type WrappedTokenMeta<'b, const State: AccountState> = Data<'b, WrappedMeta, { State }>;
|
pub type WrappedTokenMeta<'b, const State: AccountState> = Data<'b, WrappedMeta, { State }>;
|
||||||
|
|
||||||
impl<'b, const State: AccountState> Seeded<&WrappedDerivationData>
|
pub struct WrappedMetaDerivationData {
|
||||||
|
pub mint_key: Pubkey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'b, const State: AccountState> Seeded<&WrappedMetaDerivationData>
|
||||||
for WrappedTokenMeta<'b, { State }>
|
for WrappedTokenMeta<'b, { State }>
|
||||||
{
|
{
|
||||||
fn seeds(data: &WrappedDerivationData) -> Vec<Vec<u8>> {
|
fn seeds(data: &WrappedMetaDerivationData) -> Vec<Vec<u8>> {
|
||||||
vec![
|
vec![
|
||||||
String::from("meta").as_bytes().to_vec(),
|
String::from("meta").as_bytes().to_vec(),
|
||||||
data.token_chain.to_be_bytes().to_vec(),
|
data.mint_key.to_bytes().to_vec(),
|
||||||
data.token_address.to_vec(),
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,14 +90,14 @@ pub fn complete_native(
|
||||||
accs.custody.verify_derivation(ctx.program_id, &derivation_data)?;
|
accs.custody.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||||
|
|
||||||
// Verify mints
|
// Verify mints
|
||||||
if accs.mint.info().key != accs.to.info().key {
|
if *accs.mint.info().key != accs.to.mint {
|
||||||
return Err(InvalidMint.into());
|
return Err(InvalidMint.into());
|
||||||
}
|
}
|
||||||
if accs.mint.info().key != accs.custody.info().key {
|
if *accs.mint.info().key != accs.custody.mint {
|
||||||
return Err(InvalidMint.into());
|
return Err(InvalidMint.into());
|
||||||
}
|
}
|
||||||
if &accs.custody.owner != accs.custody_signer.key {
|
if *accs.custody_signer.key != accs.custody.owner {
|
||||||
return Err(InvalidMint.into());
|
return Err(WrongAccountOwner.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify VAA
|
// Verify VAA
|
||||||
|
@ -109,6 +109,7 @@ pub fn complete_native(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent vaa double signing
|
// Prevent vaa double signing
|
||||||
|
accs.vaa.verify(ctx.program_id)?;
|
||||||
accs.vaa.claim(ctx, accs.payer.key)?;
|
accs.vaa.claim(ctx, accs.payer.key)?;
|
||||||
|
|
||||||
let mut amount = accs.vaa.amount.as_u64();
|
let mut amount = accs.vaa.amount.as_u64();
|
||||||
|
@ -189,10 +190,11 @@ pub fn complete_wrapped(
|
||||||
accs.mint.verify_derivation(ctx.program_id, &derivation_data)?;
|
accs.mint.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||||
|
|
||||||
// Verify mints
|
// Verify mints
|
||||||
if accs.mint.info().key != accs.to.info().key {
|
if *accs.mint.info().key != accs.to.mint {
|
||||||
return Err(InvalidMint.into());
|
return Err(InvalidMint.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accs.vaa.verify(ctx.program_id)?;
|
||||||
accs.vaa.claim(ctx, accs.payer.key)?;
|
accs.vaa.claim(ctx, accs.payer.key)?;
|
||||||
|
|
||||||
// Mint tokens
|
// Mint tokens
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::{
|
||||||
Endpoint,
|
Endpoint,
|
||||||
EndpointDerivationData,
|
EndpointDerivationData,
|
||||||
MintSigner,
|
MintSigner,
|
||||||
|
WrappedMetaDerivationData,
|
||||||
WrappedDerivationData,
|
WrappedDerivationData,
|
||||||
WrappedMint,
|
WrappedMint,
|
||||||
WrappedTokenMeta,
|
WrappedTokenMeta,
|
||||||
|
@ -71,6 +72,14 @@ impl<'a> From<&CreateWrapped<'a>> for WrappedDerivationData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&CreateWrapped<'a>> for WrappedMetaDerivationData {
|
||||||
|
fn from(accs: &CreateWrapped<'a>) -> Self {
|
||||||
|
WrappedMetaDerivationData {
|
||||||
|
mint_key: *accs.mint.info().key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'b> InstructionContext<'b> for CreateWrapped<'b> {
|
impl<'b> InstructionContext<'b> for CreateWrapped<'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,11 +93,14 @@ pub fn create_wrapped(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let derivation_data: WrappedDerivationData = (&*accs).into();
|
let derivation_data: WrappedDerivationData = (&*accs).into();
|
||||||
accs.mint.verify_derivation(ctx.program_id, &derivation_data)?;
|
accs.mint.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||||
accs.meta.verify_derivation(ctx.program_id, &derivation_data)?;
|
|
||||||
|
let meta_derivation_data: WrappedMetaDerivationData = (&*accs).into();
|
||||||
|
accs.meta.verify_derivation(ctx.program_id, &meta_derivation_data)?;
|
||||||
|
|
||||||
let derivation_data: EndpointDerivationData = (&*accs).into();
|
let derivation_data: EndpointDerivationData = (&*accs).into();
|
||||||
accs.chain_registration.verify_derivation(ctx.program_id, &derivation_data)?;
|
accs.chain_registration.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||||
|
|
||||||
|
accs.vaa.verify(ctx.program_id)?;
|
||||||
accs.vaa.claim(ctx, accs.payer.key)?;
|
accs.vaa.claim(ctx, accs.payer.key)?;
|
||||||
|
|
||||||
// Create mint account
|
// Create mint account
|
||||||
|
|
|
@ -40,7 +40,7 @@ use std::ops::{
|
||||||
};
|
};
|
||||||
|
|
||||||
// Confirm that a ClaimableVAA came from the correct chain, signed by the right emitter.
|
// Confirm that a ClaimableVAA came from the correct chain, signed by the right emitter.
|
||||||
fn verify_claim<'a, T>(vaa: &ClaimableVAA<'a, T>) -> Result<()>
|
fn verify_governance<'a, T>(vaa: &ClaimableVAA<'a, T>) -> Result<()>
|
||||||
where
|
where
|
||||||
T: DeserializePayload,
|
T: DeserializePayload,
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,6 @@ where
|
||||||
"{}",
|
"{}",
|
||||||
Pubkey::new_from_array(vaa.message.meta().emitter_address)
|
Pubkey::new_from_array(vaa.message.meta().emitter_address)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fail if the emitter is not the known governance key, or the emitting chain is not Solana.
|
// Fail if the emitter is not the known governance key, or the emitting chain is not Solana.
|
||||||
if expected_emitter != current_emitter || vaa.message.meta().emitter_chain != CHAIN_ID_SOLANA {
|
if expected_emitter != current_emitter || vaa.message.meta().emitter_chain != CHAIN_ID_SOLANA {
|
||||||
Err(InvalidGovernanceKey.into())
|
Err(InvalidGovernanceKey.into())
|
||||||
|
@ -99,7 +98,8 @@ pub fn upgrade_contract(
|
||||||
accs: &mut UpgradeContract,
|
accs: &mut UpgradeContract,
|
||||||
_data: UpgradeContractData,
|
_data: UpgradeContractData,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
verify_claim(&accs.vaa)?;
|
verify_governance(&accs.vaa);
|
||||||
|
accs.vaa.verify(&ctx.program_id)?;
|
||||||
|
|
||||||
accs.vaa.claim(ctx, accs.payer.key)?;
|
accs.vaa.claim(ctx, accs.payer.key)?;
|
||||||
|
|
||||||
|
@ -154,6 +154,8 @@ pub fn register_chain(
|
||||||
accs.endpoint.verify_derivation(ctx.program_id, &derivation_data)?;
|
accs.endpoint.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||||
|
|
||||||
// Claim VAA
|
// Claim VAA
|
||||||
|
verify_governance(&accs.vaa);
|
||||||
|
accs.vaa.verify(&ctx.program_id)?;
|
||||||
accs.vaa.claim(ctx, accs.payer.key)?;
|
accs.vaa.claim(ctx, accs.payer.key)?;
|
||||||
|
|
||||||
// Create endpoint
|
// Create endpoint
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
EmitterAccount,
|
EmitterAccount,
|
||||||
MintSigner,
|
MintSigner,
|
||||||
WrappedDerivationData,
|
WrappedDerivationData,
|
||||||
|
WrappedMetaDerivationData,
|
||||||
WrappedMint,
|
WrappedMint,
|
||||||
WrappedTokenMeta,
|
WrappedTokenMeta,
|
||||||
},
|
},
|
||||||
|
@ -123,10 +124,11 @@ pub fn transfer_native(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Verify that the custody account is derived correctly
|
// Verify that the custody account is derived correctly
|
||||||
let derivation_data: CustodyAccountDerivationData = (&*accs).into();
|
let derivation_data: CustodyAccountDerivationData = (&*accs).into();
|
||||||
accs.custody.verify_derivation(ctx.program_id, &derivation_data)?;
|
accs.custody
|
||||||
|
.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||||
|
|
||||||
// Verify mints
|
// Verify mints
|
||||||
if accs.mint.info().key != accs.from.info().key {
|
if accs.from.mint != *accs.mint.info().key {
|
||||||
return Err(TokenBridgeError::InvalidMint.into());
|
return Err(TokenBridgeError::InvalidMint.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +245,14 @@ impl<'a> From<&TransferWrapped<'a>> for WrappedDerivationData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&TransferWrapped<'a>> for WrappedMetaDerivationData {
|
||||||
|
fn from(accs: &TransferWrapped<'a>) -> Self {
|
||||||
|
WrappedMetaDerivationData {
|
||||||
|
mint_key: *accs.mint.info().key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'b> InstructionContext<'b> for TransferWrapped<'b> {
|
impl<'b> InstructionContext<'b> for TransferWrapped<'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,8 +281,11 @@ pub fn transfer_wrapped(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that meta is correct
|
// Verify that meta is correct
|
||||||
accs.wrapped_meta
|
let derivation_data: WrappedMetaDerivationData = (&*accs).into();
|
||||||
.verify_derivation(ctx.program_id, &(&*accs).into())?;
|
accs.wrapped_meta.verify_derivation(
|
||||||
|
ctx.program_id,
|
||||||
|
&derivation_data,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Burn tokens
|
// Burn tokens
|
||||||
let burn_ix = spl_token::instruction::burn(
|
let burn_ix = spl_token::instruction::burn(
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
EndpointDerivationData,
|
EndpointDerivationData,
|
||||||
MintSigner,
|
MintSigner,
|
||||||
WrappedDerivationData,
|
WrappedDerivationData,
|
||||||
|
WrappedMetaDerivationData,
|
||||||
WrappedMint,
|
WrappedMint,
|
||||||
WrappedTokenMeta,
|
WrappedTokenMeta,
|
||||||
},
|
},
|
||||||
|
@ -215,9 +216,8 @@ pub fn create_wrapped(
|
||||||
&program_id,
|
&program_id,
|
||||||
);
|
);
|
||||||
let mint_meta_key = WrappedTokenMeta::<'_, { AccountState::Uninitialized }>::key(
|
let mint_meta_key = WrappedTokenMeta::<'_, { AccountState::Uninitialized }>::key(
|
||||||
&WrappedDerivationData {
|
&WrappedMetaDerivationData {
|
||||||
token_chain: payload.token_chain,
|
mint_key,
|
||||||
token_address: payload.token_address,
|
|
||||||
},
|
},
|
||||||
&program_id,
|
&program_id,
|
||||||
);
|
);
|
||||||
|
@ -395,9 +395,8 @@ pub fn transfer_wrapped(
|
||||||
&program_id,
|
&program_id,
|
||||||
);
|
);
|
||||||
let wrapped_meta_key = WrappedTokenMeta::<'_, { AccountState::Uninitialized }>::key(
|
let wrapped_meta_key = WrappedTokenMeta::<'_, { AccountState::Uninitialized }>::key(
|
||||||
&WrappedDerivationData {
|
&WrappedMetaDerivationData {
|
||||||
token_chain,
|
mint_key: wrapped_mint_key,
|
||||||
token_address,
|
|
||||||
},
|
},
|
||||||
&program_id,
|
&program_id,
|
||||||
);
|
);
|
||||||
|
|
|
@ -381,7 +381,7 @@ mod helpers {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn complete_transfer_native(
|
pub fn complete_native(
|
||||||
client: &RpcClient,
|
client: &RpcClient,
|
||||||
program: &Pubkey,
|
program: &Pubkey,
|
||||||
bridge: &Pubkey,
|
bridge: &Pubkey,
|
||||||
|
|
|
@ -293,7 +293,7 @@ fn test_transfer_native(context: &mut Context) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_transfer_wrapped(context: &mut Context, token_account: Pubkey) -> () {
|
fn test_transfer_wrapped(context: &mut Context, token_account: Pubkey) -> () {
|
||||||
println!("Transfer Wrapped");
|
println!("TransferWrapped");
|
||||||
use token_bridge::{
|
use token_bridge::{
|
||||||
accounts::ConfigAccount,
|
accounts::ConfigAccount,
|
||||||
types::Config,
|
types::Config,
|
||||||
|
@ -401,7 +401,7 @@ fn test_transfer_native_in(context: &mut Context) -> () {
|
||||||
let (vaa, _, _) = common::generate_vaa([0u8; 32], 2, message, nonce, 1);
|
let (vaa, _, _) = common::generate_vaa([0u8; 32], 2, message, nonce, 1);
|
||||||
let message_key = common::post_vaa(client, bridge, payer, vaa.clone()).unwrap();
|
let message_key = common::post_vaa(client, bridge, payer, vaa.clone()).unwrap();
|
||||||
|
|
||||||
common::complete_transfer_native(
|
common::complete_native(
|
||||||
client,
|
client,
|
||||||
token_bridge,
|
token_bridge,
|
||||||
bridge,
|
bridge,
|
||||||
|
@ -414,7 +414,7 @@ fn test_transfer_native_in(context: &mut Context) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_transfer_wrapped_in(context: &mut Context, to: Pubkey) -> () {
|
fn test_transfer_wrapped_in(context: &mut Context, to: Pubkey) -> () {
|
||||||
println!("TransferWrapped");
|
println!("TransferWrappedIn");
|
||||||
use token_bridge::{
|
use token_bridge::{
|
||||||
accounts::ConfigAccount,
|
accounts::ConfigAccount,
|
||||||
types::Config,
|
types::Config,
|
||||||
|
|
Loading…
Reference in New Issue