Преглед на файлове

solana: Update last_lamports after transfer_fees

Csongor Kiss преди 3 години
родител
ревизия
be38cf5d7e
променени са 3 файла, в които са добавени 87 реда и са изтрити 6 реда
  1. 7 5
      solana/bridge/program/src/api/governance.rs
  2. 1 1
      solana/bridge/program/src/instructions.rs
  3. 79 0
      solana/bridge/program/tests/integration.rs

+ 7 - 5
solana/bridge/program/src/api/governance.rs

@@ -224,7 +224,7 @@ pub struct TransferFees<'b> {
     pub payer: Mut<Signer<Info<'b>>>,
 
     /// Bridge config
-    pub bridge: Bridge<'b, { AccountState::Initialized }>,
+    pub bridge: Mut<Bridge<'b, { AccountState::Initialized }>>,
 
     /// Governance VAA
     pub vaa: ClaimableVAA<'b, GovernancePayloadTransferFees>,
@@ -255,15 +255,17 @@ pub fn transfer_fees(
     verify_governance(&accs.vaa)?;
     accs.vaa.verify(ctx.program_id)?;
 
-    if accs
+    let new_balance = accs
         .fee_collector
         .lamports()
-        .saturating_sub(accs.vaa.amount.as_u64())
-        < accs.rent.minimum_balance(accs.fee_collector.data_len())
-    {
+        .saturating_sub(accs.vaa.amount.as_u64());
+
+    if new_balance < accs.rent.minimum_balance(accs.fee_collector.data_len()) {
         return Err(InvalidGovernanceWithdrawal.into());
     }
 
+    accs.bridge.last_lamports = new_balance;
+
     accs.vaa.claim(ctx, accs.payer.key)?;
 
     // Transfer fees

+ 1 - 1
solana/bridge/program/src/instructions.rs

@@ -405,7 +405,7 @@ pub fn transfer_fees(
 
         accounts: vec![
             AccountMeta::new(payer, true),
-            AccountMeta::new_readonly(bridge, false),
+            AccountMeta::new(bridge, false),
             AccountMeta::new_readonly(message, false),
             AccountMeta::new(claim, false),
             AccountMeta::new(fee_collector, false),

+ 79 - 0
solana/bridge/program/tests/integration.rs

@@ -462,6 +462,85 @@ async fn test_bridge_messages_unreliable_do_not_override_reliable() {
     .is_err());
 }
 
+#[tokio::test]
+async fn bridge_works_after_transfer_fees() {
+    // This test aims to ensure that the bridge remains operational after the
+    // fees have been transferred out.
+    // NOTE: the bridge is initialised to take a minimum of 500 in fees.
+    let (ref mut context, ref mut client, ref payer, ref program) = initialize().await;
+    let fee_collector = FeeCollector::key(None, program);
+    let initial_balance = common::get_account_balance(client, fee_collector).await;
+
+    // First, post a message that transfer out 500 lamports.
+    // Since posting the message itself costs 500 lamports, this should result
+    // in the fee collector's account being reset to the initial amount (which
+    // is the rent exemption amount)
+    {
+        let emitter = Keypair::from_bytes(&GOVERNANCE_KEY).unwrap();
+        let sequence = context.seq.next(emitter.pubkey().to_bytes());
+
+        let nonce = rand::thread_rng().gen();
+        let message = GovernancePayloadTransferFees {
+            amount: 500u128.into(),
+            to: payer.pubkey().to_bytes(),
+        }
+        .try_to_vec()
+        .unwrap();
+
+        let message_key = common::post_message(
+            client,
+            program,
+            payer,
+            &emitter,
+            None,
+            nonce,
+            message.clone(),
+            500,
+        )
+        .await
+        .unwrap();
+
+        common::transfer_fees(
+            client,
+            program,
+            payer,
+            message_key,
+            emitter.pubkey(),
+            payer.pubkey(),
+            sequence,
+        )
+        .await
+        .unwrap();
+
+        common::sync(client, payer).await;
+    }
+
+    // Ensure that the account has the same amount of money as we started with
+    let account_balance = common::get_account_balance(client, fee_collector).await;
+    assert_eq!(account_balance, initial_balance);
+
+    // Next, make sure that we can still post a message.
+    {
+        let emitter = Keypair::new();
+
+        let nonce = rand::thread_rng().gen();
+        let message: [u8; 32] = rand::thread_rng().gen();
+
+        common::post_message(
+            client,
+            program,
+            payer,
+            &emitter,
+            None,
+            nonce,
+            message.to_vec(),
+            500,
+        )
+        .await
+        .unwrap();
+    }
+}
+
 // Make sure that solitaire can claim accounts that already hold lamports so the protocol can't be
 // DoSd by someone funding derived accounts making CreateAccount fail.
 #[tokio::test]