Derive Wrapped Mint/Tokens

Change-Id: Ic530013e1932daef382cd89b9f14d1069c4006b0
This commit is contained in:
Reisen 2021-07-29 18:21:53 +00:00 committed by David Paryente
parent 108a4a2ff9
commit 0a669111dd
10 changed files with 83 additions and 42 deletions

View File

@ -2,6 +2,7 @@ use solitaire::*;
use solana_program::{
program::invoke_signed,
pubkey::Pubkey,
sysvar::{
clock::Clock,
rent::Rent,
@ -20,6 +21,7 @@ use crate::{
},
error::Error::{
InvalidFeeRecipient,
InvalidGovernanceKey,
InvalidGovernanceWithdrawal,
InvalidGuardianSetUpgrade,
},
@ -30,8 +32,27 @@ use crate::{
GovernancePayloadUpgrade,
},
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)]
pub struct UpgradeContract<'b> {
/// Payer for account creation (vaa-claim)
@ -76,6 +97,7 @@ pub fn upgrade_contract(
accs: &mut UpgradeContract,
_data: UpgradeContractData,
) -> Result<()> {
verify_governance(&accs.vaa)?;
accs.vaa.verify(ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?;
@ -135,6 +157,7 @@ pub fn upgrade_guardian_set(
return Err(InvalidGuardianSetUpgrade.into());
}
verify_governance(&accs.vaa)?;
accs.vaa.verify(ctx.program_id)?;
accs.guardian_set_old.verify_derivation(
ctx.program_id,
@ -196,6 +219,7 @@ impl<'b> InstructionContext<'b> for SetFees<'b> {
pub struct SetFeesData {}
pub fn set_fees(ctx: &ExecutionContext, accs: &mut SetFees, _data: SetFeesData) -> Result<()> {
verify_governance(&accs.vaa)?;
accs.vaa.verify(ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?;
accs.bridge.config.fee = accs.vaa.fee.as_u64();
@ -240,6 +264,7 @@ pub fn transfer_fees(
return Err(InvalidFeeRecipient.into());
}
verify_governance(&accs.vaa)?;
accs.vaa.verify(ctx.program_id)?;
if accs

View File

@ -6,7 +6,6 @@ use crate::{
error::Error::{
InvalidGovernanceAction,
InvalidGovernanceChain,
InvalidGovernanceKey,
InvalidGovernanceModule,
VAAAlreadyExecuted,
},
@ -162,20 +161,6 @@ impl<'b, T: DeserializePayload> ClaimableVAA<'b, T> {
pub fn verify(&self, program_id: &Pubkey) -> Result<()> {
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
self.claim.verify_derivation(
program_id,

View File

@ -54,14 +54,17 @@ impl<'b, const State: AccountState> Seeded<&WrappedDerivationData> for WrappedMi
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 }>
{
fn seeds(data: &WrappedDerivationData) -> Vec<Vec<u8>> {
fn seeds(data: &WrappedMetaDerivationData) -> Vec<Vec<u8>> {
vec![
String::from("meta").as_bytes().to_vec(),
data.token_chain.to_be_bytes().to_vec(),
data.token_address.to_vec(),
data.mint_key.to_bytes().to_vec(),
]
}
}

View File

@ -90,14 +90,14 @@ pub fn complete_native(
accs.custody.verify_derivation(ctx.program_id, &derivation_data)?;
// Verify mints
if accs.mint.info().key != accs.to.info().key {
if *accs.mint.info().key != accs.to.mint {
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());
}
if &accs.custody.owner != accs.custody_signer.key {
return Err(InvalidMint.into());
if *accs.custody_signer.key != accs.custody.owner {
return Err(WrongAccountOwner.into());
}
// Verify VAA
@ -109,6 +109,7 @@ pub fn complete_native(
}
// Prevent vaa double signing
accs.vaa.verify(ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?;
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)?;
// Verify mints
if accs.mint.info().key != accs.to.info().key {
if *accs.mint.info().key != accs.to.mint {
return Err(InvalidMint.into());
}
accs.vaa.verify(ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?;
// Mint tokens

View File

@ -4,6 +4,7 @@ use crate::{
Endpoint,
EndpointDerivationData,
MintSigner,
WrappedMetaDerivationData,
WrappedDerivationData,
WrappedMint,
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> {
}
@ -84,11 +93,14 @@ pub fn create_wrapped(
) -> Result<()> {
let derivation_data: WrappedDerivationData = (&*accs).into();
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();
accs.chain_registration.verify_derivation(ctx.program_id, &derivation_data)?;
accs.vaa.verify(ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?;
// Create mint account

View File

@ -40,7 +40,7 @@ use std::ops::{
};
// 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
T: DeserializePayload,
{
@ -49,7 +49,6 @@ where
"{}",
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())
@ -99,7 +98,8 @@ pub fn upgrade_contract(
accs: &mut UpgradeContract,
_data: UpgradeContractData,
) -> Result<()> {
verify_claim(&accs.vaa)?;
verify_governance(&accs.vaa);
accs.vaa.verify(&ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?;
@ -154,6 +154,8 @@ pub fn register_chain(
accs.endpoint.verify_derivation(ctx.program_id, &derivation_data)?;
// Claim VAA
verify_governance(&accs.vaa);
accs.vaa.verify(&ctx.program_id)?;
accs.vaa.claim(ctx, accs.payer.key)?;
// Create endpoint

View File

@ -8,6 +8,7 @@ use crate::{
EmitterAccount,
MintSigner,
WrappedDerivationData,
WrappedMetaDerivationData,
WrappedMint,
WrappedTokenMeta,
},
@ -123,10 +124,11 @@ pub fn transfer_native(
) -> Result<()> {
// Verify that the custody account is derived correctly
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
if accs.mint.info().key != accs.from.info().key {
if accs.from.mint != *accs.mint.info().key {
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> {
}
@ -271,8 +281,11 @@ pub fn transfer_wrapped(
}
// Verify that meta is correct
accs.wrapped_meta
.verify_derivation(ctx.program_id, &(&*accs).into())?;
let derivation_data: WrappedMetaDerivationData = (&*accs).into();
accs.wrapped_meta.verify_derivation(
ctx.program_id,
&derivation_data,
)?;
// Burn tokens
let burn_ix = spl_token::instruction::burn(

View File

@ -10,6 +10,7 @@ use crate::{
EndpointDerivationData,
MintSigner,
WrappedDerivationData,
WrappedMetaDerivationData,
WrappedMint,
WrappedTokenMeta,
},
@ -215,9 +216,8 @@ pub fn create_wrapped(
&program_id,
);
let mint_meta_key = WrappedTokenMeta::<'_, { AccountState::Uninitialized }>::key(
&WrappedDerivationData {
token_chain: payload.token_chain,
token_address: payload.token_address,
&WrappedMetaDerivationData {
mint_key,
},
&program_id,
);
@ -395,9 +395,8 @@ pub fn transfer_wrapped(
&program_id,
);
let wrapped_meta_key = WrappedTokenMeta::<'_, { AccountState::Uninitialized }>::key(
&WrappedDerivationData {
token_chain,
token_address,
&WrappedMetaDerivationData {
mint_key: wrapped_mint_key,
},
&program_id,
);

View File

@ -381,7 +381,7 @@ mod helpers {
)
}
pub fn complete_transfer_native(
pub fn complete_native(
client: &RpcClient,
program: &Pubkey,
bridge: &Pubkey,

View File

@ -293,7 +293,7 @@ fn test_transfer_native(context: &mut Context) -> () {
}
fn test_transfer_wrapped(context: &mut Context, token_account: Pubkey) -> () {
println!("Transfer Wrapped");
println!("TransferWrapped");
use token_bridge::{
accounts::ConfigAccount,
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 message_key = common::post_vaa(client, bridge, payer, vaa.clone()).unwrap();
common::complete_transfer_native(
common::complete_native(
client,
token_bridge,
bridge,
@ -414,7 +414,7 @@ fn test_transfer_native_in(context: &mut Context) -> () {
}
fn test_transfer_wrapped_in(context: &mut Context, to: Pubkey) -> () {
println!("TransferWrapped");
println!("TransferWrappedIn");
use token_bridge::{
accounts::ConfigAccount,
types::Config,