Foil engaged Guardian to review the security of its Vault, providing liquidity across the epoch's price range. From the 19th of November to the 27th of November, a team of 6 auditors reviewed the source code in scope.
- Published
- Review window
- November 19 to 27, 2025
- Language
- Solidity
- Chains
- Ethereum
- Sector
- Derivatives
- 2 Critical
- 2 High
- 14 Medium
- 17 Low
- 0 Informational
Scope
Overview
Foil engaged Guardian to review the security of its Vault, providing liquidity across the epoch's price range. From the 19th of November to the 27th of November, a team of 6 auditors reviewed the source code in scope.
Issues Detected Throughout the engagement 4 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 the Vault.
Security Recommendation Given the number of High and Critical issues detected, Guardian supports a secondary security review of the Vault at a finalized frozen commit. Furthermore, the Foil team should increase testing with various settlement scenarios which may present opportunities to DoS the Vault’s operations.
Findings 35
-
C-01 Critical Total DoS Of Epochs DoS Resolved
Description
Users can create redemption requests for their vault shares using the
requestRedeemfunction, which will increase thetotalPendingWithdrawalsvariable. The only requirement regarding the request amount is that the users' balance must be sufficient.Users’ shares are neither transferred nor burned at the creation of the request. Since these shares are transferable, a user can create a request using
requestRedeem, transfer shares to another address, create another request, and repeat this process as many times as desired.As a result,
totalPendingWithdrawalswill be inflated. This allows users to manipulatependingSharesToBurnandtotalSupply, or even cause a complete DoS in the system due to an underflow here in the_reconcilePendingTransactionsfunction.Recommendation
The redeem workflow should transfer tokens during the request creation process, similar to the deposit flow.
The
requestRedeemfunction should transfer shares from the user to the vault. And then, the_redeemSharesfunction should burn these shares from the vault instead of burning from the owner.Resolution
Foil Team: The issue was resolved in PR#193.
-
C-02 Critical Bond Cannot Be Returned Logical Error Resolved
Description
When
submitMarketSettlementPriceis called inVault.sol, the vault is set as the asserter in the UMA oracle. Upon successful settlement of the assertion price, the bond is returned to the vault.However, there is no mechanism to refund this bond to the user who submitted the price and paid for it. Additionally, there is no recovery function, causing the bond to remain permanently stuck in the vault.
Recommendation
In
UMASettlementModule.submitSettlementPrice, allow the caller to specify an address to be set as the asserter. Then, inVault.submitMarketSettlementPrice, ensure the caller’s address is passed as the asserter to enable proper bond refunds.Resolution
Foil Team: The issue was resolved in PR#181.
-
H-01 High tradeRatio Rounded In Wrong Direction Rounding Resolved
Description
The recommendation of H-03 is to round up the trade ratio when going towards the long direction as a short. However, the fix implemented is the opposite - the trade ratio is being rounded down if
isLongDirectionand rounded up otherwise. Since the problem is not solved, the insolvency issue still exists.Currently, tradeRatioD18 is used to compute both
closePnLandvEthAmount/borrowedVEth. Foil's goal should always be to maximizeborrowedVEthand minimizeclosePnLandvEthAmount. Because of this, different rounding directions should be used depending on what's being calculated.Recommendation
The end goal should be to maximize the
borrowedVEthand minimize thevEthAmountandclosePnL. To accomplish this, you can have two different tradeRatios - one rounded down and one rounded up. You will also have three differentvEthToZero.The first one will be to calculate the
closePnLand you will use thetradeRatiothat’s rounded down if the position is a long, otherwise use the rounded up one. The secondvEthToZerowill always use thetradeRatiothat’s rounded down and the thirdvEthToZerowill always use thetradeRatiothat’s rounded up.Next, you will also have two different
vEthFromZerofor eachvEthToZero. Finally, in theif/elsestatement where you setborrowedVEthandvEthAmountyou will choose the appropriatevEthFromZero.For the
ifcase you should use thevEthFromZerowhich absolute value is bigger to maximize borrow and for theelsecase you should use thevEthFromZerowhich absolute value is smaller to minimize the credited vETH.Resolution
Foil Team: The issue was resolved in PR#198.
-
H-02 High Faulty Quoting With Small Amounts Logical Error Resolved
Description
Proof of concept: PoC
When a new epoch is created, the Vault uses the assets in its reserves to deposit them as collateral in order to create a liquidity position. The vault will call
quoteLiquidityPositionTokensto get theamount0andamount1that can be added as liquidity for the available collateral.However,
Epoch.requiredCollateralForLiquidity()now adds 1 toloanAmount0andloanAmount1. This means the actual required collateral for the position may exceed the available collateral in the vault.In result, the transaction will revert because of
InsufficientCollateral()and the epoch creation will not be successful. This issue can occur with non-trivial amounts, for example1e17.Recommendation
Consider implementing higher minimum collateral amounts and documenting this behavior for clarity. Another option to consider is subtracting 1 wei from
amount0andamount1when creating theLiquidityMintParams, which should account for the additional 1 wei.Resolution
Foil Team: The issue was resolved in PR#197.
-
M-01 Medium Position With Zero Collateral Logical Error Resolved
Description
Proof of concept: PoC
When a position is operating with small amounts, the required collateral for the position can be calculated to be zero due to rounding when calculating value of debt. Consequently, a user can modify their position to a size within a couple thousand wei and have to provide zero collateral.
All their prior deposited collateral would be returned, and their position would have no backing. In the original review, this issue was not possible since the minimum
requiredCollateralwas always at least 2 wei.Recommendation
Have a minimum required collateral.
Resolution
Foil Team: The issue was resolved in PR#198.
-
M-02 Medium Inaccessible onlyOwner Functions Access Control Acknowledged
Description
Since the
Vaultcontract will be executing theonlyOwner createEpoch()function, it will be set as the owner of the foil system. TheConfigurationModule.updateMarket()function can be called by the Foil owner to update the market parameters.However, this function is never called in the
Vaultcontract. This means the market can never be updated once the ownership is transferred to the contract. There is also no call totransferOwnershipinVault, so you can't just use a new vault as the owner.Recommendation
Add calls to
updateMarketandtransferOwnershipin the vault.Resolution
Foil Team: We are keeping everything immutable.
-
M-03 Medium DoS Via Deposit Before First Epoch DoS Resolved
Description
Deposits before the first epoch are possible, with a minimum deposit amount of 1e3. Any pending deposits before the first epoch are utilized to establish the initial liquidity position within the
_createNewLiquidityPositionfunction.This function deducts a dust amount of 1e4 from the deposited collateral amounts. If a user intentionally deposits an amount between 1e3 and 1e4 before the first epoch, and there are no other deposits, the initialization will fail due to underflow at this line.
Recommendation
Consider setting the minimum deposit amount higher than the dust. Alternatively, keep the codebase unchanged but externally deposit the difference if this situation occurs.
Resolution
Foil Team: The issue was resolved in PR#197.
-
M-04 Medium DoS Via Frontrunning Pool Creation DoS Resolved
Description
After the implementation of the Vault, epoch settlements and the creation of the new epoch happens at the same transaction via callbacks. Because of this atomic behavior, failure of the pool creation for the next epoch will DoS the settlement of the previous epoch.
An attacker can precompute the virtual token addresses and create the Uniswap pool with these addresses as creating pools is permissionless in the Uniswap. This will cause
Epoch.createValidfunction to revert while callingIUniswapV3Factory.createPooldue torequire(getPool[token0][token1][fee] == address(0))check in the factory.The attack can cause complete blocking of the epoch settlements and creations. However, attackers must keep frontrunning and create new pools every time someone tries to
settleAssertionin the optimistic oracle.Recommendation
Check whether the pool already exists or not by calling the
getPoolin the factory instead of directly calling thecreatePool. If the pool already exists, check whether it was already initialized or not and set the starting price. Alternatively, always make sure to use a private RPC to prevent frontrunning.Resolution
Foil Team: The issue was resolved in PR#209.
-
M-05 Medium Gas Griefing Of Epoch Creation Griefing Resolved
Description
When a new epoch is created,
block.timestampis used as the salt for generating two virtual tokens. In_createVirtualToken, a loop probes for an available salt if a collision occurs.However, the salt increments by 1 on each iteration, making it highly predictable and susceptible to front-running. An attacker can exploit this predictability to deliberately create collisions.
During testing, each iteration of the loop was found to cost approximately 600k gas, making it feasible for an attacker to force the epoch creation process to fail due to an Out-of-Gas error.
Recommendation
Consider using a less predictable and more robust mechanism for generating the salt, such as hashing with block variables. Alternatively, consider using CREATE3 which ensure that the address is only dependent on deployer and salt.
Resolution
Foil Team: The issue was resolved in PR#197.
-
M-06 Medium Positions With 0 Collateral Logical Error Resolved
Description
When a position is operating with small amounts, the required collateral for the position can be calculated to be zero due to rounding when calculating value of debt. Consequently, a user can modify their position to a size within a couple thousand wei and have to provide zero collateral.
All their prior deposited collateral would be returned, and their position would have no backing. In the original review, this issue was not possible since the minimum
requiredCollateralwas always at least 2 wei.Recommendation
Have a minimum required collateral.
Resolution
Foil Team: The issue was resolved in PR#198.
-
M-07 Medium Fee Collector Can Hoard Fees Logical Error Acknowledged
Description
M-01 of the previous audit was not addressed. 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-08 Medium Decreasing LP May Require Collateral Logical Error Acknowledged
Description
Proof of concept: PoC
The M-05's recommendation to let the user specify an amount of collateral to be added when decreasing a liquidity position has not been implemented which leaves the problem unsolved.
Recommendation
Allow the user to supply additional collateral when decreasing their position.
Resolution
Foil Team: Letting users know to decrease by larger than a few wei is acceptable due to this rounding issue.
-
M-09 Medium vEth Credited When Closing A Position Logical Error Resolved
Description
Proof of concept: PoC
When closing a position, the
vEthToZerois calculated asinitialSize * tradeRatioand should be equal to thesignedTradedVEth. However, Solidity division truncates the result. Because of this,tradeRatiowill be slightly off - both when rounded down or up - thereforevEthToZeroas well.Even though
vEthFromZeroshould be roughly equal totargetSize * tradeRatio, the value assigned to it (fortargetSize = 0) will be non-zero - positive or negative depending on the rounding. After that the absolute value ofvEthFromZerowill be assigned tovEthAmount.In result, closed positions end up having positive
vEthAmount, which is especially bad for long positions. This ultimately leads to an undercollateralized market, preventing the last user from settling.Recommendation
Consider setting the
vEthAmountof the new position to 0, if its size is 0 as well.Resolution
Foil Team: The issue was resolved in PR#198.
-
M-10 Medium resolutionCallback Fails On Small Amounts Logical Error Resolved
Description
Function
_createEpochAndPositionpassing is critical to the Vault's flow, since if theresolutionCallbackfails the Vault's functionality is stopped. If the Vault has more collateral than the current minimum collateral, the Vault attempts to_createNewLiquidityPosition.The issue is that even with enough collateral to meet the minimum threshold, is it not guaranteed that the liquidity to-be minted from the calculated amount0 and amount1 is greater than 0 due to Uniswap rounding down on small amounts, which would trigger a revert in
UniswapV3Pool.mint:require(amount > 0);Ultimately, the Vault will attempt to mint which will revert, causing the callback to fail and the mints/epoch creation will not occur.
Recommendation
Consider enforcing a higher minimum collateral.
Resolution
Foil Team: The issue was resolved in PR#197.
-
M-11 Medium Cleared borrowedVEth Logical Error Resolved
Description
Proof of concept: PoC
When a long position is being modified, its
borrowedVEthis set to the absolute value ofvEthFromZero. In some cases, it's possible to have a small amount ofvGasAmountwith 0vEthFromZerodue to the traded vETH matching thevEthToZero, primarily when operating with small position sizes and trade prices.This leads to a long position that does not have a loaned amount. This leaves the Foil contract with less available collateral than it should have and in result, the last user will not be able to exit.
Recommendation
Validate that any opened long position has positive
borrowedVEth:require(borrowedVEth > 0)Resolution
Foil Team: The issue was resolved in PR#198.
-
M-12 Medium Resetting Does Not Refund Tokens Logical Error Resolved
Description
Proof of concept: PoC
When a user calls
withdrawRequestRedeem(), if their balance after is less thanminimumCollateralthenresetTransaction()will set their pending amount to zero. However,totalPendingWithdrawalswill only be decremented by the amount of shares the user passes in.This will lead to
totalPendingWithdrawalsbeing larger than the actual amount that is intended to be withdrawn. A malicious user could continuously callrequestRedeem()in conjunction withwithdrawRequestRedeemin order to inflatetotalPendingWithdrawalsto be larger thancollateralFromPreviousEpochplustotalPendingDeposits.This will cause a DoS via underflow when
_reconcilePendingTransactions()is called. Additionally, when a user callswithdrawRequestDeposit(),totalPendingDepositsis only decremented byassets. This will lead to the user’s remaining tokens to be donated to other users of the protocol.Recommendation
If the user’s remaining amount is less than the
minimumCollateral, then decrementtotalPendingWithdrawalsby the full amount or refund the remainder of their balance before callingresetTransaction(), depending on if it is a redeem or deposit.Resolution
Foil Team: The issue was resolved in PR#197.
-
M-13 Medium Collateral Of Epoch Ahead Can Be Stolen Logical Error Resolved
Description
When updating share price after an epoch, if no collateral was received, the share price is set to
1e18. This creates a significant issue as depositors can redeem their entire collateral even though no collateral was received after closing the liquidity position.Effectively, this allows depositors to withdraw funds that belong to the next epoch's depositors, who have already transferred their collateral into the contract.
Recommendation
Initially, setting
sharePriceto0instead of1e18was considered. However, this would affect the minting of new shares for the next epoch.As a solution, if no collateral is received, set the
sharePricefor the current epoch to0while ensuring thesharePricefor the next epoch is reset to1e18.Resolution
Foil Team: The issue was resolved in PR#197.
Guardian Team: The issue was not fixed. The price of the epoch is hardcoded to 1e18 if no collateral is received.
Foil Team: Let’s halt the vault and allow a request deposit of something higher than 1e8 which will fix this.
-
M-14 Medium Tick Modulus Hardcoded For Fee Tier Logical Error Resolved
Description
_calculateTickBounds()uses modulus 200 in order to set the target tick value to the closest acceptable tick range. However, Foil is compatible with multiple fee tiers, but the value 200 is not.For instance, the 0.3% fee tier uses a tick spacing of 60, which is not a divisor of 200. This will cause a revert when attempting to create the epoch.
Recommendation
Instead of hardcoding 200, use the appropriate value for the fee tier of the pool.
Resolution
Foil Team: The issue was resolved in PR#197.
-
L-01 Low Single Vault Circuit Should Not Skip Iteration Logical Error Acknowledged
Description
In
_calculateNextStartTime, if there is a significant delay in resolving an epoch, the vault skips an entirevaultCycleDurationto maintain synchronization with other vaults in the circuit.However, if only a single vault exists in the circuit, this synchronization is unnecessary. Skipping
vaultCycleDurationin this scenario causes unnecessary downtime where no vaults are available.Recommendation
Introduce a condition to check if only one vault exists in the circuit. In such cases, avoid skipping the
vaultCycleDurationand instead start the next epoch immediately after resolution.Resolution
Foil Team: Acknowledged.
-
L-02 Low Overflow In DecimalPrice Library Overflow Resolved
Description
There is a comment left on L-02 that Foil now uses
OpenZeppelin's code for its calculations, but the code inDecimalPriceis not changed - it's still possible for the result of the multiplication to exceed 2^256-1Recommendation
Fix the issue.
Resolution
Foil Team: The issue was resolved in PR#202.
-
L-03 Low Deposit/Withdraw On Behalf Of Others Access Control Acknowledged
Description
In the Vault contract, only the owners can request deposits and redemptions. However, claiming of these requests are external and anyone can claim on behalf of the owner.
Even though the owner created these requests, timing of the claim might matter for the owner and these actions should be access controlled.
Recommendation
Not allow other users to claim on behalf of owners.
Resolution
Foil Team: I don’t think there’s any advantage to claiming after the epcoh is settled, if anything, these functions not being gated gives us flexibility to force redemptions to clear any pending txns.
-
L-04 Low New Vaults Cannot Be Added Warning Acknowledged
Description
totalVaultsis stored as an immutable variable whenVault.solis created. This implies that no new vaults can be added after the first batch of vaults. This may run counter to protocol design that new collateral types may be added.Recommendation
Consider allowing for new vaults to be added.
Resolution
Foil Team: At least the plan right now is not to add any more vaults once a vault is initialized.
-
L-05 Low minCollateral Redeem Denomination Validation Acknowledged
Description
Vault.requestRedeemrequires the amount of shares being redeemed to be greater thanminimumCollateral. However,minimumCollateralis denominated in assets, not shares.Recommendation
Consider having different validation with the proper denomination.
Resolution
Foil Team: Maybe a rename of the variable would be better. Will do that.
-
L-06 Low Cheaper Settlement Delay Logical Error Acknowledged
Description
As pointed out in this issue, anyone can dispute rightful assertions to delay the start of a given epoch by paying the bond of $5000.
Since now anyone can submit a price, the same entity can assert a rightful price and dispute it at the same time towards the end of the
assertionLivenessperiod.By doing so, they will receive half of their disputer bond. In result, the cost of the attack will be reduced from $5000 to $2500.
Recommendation
Be aware of the reduction in cost.
Resolution
Foil Team: Acknowledged.
-
L-07 Low Insufficient Balance For Last Withdrawer Logical Error Resolved
Description
The last user attempting to settle their position may be unable to do so if:
market.collateralAsset.balanceOf(address(this)) < withdrawableCollateral.This discrepancy can occur due to minor rounding errors during trade or liquidity activities, leaving the contract balance short by a few wei. As a result, the user cannot fully recover their collateral.
Recommendation
If
market.collateralAsset.balanceOf(address(this))is less thanwithdrawableCollateral, consider transferring the remaining contract balance to the user instead.This ensures the user can recover as much of their collateral as possible without leaving residual funds in the contract.
Resolution
Foil Team: The issue was resolved in PR#202.
-
L-08 Low Consider Adding Exception Handling Mechanisms Logical Error Resolved
Description
With the implementation of the
Vaultcontract, the settlement of the previous epoch and the creation of the next epoch happen in a single transaction.Because of this, an unexpected failure at any step of the process (e.g., settlement, new epoch creation, quoting, or adding new liquidity) may cause the system to halt.
Recommendation
Consider implementing mechanisms like
try/catchblocks along the transaction flow, allowing unexpected issues to be resolved externally and ensuring the system remains operational.Resolution
Foil Team: The issue was resolved in PR#209.
-
L-09 Low minTradeSize For Liquidty Turned Trade Logical Error Acknowledged
Description
When closing a liquidity position, it can turn into a
Tradeposition if it cannot be repaid. If the amount left for the newTradeposition is less than theminTradeSize, the owner of the position will not be able to directly close it.They will have to make a bigger trade and close if after that. By doing so, they suffer losses because of price impacts.
Recommendation
Be sure to warn the users of Foil about this case.
Resolution
Foil Team: Acknowledged.
-
L-10 Low Traders Unable To Close Profitable Position Logical Error Acknowledged
Description
L-20 of the previous audit was not addressed. 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-11 Low Epoch startTime Not Utilized Logical Error Resolved
Description
Epochs in Foil have
startTime. However, liquidity and trades for a given epoch can be executed as soon as the epoch is created, no matter itsstartTime.Recommendation
Be aware of this behavior.
Resolution
Foil Team: The issue was resolved in PR#202.
-
L-12 Low Incorrect Error String Logical Error Resolved
Description
"Previous deposit request is not in the same epoch" message in the
withdrawRequestRedeemfunction (L642) should be "Previous withdraw request is not in the same epoch".Recommendation
Change the error string in the require statement.
Resolution
Foil Team: The issue was resolved in PR#202.
-
L-13 Low Pending Functions Might Be Misleading Informational Resolved
Description
Vault contract has
pendingDepositRequestandpendingRedeemRequestfunctions. However, these functions do not check the transaction type of the pending request and directly returnuserPendingTransactions[owner].pendingDepositRequestfunction can return a redeem request and vice versa.Recommendation
Consider checking the transaction type in these functions, or implement a single function (e.g.
pendingRequest) for all transaction types.Resolution
Foil Team: The issue was resolved in PR#202.
-
L-14 Low Insufficient Trade Size Validation Validation Resolved
Description
A
minTradeSizeconfiguration has been added to the Market in response to L-15. This works fine forcreateTraderPosition, but it's wrongly implemented inmodifyTraderPosition. It calls_checkTradeSize(size)to ensure the trade size is bounded.However, the argument passed is size (the final size), not
deltaSize. Because of this, small trades (below theminTradeSize) will still be successfully executed.Recommendation
Pass
deltaSizeinstead ofsizeto_checkTradeSizeto ensure trades are beyond a minimum delta.Furthermore, consider also validating the resulting size of the position, such that situations do not arise where a user creates a large position, decreases by position size-1, such that the delta trade size is large enough but the final position size is 1 wei.
Resolution
Foil Team: The issue was resolved in PR#198.
-
L-15 Low Fee Collectors Can Make Unbacked Trade Positions Logical Error Acknowledged
Description
Proof of concept: PoC
Because the fee collector is not required to deposit collateral for their position, situations can arise where fee collectors close their liquidity position yet the the resulting position will become a Trade position with non-zero borrowed amounts but zero credit amounts.
This is because fee collectors will typically enter the following case
if(position.depositedCollateralAmount < collateralDelta)due to no collateral requirements which will set a non-zeroborrowedvETH.Consequently, an unbacked Trade position may be created that cannot be directly decreased and closed, since the
deltaSizewould be zero andErrors.DeltaTradeIsZero()would be triggered.Recommendation
Clearly document this behavior and even consider if
FeeCollectorsshould close their LP positions before epoch settlement as this allows them to profit without ever depositing collateral.Resolution
Foil Team: Acknowledged.
-
L-16 Low Negative Ticks Are Rounded Up Logical Error Acknowledged
Description
During epoch creation, in
_calculateTickBoundspositive ticks are rounded down but negative ticks are rounded up, which could lead to unexpected behavior.Recommendation
Consider rounding down negative ticks for consistency or clearly documenting this behavior.
Resolution
Foil Team: Acknowledged.
-
L-17 Low Vault Is Not EIP Compliant EIP Resolved
Description
Multiple functions in the Vault are not EIP compliant.
totalAssets: Must not revert. However, it can revert if thepositionIdis not valid.convertToShares: Must not revert. However, it can revert iftotalAssets == 0.- preview functions: Must be as close as possible to on-chain conditions and must not revert based
on vault specific user/global limits. May only revert that would also cause mint/withdraw etc. to revert too. However, these function are not supported at all.
deposit: Mints shares by depositing exactlyassetsamount. However, the amount is ignored in the
codebase.
mint: Mints exactly thesharesamount. However, the amount is ignored in the codebase.withdraw: Burns shares and sends exactly theassetsamount. However, the amount is ignored in
the codebase.
redeem: Burns exactly thesharesamount. However, the amount is ignored in the codebase.
The contract incorrectly signals supporting the ERC4626 interface with the
supportsInterfacefunction.Recommendation
One option is trying to make the contract EIP compliant. However, based on what the contract wants to achieve, it might be best to not support ERC4626.
Consider removing
interfaceId == type(IERC4626).interfaceIdline from thesupportsInterfacefunction to prevent incorrect signaling for the external integrators.Resolution
Foil Team: The issue was resolved in PR#202.
No findings match.
Invariants 37
The review's fuzzing suite asserted 37 invariants. 25 held and 12 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 | Held |
GLOBAL-04 | max supply The amount of vGAS in the system, position manager & swap router should equal the | Held |
TRADE-01 | max 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 | Broken |
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 | Held |
SETTLE-03 | vGAS nor vETH (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 | Held |
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 | Held |
VLT-05 | Pending transaction requested epoch should never be greater than current epoch | Held |
VLT-06 | Vault should not Panic | Broken |
VLT-07 | mint/deposit should decrease balance of shares in the Vault contract, total supply | Held |
VLT-08 | should stay the same redeem/withdraw should decrease total supply | Held |
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 Updates
36 findings2 critical · 4 high 36 findings: 2 critical, 4 high, 7 medium, 23 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.
