Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions dlp-api/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@ use pinocchio::Address;

use crate::compat::{pubkey, Pubkey};

/// The delegation session fees (extracted in percentage from the delegation PDAs rent on closure).
pub const RENT_FEES_PERCENTAGE: u8 = 10;

Comment on lines -5 to -7

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed because it was unused.

/// The fees extracted from the validator earnings (extracted in percentage from the validator fees claims).
pub const PROTOCOL_FEES_PERCENTAGE: u8 = 10;

/// Fixed fee per commit (charged for each commit after the first).
pub const COMMIT_FEE_LAMPORTS: u64 = 100_000;
/// Fixed fee per commit after the first.
pub const COMMIT_FEE_LAMPORTS: u64 = 1_000_000;

/// Fixed fee per delegation session (0.0003 SOL).
pub const SESSION_FEE_LAMPORTS: u64 = 300_000;
/// Fixed fee per delegation session.
pub const SESSION_FEE_LAMPORTS: u64 = 3_000_000;

/// Default and minimum timeout for requested undelegation.
/// Assuming 1 slot is roughly 400ms, then 9000 slots = 60min.
Expand Down
6 changes: 3 additions & 3 deletions src/processor/fast/commit_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
args::CommitStateArgs,
error::DlpError,
merge_diff_copy, pda,
processor::fast::utils::pda::create_pda,
processor::fast::utils::pda::{create_pda, AccountSpace},
requires::{
require_initialized_delegation_metadata,
require_initialized_delegation_record,
Expand Down Expand Up @@ -283,7 +283,7 @@ pub(crate) fn process_commit_state_internal(
create_pda(
args.commit_state_account,
&crate::fast::ID,
args.commit_state_bytes.data_len(),
AccountSpace::CurrentRent(args.commit_state_bytes.data_len()),
&[Signer::from(&seeds!(
pda::COMMIT_STATE_TAG,
args.delegated_account.address().as_ref(),
Expand All @@ -296,7 +296,7 @@ pub(crate) fn process_commit_state_internal(
create_pda(
args.commit_record_account,
&crate::fast::ID,
CommitRecord::size_with_discriminator(),
AccountSpace::CurrentRent(CommitRecord::size_with_discriminator()),
&[Signer::from(&seeds!(
pda::COMMIT_RECORD_TAG,
args.delegated_account.address().as_ref(),
Expand Down
9 changes: 6 additions & 3 deletions src/processor/fast/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use crate::{
error::DlpError,
pda,
processor::{
fast::{to_pinocchio_program_error, utils::pda::create_pda},
fast::{
to_pinocchio_program_error,
utils::pda::{create_pda, AccountSpace},
},
utils::curve::is_on_curve_fast,
},
requires::{
Expand Down Expand Up @@ -215,7 +218,7 @@ fn process_delegate_inner(
create_pda(
delegation_record_account,
&crate::fast::ID,
DelegationRecord::size_with_discriminator(),
AccountSpace::LegacyRent(DelegationRecord::size_with_discriminator()),
&[Signer::from(&[
Seed::from(pda::DELEGATION_RECORD_TAG),
Seed::from(delegated_account.address().as_ref()),
Expand Down Expand Up @@ -250,7 +253,7 @@ fn process_delegate_inner(
create_pda(
delegation_metadata_account,
&crate::fast::ID,
delegation_metadata.serialized_size(),
AccountSpace::LegacyRent(delegation_metadata.serialized_size()),
&[Signer::from(&[
Seed::from(pda::DELEGATION_METADATA_TAG),
Seed::from(delegated_account.address().as_ref()),
Expand Down
11 changes: 8 additions & 3 deletions src/processor/fast/delegate_with_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use crate::{
error::DlpError,
pda,
processor::{
fast::{to_pinocchio_program_error, utils::pda::create_pda},
fast::{
to_pinocchio_program_error,
utils::pda::{create_pda, AccountSpace},
},
utils::curve::is_on_curve_fast,
},
require_n_accounts_with_optionals,
Expand Down Expand Up @@ -217,7 +220,9 @@ pub fn process_delegate_with_actions(
create_pda(
delegation_record_account,
&crate::fast::ID,
DelegationRecord::size_with_discriminator() + action_data.len(),
AccountSpace::LegacyRent(
DelegationRecord::size_with_discriminator() + action_data.len(),
),
&[Signer::from(&[
Seed::from(pda::DELEGATION_RECORD_TAG),
Seed::from(delegated_account.address().as_ref()),
Expand Down Expand Up @@ -262,7 +267,7 @@ pub fn process_delegate_with_actions(
create_pda(
delegation_metadata_account,
&crate::fast::ID,
delegation_metadata.serialized_size(),
AccountSpace::LegacyRent(delegation_metadata.serialized_size()),
&[Signer::from(&[
Seed::from(pda::DELEGATION_METADATA_TAG),
Seed::from(delegated_account.address().as_ref()),
Expand Down
9 changes: 7 additions & 2 deletions src/processor/fast/request_undelegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use super::to_pinocchio_program_error;
use crate::{
error::DlpError,
pda,
processor::{fast::utils::pda::create_pda, utils::curve::is_on_curve_fast},
processor::{
fast::utils::pda::{create_pda, AccountSpace},
utils::curve::is_on_curve_fast,
},
require, require_eq_keys, require_n_accounts,
requires::{
is_uninitialized_account, require_initialized_delegation_metadata,
Expand Down Expand Up @@ -125,7 +128,9 @@ pub fn process_request_undelegation(
create_pda(
undelegation_request_account,
&crate::fast::ID,
UndelegationRequest::size_with_discriminator(),
AccountSpace::CurrentRent(
UndelegationRequest::size_with_discriminator(),
),
&[Signer::from(&seeds!(
pda::UNDELEGATION_REQUEST_TAG,
delegated_account.address().as_ref(),
Expand Down
6 changes: 4 additions & 2 deletions src/processor/fast/undelegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use crate::{
},
error::DlpError,
pda,
processor::fast::utils::pda::{close_pda, close_pda_with_fees, create_pda},
processor::fast::utils::pda::{
close_pda, close_pda_with_fees, create_pda, AccountSpace,
},
require_n_accounts_with_optionals,
requires::{
require_initialized_delegation_metadata,
Expand Down Expand Up @@ -256,7 +258,7 @@ pub fn process_undelegate(
create_pda(
undelegate_buffer_account,
&crate::fast::ID,
delegated_account.data_len(),
AccountSpace::CurrentRent(delegated_account.data_len()),
&[Signer::from(&seeds!(
pda::UNDELEGATE_BUFFER_TAG,
delegated_account.address().as_ref(),
Expand Down
4 changes: 2 additions & 2 deletions src/processor/fast/undelegate_confined_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{process_undelegation_with_cpi, to_pinocchio_program_error};
use crate::{
error::DlpError,
pda,
processor::fast::utils::pda::{close_pda, create_pda},
processor::fast::utils::pda::{close_pda, create_pda, AccountSpace},
require_eq_keys,
requires::{
require_authorization, require_initialized_delegation_metadata,
Expand Down Expand Up @@ -116,7 +116,7 @@ pub fn process_undelegate_confined_account(
create_pda(
undelegate_buffer_account,
&crate::fast::ID,
delegated_account.data_len(),
AccountSpace::CurrentRent(delegated_account.data_len()),
&[Signer::from(&seeds!(
pda::UNDELEGATE_BUFFER_TAG,
delegated_account.address().as_ref(),
Expand Down
89 changes: 81 additions & 8 deletions src/processor/fast/utils/pda.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,88 @@
use pinocchio::{
cpi::Signer,
error::ProgramError,
sysvars::{rent::Rent, Sysvar},
AccountView, Address, ProgramResult,
};
use pinocchio_system::instructions as system;

use crate::consts::PROTOCOL_FEES_PERCENTAGE;
use crate::{consts::PROTOCOL_FEES_PERCENTAGE, error::DlpError};

// Legacy rent math follows SIMD-0194, which defines the 6,960
// lamports-per-byte value used by the simplified rent-exemption formula.
//
// ref:
// https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0194-deprecate-rent-exemption-threshold.md
const LEGACY_RENT_EXEMPT_LAMPORTS_PER_BYTE: u64 = 6960;
const LEGACY_RENT_ACCOUNT_STORAGE_OVERHEAD: u64 = 128;

// AccountSpace represents the account allocation size.
// Its variant lets the caller choose how rent funding should be computed for that size.
pub(crate) enum AccountSpace {
CurrentRent(usize),
LegacyRent(usize),
}

impl AccountSpace {
fn space(&self) -> usize {
match self {
Self::CurrentRent(space) | Self::LegacyRent(space) => *space,
}
}

fn minimum_balance(&self) -> Result<u64, ProgramError> {
let current_rent = Rent::get()?.try_minimum_balance(self.space())?;
match self {
Self::CurrentRent(_) => Ok(current_rent),
// Legacy rent is a fee-budget floor, not a substitute for current
// rent exemption. Keep live rent as the lower bound if it ever
// exceeds the legacy formula.
Self::LegacyRent(_) => {
Ok(current_rent.max(legacy_rent(self.space())?))
}
}
}
}

// ref:
// https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0194-deprecate-rent-exemption-threshold.md
fn legacy_rent(space: usize) -> Result<u64, ProgramError> {
let space = u64::try_from(space).map_err(|_| DlpError::Overflow)?;
space
.checked_add(LEGACY_RENT_ACCOUNT_STORAGE_OVERHEAD)
.and_then(|bytes| {
bytes.checked_mul(LEGACY_RENT_EXEMPT_LAMPORTS_PER_BYTE)
})
.ok_or(DlpError::Overflow.into())
}

/// Creates a new pda
#[inline(always)]
pub(crate) fn create_pda(
target_account: &AccountView,
owner: &Address,
space: usize,
account_space: AccountSpace,
pda_signers: &[Signer],
payer: &AccountView,
) -> ProgramResult {
// Create the account manually or using the create instruction

let rent = Rent::get()?;
if target_account.lamports().eq(&0) {
// If balance is zero, create account
system::CreateAccount {
from: payer,
to: target_account,
lamports: rent.try_minimum_balance(space)?,
space: space as u64,
lamports: account_space.minimum_balance()?,
space: account_space.space() as u64,
owner,
}
.invoke_signed(pda_signers)
} else {
// Otherwise, if balance is nonzero:

// 1) transfer sufficient lamports for rent exemption
let rent_exempt_balance = rent
.try_minimum_balance(space)?
let rent_exempt_balance = account_space
.minimum_balance()?
.saturating_sub(target_account.lamports());
if rent_exempt_balance > 0 {
system::Transfer {
Expand All @@ -48,7 +96,7 @@ pub(crate) fn create_pda(
// 2) allocate space for the account
system::Allocate {
account: target_account,
space: space as u64,
space: account_space.space() as u64,
}
.invoke_signed(pda_signers)?;

Expand Down Expand Up @@ -115,3 +163,28 @@ pub(crate) fn close_pda_with_fees(

target_account.resize(0)
}

#[cfg(test)]
mod tests {
use super::legacy_rent;
use crate::{
state::{DelegationMetadata, DelegationRecord, UndelegationRequester},
Pubkey,
};

#[test]
fn legacy_rent_uses_pre_reduction_rent_exempt_formula() {
let metadata = DelegationMetadata {
last_commit_id: 0,
undelegation_requester: UndelegationRequester::None,
seeds: vec![b"test-pda".to_vec()],
rent_payer: Pubkey::default(),
};

let delegation_rent =
legacy_rent(DelegationRecord::size_with_discriminator()).unwrap()
+ legacy_rent(metadata.serialized_size()).unwrap();

assert_eq!(delegation_rent, 2_902_320);
}
}
16 changes: 14 additions & 2 deletions tests/test_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,35 @@ async fn test_delegate() {
.unwrap()
.unwrap();
assert!(delegation_metadata_account.owner.eq(&dlp_api::id()));
assert_eq!(
delegation_metadata_account.lamports,
legacy_rent(delegation_metadata_account.data.len())
);

// Assert that the delegation record exists and can be parsed
let delegation_record = banks
let delegation_record_account = banks
.get_account(delegation_record_pda_from_delegated_account(
&DELEGATED_PDA_ID,
))
.await
.unwrap()
.unwrap();
assert_eq!(
delegation_record_account.lamports,
legacy_rent(delegation_record_account.data.len())
);
let delegation_record =
DelegationRecord::try_from_bytes_with_discriminator(
&delegation_record.data,
&delegation_record_account.data,
)
.unwrap();
assert_eq!(delegation_record.owner, DELEGATED_PDA_OWNER_ID);
}

fn legacy_rent(space: usize) -> u64 {
(space as u64 + 128) * 6_960
}

async fn setup_program_test_env() -> (BanksClient, Keypair, Keypair, Hash) {
let mut program_test = ProgramTest::new("dlp", dlp_api::ID, None);

Expand Down
Loading