Skip to content

Commit

Permalink
add fee to Mint operation
Browse files Browse the repository at this point in the history
  • Loading branch information
MarioDfinity committed Mar 21, 2024
1 parent 804a450 commit bc41828
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 47 deletions.
64 changes: 30 additions & 34 deletions cycles-ledger/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ pub enum Operation {
Mint {
to: Account,
amount: u128,
// Custom non-standard fee to record the amount
// of cycles "burn" when cycles are deposited, i.e.
// the diffence between the cycles deposited and
// the cycles minted. Note that this field has
// no effect on the balance of the `to` account.
fee: u128,
},
Transfer {
from: Account,
Expand Down Expand Up @@ -177,10 +183,11 @@ impl Display for Operation {
write!(f, ", amount: {amount}")?;
write!(f, " }}")
}
Self::Mint { to, amount } => {
Self::Mint { to, amount, fee } => {
write!(f, "Mint {{")?;
write!(f, " to: {to}")?;
write!(f, ", amount: {amount}")?;
write!(f, ", fee: {fee}")?;
write!(f, " }}")
}
Self::Transfer {
Expand Down Expand Up @@ -260,6 +267,9 @@ impl TryFrom<FlattenedTransaction> for Transaction {
"mint" => Operation::Mint {
to: value.to.ok_or("`to` field required for `mint` operation")?,
amount: value.amount,
fee: value
.fee
.ok_or("`fee` field required for `mint` operation")?,
},
"xfer" => Operation::Transfer {
from: value
Expand Down Expand Up @@ -328,6 +338,7 @@ impl From<Transaction> for FlattenedTransaction {
},
fee: match &t.operation {
Transfer { fee, .. } | Approve { fee, .. } => fee.to_owned(),
Mint { fee, .. } => Some(fee.to_owned()),
_ => None,
},
expected_allowance: match &t.operation {
Expand Down Expand Up @@ -720,32 +731,6 @@ pub fn balance_of(account: &Account) -> u128 {
read_state(|s| s.balances.get(&to_account_key(account)).unwrap_or_default())
}

pub fn record_deposit(
account: &Account,
amount: u128,
memo: Option<Memo>,
now: u64,
) -> anyhow::Result<(u64, u128, Hash)> {
mutate_state(|s| {
let new_balance = s.credit(account, amount)?;
let phash = s.last_block_hash();
let block_hash = s.emit_block(Block {
transaction: Transaction {
operation: Operation::Mint {
to: *account,
amount,
},
memo,
created_at_time: None,
},
timestamp: now,
phash,
effective_fee: Some(0),
});
Ok((s.blocks.len() - 1, new_balance, block_hash))
})
}

pub fn deposit(
to: Account,
amount: u128,
Expand Down Expand Up @@ -786,7 +771,11 @@ pub fn mint(to: Account, amount: u128, memo: Option<Memo>, now: u64) -> anyhow::
// we are not checking for duplicates, since mint is executed with created_at_time: None
let block_index = process_transaction(
Transaction {
operation: Operation::Mint { to, amount },
operation: Operation::Mint {
to,
amount,
fee: crate::config::FEE,
},
created_at_time: None,
memo,
},
Expand Down Expand Up @@ -1409,7 +1398,8 @@ fn validate_suggested_fee(op: &Operation) -> Result<Option<u128>, u128> {
use Operation as Op;

match op {
Op::Burn { .. } | Op::Mint { .. } => Ok(Some(config::FEE)),
Op::Mint { .. } => Ok(Some(0)),
Op::Burn { .. } => Ok(Some(config::FEE)),
Op::Transfer { fee, .. } | Op::Approve { fee, .. } => {
if fee.is_some() && fee != &Some(config::FEE) {
return Err(config::FEE);
Expand Down Expand Up @@ -2003,7 +1993,11 @@ fn reimburse(
memo: [u8; MAX_MEMO_LENGTH as usize],
) -> Result<u64, ProcessTransactionError> {
let transaction = Transaction {
operation: Operation::Mint { to: acc, amount },
operation: Operation::Mint {
to: acc,
amount,
fee: 0,
},
created_at_time: None,
memo: Some(Memo::from(ByteBuf::from(memo))),
};
Expand Down Expand Up @@ -2304,8 +2298,9 @@ mod tests {
icrc3,
};
use proptest::{
prelude::any, prop_assert, prop_assert_eq, prop_compose, prop_oneof, proptest,
strategy::Strategy,
prelude::any,
prop_assert, prop_assert_eq, prop_compose, prop_oneof, proptest,
strategy::{Just, Strategy},
};

use crate::{
Expand Down Expand Up @@ -2361,9 +2356,10 @@ mod tests {
prop_compose! {
fn mint_strategy()
(to in account_strategy(),
amount in any::<u128>())
amount in any::<u128>(),
fee in prop_oneof![Just(0), Just(config::FEE)])
-> Operation {
Operation::Mint { to, amount }
Operation::Mint { to, amount, fee }
}
}

Expand Down
41 changes: 28 additions & 13 deletions cycles-ledger/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,8 @@ fn test_deposit_flow() {
&Block {
// 1.2.0 first block has no parent hash.
phash: None,
// 1.2.1 effective fee of mint blocks is the configured fee.
effective_fee: Some(fee),
// 1.2.1 effective fee of mint blocks is 0.
effective_fee: Some(0),
// 1.2.2 timestamp is set by the ledger.
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
Expand All @@ -639,6 +639,8 @@ fn test_deposit_flow() {
to: account0,
// 1.2.7 transaction.operation.amount is the deposited amount.
amount: 1_000_000_000,
// 1.2.8 transaction.operation.fee is the ledger fee.
fee,
},
},
},
Expand All @@ -663,8 +665,8 @@ fn test_deposit_flow() {
&Block {
// 2.2.0 second block has the first block hash as parent hash.
phash: Some(block0.hash().unwrap()),
// 2.2.1 effective fee of mint blocks is the configured fee.
effective_fee: Some(fee),
// 2.2.1 effective fee of mint blocks is 0.
effective_fee: Some(0),
// 2.2.2 timestamp is set by the ledger.
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
Expand All @@ -678,6 +680,8 @@ fn test_deposit_flow() {
to: account0,
// 2.2.7 transaction.operation.amount is the deposited amount.
amount: 500_000_000,
// 2.2.8 transaction.operation.fee is the ledger fee.
fee,
},
},
},
Expand Down Expand Up @@ -1089,7 +1093,7 @@ fn test_withdraw_fails() {
id: Nat::from(blocks.len()) + 1u8,
block: Block {
phash: Some(burn_block.block.hash()),
effective_fee: Some(config::FEE),
effective_fee: Some(0),
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
created_at_time: None,
Expand All @@ -1099,6 +1103,7 @@ fn test_withdraw_fails() {
// refund the amount minus the fee to make
// the caller pay for the refund block too
amount: 500_000_000_u128 - FEE,
fee: 0,
},
},
}
Expand Down Expand Up @@ -1740,14 +1745,15 @@ fn test_withdraw_from_fails() {
id: Nat::from(blocks.len()) + 1u8,
block: Block {
phash: Some(burn_block.block.hash()),
effective_fee: Some(config::FEE),
effective_fee: Some(0),
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
created_at_time: None,
memo: Some(Memo(ByteBuf::from(PENALIZE_MEMO))),
operation: Operation::Mint {
to: account1_2,
amount: 400_000_000_u128,
fee: 0,
},
},
}
Expand Down Expand Up @@ -1860,14 +1866,15 @@ fn test_withdraw_from_fails() {
id: Nat::from(blocks.len()) + 1u8,
block: Block {
phash: Some(burn_block.block.hash()),
effective_fee: Some(config::FEE),
effective_fee: Some(0),
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
created_at_time: None,
memo: Some(Memo(ByteBuf::from(PENALIZE_MEMO))),
operation: Operation::Mint {
to: account1_3,
amount: 10_000_u128,
fee: 0,
},
},
}
Expand Down Expand Up @@ -1958,14 +1965,15 @@ fn test_withdraw_from_fails() {
id: Nat::from(blocks.len()) + 1u8,
block: Block {
phash: Some(burn_block.block.hash()),
effective_fee: Some(config::FEE),
effective_fee: Some(0),
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
created_at_time: None,
memo: Some(Memo(ByteBuf::from(PENALIZE_MEMO))),
operation: Operation::Mint {
to: account1_4,
amount: 10_000_u128,
fee: 0,
},
},
}
Expand Down Expand Up @@ -2091,14 +2099,15 @@ fn test_withdraw_from_fails() {
id: Nat::from(blocks.len()) + 1u8,
block: Block {
phash: Some(burn_block.block.hash()),
effective_fee: Some(config::FEE),
effective_fee: Some(0),
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
created_at_time: None,
memo: Some(Memo(ByteBuf::from(PENALIZE_MEMO))),
operation: Operation::Mint {
to: account1_6,
amount: 400_000_000_u128,
fee: 0,
},
},
}
Expand Down Expand Up @@ -4482,6 +4491,7 @@ fn test_icrc3_get_blocks() {
Mint {
to: account1,
amount: 5_000_000_000,
fee,
},
None,
None,
Expand All @@ -4506,6 +4516,7 @@ fn test_icrc3_get_blocks() {
Mint {
to: account2,
amount: 3_000_000_000,
fee,
},
None,
None,
Expand Down Expand Up @@ -4709,7 +4720,8 @@ fn block(
phash: Option<[u8; 32]>,
) -> Block {
let effective_fee = match operation {
Burn { .. } | Mint { .. } => Some(FEE),
Mint { .. } => Some(0),
Burn { .. } => Some(FEE),
Transfer { fee, .. } | Approve { fee, .. } => {
if fee.is_none() {
Some(FEE)
Expand Down Expand Up @@ -5506,14 +5518,15 @@ fn test_create_canister_fail() {
id: Nat::from(blocks.len() + 1),
block: Block {
phash: Some(burn_block.block.clone().hash()),
effective_fee: Some(config::FEE),
effective_fee: Some(0),
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
created_at_time: None,
memo: Some(Memo::from(ByteBuf::from(REFUND_MEMO))),
operation: Operation::Mint {
to: account1,
amount: amount - fee,
fee: 0,
},
},
}
Expand Down Expand Up @@ -6131,14 +6144,15 @@ fn test_create_canister_from_fail() {
id: Nat::from(blocks.len() + 1),
block: Block {
phash: Some(burn_block.block.clone().hash()),
effective_fee: Some(config::FEE),
effective_fee: Some(0),
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
created_at_time: None,
memo: Some(Memo::from(ByteBuf::from(REFUND_MEMO))),
operation: Operation::Mint {
to: account1_3,
amount: FEE / 2,
fee: 0,
},
},
}
Expand Down Expand Up @@ -6232,14 +6246,15 @@ fn test_create_canister_from_fail() {
id: Nat::from(blocks.len() + 1),
block: Block {
phash: Some(burn_block.block.clone().hash()),
effective_fee: Some(config::FEE),
effective_fee: Some(0),
timestamp: env.nanos_since_epoch_u64(),
transaction: Transaction {
created_at_time: None,
memo: Some(Memo::from(ByteBuf::from(REFUND_MEMO))),
operation: Operation::Mint {
to: account1_4,
amount: FEE + FEE / 2,
fee: 0,
},
},
}
Expand Down

0 comments on commit bc41828

Please sign in to comment.