Skip to content

akiratechhq/review-opyn-squeeth-2021-11

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Project
Opyn Squeeth
Client
Opyn
Date
December 2021
Reviewers
Andrei Simion
@andreiashu
Daniel Luca
@cleanunicorn

Table of Contents

Details

  • Client Opyn
  • Date December 2021
  • Lead reviewer Andrei Simion (@andreiashu)
  • Reviewers Daniel Luca (@cleanunicorn), Andrei Simion (@andreiashu)
  • Repository: Opyn Squeeth
  • Commit hash 474413cbba52708c953a23a500acc4194735c87b
  • Technologies
    • Solidity
    • Typescript

Issues Summary

SEVERITY OPEN CLOSED
Informational 0 0
Minor 0 0
Medium 0 0
Major 0 1

Executive summary

This report represents the results of the engagement with Opyn to review Opyn Squeeth.

The review was conducted over the course of 2 weeks from November 29 to December 10, 2021. A total of 15 person-days were spent reviewing the code.

The code is well written, and the design is thoroughly thought out. There are unit and integration tests, and the code is gas efficient.

The team has been very helpful in guiding our understanding of the design and its implementation - especially since some of the constructs are somewhat novel in the crypto space.

Week 1

We started by reviewing the provided documentation and the initial kickoff recording during the first week.

Within the first few days of the review, we identified an issue with the way ERC721 tokens are handled and raised it with the team.

It became clear that this issue had been identified in a previous code review by the ToB team, and we were given access to their report.

Week 2

We kept close contact with the Squeeth team on an almost daily basis. We went through the mechanics for funding rate, vault liquidations, the incentives that will keep the Mark Price within certain bounds relative to Index, Crab Strategy, and different parameters for the funding period.

In the second week we reviewied patches that addressed some of the issues that were found in the code (by us and previously by ToB team).

We expressed our concerns to the team regarding the financial constructs involved in the Squeeth product - we recommend seeking further review of the code and high-level mechanics from a third party that is specialized in this area. While the code might be correct from a security standpoint, we cannot guarantee that the game-theoretical model is going to perform as predicted in all conditions.

Scope

The initial review focused on the Opyn Squeeth repository, identified by the commit hash 474413cbba52708c953a23a500acc4194735c87b.

We focused on manually reviewing the codebase, searching for security issues such as, but not limited to, re-entrancy problems, transaction ordering, block timestamp dependency, exception handling, call stack depth limitation, integer overflow/underflow, self-destructible contracts, unsecured balance, use of origin, costly gas patterns, architectural problems, code readability.

Includes:

  • packages/hardhat/contracts/core/Controller.sol
  • packages/hardhat/contracts/core/Oracle.sol
  • packages/hardhat/contracts/core/WPowerPerp.sol
  • packages/hardhat/contracts/core/ShortPowerPerp.sol
  • packages/hardhat/contracts/periphery/ShortHelper.sol
  • packages/hardhat/contracts/libs/Power2Base.sol
  • packages/hardhat/contracts/libs/Uint256Casting.sol
  • packages/hardhat/contracts/libs/ABDKMath64x64.sol
  • packages/hardhat/contracts/libs/VaultLib.sol
  • packages/hardhat/contracts/libs/OracleLibrary.sol
  • packages/hardhat/contracts/external/WETH9.sol
  • packages/hardhat/contracts/import/Uni.sol
  • packages/hardhat/contracts/interfaces/IWETH9.sol
  • packages/hardhat/contracts/interfaces/IWPowerPerp.sol
  • packages/hardhat/contracts/interfaces/IOracle.sol
  • packages/hardhat/contracts/interfaces/IERC20Detailed.sol
  • packages/hardhat/contracts/interfaces/IShortPowerPerp.sol
  • packages/hardhat/contracts/interfaces/IController.sol
  • packages/hardhat/contracts/strategy/CrabStrategy.sol
  • packages/hardhat/contracts/strategy/base/StrategyFlashSwap.sol
  • packages/hardhat/contracts/strategy/base/StrategyBase.sol
  • packages/hardhat/contracts/strategy/base/StrategyMath.sol

Issues

Issue status: Fixed Major

Description

Edit: issue fixed in opynfinance/squeeth-monorepo#630.

The ShortPowerPerp contract is used to generate an NFT, which represents the user's ownership of a vault within the Squeeth platform:

code/packages/hardhat/contracts/core/ShortPowerPerp.sol#L38-L46

    /**
     * @notice mint new NFT
     * @dev autoincrement tokenId starts at 1
     * @param _recipient recipient address for NFT
     */
    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {
        // mint NFT
        _mint(_recipient, (tokenId = nextId++));
    }

The issue is that the function uses OpenZeppelin's ERC721._mint function instead of _safeMint. The difference between these two functions is that _safeMint ensures that the onERC721Received function is called on the destination address to handle the receipt of the NFT (for non-contract addresses this is a no-op):

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
        _mint(to, tokenId);
        require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

