Foil engaged Guardian to review the security of its updates to the virtual gas marketplace. From the 21st of October to the 4th of November, a team of 6 auditors reviewed the source code in scope.
- Published
- Review window
- October 21 to November 4, 2025
- Language
- Solidity
- Chains
- Ethereum
- Sector
- Derivatives
- 2 Critical
- 4 High
- 7 Medium
- 23 Low
- 0 Informational
Scope
Overview
Foil engaged Guardian to review the security of its updates to the virtual gas marketplace. From the 21st of October to the 4th of November, a team of 6 auditors reviewed the source code in scope.
Issues Detected Throughout the engagement 6 High/Critical issues were uncovered and promptly remediated by the Foil team. Several issues impacted the fundamental behavior of the protocol, following their remediation Guardian believes the protocol to uphold the functionality described for Foil.
Security Recommendation Given the number of High and Critical issues detected, Guardian supports a secondary security review of the protocol at a finalized frozen commit.
Findings 36
-
C-01 Critical Collateral Removed On Position Adjustment Logical Error Resolved
Description
Proof of concept: PoC
Fee collectors can create under-collateralized positions and collateralize them using
depositCollateral.However, when calling
increaseLiquidityPositionordecreaseLiquidityPosition, the zero collateral requirement for fee collectors causesupdateCollateralto mistakenly remove and transfer all collateral back to the fee collector.This allows fee collectors to withdraw collateral after depositing, potentially avoiding any loss at the end of the epoch. This is against protocol spec that the fee collector should never be able to back out of provided collateral, even if adjusting positions.
Recommendation
updateCollateralshould not be triggered for fee collectors when modifying a position or position modification should be restricted during the epoch.Resolution
Foil Team: The issue was resolved in PR#155.
-
C-02 Critical tradeRatio Can Be Manipulated To Wipe Debt Logical Error Resolved
Description
Proof of concept: PoC
When modifying a trade position, the output of a swap is used to calculate
tradeRatio, which serves as a proxy price to determine the value of vGas. This ratio is essential for calculating PnL and setting the borrowed amounts for the new position.However, if a small (dust) amount of vGas is swapped,
amountInoramountOutfor vETH may round to zero due to Uniswap’s rounding behavior, causingtradeRatioto also be zero. This allows for potential exploitation: in a long position,borrowedVEthbecomes zero, effectively wiping the position's debt and creating bad debt in the system.Attack Scenario: 1. Alice opens a long position. 2. Alice decreases the position by 1 wei, setting
tradeRatioto zero, which is belowminPrice, creating bad debt by wiping allborrowedVEth. 3. Alice closes the position, recovering all previously deposited collateral plus additional funds, effectively stealing from the system.Recommendation
If the trade price is below or above the min or max price for a pool, then revert.
Resolution
Foil Team: The issue was resolved in PR#161.
-
H-01 High Last User Of Epoch Cannot Withdraw Collateral Logical Error Resolved
Description
Proof of concept: PoC
In
LiquidityModule._closeLiquidityPosition, collected amounts are rounded up by adding 1 wei to offset Uniswap’s rounding when opening a position.However, borrowed amounts may be zero (e.g., when adding liquidity outside the current price tick), and collected amounts can also be zero, depending on the price tick.
By adding 1 wei, users may withdraw more collateral than they initially deposited. Over time, this leads to the last user in an epoch being unable to withdraw due to insufficient collateral.
This behavior can also be exploited by malicious users with the following steps:
- Provide liquidity above the current price tick, so only vGas is borrowed and no vETH.
- Immediately decrease liquidity, collecting all borrowed vGas plus 1 wei of vETH.
- The 1 wei of vETH is added to the user's deposited collateral and then withdrawn.
Recommendation
- If collected amount is zero, do not add the 1 wei adjustment.
- Modify
settlePositionto allow payouts of the contract's remaining balance when the exact
collateral amount is insufficient, preventing the last withdrawal from reverting if the balance is short by a few wei.
Resolution
Foil Team: The issue was resolved in PR#150.
-
H-02 High Collateral Returned Despite Bad Debt Logical Error Resolved
Description
Proof of concept: PoC
When a trader is closing out a position, if the loss exceeds collateral deposited then this case is entered. As bad debt has been incurred, the collateral should be reduced to zero but currently
depositedCollateralAmountremains unchanged.The
extraCollateralRequiredwould cover the losses, but however it is only taken into account if the trader is re-opening a new position.So, If the trader was closing the position (i.e. size = 0), then all deposited collateral is returned to the trader implying losses are borne by the protocol/other LPs and traders.
Recommendation
Change the logic to:
if (collateralLoss > params.oldPosition.depositedCollateralAmount) output.position.depositedCollateralAmount = 0; extraCollateralRequired = collateralLoss - params.oldPosition.depositedCollateralAmount;Resolution
Foil Team: The issue was resolved in PR#164.
-
H-03 High Insolvency Because Of tradeRatio Rounding Rounding Resolved
Description
Proof of concept: PoC
When
_quoteOrTradeis called and PnL is calculated, thetradeRatioexperiences precision loss because of rounding down when performingdivDecimal. While this is fine for longs, it's not for shorts.That's because the
tradeRatiois a fill price and if the fill price is lower, shorts will have made a profit. In result, when the PnL for shorts is calculated the trader will experience a smaller loss, leaving the system with fewer funds available than it should have in order to operate.This can be most visible if a position has only
borrowedVGas(short) and makes a trade to close the position. Because the entirety of the debt is being paid off, it would be expected that thevEthToZerowould at least match theruntime.tradedVEth.However, the
vEthToZerowould be slightly less due to thetradeRatioD18rounding, and less collateral being held in the Foil contract. Later, when LPs try to close or settle their position, they will not be able to do so.The contract will try to send them the amount they have earned, but this amount is not fully backed by the losses of the traders and the transaction will revert with
ERC20: transfer amount exceedsbalance.Recommendation
In case of a short position, round the
tradeRatioup to provide a worse fill price when going towards the long direction.Resolution
Foil Team: The issue was resolved in PR#168.
-
H-04 High Settlement Failure Due To Underflow DOS Resolved
Description
Proof of concept: PoC
When settling a liquidity position,
getCurrentPositionTokenAmountsis called to retrieve the correspondingvGasandvETHtoken amounts of the position, which are then later rebalanced duringposition.settle.The rebalancing process converts everything to ETH, adding all value to
depositedCollateraland subtracting all debt fromdepositedCollateral.However, the calculation during
getCurrentPositionTokenAmountsrounds down, which can cause the total value of the position (including the collateral) to be less than the total debt in some cases.This results in the settlement reverting due to an underflow in the following line:
self.depositedCollateralAmount = self.borrowedVEth.Recommendation
Rounding should be accounted for when calculating the required collateral. Consider adjusting
loanAmount0andloanAmount1up by 1 wei during calculation.Resolution
Foil Team: The issue was resolved in PR#174.
-
M-01 Medium Fee Collector Can Horde Fees Logical Error Acknowledged
Description
Fee collectors can create under-collateralized positions and collateralize them using
depositCollateral.Currently, there are no restrictions preventing a fee collector from creating an oversized liquidity position, which can monopolize all available liquidity and hoard fees, preventing other fee collectors from benefiting.
Recommendation
Impose limits on the size of liquidity positions that fee collectors can create to ensure fair distribution of fees.
Resolution
Foil Team: Acknowledged.
-
M-02 Medium _checkOnERC721Received Bool Is Not Checked Validation Resolved
Description
While creating a position in the liquidity or trading modules,
_checkOnERC721Receivedfunction is called and then the position NFT is minted.However,
_checkOnERC721Receiveddoes not revert on failure but only returns false. Return value is not checked and positions can be minted to contracts that can't hold NFTsRecommendation
Check the return value of the function before continuing.
Resolution
Foil Team: The issue was resolved in PR#149.
-
M-03 Medium Incorrect deltaCollateral Check When Negative Validation Resolved
Description
Users provide
deltaCollateralLimitwhen modifying their trade positions. While a positivedeltaCollateralLimitindicates the maximum amount a user wants to provide to the protocol, a negativedeltaCollateralLimitrepresents the minimum collateral amount a user wishes to receive from the protocol when decreasing or closing a position.However, the negative case in
_checkDeltaCollateralLimitis incorrect and behaves oppositely. It reverts whendeltaCollateralLimit < 0 && deltaCollateral < deltaCollateralLimit. The user-provided value functions as a maximum limit instead of a minimum limit, resulting in the user receiving less than intended all the time.Recommendation
Change
deltaCollateral < deltaCollateralLimittodeltaCollateral > deltaCollateralLimit.Resolution
Foil Team: The issue was resolved in PR#159.
-
M-04 Medium Rightful Disputer Might Lose Bonds Validation Resolved
Description
Currently, there is no mechanism that checks whether there is already an ongoing dispute or not while submitting a price. Asserter can submit a new price after an initial incorrect submission without waiting a dispute to resolve in 48-96 hours.
This would cause disputer to lose their bonds since the settlement will fail at this line as the assertionIds won't match.
Recommendation
Do not allow submitting new price if there is already an ongoing dispute.
Resolution
Foil Team: The issue was resolved in PR#169.
-
M-05 Medium Decreasing LP May Require Collateral DOS Acknowledged
Description
Whenever a position is modified in
position.updateValidLp, the required collateral for that position is calculated and compared against the current available collateral.The collateral is calculated by using two values -
debitEthandcreditEth(debit is taken from the user and credit is given to them).When removing a small amount of liquidity, it's possible that the decrease in
creditEthis larger than the decrease indebitEth, which would lead to increased collateral requirements.Since
additionalCollateralis 0 when decreasing a position, the transaction will revert withInsufficientCollateral().Recommendation
Allow the user to supply additional collateral when decreasing their position.
Resolution
Foil Team: Acknowledged.
-
M-06 Medium Using LP For More Efficient Trades Logical Error Acknowledged
Description
Proof of concept: PoC
Instead of opening a long position in the
TradeModuleto gain exposure to vGas, traders can use theLiquidityModulefor a more efficient strategy.By adding liquidity below the current price with a lower tick set to their desired entry price, traders can effectively create a limit order.
When the price reaches this minimum tick, the LP position converts fully to vGas, which can then be closed and transitioned into a Trade position.
Since LP positions have reduced collateral requirements (no swap fees nor price impact on entry), this approach allows for the same vGas position with less collateral.
Recommendation
Consider if this behavior should be prevented from a protocol perspective. One possible solution would be to fully close an LP's position in
_closeLiquidityPositioninstead of the transition to a Trade position, although low liquidity environments would have to be taken into consideration, and slippage protection would have to be appropriately handled.Resolution
Foil Team: Acknowledged.
-
M-07 Medium Dangerous Price Used For Resolution Callback Logical Error Acknowledged
Description
If
settlement.settlementPriceD18inassertionResolvedCallback()is outside the acceptable price range for the given epoch, the new price for the epoch will be capped to eitherminormaxwith functionsetSettlementPriceInRange.However,
resolutionCallback()is still called with the originalsettlement.settlementPriceD18and not the newly set price of the epoch. Whenever the settlement price is outside the acceptable range, the callback will receive an incorrect price.The protocol team plans to create new epochs with that price which will lead to an epoch starting with prices outside the valid range.
Recommendation
Pass
epoch.settlementPriceD18instead ofsettlement.settlementPriceD18toassertionResolvedCallback().Resolution
Foil Team: In Vault we use the resolution
settlementPrice(not capped) to create the next epoch and compute new bounds. -
L-01 Low Frontrunning Pool Creation DOS Partially resolved
Description
When a new epoch is created by calling
Epoch.createValid()two virtual tokens are deployed and used to create a newUniswapV3Pool.The virtual tokens are deployed by the Epoch contract via the CREATE2 opcode. The owner of the Foil market will pass a salt parameter which will determine the address of the newly deployed tokens.
A malicious entity can frontrun the epoch creation transaction and use the salt passed in order to calculate the addresses of the two virtual tokens. These addresses can then be used to call UniswapV3Factory.createPool().
The pool for the two tokens will be created and when the Foil owner's transaction calls
createPool(), it will revert because the pool already exists and the epoch won't be created. This frontrunning can be executed to stop any epoch creation.Recommendation
Be sure to use a private network RPC when submitting the create transaction.
Resolution
Foil Team: Partially Resolved.
-
L-02 Low Overflow In DecimalPrice Library Arithmetic Error Resolved
Description
The function
sqrtRatioX96ToPriceis used to obtain price in several parts of the codebase. The issue lies with performing a square of twouint160numbers which could overflowuint256. Overflow occurs whensqrtRatioX96exceeds2^128 - 1.Recommendation
Perform
>> 96shift operation onsqrtRatioX96first before doing square operation. Alternatively, use Uniswap'sFullMath.mulDivwhich handles the intermediate overflow case.Resolution
Foil Team: The issue was resolved in PR#168.
-
L-03 Low Unused Function Unused code Resolved
Description
The
Position.getRequiredCollateral()function is not used anywhereRecommendation
Consider removing it if unnecessary
Resolution
Foil Team: The issue was resolved in PR#168.
-
L-04 Low Redundant Function Call Informational Resolved
Description
In
quoteModifyTraderPosition,validateNotSettledis called redundantly twice. Additionally, thevalidateSettlementSanityfunction inEpoch.solis unused and can be removed.Recommendation
Remove the redundant
validateNotSettledcall and delete the unusedvalidateSettlementSanityfunction.Resolution
Foil Team: The issue was resolved in PR#168.
-
L-05 Low FeeCollectorNft Is Transferable Informational Acknowledged
Description
The
FeeCollectorNftis used to assert a user is a fee collector. Fee collectors are given special privileges that allow them to take under collateralized loans.The
FeeCollectorNftis transferable, and a malicious fee collector could take advantage of this to sell theirFeeCollectorNftto users so they can take under collateralized loans, and jeopardize the health of the protocol.Recommendation
Do not allow fee collectors to transfer
FeeCollectorNfts.Resolution
Foil Team: Acknowledged.
-
L-06 Low Missing unchecked In Uniswap Libraries Arithmetic Error Resolved
Description
The
FullMathandTickMathlibraries were adapted from Uniswap, which relies on overflow wrapping behavior available only in Solidity versions <0.8. Foil’s implementation targets Solidity versions >0.8.2, where unchecked arithmetic is not default.Without wrapping these functions with
unchecked, phantom overflows may occur, causing unexpected reverts when intermediate values exceed 256 bits.For example,
mulDiv(type(uint).max,type(uint).max,type(uint).max)would revert in Solidity >0.8 but returntype(uint).maxin older versions.Recommendation
Wrap all relevant function bodies in unchecked to prevent phantom overflows. See the Uniswap v0.8 library implementation for reference:
https://github.com/Uniswap/v3-core/blob/0.8/contracts/libraries/FullMath.sol
Resolution
Foil Team: The issue was resolved in PR#168.
-
L-07 Low Disputer Never Updated Informational Resolved
Description
When a settlement price is submitted,
disputeris set asaddress(0). However, thedisputeris never updated in the even if a dispute happens and will remain asaddress(0).Recommendation
Consider removing
disputeras it is never used in the codebase or update it by getting the address from the oracle contract.Resolution
Foil Team: The issue was resolved in PR#169.
-
L-08 Low Inaccurate Custom Error Informational Resolved
Description
Epoch.validateNotSettled()will revert withEpochNotSettledif the epoch has expired and is not settled. This is slightly inaccurate because the main reason the revert happens is because the epoch has expired.Recommendation
Consider changing the error to
EpochExpiredResolution
Foil Team: The issue was resolved in PR#168.
-
L-09 Low Authorized Addresses Can’t Modify Positions Informational Resolved
Description
Currently, only the position owners can modify liquidity or trade positions. However, since positions are NFTs, users can assign operators or approve other addresses to manage their NFTs. An operator, even if authorized, cannot modify users' positions.
Additionally, the error message during the ownership check is
NotAccountOwnerOrAuthorized, which implies that authorized addresses should be able to modify positions.Recommendation
Consider allowing authorized addresses to modify positions.
Resolution
Foil Team: The issue was resolved in PR#169.
-
L-10 Low QuoterV2 Should Not Be Called On-Chain Informational Acknowledged
Description
quoteCreateTraderPosition()andquoteModifyTraderPosition()are both functions that are meant to be used to quote prices, however neither of them are marked as view functions. They cannot be marked as view functions because they useIQuoterV2.Uniswaps documentation on
IQuoterV2states, “These functions are not marked view because they rely on calling non-view functions and reverting to compute the result. They are also not gas efficient and should not be called on-chain.”This will lead to users having to pay gas costs if these functions are called.
Recommendation
Document to users that they should only call
quoteCreateTraderPosition()andquoteModifyTraderPosition()off-chain.Resolution
Foil Team: Acknowledged.
-
L-11 Low Typo Typo Resolved
Description
The Natspec comment above the
Epoch.getCollateralRequirementsForTradefunction has a typo: “Gets the reuired collateral amount…”Recommendation
Update the comment.
Resolution
Foil Team: The issue was resolved in PR#168.
-
L-12 Low Insufficient startingSqrtPriceX96 Validation Validation Acknowledged
Description
An Epoch is meant to have it's price bounded between its
minPriceD18andmaxPriceD18. Upon creation, the owner passes astartingSqrtPriceX96parameter to initialize the epoch's pool with. This price is not validated to be in the allowed range which allows a pool creation with invalid price.Recommendation
Validate the
startingSqrtPriceX96variable.Resolution
Foil Team: Later will be done by the vault, so will be secure.
-
L-13 Low View Function Should Account For Loss Logical Error Resolved
Description
The function
getPositionCollateralValueshould return the current value of a position. However, in the current implementation it only accounts for gains and not losses, therefore returning an inaccurate value if it is a losing position.Recommendation
Do not cap
totalNetValueto a minimum of zero, and subtract any losses fromdepositedCollateral.Resolution
Foil Team: The issue was resolved in PR#170.
-
L-14 Low Unnecessary Casting Informational Resolved
Description
When an epoch is created,
epoch.poolis assigned theIUniswapV3Poolvalue of the newly deployed pool. After that, epoch.pool is again casted toIUniswapV3Pool, which is redundant since it's already a variable of that type.Recommendation
You can use
epoch.poolwithout casting.Resolution
Foil Team: The issue was resolved in PR#168.
-
L-15 Low Unexpected Revert With Small Amounts DOS Resolved
Description
When modifying positions in the
TradeModule, theTrade.swapOrQuoteTokensExactInfunction is called, which subsequently calls the Uniswap swap router.The swap router performs the swap within the Uniswap pool, and the pool then invokes the
uniswapV3SwapCallbackfunction of the router.The
uniswapV3SwapCallbackfunction expects at least one of the delta amounts to be greater than zero. However, if the trade amounts are very small, the swap steps in the Uniswap pool can result in both delta amounts being zero, which causesuniswapV3SwapCallbackto revert.Therefore, it is possible for a user to create a small trade e.g. long 1 wei vGas, and then be unable to close it due to the swap amounts rounding down in Uniswap when calculating swap steps.
This will ultimately cause a revert within the
uniswapV3SwapCallback:require(amount0Delta > 0 ||amount1Delta > 0);. Consequently, a user has a position they are unable to close.Recommendation
Consider implementing minimum trade sizes and/or documenting this behavior.
Resolution
Foil Team: The issue was resolved in PR#154.
-
L-16 Low MarketNotInitialized Is Never Thrown Informational Resolved
Description
The
onlyOwnermodifier inConfigurationModuleshould revert with theMarketNotInitialized()error if theownerof the market is not set.However, the
onlyOwnermodifier first checks if themsg.senderis the current market owner and if they are not, the transaction will revert withOnlyOwner()error.In the case where the market is not initialized, i.e
owner == address(0), the revert reason will always beOnlyOwner(), since nobody can send a call fromaddress(0). In result, theMarketNotInitialized()error will never be used.Recommendation
Switch the order of the two ifs.
Resolution
Foil Team: The issue was resolved in PR#168.
-
L-17 Low Fee Collectors Can Block Initialization Warning Acknowledged
Description
ConfigurationModule.initializeMarket()is used to create the market. It also mints theFeeCollectorNFT to the fee collectors. If any of them don't support receiving NFTs or revert intentionally, the market won't be created.Recommendation
Be aware of this situation. If this happens, you can call
initializeMarketagain, but this time without the specific fee collector.Resolution
Foil Team: Acknowledged.
-
L-18 Low bondAmount Is Not Sufficiently Validated Warning Resolved
Description
Epoch.validateEpochParams()validates that thebondAmountshould be a positive number. However, it should be at least as big as the result of thegetMinimumBond()function of the UMA oracle. Otherwise, the assertions will not be accepted.Recommendation
Make sure to pass a valid
bondAmountwhen creating the market.Resolution
Foil Team: The issue was resolved in PR#172.
-
L-19 Low Uniswap tickSpacing May Be Changed Warning Acknowledged
Description
Market.getTickSpacingForFee()returns the Uniswap tick spacing associated with the given fee tier. The tick spacings are hardcoded, but the Uniswap Factory has a function enableFeeAmount() which allows the owner to change the fee tiers. If this happens, the Foil contracts may use stale data.Recommendation
Be aware of the risk.
Resolution
Foil Team: Acknowledged.
-
L-20 Low Traders Unable To Close Profitable Position Logical Error Acknowledged
Description
Fee Collectors opened LP positions at the beginning of an epoch and deposit collateral after they've earned fees. This collateral could be streamed in periodically or provided in bulk at settlement.
Due to the under-collateralized LP positions, traders may find themselves unable to exit profitable positions until Fee Collectors deposit collateral. As Fee Collectors are expected to hold large LP positions, this may affect a large group of traders.
This leads to temporarily locked funds and potential loss of yield for traders who are unable to close a profitable position promptly.
Recommendation
Consider implementing a minimum deposit amount for fee collectors. Or else, document this risk for users.
Resolution
Foil Team: Acknowledged.
-
L-21 Low tokenById Revert Reason Error string Resolved
Description
ERC721EnumerableStorage.tokenByIndex()reverts with a custom error if a non existent token was passed. It does so whenindex > totalSupply(). Because the index ofallTokensstarts from 0, this statement will not catch all possible cases.For example, when
totalSupplyis 1, there is only 1 token in theallTokensarray, at index 0 and index 1 is empty. If we calltokenByIndex(1)it won't enter the if statement and will revert with index out of bounds error instead of the custom error.Recommendation
Change the condition to
index >= totalSupply()Resolution
Foil Team: The issue was resolved in PR#169.
-
L-22 Low Comment Typo Logical Error Resolved
Description
The comment
// net vEth from oritinal positon minus the vEth to zeromisspells “original”.Recommendation
Correct the typo.
Resolution
Foil Team: The issue was resolved in PR#168.
-
L-23 Low Epoch End Time Off-by-One Typo Resolved
Description
Epoch trade and liquidity activity is prevented once the
block.timestamp >= self.endTimeas can be seen in functionvalidateNotSettled.However, price submissions are restricted with
block.timestamp > epoch.endTimewithin functionvalidateSubmission.When the
block.timestamp == epoch.endTime, prices can be submitted since market activity is disallowed at that point, but submissions are restricted with current validation.Recommendation
Adjust the validations appropriately within the
UMASettlementModuleor clearly document this behavior as this is extremely edgecase behavior.Resolution
Foil Team: The issue was resolved in PR#169.
No findings match.
Invariants 37
The review's fuzzing suite asserted 37 invariants. 21 held and 16 did not.
Every invariant tested
| ID | Invariant | Result |
|---|---|---|
GLOBAL-01 | The price of vGAS should always be in range of the configured min/max ticks. | Held |
GLOBAL-02 | There should never be any liquidity outside of the [min, max] range of an epoch. | Held |
GLOBAL-03 | The amount of vETH in the system, position manager & swap router should equal the max | Held |
GLOBAL-04 | supply The amount of vGAS in the system, position manager & swap router should equal the max | Held |
TRADE-01 | supply. The debt of a position should never be > the collateral of the position. | Held |
TRADE-02 | Long positions have their debt in vETH and own vGAS | Broken |
TRADE-03 | Short positions have their debt in vGAS and own vETH. | Broken |
TRADE-04 | Trader should never have both borrowedVGas and borrowedVEth be | Held |
TRADE-05 | non-zero. Trader's pending loss in ETH-worth should never exceed collateral put down (should never be in negative equity) | Broken |
TRADE-06 | after creating/modifying trade position, the depositedCollateralAmount > debtValue - | Held |
TRADE-07 | tokensValue After creating a trade position deposited collateral should be non-zero | Held |
TRADE-08 | After user closes a trade position, no vGAS, vETH, borrowed vGAS, borrowed vETH | Held |
TRADE-09 | After creating a trader position, positionSize is non-zero. | Held |
TRADE-10 | createTradePosition should create a unique positionId | Held |
LIQUID-01 | The debt of a position should not be > the collateral of the position. | Held |
LIQUID-02 | A open LP position should not own any vETH or vGAS. | Held |
LIQUID-03 | After all LP positions have been closed, for the remaining trader positions: net shorts == net | Held |
LIQUID-04 | longs. Position.depositedCollateralAmount should be at least the required collateral for their position | Held |
LIQUID-05 | if their position turned into a Trade type. QuoteLiquidityPositionTokens should match how many tokens are borrowed and how much liquidity is added after creating an LP position | Held |
LIQUID-06 | with createLiquidityPosition After creating an LP position, liquidity in the Uni pool increases | Held |
LIQUID-07 | After increasing an LP position, liquidity in the Uni pool increases | Held |
LIQUID-08 | After decrease an LP position, liquidity in the Uni pool decreases | Broken |
LIQUID-09 | After partial decrease an LP Position, should not get InsufficientColateral revert | Broken |
LIQUID-10 | (unexpected in this case) createLiquidityPosition should create a unique positionId | Held |
SETTLE-01 | It should always be possible to settle all positions after the epoch is settled. | Broken |
SETTLE-02 | After settlement with settlePosition, position should not have any borrowedvETH nor borrowedVGAS, and no vGAS nor vETH | Held |
SETTLE-03 | (cleared out position) Settlement should not revert with ERC20InsufficientBalance. | Broken |
SETTLE-04 | Settlement should not panic underflow | Broken |
EPOCH-01 | Position with non zero loan amount for lp should always have non-zero collateral | Held |
VLT-01 | required. Vault functions should never revert with ERC20InsufficientBalance error | Broken |
VLT-02 | totalPendingDeposits should be sum of deposit requests - withdrawRequestDeposit(s) | Broken |
VLT-03 | totalPendingWithdrawals should be sum of requestRedeem(s) - | Broken |
VLT-04 | withdrawRequestRedeem(s) pendingSharesToBurn should always be less than or equal to total supply of shares | Broken |
VLT-05 | Pending transaction requested epoch should never be greater than current epoch | Broken |
VLT-06 | Vault should not Panic | Broken |
VLT-07 | mint/deposit should decrease balance of shares in the Vault contract, total supply | Broken |
VLT-08 | should stay the same redeem/withdraw should decrease total supply | Broken |
More from Sapience
All 6 reports-
LayerZero Composer
7 findings 7 findings: 5 low, 2 informational -
Foil Vault and Prediction Market
61 findings2 critical · 3 high 61 findings: 2 critical, 3 high, 7 medium, 26 low, 23 informational -
Sapience
87 findings8 high 87 findings: 8 high, 18 medium, 30 low, 31 informational -
Foil Vault
35 findings2 critical · 2 high 35 findings: 2 critical, 2 high, 14 medium, 17 low
Put your code through the same review.
This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.
