Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

missing Invariant check

[M-1] missing Invariant check

Description: According to netspac "user MUST have enough shares in their balance" but the protocol fails to implement this invariant right away in the code, other invariant mentioned by the protocol was implemented except this particular invariant

Impact:
This can lead to future impact such as user withdrawing more share than they have

Proof of Concept:

///.@notice Initiates a withdrawal request for a given amount of index tokens from the provided vault.
/// @dev Even if the vault doesn't have enough unlocked credit capacity to fulfill the withdrawal request, the
/// user can still initiate it, wait for the withdrawal delay period to elapse, and redeem the shares when
/// liquidity is available.
/// @dev Invariants involved in the call:
/// The shares to withdraw MUST be greater than zero.
/// The user MUST have enough shares in their balance to initiate the withdrawal.
/// The Vault MUST exist.
/// The Vault MUST be live.
/// @param vaultId The vault identifier.
/// @param shares The amount of index tokens to withdraw, in 18 decimals.
function initiateWithdrawal(uint128 vaultId, uint128 shares) external {
if (shares == 0) {
revert Errors.ZeroInput("sharesAmount");
}
// fetch storage slot for vault by id, vault must exist with valid collateral
Vault.Data storage vault = Vault.loadLive(vaultId);
if (!vault.collateral.isEnabled) revert Errors.VaultDoesNotExist(vaultId);
// increment vault/user withdrawal request counter and set withdrawal request id
uint128 withdrawalRequestId = ++vault.withdrawalRequestIdCounter[msg.sender];
// load storage slot for withdrawal request
WithdrawalRequest.Data storage withdrawalRequest =
WithdrawalRequest.load(vaultId, msg.sender, withdrawalRequestId);
// update withdrawal request create time
withdrawalRequest.timestamp = block.timestamp.toUint128();
// update withdrawal request shares
withdrawalRequest.shares = shares;
// transfer shares to the contract to be later redeemed
IERC20(vault.indexToken).safeTransferFrom(msg.sender, address(this), shares);
// emit an event
emit LogInitiateWithdrawal(vaultId, msg.sender, shares);
}

Recommended Mitigation:
kindly implement this invariant in the code

// Add these checks
require(shares <= IERC20(vault.indexToken).balanceOf(msg.sender), "Insufficient shares");
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.