#37660 [SC-High] incorrect tracking of `TOTAL_ACTIVE_STAKE` leads to permanent freezing of funds

Submitted on Dec 11th 2024 at 21:56:47 UTC by @A2Security for Audit Comp | Folks: Liquid Staking

  • Report ID: #37660

  • Report Type: Smart Contract

  • Report severity: High

  • Target: https://github.com/Folks-Finance/algo-liquid-staking-contracts/blob/8bd890fde7981335e9b042a99db432e327681e1a/contracts/xalgo/consensus_v2.py

  • Impacts:

    • Permanent freezing of funds

Description

Brief/Intro

There is a flow in the internal accounting for tracking the total active amount of staked Algo in the state variable TOTAL_ACTIVE_STAKE, this state variable is only incremented by the amount of algo deposited (increased in claim_delayed_mint() and immediate_mint()) when minting xAlgo.

The bug however arises from the fact that in the burn() function we reduce the TOTAL_ACTIVE_STAKE by the amount of the algo recieved from burning the xAlgo.

To simplify the bug:

  • User A deposits 100 ALGO recieves 100 xALGO, TOTAL_ACTIVE_STAKE = 100 ALGO

  • After a year the user, accrues some rewards 10 ALGO so the XALGO he owns is now worth 110 ALGO

  • when the user will try to burn hi 100 xAlgo, he will fail because in burn() we will try to reduce TOTAL_ACTIVE_STAKE (100 ALGO) by 110 ALGO which will underflow. (10 ALGO are locked in the contract)

Vulnerability Details

The vulnerability arises from the fact that Total Active Stake is not tracked correctly leading to an undersestimation which wil result in an underflow in the burn() function.

The TOTAL_ACTIVE_STAKE is only updated in the immediate_mint() and claim_delayed_mint() functions.

The problem however arises because we don't increase the TOTAL_ACTIVE_STAKE when we sync rewards and unclaimed fees for the protocol. This leads to underestimating the TOTAL_ACTIVE_STAKE by the accumalted amounts

This will lead to the actual withdrawable assets of users to be significantly higher than the value stored in the state variable TOTAL_ACTIVE_STAKE. Which will lead to an underflow in the burn() function

N.B algo to

Impact Details

  • Permanent locked funds for the user who withdraws last.

A simplified example to showcase this vulnerability. 2 users A and B.

  • User A deposits 100 ALGO recieves 100 xALGO, TOTAL_ACTIVE_STAKE = 100 ALGO w8 a year and his 100 xAlgo will be worth 110 ALGO

  • User B deposits 10 ALGO recieves ~8 xALGO, TOTAL_ACTIVE_STAKE = 110 ALGO (100 from User A and 10 from User B)

  • User A burns his xAlgo (worth 110 ALGO), TOTAL_ACTIVE_STAKE = 110 - 110 = 0 ALGO

  • User B can't withdraw his ALGO because when he tries to withdraw reducing 10 from 0 will underflow.

Proof of Concept

Proof of Concept

xpected Result:

Please add the following modifications:

Last updated

Was this helpful?