And when he tries to sell it it checks if SHARE_LOCK_PERIOD has passed, which is set to 10 minutes. This is done in order to prevent from flash loan attacks, reported in the previous audit:
However the newly introduced share lock period opens possibilities for gas griefing attacks on honest users combined with an option the protocol offers, to buy creds for other curators:
function buyShareCredFor(uint256 credId_, uint256 amount_, address curator_, uint256 maxPrice_) public payable {
if (curator_ == address(0)) revert InvalidAddressZero();
_handleTrade(credId_, amount_, true, curator_, maxPrice_);
}
Proof of Concept
Consider the following scenario:
Alice wants to sell her shares on credId's from [1-100] and calls batchSellShareCred(), which calls _executeBatchSell, where _executeBatchTrade is revoked, where the curator parameter will be Alice's address:
As can be seen above the same restriction for the lock period is applied.
An attacker front-runs her tx and calls buyShareCredFor() specifiying Alice's address as the curator and the credId as the last one from her batch tx (i.e 100) to maximize the costs, subsequently _handleTrade() will be invoked, where the lastTradeTimestamp mapping will be updated as follows: lastTradeTimestamp[100][Alice] = block.timestamp
Now Alice's submitted tx proceeds, loops over the provided cred id's and reverts on the last index (i.e 100). As a result Alice's tx reverts because the locked period has not passed.
Here is a coded PoC:
Add the following test in Cred.t.sol and run forge test --mt test_Dos
Based on the current design, consider if the buyShareCredFor function contributes the necessary value to the protocol. Or one mitigation would be to update the lastTradeTimestamp mapping with the caller's address instead of curator's, this will not limit the users from trading and such attacks would not be possible. However this would require a little refactoring to the functions.
Lines of code
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L186-L188 https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L757-L764
Vulnerability details
Impact
Everytime when a user buys creds the
lastTradeTimestamp
mapping is updated to keep track the exact time of the trade:And when he tries to sell it it checks if
SHARE_LOCK_PERIOD
has passed, which is set to 10 minutes. This is done in order to prevent from flash loan attacks, reported in the previous audit:However the newly introduced share lock period opens possibilities for gas griefing attacks on honest users combined with an option the protocol offers, to buy creds for other curators:
Proof of Concept
Consider the following scenario:
credId's
from [1-100] and callsbatchSellShareCred()
, which calls_executeBatchSell
, where_executeBatchTrade
is revoked, where thecurator
parameter will be Alice's address:As can be seen above the same restriction for the lock period is applied.
An attacker front-runs her tx and calls
buyShareCredFor()
specifiying Alice's address as thecurator
and thecredId
as the last one from her batch tx (i.e 100) to maximize the costs, subsequently_handleTrade()
will be invoked, where thelastTradeTimestamp
mapping will be updated as follows:lastTradeTimestamp[100][Alice] = block.timestamp
Now Alice's submitted tx proceeds, loops over the provided cred id's and reverts on the last index (i.e 100). As a result Alice's tx reverts because the locked period has not passed.
Here is a coded PoC:
Add the following test in
Cred.t.sol
and runforge test --mt test_Dos
Tools Used
Manual Review
Recommended Mitigation Steps
Based on the current design, consider if the
buyShareCredFor
function contributes the necessary value to the protocol. Or one mitigation would be to update thelastTradeTimestamp
mapping with the caller's address instead ofcurator
's, this will not limit the users from trading and such attacks would not be possible. However this would require a little refactoring to the functions.Assessed type
DoS