When transferring Uniswap V3 LP tokens, since they implement the EIP-721 standard, the safeTransferFrom function should be called instead (the NonfungiblePositionManager contract extends OpenZeppeling's EIP721 contract):

code/packages/hardhat/contracts/core/Controller.sol#L800

        INonfungiblePositionManager(uniswapPositionManager).transferFrom(_account, address(this), _uniTokenId);

A user can deposit Uniswap V3 LP positions as collateral in a vault by calling Controller.depositUniPositionToken:

code/packages/hardhat/contracts/core/Controller.sol#L344

    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {

According to the EIP-721 specification a contract that receives NFT tokens should implement the onERC721Received function:

/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface ERC721TokenReceiver {
    /// @notice Handle the receipt of an NFT
    /// @dev The ERC721 smart contract calls this function on the recipient
    ///  after a `transfer`. This function MAY throw to revert and reject the
    ///  transfer. Return of other than the magic value MUST result in the
    ///  transaction being reverted.
    ///  Note: the contract address is always the message sender.
    /// @param _operator The address which called `safeTransferFrom` function
    /// @param _from The address which previously owned the token
    /// @param _tokenId The NFT identifier which is being transferred
    /// @param _data Additional data with no specified format
    /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    ///  unless throwing
    function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
}

References

EIP-721 specification


Artifacts

Surya

SΕ«rya is a utility tool for smart contract systems. It provides a number of visual outputs and information about the structure of smart contracts. It also supports querying the function call graph in multiple ways to aid in the manual inspection and control flow analysis of contracts.

SΕ«rya's Description Report

Files Description Table

File Name SHA-1 Hash
code/packages/hardhat/contracts/core/Controller.sol c9b7623dc1c6be03b9215514954993fb897fa02d
code/packages/hardhat/contracts/core/Oracle.sol 5e5c129114521d1c9062e610a534b48596cb92bb
code/packages/hardhat/contracts/core/ShortPowerPerp.sol 748ece1c47274a9c79f1fa66cf33c60b433d2dd7
code/packages/hardhat/contracts/core/WPowerPerp.sol c3beb4844213cca1b471bc2989cef4a753055d26
code/packages/hardhat/contracts/external/WETH9.sol 6a93c6c5baf98e8923d485dbd5f2346fd72ee4ec
code/packages/hardhat/contracts/import/Uni.sol 252b195115988472905100d43ed1e1673be961d9
code/packages/hardhat/contracts/interfaces/IController.sol d6d01a0ccfdbd2cff36d40f87337f59991c6c5fb
code/packages/hardhat/contracts/interfaces/IERC20Detailed.sol b9a4037e3b33da4487c54347d589faf1e75e14bc
code/packages/hardhat/contracts/interfaces/IOracle.sol 2f4f6a90b16ae4bd43ea54803eb4825cff62503d
code/packages/hardhat/contracts/interfaces/IShortPowerPerp.sol b3981690bd6376030a2892600dbeb09d12b15ada
code/packages/hardhat/contracts/interfaces/IWETH9.sol b363e7995b3cee76aa9c28fee3e80dbe2d38c5ea
code/packages/hardhat/contracts/interfaces/IWPowerPerp.sol dc73dda5c13111c1983d22a5e5b7e5759c2513e9
code/packages/hardhat/contracts/libs/ABDKMath64x64.sol 84f69ee125b5a9ea07cd8d2354c79af41e7b9b3b
code/packages/hardhat/contracts/libs/OracleLibrary.sol d8f077a1f554eff6206c4555d136a422e116e6b8
code/packages/hardhat/contracts/libs/Power2Base.sol 79bfaaaa3596eb8fbdab663c2a069fab124cc667
code/packages/hardhat/contracts/libs/Uint256Casting.sol 0f53355e4e4fd4f2c5a26e01ceb0e3b64f670d4f
code/packages/hardhat/contracts/libs/VaultLib.sol 99add4f6af3d001b5428f2083a782397b30fcd50
code/packages/hardhat/contracts/periphery/ShortHelper.sol 444058180fbb9d6eb7202df88106488b4993232b
code/packages/hardhat/contracts/strategy/CrabStrategy.sol bb1b91698205c22d992ebcb8fc2fc7594792436b

Contracts Description Table

Contract Type Bases
β”” Function Name Visibility Mutability Modifiers
Controller Implementation Ownable, ReentrancyGuard
β”” Public ❗️ πŸ›‘ NO❗️
β”” getExpectedNormalizationFactor External ❗️ NO❗️
β”” getIndex External ❗️ NO❗️
β”” getUnscaledIndex External ❗️ NO❗️
β”” getDenormalizedMark External ❗️ NO❗️
β”” getDenormalizedMarkForFunding External ❗️ NO❗️
β”” isVaultSafe External ❗️ NO❗️
β”” mintPowerPerpAmount External ❗️ πŸ’΅ notPaused nonReentrant
β”” mintWPowerPerpAmount External ❗️ πŸ’΅ notPaused nonReentrant
β”” deposit External ❗️ πŸ’΅ notPaused nonReentrant
β”” depositUniPositionToken External ❗️ πŸ›‘ notPaused nonReentrant
β”” withdraw External ❗️ πŸ›‘ notPaused nonReentrant
β”” withdrawUniPositionToken External ❗️ πŸ›‘ notPaused nonReentrant
β”” burnWPowerPerpAmount External ❗️ πŸ›‘ notPaused nonReentrant
β”” burnPowerPerpAmount External ❗️ πŸ›‘ notPaused nonReentrant
β”” reduceDebtShutdown External ❗️ πŸ›‘ isShutdown nonReentrant
β”” reduceDebt External ❗️ πŸ›‘ notPaused nonReentrant
β”” liquidate External ❗️ πŸ›‘ notPaused nonReentrant
β”” updateOperator External ❗️ πŸ›‘ NO❗️
β”” setFeeRecipient External ❗️ πŸ›‘ onlyOwner
β”” setFeeRate External ❗️ πŸ›‘ onlyOwner
β”” shutDown External ❗️ πŸ›‘ onlyOwner notShutdown
β”” pause External ❗️ πŸ›‘ onlyOwner notShutdown notPaused
β”” unPauseAnyone External ❗️ πŸ›‘ isPaused notShutdown
β”” unPauseOwner External ❗️ πŸ›‘ onlyOwner isPaused notShutdown
β”” redeemLong External ❗️ πŸ›‘ isShutdown nonReentrant
β”” redeemShort External ❗️ πŸ›‘ isShutdown nonReentrant
β”” applyFunding External ❗️ πŸ›‘ notPaused
β”” donate External ❗️ πŸ’΅ isShutdown
β”” External ❗️ πŸ’΅ NO❗️
β”” _checkVaultId Internal πŸ”’
β”” _checkCanModifyVault Internal πŸ”’
β”” _openDepositMint Internal πŸ”’ πŸ›‘
β”” _burnAndWithdraw Internal πŸ”’ πŸ›‘
β”” _openVault Internal πŸ”’ πŸ›‘
β”” _depositUniPositionToken Internal πŸ”’ πŸ›‘
β”” _addEthCollateral Internal πŸ”’ πŸ›‘
β”” _withdrawUniPositionToken Internal πŸ”’ πŸ›‘
β”” _withdrawCollateral Internal πŸ”’ πŸ›‘
β”” _mintWPowerPerp Internal πŸ”’ πŸ›‘
β”” _burnWPowerPerp Internal πŸ”’ πŸ›‘
β”” _liquidate Internal πŸ”’ πŸ›‘
β”” _reduceDebt Internal πŸ”’ πŸ›‘
β”” _getFee Internal πŸ”’
β”” _writeVault Private πŸ” πŸ›‘
β”” _redeemUniToken Internal πŸ”’ πŸ›‘
β”” _applyFunding Internal πŸ”’ πŸ›‘
β”” _getNewNormalizationFactor Internal πŸ”’
β”” _checkVault Internal πŸ”’
β”” _isVaultSafe Internal πŸ”’
β”” _getVaultStatus Internal πŸ”’
β”” _getReduceDebtResultInVault Internal πŸ”’
β”” _getReduceDebtBounty Internal πŸ”’
β”” _getLiquidationResult Internal πŸ”’
β”” _getSingleLiquidationAmount Internal πŸ”’
β”” _getConsistentPeriodForOracle Internal πŸ”’
Oracle Implementation
β”” getTwap External ❗️ NO❗️
β”” getHistoricalTwap External ❗️ NO❗️
β”” getMaxPeriod External ❗️ NO❗️
β”” getTimeWeightedAverageTickSafe External ❗️ NO❗️
β”” _fetchTwap Internal πŸ”’
β”” _fetchRawTwap Internal πŸ”’
β”” _fetchHistoricTwap Internal πŸ”’
β”” _getMaxPeriod Internal πŸ”’
ShortPowerPerp Implementation ERC721, Initializable
β”” Public ❗️ πŸ›‘ ERC721
β”” init Public ❗️ πŸ›‘ initializer
β”” mintNFT External ❗️ πŸ›‘ onlyController
WPowerPerp Implementation ERC20, Initializable, IWPowerPerp
β”” Public ❗️ πŸ›‘ ERC20
β”” init External ❗️ πŸ›‘ initializer
β”” mint External ❗️ πŸ›‘ onlyController
β”” burn External ❗️ πŸ›‘ onlyController
WETH9 Implementation
β”” deposit Public ❗️ πŸ’΅ NO❗️
β”” withdraw Public ❗️ πŸ›‘ NO❗️
β”” totalSupply Public ❗️ NO❗️
β”” approve Public ❗️ πŸ›‘ NO❗️
β”” transfer Public ❗️ πŸ›‘ NO❗️
β”” transferFrom Public ❗️ πŸ›‘ NO❗️
Uni Implementation
IController Interface
β”” ethQuoteCurrencyPool External ❗️ NO❗️
β”” feeRate External ❗️ NO❗️
β”” getFee External ❗️ NO❗️
β”” quoteCurrency External ❗️ NO❗️
β”” vaults External ❗️ NO❗️
β”” shortPowerPerp External ❗️ NO❗️
β”” wPowerPerp External ❗️ NO❗️
β”” getExpectedNormalizationFactor External ❗️ NO❗️
β”” mintPowerPerpAmount External ❗️ πŸ’΅ NO❗️
β”” mintWPowerPerpAmount External ❗️ πŸ’΅ NO❗️
β”” deposit External ❗️ πŸ’΅ NO❗️
β”” withdraw External ❗️ πŸ’΅ NO❗️
β”” burnWPowerPerpAmount External ❗️ πŸ›‘ NO❗️
β”” burnOnPowerPerpAmount External ❗️ πŸ›‘ NO❗️
β”” liquidate External ❗️ πŸ›‘ NO❗️
β”” applyFunding External ❗️ πŸ›‘ NO❗️
β”” reduceDebtShutdown External ❗️ πŸ›‘ NO❗️
IERC20Detailed Interface IERC20
β”” decimals External ❗️ NO❗️
IOracle Interface
β”” getHistoricalTwap External ❗️ NO❗️
β”” getTwap External ❗️ NO❗️
β”” getMaxPeriod External ❗️ NO❗️
β”” getTimeWeightedAverageTickSafe External ❗️ NO❗️
IShortPowerPerp Interface IERC721
β”” nextId External ❗️ NO❗️
β”” mintNFT External ❗️ πŸ›‘ NO❗️
IWETH9 Interface IERC20
β”” deposit External ❗️ πŸ’΅ NO❗️
β”” withdraw External ❗️ πŸ›‘ NO❗️
IWPowerPerp Interface IERC20
β”” mint External ❗️ πŸ›‘ NO❗️
β”” burn External ❗️ πŸ›‘ NO❗️
ABDKMath64x64 Library
β”” mul Internal πŸ”’
β”” mulu Internal πŸ”’
β”” divu Public ❗️ NO❗️
β”” log_2 Public ❗️ NO❗️
β”” exp_2 Public ❗️ NO❗️
β”” divuu Private πŸ”
OracleLibrary Library
β”” consultAtHistoricTime Internal πŸ”’
β”” getQuoteAtTick Internal πŸ”’
Power2Base Library
β”” _getIndex Internal πŸ”’
β”” _getUnscaledIndex Internal πŸ”’
β”” _getDenormalizedMark Internal πŸ”’
β”” _getDebtValueInEth Internal πŸ”’
β”” _getScaledTwap Internal πŸ”’
β”” _getTwap Internal πŸ”’
β”” _getLongSettlementValue Internal πŸ”’
Uint256Casting Library
β”” toUint128 Internal πŸ”’
β”” toUint96 Internal πŸ”’
β”” toUint32 Internal πŸ”’
VaultLib Library
β”” addEthCollateral Internal πŸ”’
β”” addUniNftCollateral Internal πŸ”’
β”” removeEthCollateral Internal πŸ”’
β”” removeUniNftCollateral Internal πŸ”’
β”” addShort Internal πŸ”’
β”” removeShort Internal πŸ”’
β”” getVaultStatus Internal πŸ”’
β”” _getEffectiveCollateral Internal πŸ”’
β”” _getUniPositionBalances Internal πŸ”’
β”” _getUniswapPositionInfo Internal πŸ”’
β”” _getToken0Token1Balances Internal πŸ”’
ShortHelper Implementation
β”” Public ❗️ πŸ›‘ NO❗️
β”” openShort External ❗️ πŸ’΅ NO❗️
β”” closeShort External ❗️ πŸ’΅ NO❗️
β”” External ❗️ πŸ’΅ NO❗️
CrabStrategy Implementation StrategyBase, StrategyFlashSwap, ReentrancyGuard
β”” Public ❗️ πŸ›‘ StrategyBase StrategyFlashSwap
β”” External ❗️ πŸ’΅ NO❗️
β”” flashDeposit External ❗️ πŸ’΅ nonReentrant
β”” flashWithdraw External ❗️ πŸ›‘ nonReentrant
β”” deposit External ❗️ πŸ’΅ nonReentrant
β”” withdraw External ❗️ πŸ’΅ nonReentrant
β”” timeHedgeOnUniswap External ❗️ πŸ›‘ NO❗️
β”” priceHedgeOnUniswap External ❗️ πŸ’΅ NO❗️
β”” timeHedge External ❗️ πŸ’΅ nonReentrant
β”” priceHedge External ❗️ πŸ’΅ nonReentrant
β”” checkPriceHedge External ❗️ NO❗️
β”” checkTimeHedge External ❗️ NO❗️
β”” getWsqueethFromCrabAmount External ❗️ NO❗️
β”” _strategyFlash Internal πŸ”’ πŸ›‘
β”” _deposit Internal πŸ”’ πŸ›‘
β”” _withdraw Internal πŸ”’ πŸ›‘
β”” _hedge Internal πŸ”’ πŸ›‘
β”” _hedgeOnUniswap Internal πŸ”’ πŸ›‘
β”” _executeSellAuction Internal πŸ”’ πŸ›‘
β”” _executeBuyAuction Internal πŸ”’ πŸ›‘
β”” _startAuction Internal πŸ”’ πŸ›‘
β”” _syncStrategyState Internal πŸ”’
β”” _calcFeeAdjustment Internal πŸ”’
β”” _calcWsqueethToMintAndFee Internal πŸ”’
β”” _isTimeHedge Internal πŸ”’
β”” _isPriceHedge Internal πŸ”’
β”” _getAuctionPrice Internal πŸ”’
β”” _checkAuctionType Internal πŸ”’
β”” _calcSharesToMint Internal πŸ”’
β”” _calcCrabRatio Internal πŸ”’
β”” _calcEthToWithdraw Internal πŸ”’
β”” _getTargetHedgeAndAuctionType Internal πŸ”’

Legend

Symbol Meaning
πŸ›‘ Function can modify state
πŸ’΅ Function is payable

Graphs

Controller Graph CrabStrategy Graph

Inheritance

Controller Inheritance CrabStrategy Inheritance

Describe


$ npx surya describe packages/hardhat/contracts/{core,external,import,interfaces,libs,periphery,strategy}/*.sol
 +  Controller (Ownable, ReentrancyGuard)
    - [Pub] <Constructor> #
    - [Ext] getExpectedNormalizationFactor
    - [Ext] getIndex
    - [Ext] getUnscaledIndex
    - [Ext] getDenormalizedMark
    - [Ext] getDenormalizedMarkForFunding
    - [Ext] isVaultSafe
    - [Ext] mintPowerPerpAmount ($)
       - modifiers: notPaused,nonReentrant
    - [Ext] mintWPowerPerpAmount ($)
       - modifiers: notPaused,nonReentrant
    - [Ext] deposit ($)
       - modifiers: notPaused,nonReentrant
    - [Ext] depositUniPositionToken #
       - modifiers: notPaused,nonReentrant
    - [Ext] withdraw #
       - modifiers: notPaused,nonReentrant
    - [Ext] withdrawUniPositionToken #
       - modifiers: notPaused,nonReentrant
    - [Ext] burnWPowerPerpAmount #
       - modifiers: notPaused,nonReentrant
    - [Ext] burnPowerPerpAmount #
       - modifiers: notPaused,nonReentrant
    - [Ext] reduceDebtShutdown #
       - modifiers: isShutdown,nonReentrant
    - [Ext] reduceDebt #
       - modifiers: notPaused,nonReentrant
    - [Ext] liquidate #
       - modifiers: notPaused,nonReentrant
    - [Ext] updateOperator #
    - [Ext] setFeeRecipient #
       - modifiers: onlyOwner
    - [Ext] setFeeRate #
       - modifiers: onlyOwner
    - [Ext] shutDown #
       - modifiers: onlyOwner,notShutdown
    - [Ext] pause #
       - modifiers: onlyOwner,notShutdown,notPaused
    - [Ext] unPauseAnyone #
       - modifiers: isPaused,notShutdown
    - [Ext] unPauseOwner #
       - modifiers: onlyOwner,isPaused,notShutdown
    - [Ext] redeemLong #
       - modifiers: isShutdown,nonReentrant
    - [Ext] redeemShort #
       - modifiers: isShutdown,nonReentrant
    - [Ext] applyFunding #
       - modifiers: notPaused
    - [Ext] donate ($)
       - modifiers: isShutdown
    - [Ext] <Fallback> ($)
    - [Int] _checkVaultId
    - [Int] _checkCanModifyVault
    - [Int] _openDepositMint #
    - [Int] _burnAndWithdraw #
    - [Int] _openVault #
    - [Int] _depositUniPositionToken #
    - [Int] _addEthCollateral #
    - [Int] _withdrawUniPositionToken #
    - [Int] _withdrawCollateral #
    - [Int] _mintWPowerPerp #
    - [Int] _burnWPowerPerp #
    - [Int] _liquidate #
    - [Int] _reduceDebt #
    - [Int] _getFee
    - [Prv] _writeVault #
    - [Int] _redeemUniToken #
    - [Int] _applyFunding #
    - [Int] _getNewNormalizationFactor
    - [Int] _checkVault
    - [Int] _isVaultSafe
    - [Int] _getVaultStatus
    - [Int] _getReduceDebtResultInVault
    - [Int] _getReduceDebtBounty
    - [Int] _getLiquidationResult
    - [Int] _getSingleLiquidationAmount
    - [Int] _getConsistentPeriodForOracle

 +  Oracle 
    - [Ext] getTwap
    - [Ext] getHistoricalTwap
    - [Ext] getMaxPeriod
    - [Ext] getTimeWeightedAverageTickSafe
    - [Int] _fetchTwap
    - [Int] _fetchRawTwap
    - [Int] _fetchHistoricTwap
    - [Int] _getMaxPeriod

 +  ShortPowerPerp (ERC721, Initializable)
    - [Pub] <Constructor> #
       - modifiers: ERC721
    - [Pub] init #
       - modifiers: initializer
    - [Ext] mintNFT #
       - modifiers: onlyController

 +  WPowerPerp (ERC20, Initializable, IWPowerPerp)
    - [Pub] <Constructor> #
       - modifiers: ERC20
    - [Ext] init #
       - modifiers: initializer
    - [Ext] mint #
       - modifiers: onlyController
    - [Ext] burn #
       - modifiers: onlyController

 +  WETH9 
    - [Pub] deposit ($)
    - [Pub] withdraw #
    - [Pub] totalSupply
    - [Pub] approve #
    - [Pub] transfer #
    - [Pub] transferFrom #

 +  Uni 

 + [Int] IController 
    - [Ext] ethQuoteCurrencyPool
    - [Ext] feeRate
    - [Ext] getFee
    - [Ext] quoteCurrency
    - [Ext] vaults
    - [Ext] shortPowerPerp
    - [Ext] wPowerPerp
    - [Ext] getExpectedNormalizationFactor
    - [Ext] mintPowerPerpAmount ($)
    - [Ext] mintWPowerPerpAmount ($)
    - [Ext] deposit ($)
    - [Ext] withdraw ($)
    - [Ext] burnWPowerPerpAmount #
    - [Ext] burnOnPowerPerpAmount #
    - [Ext] liquidate #
    - [Ext] applyFunding #
    - [Ext] reduceDebtShutdown #

 + [Int] IERC20Detailed (IERC20)
    - [Ext] decimals

 + [Int] IOracle 
    - [Ext] getHistoricalTwap
    - [Ext] getTwap
    - [Ext] getMaxPeriod
    - [Ext] getTimeWeightedAverageTickSafe

 + [Int] IShortPowerPerp (IERC721)
    - [Ext] nextId
    - [Ext] mintNFT #

 + [Int] IWETH9 (IERC20)
    - [Ext] deposit ($)
    - [Ext] withdraw #

 + [Int] IWPowerPerp (IERC20)
    - [Ext] mint #
    - [Ext] burn #

 + [Lib] ABDKMath64x64 
    - [Int] mul
    - [Int] mulu
    - [Pub] divu
    - [Pub] log_2
    - [Pub] exp_2
    - [Prv] divuu

 + [Lib] OracleLibrary 
    - [Int] consultAtHistoricTime
    - [Int] getQuoteAtTick

 + [Lib] Power2Base 
    - [Int] _getIndex
    - [Int] _getUnscaledIndex
    - [Int] _getDenormalizedMark
    - [Int] _getDebtValueInEth
    - [Int] _getScaledTwap
    - [Int] _getTwap
    - [Int] _getLongSettlementValue

 + [Lib] Uint256Casting 
    - [Int] toUint128
    - [Int] toUint96
    - [Int] toUint32

 + [Lib] VaultLib 
    - [Int] addEthCollateral
    - [Int] addUniNftCollateral
    - [Int] removeEthCollateral
    - [Int] removeUniNftCollateral
    - [Int] addShort
    - [Int] removeShort
    - [Int] getVaultStatus
    - [Int] _getEffectiveCollateral
    - [Int] _getUniPositionBalances
    - [Int] _getUniswapPositionInfo
    - [Int] _getToken0Token1Balances

 +  ShortHelper 
    - [Pub] <Constructor> #
    - [Ext] openShort ($)
    - [Ext] closeShort ($)
    - [Ext] <Fallback> ($)

 +  CrabStrategy (StrategyBase, StrategyFlashSwap, ReentrancyGuard)
    - [Pub] <Constructor> #
       - modifiers: StrategyBase,StrategyFlashSwap
    - [Ext] <Fallback> ($)
    - [Ext] flashDeposit ($)
       - modifiers: nonReentrant
    - [Ext] flashWithdraw #
       - modifiers: nonReentrant
    - [Ext] deposit ($)
       - modifiers: nonReentrant
    - [Ext] withdraw ($)
       - modifiers: nonReentrant
    - [Ext] timeHedgeOnUniswap #
    - [Ext] priceHedgeOnUniswap ($)
    - [Ext] timeHedge ($)
       - modifiers: nonReentrant
    - [Ext] priceHedge ($)
       - modifiers: nonReentrant
    - [Ext] checkPriceHedge
    - [Ext] checkTimeHedge
    - [Ext] getWsqueethFromCrabAmount
    - [Int] _strategyFlash #
    - [Int] _deposit #
    - [Int] _withdraw #
    - [Int] _hedge #
    - [Int] _hedgeOnUniswap #
    - [Int] _executeSellAuction #
    - [Int] _executeBuyAuction #
    - [Int] _startAuction #
    - [Int] _syncStrategyState
    - [Int] _calcFeeAdjustment
    - [Int] _calcWsqueethToMintAndFee
    - [Int] _isTimeHedge
    - [Int] _isPriceHedge
    - [Int] _getAuctionPrice
    - [Int] _checkAuctionType
    - [Int] _calcSharesToMint
    - [Int] _calcCrabRatio
    - [Int] _calcEthToWithdraw
    - [Int] _getTargetHedgeAndAuctionType


 ($) = payable function
 # = non-constant function

Tests


$ npm run test

> @squeeth/monorepo@1.0.0 test
> yarn workspace @squeeth/hardhat test

yarn workspace v1.22.17
yarn run v1.22.17
$ hardhat test --network hardhat
No need to generate any newer typings.


  Liquidation Integration Test
    Liquidate normal vault when price is 2x
      βœ“ liquidate vault 0 (176ms)
      βœ“ should revert if trying to leave vault1 a dust vault (162ms)
      βœ“ fully liquidate vault 1, get the full collateral amount from the vault (205ms)
      βœ“ fully liquidate vault 2, get expected payout (179ms)
      βœ“ should revert when trying to liquidate vault 6 (nft vault underwater) but leave dust behind (243ms)
      βœ“ fully liquidate vault 6, redeem nft and liquidate (276ms)
      βœ“ should revert when trying to liquidate a safe vault (96ms)
    Save vault with uni nft when price is 4x
      βœ“ calling liquidation now will save vault 3 and get bounty (496ms)
      βœ“ seller4 can save his own vault (201ms)
    Liquidate vault with uni nft when price is 8x
      βœ“ calling liquidation now will save vault5 + liquidate half of the remaining debt (415ms)

  Oracle Integration Test
    Get TWAP right after setup
      TWAP for squeeth/eth
        βœ“ fetch initial price
        βœ“ fetch price twap for last 10 seconds
        βœ“ should revert while requesting twap with price too old
      TWAP for eth/dai
        βœ“ fetch initial price
        βœ“ fetch price twap for last 10 seconds
        βœ“ should revert while requesting twap with price too old
    Get TWAP right after 10 mins
      βœ“ go 10 mins
      βœ“ fetch squeeth twap for last 10 mins
      βœ“ fetch eth twap for last 10 mins
    Adding liquidity mess up things
      βœ“ add liquidity (672ms)
      βœ“ fetch squeeth twap for last 10 mins

  Testing system stability during extreme market conditions
    Scenario: ETH/DAI price spikes 100%
      1 second after eth price spikes (similar to the state created by flashloan)
        βœ“ index price is updated if requesting with period 1
        βœ“ vaults remains safe because of TWAP (59ms)
        βœ“ can still mint with the same amount of collateral (because of TWAP) (74ms)
        βœ“ should revert when trying to mint the same amount with smaller collateral (75ms)
      3 minutes after eth price spiked
        βœ“ index price is updated if requesting with period 180
        βœ“ vaults becomes unsafe (56ms)
        βœ“ should revert when trying to mint with same amount of collateral as before (69ms)
    Scenario: ETH/DAI price crashes 50%
      1 second after eth price crash (Similar to the state created by flashloan)
        βœ“ index price is updated if requesting with period 1
        βœ“ vaults is still safe (because price moves down) (71ms)
        βœ“ should revert if trying to mint more squeeth (72ms)
      1 minutes after eth price crashed
        βœ“ index price is updated if requesting with period 60
        βœ“ will be able to mint more squeeth (147ms)

  ShortHelper Integration Test
    Basic settings
      deployment
        βœ“ should revert if argument address is invalid
        βœ“ should deploy ShortHelper (49ms)
    Create short position
      βœ“ should revert if trying to open a vault with non-weth address and squeeth for swap
      βœ“ should revert if trying to open a vault with weth address and non-squeeth for swap
      βœ“ should revert is slippage is too high (97ms)
      βœ“ should revert if end price is lower than limit (94ms)
      βœ“ should open new vault and sell squeeth, receive weth in return (105ms)
      βœ“ should add ShortHelper as an operator
      βœ“ should add collateral to an existing vault and sell squeeth, receive weth in return (100ms)
      βœ“ should revert if a random address tries to mint and sell squeeth on someone elses vault
      βœ“ should revert if collateral amount put down is dust (69ms)
      βœ“ should revert if user does not put enough collateral (72ms)
      βœ“ should open new vault and sell squeeth, receive eth at the end (106ms)
      βœ“ should revert if trying to short more from the current vault (75ms)
    Checking eth payable reverts
      βœ“ should revert if ETH is sent from a contract other than weth or the controller
    Close short position
      βœ“ should revert if a random user to withdraw ETH from someone elses vault
      βœ“ should revert if trying to partially close a position using squeeth and not weth
      βœ“ should revert if trying to partially close a position using weth and non-squeeth
      βœ“ should revert if slippage is too high
      βœ“ should revert if end price is too high (46ms)
      βœ“ should revert when leaving vault with dust collateral and debt (93ms)
      βœ“ should revert if remove too much collateral vs debt bought back (90ms)
      βœ“ should partially close a short position and get back eth (95ms)
      βœ“ should fully close a short position and get back eth (110ms)

  Crab flashswap integration test: crab vault liquidation
    liquidate vault
      βœ“ should liquidate crab vault (145ms)
      βœ“ should let user deposit post liquidation and update vault state and provide correct wSqueeth and crab tokens (229ms)
      βœ“ depositor should withdraw correct amount of ETH collateral (137ms)
      βœ“ depositor2 should withdraw correct amount of ETH collateral (141ms)

  Crab flashswap integration test: uniswap price based hedging
    Sell auction
      βœ“ it should be eligible for a hedge after time has passed for twap to update but will revert due to hedge sign change (116ms)
      βœ“ should revert if not positive PnL (177ms)
      βœ“ it should revert if PnL is less than min wsqueeth (180ms)
      βœ“ it should allow a hedge based on price (319ms)
      βœ“ should revert price hedging if the price threshold has not been reached
    Buy auction
      βœ“ should revert if not positive PnL (179ms)
      βœ“ it should revert if profit is less than min ETH (536ms)
      βœ“ it should allow a hedge based on price (307ms)

  Crab flashswap integration test: uniswap time based hedging
    Sell auction
      βœ“ should revert time hedging if the time threshold has not been reached
      βœ“ should revert hedging if strategy is delta neutral (70ms)
      βœ“ should revert hedging if target hedge sign change (auction change from selling to buying) (353ms)
      βœ“ should revert if not positive PnL (171ms)
      βœ“ hedge on uniswap based on time threshold (195ms)
    Buy auction
      βœ“ should revert time hedging if the time threshold has not been reached
      βœ“ should revert hedging if target hedge sign change (auction change from buying to selling) (79ms)
      βœ“ should revert if not positive PnL (162ms)
      βœ“ hedge based on time on uniswap (163ms)

  Crab flashswap integration test: price based hedging
    Sell auction
      βœ“ should revert price hedging if the time threshold has not been reached (57ms)
      βœ“ price hedging should not immediately be eligible for a hedge (364ms)
      βœ“ it should be eligible for a hedge after time has passed for twap to update but will revert due to hedge sign change (106ms)
      βœ“ it should revert if hedger specifies the wrong direction (90ms)
      βœ“ it should allow a hedge based on price (185ms)
    Buy auction
      βœ“ should not immediately be eligible for a hedge (48ms)
      βœ“ it should be eligible for a hedge after time has passed for twap to update but will revert due to hedge sign change (96ms)
      βœ“ it should revert if hedger specifies the wrong direction (96ms)
      βœ“ it should revert if eth is attached to a buy auction (106ms)
      βœ“ it should revert if the limit price is breached (104ms)
      βœ“ it should allow a hedge based on price (279ms)

  Crab flashswap integration test: time based hedging
    Sell auction
      βœ“ should revert time hedging if the time threshold has not been reached
      βœ“ should revert hedging if strategy is delta neutral (90ms)
      βœ“ should revert hedging if target hedge sign change (auction change from selling to buying) (388ms)
      βœ“ should revert hedging if sent ETH to sell for WSqueeth is not enough (93ms)
      βœ“ should revert if hedger specifies wrong direction (88ms)
      βœ“ should revert if hedger specifies a limit price that is low (89ms)
      βœ“ should hedge by selling WSqueeth for ETH and update timestamp and price at hedge (197ms)
    Buy auction
      βœ“ should revert when the limit price is too high (102ms)
      βœ“ should revert hedging when eth is attached to a buy hedge (102ms)
      βœ“ should revert hedging when WSqueeth seller have less amount that target hedge (105ms)
      βœ“ should hedge by buying WSqueeth for ETH  (261ms)

  Crab integration test: crab vault dust liquidation with excess collateral
    liquidate vault
      βœ“ should liquidate crab vault using a full dust (0 collateral >0 debt remain) (171ms)
      βœ“ should revert if user flash deposits post liquidation due to AS, because of amount specified of 0 (90ms)
      βœ“ should let user deposit post liquidation, with only ETH, and mint no squeeth for them (197ms)
      βœ“ depositor should revert trying to flashWithdraw with AS due to amount of wSqueeth to buy being 0
      βœ“ depositor should be able to withdraw and get some ETH, without any wSqueeth (166ms)

  Crab integration test: crab vault full liquidation and shutdown of contracts
    liquidate vault
      βœ“ should liquidate crab vault using a full insolvent liquidation (0 collateral 0 debt remain) (155ms)
      βœ“ should NOT let user flash deposit post liquidation (85ms)
      βœ“ should NOT let user deposit post liquidation (119ms)
      βœ“ depositor should revert trying to flashWithdraw with AS due to amount of wSqueeth to buy being 0
      βœ“ depositor fwithdraw and get 0 (122ms)

  Crab integration test: flash deposit - deposit - withdraw
    flash deposit - deposit - withdraw - flash withdraw
      βœ“ should revert flash depositing if not enough ETH (169ms)
      βœ“ should flash deposit correct amount and mint correct shares amount (260ms)
      βœ“ should deposit and mint correct LP and return the correct amount of wSqueeth debt per crab strategy token (155ms)
      βœ“ should withdraw correct amount of ETH (100ms)
      βœ“ should revert if slippage is too high (101ms)
      βœ“ should flash withdraw correct amount of ETH collateral (143ms)

  Uniswap Position token integration test
    Save vault with uni position token
      βœ“ seller can redeem an Uni Position token for weth and wSqueeth to reduce debt in vault0 (101ms)
      βœ“ seller can redeem an Uni Position token for wSqueeth to reduce debt in vault1 (74ms)
      βœ“ seller can redeem an Uni Position token for eth to reduce debt in vault2 (75ms)
    deposit LP token with diff fee tier
      βœ“ deposit lp token into the vault (160ms)

  Casting Library tests
    Math checks for overflow
      βœ“ should revert if casting oversize uint256 to uint128 overflows
      βœ“ should revert if casting oversize uint256 to uint96 overflows
      βœ“ should revert if casting oversize uint256 to uint32 overflows

  Controller Funding tests
    Deployment
      βœ“ Deployment
    Funding actions
      Normalization Factor tests
        βœ“ should apply the correct normalization factor for funding
        βœ“ normalization factor changes should be bounded above (40ms)
        βœ“ normalization factor changes should be bounded below (39ms)
        βœ“ calling apply funding with little time elapsed should not affect norm factor (51ms)
      Funding collateralization tests
        mint
          βœ“ should revert if minting too much squeeth after funding
          βœ“ should mint more wSqueeth after funding
        withdraw
          βœ“ should revert when trying to withdraw too much collateral
          βœ“ should be able to withdraw more collateral after funding
      Extreme cases for normalization factor
        βœ“ should get capped normalization factor when mark = 0 
        βœ“ should get capped normalization factor if eth price crashes
        βœ“ calling applying funding every 12 hours * 2 times, will result in a lower norm factor compared to every 24 hours * 1 times (114ms)

  Controller: Uni LP tokens collateralization
    Vault1 and Vault2: Basic Flow
      βœ“ should revert when trying to deposit a LP token to vault 0
      βœ“ should revert when trying to deposit a LP token to non-existent vault
      βœ“ should revert when trying to deposit a LP token from a different pool
      βœ“ should revert when trying to deposit a LP token with id 0
      βœ“ should revert when depositor do not own the NFT
      βœ“ should deposit and NFT to an existing vault. (43ms)
      βœ“ should revert if a user tries to deposit a second nft.
      βœ“ should revert if vault id is 0
      βœ“ should revert if vault id is too high
      βœ“ should revert if non owner withdraws the nft
      βœ“ should withdraw the nft successfully
      βœ“ should revert when trying to withdraw from a empty vault
      βœ“ should deposit an NFT to an existing vault using _openDepositMint (41ms)
    Vault3: Basic Collateralization checks
      Case: price is at the same
        βœ“ should be able to mint more squeeth after lp deposit (52ms)
        βœ“ should be able to remove all collateral after lp token deposit, because the lp token is worth 2x the debt amount.
        βœ“ should revert if trying to remove LP token from the vault.
        βœ“ update nft property to stimulate losses in Uni LP
        βœ“ should revert when effective collateral after withdraw < dust limit
      Case: price increase, vault should go underwater
        βœ“ should become underwater if squeeth price increase, and LP token has no enough eth to cover short position.
        βœ“ should be able to liquidate the NFT (72ms)
      Case: price decrease, vault should above water
        βœ“ should be able to collateralize the vault
        βœ“ should revert when trying to liquidate the NFT
    Vault4: Saving vault by burning NFT
      Case: price is at the same
        βœ“ should be able to remove all collateral after lp token deposit, because the lp token is worth 2x the debt amount.
        βœ“ should revert when calling from random address
      Case: price increase, vault should go underwater and people can save it
        βœ“ should become underwater if squeeth price increase, and LP token has no enough eth
        βœ“ should be able to reduce the debt by calling liquidate (46ms)
      Case: the nft worth more wsqueeth than minted
        βœ“ anyone can safe the vault, the owner will receive extra wsqueeth withdrawn from Uniswap (75ms)
        βœ“ calling reduceDebt will not take effect if the vault has not nft
    Vault5: test combined actions
      βœ“ should just deposit lp token and mint if deposit amount is 0 (52ms)
      βœ“ should just deposit lp token and deposit eth if mint amount is 0 (55ms)
      βœ“ should do nothing but deposit uni nft if both deposit and mint amount are 0 (59ms)

  Controller
    Time bound pausing
      Pause the system
        βœ“ Should allow owner to pause the system
        βœ“ Should allow the owner to un-pause
        βœ“ Should revert when the owner tries to re-pause after 183 days
      Shut down the system
        βœ“ Should allow the system to be shutdown and paused atomically even after 183 days

  Controller
    Time bound pausing
      Pause the system and then shutdown
        βœ“ Should allow owner to pause the system
        βœ“ Should allow the system to be shutdown when paused

  Simple Vault state tests
    Deployment
      βœ“ Deployment
    isVaultSafe tests on vaults with no nft
      βœ“ should return true if vault does not exist
      βœ“ should return true if vault has no short
      βœ“ should be able to mint perfect amount of wsqueeth
      βœ“ moving the price up should make the vault insolvent
      βœ“ funding should make the vault back to safe as time goes by
    isVaultSafe tests on vaults with nft
      βœ“ should become underwater if squeeth price increase, and LP is all eth
      βœ“ should become underwater if squeeth price decrease, and LP is all squeeth

  Controller
    βœ“ Should revert when oracle is address(0)
    βœ“ Should revert when shortSqueeth is address(0)
    βœ“ Should revert when powerperp is address(0)
    βœ“ Should revert when weth is address(0)
    βœ“ Should revert when quote currency is address(0)
    βœ“ Should revert when ethUSDPool is address(0)
    βœ“ Should revert when squeethEthPool is address(0)
    βœ“ Should revert when uniPositionManager is address(0)
    Deployment
      βœ“ Check controller deployment
      βœ“ Controller tester deployment
    Owner only functions
      βœ“ Should revert if trying to set fee rate before setting fee recipient
      βœ“ Should revert if trying to set address(0) as fee recipient
      βœ“ Should set the fee recipient
      βœ“ Should revert if trying to set fee rate that is too high
      βœ“ Should revert if set fee rate is call by random address
      βœ“ Should revert if set fee recipient is call by random address
    Basic actions
      #Read basic properties
        βœ“ should be able to get normalization factor
        βœ“ should allow anyone to call applyFunding and update funding
        βœ“ should not update funding two times in one block
        βœ“ should be able to get index and mark price and mark price used for funding
        βœ“ should be able to get unscaled index price
        βœ“ should revert when sending eth to controller from an EOA
      #Mint: Open vault
        βœ“ Should be able to open vaults
      #Deposit: Deposit collateral
        βœ“ Should revert when trying to deposit to vault 0
        βœ“ Should revert when trying to access non-existent vault
        βœ“ Should revert when trying to use mint to deposit to non-existent vault
        βœ“ Should be able to deposit collateral
        βœ“ Should be able to deposit 0 collateral
      #Mint: Mint Squeeth
        βœ“ Should revert if not called by owner
        βœ“ Should revert when trying to mint to non-existent vault
        βœ“ Should be able to mint squeeth
        βœ“ Should revert when minting more than allowed
      #Burn: Burn Squeeth
        βœ“ Should revert when trying to burn for vault 0
        βœ“ Should revert when trying to burn wrapped amount for vault 0
        βœ“ Should revert when trying to burn for non-existent vault
        βœ“ Should revert when trying to burn wrapped amount for non-existent vault
        βœ“ Should revert if trying to burn more than minted
        βœ“ Should revert if trying to burn without having squeeth
        βœ“ should revert if vault after burning is underwater
        βœ“ should revert if vault after burning is dust
        βœ“ Should revert if trying to withdraw and put make vault underwater
        βœ“ anyone can burn squeeth for vault1
        βœ“ should revert when non-owner try to burn and withdraw from vault
        βœ“ Should be able to burn squeeth
      #Withdraw: Remove Collateral
        βœ“ Should revert when trying to remove from vault 0
        βœ“ Should revert if caller is not the owner
        βœ“ Should revert if trying to remove more collateral than deposited
        βœ“ should revert if trying to remove collateral which produce a vault dust (56ms)
        βœ“ Should be able to remove collateral
        βœ“ Should close the vault when it's empty
    Combined actions
      Open, deposit and mint
        βœ“ should revert if the vault has too little collateral
        βœ“ should open vault, deposit and mint in the same tx
      Deposit and mint with mintWPowerPerpAmount
        βœ“ should deposit and mint in the same tx
        βœ“ should just mint if deposit amount is 0
        βœ“ should just deposit if mint amount is 0
        βœ“ should do nothing if both deposit and mint amount are 0
      Deposit and mint By operator
        βœ“ should not allow a non owner to update an operator
        βœ“ should add an operator
        βœ“ should deposit and mint in the same tx
        βœ“ should not allow an operator to update the operator associated with an account
      Burn and withdraw
        βœ“ should burn and withdraw with burnRPowerPerp
    Deposit and withdraw with Fee
      βœ“ should be able to set fee rate
      βœ“ should revert if vault is unable to pay fee amount from attach amount or vault collateral
      βœ“ should charge fee on mintPowerPerpAmount from deposit amount
      βœ“ should charge fee on mintPowerPerpAmount from vault collateral
      βœ“ should charge fee on mintWPowerPerpAmount from deposit amount
      βœ“ should charge fee on mintWPowerPerpAmount from vault collateral
    Settlement operations should be banned
      βœ“ Should revert when calling redeemLong
      βœ“ Should revert when calling redeemShort
      βœ“ Should revert when calling donate
    Emergency Shutdown and pausing
      Pause the system
        βœ“ Should revert when called by non-owner
        βœ“ Should revert when calling unpause before system is paused
        βœ“ Should allow owner to pause the system
        βœ“ Should revert when a random person tries to unpause immediately afterwards
        βœ“ Should allow the owner to un-pause
        βœ“ Should allow the owner to re-pause
        βœ“ Should allow the anyone to unpause after sufficient time has passed
        βœ“ Should allow the owner to re-pause
        βœ“ Should revert when calling mintPowerPerpAmount
        βœ“ Should revert when calling mintWPowerPerpAmount
        βœ“ Should revert when calling deposit
        βœ“ Should revert when calling depositUniPositionToken
        βœ“ Should revert when calling burnWPowerPerpAmount
        βœ“ Should revert when calling burnPowerPerpAmount
        βœ“ Should revert when calling withdraw
        βœ“ Should revert when calling withdrawUniPositionToken
        βœ“ Should revert when calling reduceDebt
        βœ“ Should revert when calling applyFunding
        βœ“ Should revert when calling liquidate
        βœ“ Should revert when calling reduceDebt
        βœ“ Should allow the owner to un-pause
        βœ“ Should revert when a random address tries to reduce debt on a NFT containing vault and the system isnt shut down
        βœ“ Should allow the owner to re-pause
        βœ“ Should revert if shutdown is called by non-owner
        βœ“ Should allow the owner to un-pause
        βœ“ Should revert when a owner tries to pause the system after it has been paused 4 times before
      Shut down the system using shutdown when it is unpaused
        βœ“ Should revert when called by non-owner
        βœ“ Should shutdown the system at a price that it will go insolvent (46ms)
        βœ“ Should revert when calling shutdown after system is shutdown
        βœ“ Should revert when calling pause after system is shutdown
        βœ“ Should revert when calling unPause after system is shutdown
      Settlement: redeemLong
        βœ“ should go insolvent while trying to redeem fair value for seller1 (big holder)
        βœ“ should accept donation from random address
        βœ“ should be able to redeem long value for seller2
        βœ“ should be able to redeem long value for seller3
      Settlement: redeemShort
        βœ“ should revert when a underwater vault (seller2) is trying to redeem
        βœ“ should revert when a underwater vault with nft (seller8) is trying to redeem
        βœ“ should allow anyone to reduceDebt in the insolvent vault
        βœ“ should still revert when a underwater vault with nft (seller8) is trying to redeem
        βœ“ should revert when a random user is trying to redeem
        βœ“ should redeem fair value for normal vault (seller 3)
        βœ“ should redeem fair value for short side with uni v3 nft (seller 5) (38ms)
        βœ“ set seller6 LP token properties
        βœ“ should redeem fair value for seller 6 with one-sided nft
        βœ“ should redeem fair value for short vault with no debt (seller7)

  Controller: liquidation unit test
    Deployment
      βœ“ Deployment (41ms)
    Liquidation
      βœ“ Should revert liquidating a safe vault
      βœ“ set eth price to make the vault underwater
      βœ“ should revert if the vault become a dust vault after liquidation (43ms)
      βœ“ should allow liquidating a whole vault if only liquidating half of it is gonna make it a dust vault (48ms)
      βœ“ Liquidate unsafe vault (vault 1) (49ms)
    Liquidation: un-profitable scenario
      βœ“ should revert if the vault is paying out all collateral, but there are still debt (39ms)
      βœ“ can fully liquidate a underwater vault, even it's not profitable (48ms)

  Oracle
    ETH/USD pool
      βœ“ should return initial price with period = 1
      βœ“ should return correct price with safe twap
    ETH/rUSD pool
      βœ“ should return initial price with period = 1
      βœ“ should return correct price with safe twap

  Oracle
    Fetch price right after initialization
      βœ“ should return initial price with period = 1
      βœ“ should be able to get TWAP since init time
      βœ“ should be able to get TWAP since init time after time goes by
      βœ“ should revert if trying to request twap since a time before initialization
      βœ“ should NOT revert if trying to request twap since a time before initialization, with #getTwapSafe
      βœ“ should return max period
    Fetch price after touching the pool
      βœ“ should revert if requesting TWAP from init timestamp
      βœ“ should be fix in the future: if first observation is updated in the same block, the max duration will be 0 causing the library to revert.
      βœ“ should NOT revert if requesting TWAP from init timestamp, with #getTwapSafe
      βœ“ should NOT revert if requesting time weighted tick from init timestamp, with #getWeightedTickSafe
      βœ“ should be able to get TWAP since last touch
      βœ“ should revert if trying to request twap since a time before last touch
      βœ“ should NOT revert if trying to request twap since a time before last touch, with #getTwapSafe
      βœ“ should NOT revert if trying to request average tick since a time before last touch, with #testGetWeightedTickSafe
      βœ“ should return max period as timestamp[1] til now
    Fetch price after adding storage slot
      βœ“ should revert if requesting TWAP from init timestamp
      βœ“ should NOT revert if requesting TWAP from init timestamp, with #getTwapSafe
      βœ“ should NOT revert if requesting time weighted tick from init timestamp, with #getWeightedTickSafe
      βœ“ should be able to get TWAP since first touch
      βœ“ should revert if trying to request twap since a time before first touch
      βœ“ should NOT revert if trying to request twap since a time before first touch, with #getTwapSafe
      βœ“ should NOT revert if requesting time weighted tick since a time before first touch, with #getWeightedTickSafe
      βœ“ should be able to get TWAP since second touch
      βœ“ should be able to get time weighted tick from second touch, with #getWeightedTickSafe
      βœ“ should be able to get TWAP since time between first touch and second touch with #getTwapSafe
      βœ“ should be able to get a historical TWAP from now until first interaction and it should match a normal twap
      βœ“ should be able to get a historical TWAP from second interaction to first interaction
      βœ“ should be able to get TWAP since second touch with #getTwapSafe
    oracle tick is time weighted
      βœ“ tick should return the average when each price has same weight  (7607ms)
      βœ“ tick should return the weighed average when price does not have same weight (7642ms)

  ShortPowerPerp
    Deployment
      βœ“ Deployment
    Initialization
      βœ“ should revert when calling init with invalid address
      βœ“ Should be able to init contract
    Access control
      βœ“ Should revert if mint called by an address other than controller 
      βœ“ Should mint nft with expected id if mint is called by controller

  WPowerPerp
    Initialization
      βœ“ should revert when calling init with invalid address
      βœ“ should return initial with controller address
      βœ“ should revert when trying to init again
      βœ“ should have decimals 18
    Minting and burning
      βœ“ should mint with controller
      βœ“ should revert when minted from non-controller
      βœ“ should revert when burned from non-controller
      βœ“ should burn from controler

  Crab Strategy
    Deployment
      βœ“ Should revert if weth is address 0
      βœ“ Should revert if controller is address 0
      βœ“ Should revert if oracle is address 0
      βœ“ Should revert if uniswap factory is address 0
      βœ“ Should revert if wSqueethEth pool is address 0
      βœ“ Should revert if hedge time tolerrance is 0
      βœ“ Should revert if hedge price tolerance is 0
      βœ“ Should revert if invalid auction time is 0
      βœ“ Should revert if min auction slippage > 1e18 
      βœ“ Should revert if min price multiplier is 0
      βœ“ Should revert if max price multplier < 1e18
      βœ“ Deployment (49ms)
    Crab strategy vault
      βœ“ Check crab details
      βœ“ Check crab strategy opened vault
    receive checks
      βœ“ should revert when sending eth to crab strategy contract from an EOA
    Deposit into strategy
      βœ“ Should deposit and mint correct LP when initial debt = 0
      βœ“ Should deposit and mint correct LP when initial debt != 0 and return the correct amount of wSqueeth debt per crab strategy token
    Withdraw from strategy
      βœ“ should revert withdrawing with unequal share/wSqueeth ratio
      βœ“ should revert withdrawing from a random account
      βœ“ should withdraw 0 correctly
      βœ“ should withdraw correct amount

  VaultLib
    #getUniPositionBalances tests
      case: infinite range, price is always within range
        βœ“ should get the squeeth / eth amount similar to our deposit amount
        βœ“ should get the correct squeeth / eth amount after price changes
      case: LP only in a certain range
        case: price remains the same, we're in the range
          βœ“ should return approximate amount
        case: current price is 5000, above the LP range
          βœ“ should return expected amount of squeeth and eth
        case: current price 1900, below the LP range
          βœ“ should return expected amount of squeeth and eth
        case: current price 2200, within LP range
          βœ“ should return expected amount of squeeth and eth


  377 passing (3m)

Done in 213.77s.
Done in 213.94s.

License

This report falls under the terms described in the included LICENSE.

<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.4.1/highlight.min.js"></script> <script>hljs.initHighlightingOnLoad();</script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/highlightjs-solidity@1.0.20/solidity.min.js"></script> <script type="text/javascript"> hljs.registerLanguage('solidity', window.hljsDefineSolidity); hljs.initHighlightingOnLoad(); </script>