From b63dfc46256ab837c9ce8944e476542e93865cfa Mon Sep 17 00:00:00 2001 From: veeso Date: Fri, 17 Nov 2023 17:08:49 +0100 Subject: [PATCH] feat: cycles and burn functions --- src/declarations/fly/fly.did.d.ts | 2 ++ src/declarations/fly/fly.did.js | 10 +++++---- src/fly/fly.did | 2 ++ src/fly/src/app.rs | 35 ++++++++++++++++++++++++++++++- src/fly/src/app/balance.rs | 24 +++++++++++++++++++++ src/fly/src/lib.rs | 14 ++++++++++++- 6 files changed, 81 insertions(+), 6 deletions(-) diff --git a/src/declarations/fly/fly.did.d.ts b/src/declarations/fly/fly.did.d.ts index 8bab95e..8620e93 100644 --- a/src/declarations/fly/fly.did.d.ts +++ b/src/declarations/fly/fly.did.d.ts @@ -30,6 +30,8 @@ export type Result_1 = { 'Ok' : bigint } | export type Role = { 'Admin' : null } | { 'DilazionatoCanister' : null }; export interface _SERVICE { + 'admin_burn' : ActorMethod<[bigint], Result>, + 'admin_cycles' : ActorMethod<[], bigint>, 'admin_remove_role' : ActorMethod<[Principal, Role], Result>, 'admin_set_role' : ActorMethod<[Principal, Role], undefined>, 'get_contract_reward' : ActorMethod<[bigint, bigint], Result_1>, diff --git a/src/declarations/fly/fly.did.js b/src/declarations/fly/fly.did.js index be7a721..c50800b 100644 --- a/src/declarations/fly/fly.did.js +++ b/src/declarations/fly/fly.did.js @@ -9,10 +9,6 @@ export const idlFactory = ({ IDL }) => { 'admins' : IDL.Vec(IDL.Principal), 'total_supply' : IDL.Nat64, }); - const Role = IDL.Variant({ - 'Admin' : IDL.Null, - 'DilazionatoCanister' : IDL.Null, - }); const ConfigurationError = IDL.Variant({ 'AdminsCantBeEmpty' : IDL.Null, 'AnonymousAdmin' : IDL.Null, @@ -34,8 +30,14 @@ export const idlFactory = ({ IDL }) => { 'Balance' : BalanceError, }); const Result = IDL.Variant({ 'Ok' : IDL.Null, 'Err' : FlyError }); + const Role = IDL.Variant({ + 'Admin' : IDL.Null, + 'DilazionatoCanister' : IDL.Null, + }); const Result_1 = IDL.Variant({ 'Ok' : IDL.Nat, 'Err' : FlyError }); return IDL.Service({ + 'admin_burn' : IDL.Func([IDL.Nat], [Result], []), + 'admin_cycles' : IDL.Func([], [IDL.Nat], []), 'admin_remove_role' : IDL.Func([IDL.Principal, Role], [Result], []), 'admin_set_role' : IDL.Func([IDL.Principal, Role], [], []), 'get_contract_reward' : IDL.Func([IDL.Nat, IDL.Nat], [Result_1], []), diff --git a/src/fly/fly.did b/src/fly/fly.did index 0489601..13f9f63 100644 --- a/src/fly/fly.did +++ b/src/fly/fly.did @@ -20,6 +20,8 @@ type Result = variant { Ok; Err : FlyError }; type Result_1 = variant { Ok : nat; Err : FlyError }; type Role = variant { Admin; DilazionatoCanister }; service : (FlyInitData) -> { + admin_burn : (nat) -> (Result); + admin_cycles : () -> (nat); admin_remove_role : (principal, Role) -> (Result); admin_set_role : (principal, Role) -> (); get_contract_reward : (nat, nat) -> (Result_1); diff --git a/src/fly/src/app.rs b/src/fly/src/app.rs index 8dee6b8..842fec4 100644 --- a/src/fly/src/app.rs +++ b/src/fly/src/app.rs @@ -106,6 +106,23 @@ impl FlyCanister { } RolesManager::remove_role(principal, role) } + + /// Returns cycles + pub fn admin_cycles() -> Nat { + if !Inspect::inspect_is_admin(utils::caller()) { + ic_cdk::trap("Unauthorized"); + } + utils::cycles() + } + + /// Burn an arbitrary amount of tokens. + /// This method transfers `amount` tokens from the canister account to the minting account. + pub fn admin_burn(amount: PicoFly) -> FlyResult<()> { + if !Inspect::inspect_is_admin(utils::caller()) { + ic_cdk::trap("Unauthorized"); + } + Balance::burn(amount) + } } impl Icrc1 for FlyCanister { @@ -330,6 +347,22 @@ mod test { assert!(!RolesManager::is_admin(principal)); } + #[test] + fn test_should_get_cycles() { + init_canister(); + assert_eq!(FlyCanister::admin_cycles(), utils::cycles()); + } + + #[test] + fn test_should_burn() { + init_canister(); + let canister_balance = Balance::canister_balance(); + let amount = fly_to_picofly(1000); + assert!(FlyCanister::admin_burn(amount.clone()).is_ok()); + assert_eq!(Balance::canister_balance(), canister_balance - amount); + assert_eq!(Balance::total_supply(), fly_to_picofly(8_888_888 - 1000)); + } + #[test] fn test_should_get_name() { init_canister(); @@ -620,7 +653,7 @@ mod test { } #[test] - fn test_should_burn() { + fn test_should_burn_from_transfer() { init_canister(); let transfer_args = TransferArg { from_subaccount: caller_account().subaccount, diff --git a/src/fly/src/app/balance.rs b/src/fly/src/app/balance.rs index 4a40c16..202fc38 100644 --- a/src/fly/src/app/balance.rs +++ b/src/fly/src/app/balance.rs @@ -127,6 +127,15 @@ impl Balance { }) } + /// Transfer amount from canister account to minting account, to cause burn + pub fn burn(amount: PicoFly) -> FlyResult<()> { + Self::transfer_wno_fees( + Self::canister_wallet_account(), + Configuration::get_minting_account(), + amount, + ) + } + fn with_balance(account: Account, f: F) -> FlyResult where F: FnOnce(&AccountBalance) -> T, @@ -338,4 +347,19 @@ mod test { .is_ok()); assert_eq!(Balance::total_supply(), fly_to_picofly(8_888_888 - 100_000)); } + + #[test] + fn test_should_burn() { + let total_supply = fly_to_picofly(8_888_888); + let initial_balances = vec![]; + Balance::init_balances(total_supply, initial_balances); + + // burn + assert!(Balance::burn(fly_to_picofly(100_000)).is_ok()); + assert_eq!(Balance::total_supply(), fly_to_picofly(8_888_888 - 100_000)); + assert_eq!( + Balance::canister_balance(), + fly_to_picofly(8_888_888 - 100_000) + ); + } } diff --git a/src/fly/src/lib.rs b/src/fly/src/lib.rs index 003098e..80249bc 100644 --- a/src/fly/src/lib.rs +++ b/src/fly/src/lib.rs @@ -9,7 +9,7 @@ mod inspect; mod utils; use app::FlyCanister; -use candid::{candid_method, Principal}; +use candid::{candid_method, Nat, Principal}; use did::fly::{FlyInitData, FlyResult, PicoFly, Role}; use did::ID; use ic_cdk_macros::{init, post_upgrade, query, update}; @@ -49,6 +49,18 @@ pub fn admin_remove_role(principal: Principal, role: Role) -> FlyResult<()> { FlyCanister::admin_remove_role(principal, role) } +#[update] +#[candid_method(update)] +pub fn admin_cycles() -> Nat { + FlyCanister::admin_cycles() +} + +#[update] +#[candid_method(update)] +pub fn admin_burn(amount: PicoFly) -> FlyResult<()> { + FlyCanister::admin_burn(amount) +} + #[allow(dead_code)] fn main() { // The line below generates did types and service definition from the