You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Oct 1, 2023. It is now read-only.
sherlock-admin opened this issue
Mar 27, 2023
· 0 comments
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelHighA valid High severity issueRewardA payout will be made for this issue
The late deposit in Carousel contract can be used to avoid deposit fee
Summary
The Carousel contract has two deposit methods: direct deposit and late deposit, among which the late deposit method can avoid the deposit fee.
Vulnerability Detail
// Carousel.solfunction _deposit(
uint256_id,
uint256_assets,
address_receiver
) internal {
// mint logic, either in queue or direct depositif (_id !=0) {
uint256 assetsToDeposit = _assets;
if (depositFee >0) {
(uint256maxX, , uint256minX) =getEpochConfig(_id);
// deposit fee is calcualted linearly between time of epoch creation and epoch starting (deposit window)// this is because late depositors have an informational advantageuint256 fee =_calculateFeePercent(int256(minX), int256(maxX));
// min minRequiredDeposit modifier ensures that _assets has high enough value to not devide by 0// 0.5% = multiply by 10000 then divide by 50uint256 feeAmount = _assets.mulDivDown(fee, 10000);
assetsToDeposit = _assets - feeAmount;
_asset().safeTransfer(treasury, feeAmount);
}
_mintShares(_receiver, _id, assetsToDeposit);
emitDeposit(msg.sender, _receiver, _id, _assets);
} else {
depositQueue.push(
QueueItem({assets: _assets, receiver: _receiver, epochId: _id})
);
emitDepositInQueue(msg.sender, _receiver, _id, _assets);
}
}
The _deposit function supports both direct deposit and late deposit.
When _id != 0, deposit fee is calculated and paid according to timestamp, and the remaining assets are used for _mintShares
When _id == 0, do not do any processing, just add the parameters to the depositQueue
Data in depositQueue is processed by mintDepositInQueue.
// Carousel.solfunction mintDepositInQueue(uint256_epochId, uint256_operations)
externalepochIdExists(_epochId)
epochHasNotStarted(_epochId)
nonReentrant
{
// make sure there is already a new epoch set// epoch has not started
QueueItem[] memory queue = depositQueue;
uint256 length = depositQueue.length;
// dont allow minting if epochId is 0if (_epochId ==0) revertInvalidEpochId();
if (length ==0) revertOverflowQueue();
// relayers can always input a very big number to mint all deposit queues, without the need to read depostQueue length firstif (_operations > length) _operations = length;
// queue is executed from the tail to the head// get last index of queueuint256 i = length -1;
while ((length - _operations) <= i) {
// this loop impelements FILO (first in last out) stack to reduce gas cost and improve code readability// changing it to FIFO (first in first out) would require more code changes and would be more expensive_mintShares(
queue[i].receiver,
_epochId,
queue[i].assets - relayerFee
);
emitDeposit(
msg.sender,
queue[i].receiver,
_epochId,
queue[i].assets - relayerFee
);
depositQueue.pop();
if (i ==0) break;
unchecked {
i--;
}
}
emitRelayerMinted(_epochId, _operations);
asset.safeTransfer(msg.sender, _operations * relayerFee);
}
In the mintDepositInQueue function, _mintShares is directly called after subtracting the relayerFee from the assets, without paying the deposit fee. And the relayerFee will be returned to the user.
Impact
Malicious users can use this issue to bypass the deposit fee.
Regardless of direct deposit or late deposit, the behavior must be consistent. It is recommended to add the logic of paying deposit fee to mintDepositInQueue.
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelHighA valid High severity issueRewardA payout will be made for this issue
J4de
high
The late deposit in
Carousel
contract can be used to avoid deposit feeSummary
The
Carousel
contract has two deposit methods: direct deposit and late deposit, among which the late deposit method can avoid the deposit fee.Vulnerability Detail
The
_deposit
function supports both direct deposit and late deposit._id != 0
, deposit fee is calculated and paid according to timestamp, and the remaining assets are used for_mintShares
_id == 0
, do not do any processing, just add the parameters to thedepositQueue
Data in
depositQueue
is processed bymintDepositInQueue
.In the
mintDepositInQueue
function,_mintShares
is directly called after subtracting therelayerFee
from the assets, without paying the deposit fee. And therelayerFee
will be returned to the user.Impact
Malicious users can use this issue to bypass the deposit fee.
Code Snippet
https://github.com/sherlock-audit/2023-03-Y2K/blob/main/Earthquake/src/v2/Carousel/Carousel.sol#L310
Tool used
Manual Review
Recommendation
Regardless of direct deposit or late deposit, the behavior must be consistent. It is recommended to add the logic of paying deposit fee to
mintDepositInQueue
.Duplicate of #75
The text was updated successfully, but these errors were encountered: