The proposeStandard function in StandardFunding.sol contract does not include a direct check to ensure that the proposed tokens requested are less than or equal to the actual available funds for the distribution period. Instead, it only checks if the proposed tokens requested exceed 90% of the distribution period's available funds.
#L390-L391
// revert if proposal requested more tokens than are available in the distribution period
if (newProposal.tokensRequested > (currentDistribution.fundsAvailable * 9 / 10)) revert InvalidProposal();
This line will only prevent proposals from requesting more tokens than 90% of the available funds for the distribution period, which is a good measure to ensure that proposals do not exhaust the funds allocated for the period. However, this check does not directly verify that the proposed tokens requested are less than or equal to the actual available funds for the period, which is the more critical measure to prevent the loss of funds.
The proposed token request exceeding available funds check missing in the proposeStandard function can be exploited by an attacker to propose a large amount of tokens that exceed the actual available funds, potentially causing a loss of funds.
StandardFunding.sol#L385-L391
// store new proposal information
newProposal.proposalId = proposalId_;
newProposal.distributionId = currentDistribution.id;
newProposal.tokensRequested = _validateCallDatas(targets_, values_, calldatas_); // check proposal parameters are valid and update tokensRequested
// revert if proposal requested more tokens than are available in the distribution period
if (newProposal.tokensRequested > (currentDistribution.fundsAvailable * 9 / 10)) revert InvalidProposal();
The function checks if the proposed tokens requested exceed 90% of the distribution period's available funds, but does not directly check if the proposed tokens requested are less than or equal to the actual available funds.
For Instance:
An attacker can propose a large amount of tokens that exceed the actual available funds. Suppose the actual available funds for the distribution period are 100,000 tokens, but the fundsAvailable value is set to 200,000 tokens. An attacker can then propose to request 150,000 tokens, which will be approved by the contract as it is less than 90% of the fundsAvailable value, but exceeds the actual available funds. This will cause a loss of 50,000 tokens, as the contract will transfer the requested tokens without verifying if they are within the actual available funds.
Tools Used
Manual review, vscode
Recommended Mitigation Steps
Add an additional check to ensure that the proposed tokens requested are less than or equal to the actual available funds for the distribution period. This can be achieved by keeping track of the total amount of tokens requested by all proposals, and subtracting this value from the distribution period's available funds to obtain the actual available funds. Then, the function can check if the proposed tokens requested exceed the actual available funds, and revert if this is the case.
uint256 totalTokensRequested = 0;
// loop through existing proposals to calculate total tokens requested
for (uint256 i = 0; i < _standardFundingProposals.length; i++) {
if (_standardFundingProposals[i].distributionId == currentDistribution.id) {
totalTokensRequested += _standardFundingProposals[i].tokensRequested;
}
}
// calculate actual available funds by subtracting total tokens requested from funds available
uint256 actualFundsAvailable = currentDistribution.fundsAvailable - totalTokensRequested;
// revert if proposal requested more tokens than are available in the distribution period
if (newProposal.tokensRequested > actualFundsAvailable) revert InvalidProposal();
By implementing this check, the contract can ensure that the proposed tokens requested do not exceed the actual available funds for the distribution period, and prevent loss of funds.
Lines of code
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-grants/src/grants/base/StandardFunding.sol#L366-L404 https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-grants/src/grants/base/StandardFunding.sol#L390-L391 https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-grants/src/grants/base/StandardFunding.sol#L385-L391
Vulnerability details
Impact
The
proposeStandard
function in StandardFunding.sol contract does not include a direct check to ensure that the proposed tokens requested are less than or equal to the actual available funds for the distribution period. Instead, it only checks if the proposed tokens requested exceed 90% of the distribution period's available funds. #L390-L391This line will only prevent proposals from requesting more tokens than 90% of the available funds for the distribution period, which is a good measure to ensure that proposals do not exhaust the funds allocated for the period. However, this check does not directly verify that the proposed tokens requested are less than or equal to the actual available funds for the period, which is the more critical measure to prevent the loss of funds.
If the
fundsAvailable
value is inaccurate or has been manipulated by an attacker, then the check newProposal.tokensRequested > (currentDistribution.fundsAvailable * 9 / 10) could still allow proposals to request more tokens than the actual available funds, leading to a loss of funds.Proof of Concept
The proposed token request exceeding available funds check missing in the proposeStandard function can be exploited by an attacker to propose a large amount of tokens that exceed the actual available funds, potentially causing a loss of funds. StandardFunding.sol#L385-L391
The function checks if the proposed tokens requested exceed 90% of the distribution period's available funds, but does not directly check if the proposed tokens requested are less than or equal to the actual available funds.
For Instance: An attacker can propose a large amount of tokens that exceed the actual available funds. Suppose the actual available funds for the distribution period are 100,000 tokens, but the
fundsAvailable
value is set to 200,000 tokens. An attacker can then propose to request 150,000 tokens, which will be approved by the contract as it is less than 90% of thefundsAvailable
value, but exceeds the actual available funds. This will cause a loss of 50,000 tokens, as the contract will transfer the requested tokens without verifying if they are within the actual available funds.Tools Used
Manual review, vscode
Recommended Mitigation Steps
Add an additional check to ensure that the proposed tokens requested are less than or equal to the actual available funds for the distribution period. This can be achieved by keeping track of the total amount of tokens requested by all proposals, and subtracting this value from the distribution period's available funds to obtain the actual available funds. Then, the function can check if the proposed tokens requested exceed the actual available funds, and revert if this is the case.
By implementing this check, the contract can ensure that the proposed tokens requested do not exceed the actual available funds for the distribution period, and prevent loss of funds.
Assessed type
Error