Ajna Protocol - TS's results

A peer to peer, oracleless, permissionless lending protocol with no governance, accepting both fungible and non fungible tokens as collateral.

General Information

Platform: Code4rena

Start Date: 03/05/2023

Pot Size: $60,500 USDC

Total HM: 25

Participants: 114

Period: 8 days

Judge: Picodes

Total Solo HM: 6

Id: 234

League: ETH

Ajna Protocol

Findings Distribution

Researcher Performance

Rank: 112/114

Findings: 1

Award: $15.58

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

15.5756 USDC - $15.58

Labels

bug
3 (High Risk)
satisfactory
duplicate-251

External Links

Lines of code

https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-core/src/RewardsManager.sol#L815

Vulnerability details

Impact

A user that after a number of epochs and whose correspond a reward may claim it and receive nothing in return, leading to the lose of those rewards

Proof of Concept

In the RewardsManager contract, the functions moveStakedLiquidity, stake, unstake and moveStakedLiquidity end up calling the _transferAjnaRewards function to transfer to the msg.sender the corresponding earned rewards.

This particular _transferAjnaRewards allow users to claim their rewards even when the RewardsManager contract does not have enough tokens. This can lead a user to a partial or complete lose of the rewards.

For example, if a user Alice can claim 500 AJNA tokens and the RewardsManager contract has zero AJNA tokens, zero tokens would be transferred to Alice, and Alice would not be able to claim again those rewards. The workflow would be the following one:

  • Alice calls the claimRewards function, which later calls _claimRewards.
  • In the line 585, the function _claimRewards emits the event ClaimRewards as if the user were claimed with 500 AJNA tokens.
  • The execution flow later calls the function _transferAjnaRewards in the line 597.
  • As the RewardsManager contract does not have any tokens, zero tokens are transferred to Alice despite 500 AJNA tokens were logged in the event.
function _transferAjnaRewards(uint256 rewardsEarned_) internal { // check that rewards earned isn't greater than remaining balance // if remaining balance is greater, set to remaining balance uint256 ajnaBalance = IERC20(ajnaToken).balanceOf(address(this)); if (rewardsEarned_ > ajnaBalance) rewardsEarned_ = ajnaBalance; if (rewardsEarned_ != 0) { // transfer rewards to sender IERC20(ajnaToken).safeTransfer(msg.sender, rewardsEarned_); } }

This would not only lead to the partial or complete lost of the rewards, but also it will difficult the traceability of the issue due that the ClaimRewards event has logged the earning of 500 AJNA tokens.

Tools Used

VSC

Ensure that the contract has enough balance to distribute rewards. Otherwise the operation should be reverted. require (ajnaBalance >= rewardsEarned_)

Assessed type

Invalid Validation

#0 - c4-judge

2023-05-12T10:34:33Z

Picodes marked the issue as duplicate of #361

#1 - c4-judge

2023-05-29T20:57:27Z

Picodes marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter