Skip to content

Commit

Permalink
solana-ibc: make fees configurable by the fee collector (#332)
Browse files Browse the repository at this point in the history
Make fees configurable by storing them in the private storage account
instead of hard-coding them in the source code.

Co-authored-by: Michal Nazarewicz <mina86@mina86.com>
  • Loading branch information
dhruvja and mina86 authored May 24, 2024
1 parent ab538c0 commit 8663c24
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 22 deletions.
32 changes: 27 additions & 5 deletions solana/solana-ibc/programs/solana-ibc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ pub const METADATA: &[u8] = b"metadata";

pub const FEE_SEED: &[u8] = b"fee";

pub const FEE_AMOUNT_IN_LAMPORTS: u64 =
solana_program::native_token::LAMPORTS_PER_SOL / 100;
pub const REFUND_FEE_AMOUNT_IN_LAMPORTS: u64 =
solana_program::native_token::LAMPORTS_PER_SOL / 100;
pub const MINIMUM_FEE_ACCOUNT_BALANCE: u64 =
solana_program::native_token::LAMPORTS_PER_SOL;

Expand Down Expand Up @@ -210,6 +206,20 @@ pub mod solana_ibc {
chain.set_stake((validator).into(), amount)
}

pub fn set_fee_amount<'a, 'info>(
ctx: Context<'a, 'a, 'a, 'info, SetFeeAmount<'info>>,
new_amount: u64,
) -> Result<()> {
let private_storage = &mut ctx.accounts.storage;

let previous_fees = private_storage.fee_in_lamports;
private_storage.fee_in_lamports = new_amount;

msg!("Fee updated to {} from {}", new_amount, previous_fees);

Ok(())
}

/// Sets up new fee collector proposal which wont be changed until the new fee collector
/// calls `accept_fee_collector_change`. If the method is called for the first time, the fee
/// collector would just be set without needing for any approval.
Expand Down Expand Up @@ -511,6 +521,8 @@ pub mod solana_ibc {
return Err(error!(error::Error::InvalidSendTransferParams));
}

let fee_amount = ctx.accounts.storage.fee_in_lamports;

let mut store = storage::from_ctx!(ctx, with accounts);
let mut token_ctx = store.clone();

Expand All @@ -534,7 +546,7 @@ pub mod solana_ibc {
&solana_program::system_instruction::transfer(
&sender.key(),
&fee_collector.key(),
FEE_AMOUNT_IN_LAMPORTS,
fee_amount,
),
&[sender.clone(), fee_collector.clone(), system_program.clone()],
)?;
Expand Down Expand Up @@ -673,6 +685,16 @@ pub struct ChainWithVerifier<'info> {
system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct SetFeeAmount<'info> {
#[account(mut)]
fee_collector: Signer<'info>,

/// The account holding private IBC storage.
#[account(mut, seeds = [SOLANA_IBC_STORAGE_SEED], bump, has_one = fee_collector)]
storage: Account<'info, storage::PrivateStorage>,
}

#[derive(Accounts)]
pub struct SetupFeeCollector<'info> {
#[account(mut)]
Expand Down
3 changes: 3 additions & 0 deletions solana/solana-ibc/programs/solana-ibc/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ pub struct PrivateStorage {
pub new_fee_collector_proposal: Option<Pubkey>,

pub assets: map::Map<CryptoHash, Asset>,

// Fee to be charged for each transfer
pub fee_in_lamports: u64,
}

#[derive(Clone, Debug, borsh::BorshSerialize, borsh::BorshDeserialize)]
Expand Down
38 changes: 25 additions & 13 deletions solana/solana-ibc/programs/solana-ibc/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub const WRITE_ACCOUNT_SEED: &[u8] = b"write";
pub const TOKEN_NAME: &str = "RETARDIO";
pub const TOKEN_SYMBOL: &str = "RTRD";
pub const TOKEN_URI: &str = "https://github.com";
pub const FEE: u64 = 10_000_000;
// const BASE_DENOM: &str = "PICA";

