Lucene search

K
code423n4Code4renaCODE423N4:2023-10-CANTO-FINDINGS-ISSUES-286
HistoryOct 06, 2023 - 12:00 a.m.

An attacker can exploit the accruing liquidity functionality to accrue liquidity for more weeks than intended.

2023-10-0600:00:00
Code4rena
github.com
4
liquiditymining
exploit
timeweightedliquidity
protocolfunds

AI Score

6.9

Confidence

High

Lines of code
<https://github.com/code-423n4/2023-10-canto/blob/40edbe0c9558b478c84336aaad9b9626e5d99f34/canto_ambient/contracts/mixins/LiquidityMining.sol#L237-L253&gt;
<https://github.com/code-423n4/2023-10-canto/blob/40edbe0c9558b478c84336aaad9b9626e5d99f34/canto_ambient/contracts/mixins/LiquidityMining.sol#L207-L221&gt;
<https://github.com/code-423n4/2023-10-canto/blob/40edbe0c9558b478c84336aaad9b9626e5d99f34/canto_ambient/contracts/mixins/LiquidityMining.sol#L94-L153&gt;

Vulnerability details

Instances

The whole exploit works due to similar functionality being broken at these 4 instances: here, here, here and here.

Impact

An attacker can accrue both Position time weighted liquidity and Global time weighted liquidity for both concentrated and ambient for more weeks than intended by the protocol. This results in attacker being able to claim rewards for more weeks than intended resulting in severe loss of funds to the protocol and hence the high severity.

This issue occurs because of incorrectly updating block.timestamp on first liquidity accrue.

Proof of Concept

Please refer to the below PoC which uses accrueConcentratedGlobalTimeWeightedLiquidity() function to demonstrate how an attacker can claim rewards for two weeks than one which is intended:

<https://gist.github.com/0xSandyy/8e4d325e6da65554891b69fa86fb9481&gt;

The attack vector with the help of this PoC is explained below:

  1. The main issue is with block.timestamp getting incorrectly updated on the first accrue as it is updated directly to the actual value here instead of being rounded down to nearest week like currWeek and nextWeek is done here.

  2. If the attacker calls claimConcentratedRewards() in around one week after previous rewards claim, the timeWeightedWeeklyGlobalConcLiquidityLastSet_ mapping is updated for two weeks instead of one as only one week has passed and this can be proven by the test_accrueIterationMoreDueToPrecisionLoss() function in this PoC.

NOTE: The claimConcentratedRewards() don’t need to be called in exact 604800 seconds ( 1 week) and this can be tested in test_pocStillWorksWithoutExactOneWeek() function the PoC.

  1. As all the four instances, here, here, here and here have the same functionality, all the respective mappings will be updated for two weeks instead of one and as these mappings are directly used in reward calculation eg:here and here, the reward for two weeks can be claimed by the attacker instead of one week and thus protocol will lose funds.

To set up the test file in the cloned repository run the following commands:

forge init --force



forge install openzeppelin/[email protected] --no-commit



forge fmt

Tools Used

Manual Analysis

Recommended Mitigation Steps

To mitigate this issue, this block.timestamp on first call should be updated like this on all the four instances here, here, here and here:

./LiquidityMining.sol

        timeWeightedWeeklyGlobalConcLiquidityLastSet_[poolIdx] = uint32(
            (block.timestamp / WEEK) * WEEK)
        );

The test_accrueIterationsMoreDueToPrecisionLossFixed() function of this PoC proves that the above fix works.

Assessed type

Other


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

All reactions

AI Score

6.9

Confidence

High