One Shot: Reloaded

First Flight #47
Beginner FriendlyNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Stake reward calculation is broken

Stake reward calculation is broken

Description

Staking rewards should mint whole CRED token per day and deposit them to the recipient's CoinStore.
However, the current implementation does not take into account the decimals of the token and mints 1 subunit of CRED per day.

Risk

Likelihood: High

This issue affects any user who unstakes.

Impact: High

Stakers receive an unexpected reward breaking incentives and economics.

Proof of Concept

#[test]
public fun test_staking_rewards_calculation () {
let module_owner = account::create_account_for_test(@battle_addr);
let framework = account::create_account_for_test(@0x1);
let recipient = account::create_account_for_test(@0xA);
timestamp::set_time_has_started_for_testing(&framework);
cred_token::initialize_for_test(&module_owner, &framework);
cred_token::register(&recipient);
one_shot::mint_rapper(&module_owner, signer::address_of(&recipient));
let tokens = one_shot::get_tokens();
assert!(vector::length(&tokens) == 1);
let token_address = vector::borrow(&tokens, 0);
let token = object::address_to_object<token::Token>(*token_address);
streets::stake(&recipient, token);
timestamp::fast_forward_seconds(4 * 24 * 60 * 60);
streets::unstake(&recipient, &module_owner, token);
assert!(cred_token::balance_of(signer::address_of(&recipient)) == 4);
}

The test asserts that the current reward calculation distributes 4 CRED subunits for 4 days of staking. Instead, 4 * 10^8 CRED should be minted.

Recommended Mitigation

Convert the amount to main unit by multiplying by 10^8 before calling cred_token::mint.

- if (days_staked >= 1) { cred_token::mint(module_owner, staker_addr, 1); };
- if (days_staked >= 2) { cred_token::mint(module_owner, staker_addr, 1); };
- if (days_staked >= 3) { cred_token::mint(module_owner, staker_addr, 1); };
- if (days_staked >= 4) { cred_token::mint(module_owner, staker_addr, 1); };
+ if (days_staked >= 1) { cred_token::mint(module_owner, staker_addr, 1 * 10 ** 8); };
+ if (days_staked >= 2) { cred_token::mint(module_owner, staker_addr, 1 * 10 ** 8); };
+ if (days_staked >= 3) { cred_token::mint(module_owner, staker_addr, 1 * 10 ** 8); };
+ if (days_staked >= 4) { cred_token::mint(module_owner, staker_addr, 1 * 10 ** 8); };
Updates

Lead Judging Commences

bube Lead Judge 18 days ago
Submission Judgement Published
Validated
Assigned finding tags:

The `streets::unstake` function mints less CRED tokens amount than intended

Appeal created

0xrektified Auditor
18 days ago
fredo182 Submitter
17 days ago
bube Lead Judge
17 days ago
bube Lead Judge 16 days ago
Submission Judgement Published
Validated
Assigned finding tags:

The `streets::unstake` function mints less CRED tokens amount than intended

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.