Open c4-bot-4 opened 5 months ago
MarioPoneder marked the issue as primary issue
Referring to README:
Publicly Known Issues
Mistakes by Governance: We assume that all calls that are performed by the governance address are performed with the correct parameters.
However, it's not just about correct call parameters but also about correct call timing (reward-related and block-time-related impacts
), therefore leaving this for sponsor review.
The current duplicate #19 is more affected by the README; will reconsider during judging.
OpenCoreCH (sponsor) confirmed
MarioPoneder marked the issue as satisfactory
MarioPoneder marked the issue as selected for report
Administrator mistakes usually fall under QA / Analysis reports, however, in this circumstance, the mistake is not based on input but rather on the state of the contract.
I agree with this assessment in the report.
Lines of code
https://github.com/code-423n4/2024-03-neobase/blob/main/src/LendingLedger.sol#L136-L149 https://github.com/code-423n4/2024-03-neobase/blob/main/src/LendingLedger.sol#L173-L185
Vulnerability details
Description
The
LendingLedger
utilizes an approximation system (to evaluate the time that has elapsed between two block numbers) which contains adjustable values. Additionally, it permits the governance to adjust thecantoPerBlock
value of multiple epochs at any time.The way these values are adjusted is insecure and thus can cause them to retroactively apply to markets that have not yet been updated.
In the case of the
LendingLedger::setBlockTimeParameters
, a notice exists within theLendingLedger::update_market
function that warns that:I do not consider the warning sufficient, as the
LendingLedger::setRewards
function illustrates that the problem is not understood accurately.Any market that was not updated on the exact same block that either rewards or the block time parameters are adjusted will have these adjustments retroactively applied, leading to over-estimations or under-estimations of the rewards that should be attributed to the market.
Impact
Reward measurements for markets that were not updated in the exact same block that rewards and/or block-time parameters were re-configured will result in over- or under-estimations, depending on the direction of these configurations.
Severity Rationalization
Administrator mistakes usually fall under QA / Analysis reports, however, in this circumstance, the mistake is not based on input but rather on the state of the contract. Additionally, there are cases whereby the change cannot be performed securely (i.e. if the number of markets introduced would reach the gas limit if all are attempted to be updated at the same block).
Based on the above, I believe this constitutes a valid operational vulnerability that stems from an improperly coded configuration procedure for both rewards and block time parameters.
While there is a warning for the
LendingLedger::setBlockTimeParameters
function, it is located in an entirely different function and is insufficient IMO. Even if considered sufficient, there is absolutely no warning or indication that the same restriction applies for theLendingLedger::setRewards
function.This submission may be split into two distinct ones if the reward-related and block-time-related impacts are considered distinct, however, I grouped them under the same submission as they pertain to the same operation (update of all markets) being absent albeit from two different code segments.
Proof of Concept
I have coded the following PoC in
foundry
for completeness. Please add the following segment afterLendingLedger.t.sol::setupStateBeforeClaim
:To execute the above test, I recommend the following CLI instruction:
Tools Used
Manual Review.
Recommended Mitigation Steps
I advise all markets added to a
LendingLedger
to be tracked and iterated whenever either of the submission's referenced functions is executed, ensuring that all markets are indeed updated in the same block.As a gas-optimal alternative, the total markets of the
LendingLedger
could be tracked as a number. The aforementioned adjustment functions could then accept an input array that would contain all markets, permitting afor
loop to iterate them, ensure they are distinct (i.e. in strictly ascending order), and ensure that the total number of input markets is equal to the total number of registered markets.Alternatively and as a solution solely for the
LendingLedger::setRewards
function, the epochs that are mutated could be restricted to be future ones and thus never result in a retroactive application.Assessed type
Governance