const TRANSFER_AMOUNT: u64 = 1_000_000_000_000_000;
Expand Down Expand Up @@ -123,7 +124,6 @@ fn anchor_test_deliver() -> Result<()> {
let base_denom = native_token_mint_key.to_string();
let hashed_denom = CryptoHash::digest(base_denom.as_bytes());


let port_id = ibc::PortId::transfer();
let channel_id_on_a = ibc::ChannelId::new(0);
let channel_id_on_b = ibc::ChannelId::new(1);
Expand Down Expand Up @@ -392,13 +392,34 @@ fn anchor_test_deliver() -> Result<()> {
})?;
println!(" Signature: {sig}");

/*
Set up the fees
*/

println!("\nSetting up Fees");
let sig = program
.request()
.instruction(ComputeBudgetInstruction::set_compute_unit_limit(
1_000_000u32,
))
.accounts(accounts::SetFeeAmount { fee_collector, storage })
.args(instruction::SetFeeAmount { new_amount: FEE })
.payer(fee_collector_keypair.clone())
.signer(&*fee_collector_keypair)
.send_with_spinner_and_config(RpcSendTransactionConfig {
skip_preflight: true,
..RpcSendTransactionConfig::default()
})?;
println!(" Signature: {sig}");

// Make sure all the accounts needed for transfer are ready ( mint, escrow etc.)
// Pass the instruction for transfer

/*
* Setup deliver escrow.
*/

println!("\nCreating Token mint");
let token_metadata_pda = Pubkey::find_program_address(
&[
"metadata".as_bytes(),
Expand Down Expand Up @@ -564,10 +585,7 @@ fn anchor_test_deliver() -> Result<()> {
TRANSFER_AMOUNT
);

assert_eq!(
fee_account_balance_after - min_balance_for_rent_exemption,
crate::FEE_AMOUNT_IN_LAMPORTS
);
assert_eq!(fee_account_balance_after - min_balance_for_rent_exemption, FEE);

/*
* On Destination chain
Expand Down Expand Up @@ -721,15 +739,9 @@ fn anchor_test_deliver() -> Result<()> {
(10_u64.pow((ORIGINAL_DECIMALS - EFFECTIVE_DECIMALS).into()))
);

assert_eq!(
fee_account_balance_after - fee_account_balance_before,
crate::FEE_AMOUNT_IN_LAMPORTS
);
assert_eq!(fee_account_balance_after - fee_account_balance_before, FEE);

assert_eq!(
fee_account_balance_after - fee_account_balance_before,
crate::FEE_AMOUNT_IN_LAMPORTS
);
assert_eq!(fee_account_balance_after - fee_account_balance_before, FEE);

/*
* On Source chain
Expand Down
10 changes: 6 additions & 4 deletions solana/solana-ibc/programs/solana-ibc/src/transfer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,13 @@ impl ibc::Module for IbcStorage<'_, '_> {
if !success {
let store = self.borrow();
let accounts = &store.accounts;
let private = &store.private;
let receiver = accounts.receiver.clone().unwrap();
let fee_collector = accounts.fee_collector.clone().unwrap();
**fee_collector.try_borrow_mut_lamports().unwrap() -=
crate::REFUND_FEE_AMOUNT_IN_LAMPORTS;
private.fee_in_lamports;
**receiver.try_borrow_mut_lamports().unwrap() +=
crate::REFUND_FEE_AMOUNT_IN_LAMPORTS;
private.fee_in_lamports;
}

(
Expand All @@ -284,12 +285,13 @@ impl ibc::Module for IbcStorage<'_, '_> {
if result.1.is_ok() {
let store = self.borrow();
let accounts = &store.accounts;
let private = &store.private;
let receiver = accounts.receiver.clone().unwrap();
let fee_collector = accounts.fee_collector.clone().unwrap();
**fee_collector.try_borrow_mut_lamports().unwrap() -=
crate::REFUND_FEE_AMOUNT_IN_LAMPORTS;
private.fee_in_lamports;
**receiver.try_borrow_mut_lamports().unwrap() +=
crate::REFUND_FEE_AMOUNT_IN_LAMPORTS;
private.fee_in_lamports;
}
(
result.0,
Expand Down

0 comments on commit 8663c24

Please sign in to comment.