Lucene search

K
code423n4Code4renaCODE423N4:2023-05-AJNA-FINDINGS-ISSUES-454
HistoryMay 11, 2023 - 12:00 a.m.

unstake() function: The unstake function permits the unstaking of multiple position NFTs from the same liquidity pool (LP) by the same lender. This opens the possibility for a lender to claim more Ajna token rewards than they are entitled to by staking and unstaking multiple NFTs associated with the same LP.

2023-05-1100:00:00
Code4rena
github.com
4
unstake function
multiple nfts
liquidity pool
ajna token rewards
exploitation
minting
staking
imbalance
token economy
stability
integrity
mint
stake
unstake
vsc
mitigation
data structure.

Lines of code
<https://github.com/code-423n4/2023-05-ajna/blob/d80daab705a066828ef1c5d9ba85f315c7c932db/ajna-core/src/RewardsManager.sol#L207-L260&gt;
<https://github.com/code-423n4/2023-05-ajna/blob/d80daab705a066828ef1c5d9ba85f315c7c932db/ajna-core/src/PositionManager.sol#L227-L241&gt;

Vulnerability details

Impact

The absence of a mechanism to prevent a lender from unstaking multiple NFTs for the same liquidity pool (LP) could potentially lead to the exploitation of the Ajna token reward system. A lender can mint, stake, and unstake multiple NFTs for the same LP from the same pool, thereby claiming Ajna token rewards multiple times. This not only undermines the fairness of the reward distribution but can also lead to a significant imbalance in the token economy, undermining the overall stability and integrity of the system.

Proof of Concept

In this scenario, an attacker can exploit the staking and unstaking mechanism to claim more rewards than they deserve. The attacker starts by minting multiple position NFTs for the same LP from the same pool. Afterward, they stake these NFTs and subsequently unstake them, seemingly claiming the same Ajna token rewards multiple times.

Here’s a high-level overview of how this attack could be executed:

  1. Minting Multiple NFTs: The attacker calls the mint function multiple times to mint multiple position NFTs for the same pool and LP.

mint({pool: samePool, poolSubsetHash: sameHash, recipient: attackerAddress});
mint({pool: samePool, poolSubsetHash: sameHash, recipient: attackerAddress});
// … repeat as many times as desired

  1. Staking the NFTs: The attacker then stakes these NFTs one by one using the stake function.

stake(tokenId1);
stake(tokenId2);
// … repeat for each minted NFT

  1. Unstaking and Claiming Rewards: Finally, the attacker unstakes these NFTs one by one, each time claiming rewards using the unstake function.

unstake(tokenId1); // claims rewards
unstake(tokenId2); // claims rewards again
// … repeat for each staked NFT

By repeating this process, the attacker can seemingly claim the same Ajna token rewards multiple times, as many times as the number of NFTs they have staked. This exploits the Ajna token reward system, possibly allowing the attacker to claim more rewards than they earned.

This process illustrates that the current implementation does not prevent a user from staking and unstaking multiple NFTs from the same LP, which can lead to an imbalance in the token rewards distribution. Therefore, there is a need for a mechanism to prevent a lender from unstaking multiple NFTs associated with the same LP from the same pool.

The main functions involved in this scenario are as follows:

mint():
<https://github.com/code-423n4/2023-05-ajna/blob/d80daab705a066828ef1c5d9ba85f315c7c932db/ajna-core/src/PositionManager.sol#L227-L241&gt;

stake():
<https://github.com/code-423n4/2023-05-ajna/blob/d80daab705a066828ef1c5d9ba85f315c7c932db/ajna-core/src/RewardsManager.sol#L207-L260&gt;

unstake():
<https://github.com/code-423n4/2023-05-ajna/blob/d80daab705a066828ef1c5d9ba85f315c7c932db/ajna-core/src/RewardsManager.sol#L270-L303&gt;

_transferAjnaRewards():
<https://github.com/code-423n4/2023-05-ajna/blob/d80daab705a066828ef1c5d9ba85f315c7c932db/ajna-core/src/RewardsManager.sol#L811-L821&gt;

Tools Used

VSC.

Recommended Mitigation Steps

Introduce a data structure, such as a mapping, to keep track of the staked positions for each lender per pool. This will prevent a lender from unstaking multiple NFTs associated with the same LP from the same pool.

Enhance the mint function to restrict minting more than one NFT for the same lender + pool + LP combination. This will nip the issue in the bud.

Ensure only lenders can mint position NFTs and that they can only be minted if the recipient has existing LP in the Ajna pool. Upon unstaking, remove the flag from the stakedPools mapping.

Review the _claimRewards function for similar vulnerabilities. This function should prevent claiming rewards for multiple staked NFTs of the same LP from the same pool by a single lender.

Assessed type

Other


The text was updated successfully, but these errors were encountered:

All reactions