The treasury variable has accounting problems when the delegators claim their rewards of previous distribution(s) after a new distribution period has started, leading to a number of issues with the Ajna system.
The treasury is a critical component of the Ajna ecosystem, as it is used to fund grants, pay for development and operational expenses. The accounting problems with the treasury variable results in inaccurate reporting of funds available for grants or other expenses. This could lead to overcommitment of funds or insufficient funding for critical projects.
Additionally, if there are discrepancies between the reported treasury balance and the actual balance of funds held in reserve, this could erode trust in the Ajna system and damage its reputation.
The incorrect handling of the treasury variable has serious implications for the overall stability and functionality of the protocol.
The accurate management of the treasury balance is of utmost importance in the precise calculation of token distribution within each quarter, adhering to the guidelines stipulated by the Global Budgetary Constraint (GBC) outlined on page 33 of the whitepaper. Furthermore, it serves as a crucial factor in assessing whether a proposal meets the minimum withdrawal threshold, as described on page 35.
Given the vital role the treasury balance plays in key protocol functions, such as funds allocation, proposal thresholds, and extraordinary funding mechanisms, any vulnerability in this area poses a significant concern.
Note: Save this file to "2023-05-ajna/ajna-grants/test/unit". Run the PoC with "forge test --match-contract TreasuryAccounting -vvv"
The process of a distribution period in Ajna's grant coordination mechanism:
Projects submit proposals for funding.
The community screens and evaluates the proposals and selects 10 projects.
Token holders vote on the remaining proposals using their voting power. Delegates who participate in both stages of the grant coordination mechanism are eligible for delegate rewards based on their pro rata share of total delegate votes in the Funding Stage.
Winning proposals are decided through a one week challenge period.
The Ajna DAO distributes funds from its treasury to fund approved projects according to a fixed schedule called the Project Funding Mechanism (PFM). Delegates who participated in both stages and received delegate rewards will receive them at this stage.
[+] Intended behaviour of the treasury funds
------------------
Distribution ID 0 started
Current Funds: 500000000000000000000000000
Distribution ID 0 ended
------------------
Distribution ID 1 started
Current Funds: 485000000000000000000000000
Distribution ID 1 ended
------------------
Distribution ID 2 started
Current Funds: 470450000000000000000000000
Previous voter[1] balance 431846446912702651
User claims delegate reward
New voter[1] balance 47706036425531786009850
Current Funds: 470402294395420915126692801 //Notice the change 47045 -> 47040
Distribution ID 2 ended
------------------
But, here's what actually happens:
When a delegate doesn't claim their part of reward in current distribution, the reward amount is carried forward into the next distribution's treasury.
So, now when the delegates claims their reward of Distribution 1 in Distribution 2, the treasury variable is not being updated.
[+] Actual behaviour of the treasury funds
Distribution ID 1 started
Current Funds: 500000000000000000000000000
Distribution ID 1 ended
------------------
Treasury balance before distribution ID 2 started: 485000000000000000000000000
Distribution ID 2 started
Treasury balance after distribution ID 2 started: 481120000000000000000000000
------------------
Previous voter[1] balance 431846446912702651
User claims delegate reward
New voter[1] balance 47706036425531786009850
------------------
Treasury balance after user claims reward: 481120000000000000000000000 //No change
------------------
Conclusion: This issue persists for every delegate in every distribution, therefore it can be classified as a high severity bug in Ajna Grants due to incorrect accounting in treasury variable.
Tools Used
Manual Review and Foundry
Recommended Mitigation Steps
Origin of the issue: /ajna-grants/src/grants/base/StandardFunding.sol#claimDelegateReward()
Mitigation:
Option 1 - Update the treasury variable when the rewards are claimed by the delegates after the new distribution period has started
Option 2 - Create a seperate accounting for rewards. When the delegates are set to recieve the rewards, the cumulative rewards are subtracted from the treasury and stored into a seperate mapping (address delegate => mapping(uint distributionId => uint reward)) rewards
Lines of code
https://github.com/code-423n4/2023-05-ajna/blob/main/ajna-grants/src/grants/base/StandardFunding.sol#L236-L265
Vulnerability details
Impact
The
treasury
variable has accounting problems when the delegators claim their rewards of previous distribution(s) after a new distribution period has started, leading to a number of issues with the Ajna system.The treasury is a critical component of the Ajna ecosystem, as it is used to fund grants, pay for development and operational expenses. The accounting problems with the treasury variable results in inaccurate reporting of funds available for grants or other expenses. This could lead to overcommitment of funds or insufficient funding for critical projects. Additionally, if there are discrepancies between the reported treasury balance and the actual balance of funds held in reserve, this could erode trust in the Ajna system and damage its reputation. The incorrect handling of the treasury variable has serious implications for the overall stability and functionality of the protocol.
The accurate management of the treasury balance is of utmost importance in the precise calculation of token distribution within each quarter, adhering to the guidelines stipulated by the Global Budgetary Constraint (GBC) outlined on page 33 of the whitepaper. Furthermore, it serves as a crucial factor in assessing whether a proposal meets the minimum withdrawal threshold, as described on page 35.
Given the vital role the treasury balance plays in key protocol functions, such as funds allocation, proposal thresholds, and extraordinary funding mechanisms, any vulnerability in this area poses a significant concern.
Proof of Concept
The process of a distribution period in Ajna's grant coordination mechanism:
But, here's what actually happens:
Distribution 1
inDistribution 2
, thetreasury
variable is not being updated.Tools Used
Manual Review and Foundry
Recommended Mitigation Steps
mapping (address delegate => mapping(uint distributionId => uint reward)) rewards
Assessed type
Math