# Contracts specs

## ContractRegistry

### constructor

### addresses

### names

### versions

### versionAddress

### latestVersion

### registerContract

* ✅ registers IContractMeta compatible contract and updates respective view methods - #addresses - #versions - #names - #latestVersion - #versionAddress

*Access control*

* ✅ allowed: operator (deployer)
* ✅ denied with FRB: random address
* ✅ allowed: protocol admin

*Edge cases*

* ✅ when new contract major version differs more, than on one reverts with INVA
* ✅ when new contract version lower or equal existing one reverts with INVA
* ✅ when contract has invalid version reverts with INVA
* ✅ when contract name is not alphanumeric reverts with INV
* ✅ when address is already registered reverts with DUP

## ProtocolGovernance

### constructor

* ✅ deploys a new contract

### stagedParams

* ✅ imestamp timestamp equals #stageParams's block.timestamp + governanceDelay
* ✅ imestamp clears by #commitParams
* ✅ imestamp edge cases when nothing is set returns zero
* ✅ imestamp access control allowed: any address

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ updates by #stageParams
* ✅ clears by #commitParams

### params

### stagedValidatorsAddresses

### validatorsAddresses

### validatorsAddress

* ✅ returns correct value
* ✅ s properties @property: updates when committed validator grant for a new address
* ✅ s properties @property: doesn't update when committed validator grant for an existing address
* ✅ s access control allowed: any address

### permissionAddresses

### stagedPermissionGrantsAddresses

### addressesByPermission

* ✅ returns addresses that has the given permission set to true

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ updates by #stagePermissionGrants + #commitPermissionGrants or #revokePermissions
* ✅ is not affected by forceAllowMask
* ✅ returns empty array on unknown permissionId

### hasPermission

### hasAllPermissions

* ✅ checks if an address has all permissions set to true

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ returns false on random address
* ✅ is not affected by staged permissions
* ✅ is affected by committed permissions
* ✅ returns true for any address when forceAllowMask is set to true

*Edge cases*

* ✅ on unknown permission id returns false

### maxTokensPerVault

* ✅ returns correct value

### governanceDelay

* ✅ returns correct value

### protocolTreasury

* ✅ returns correct value

### forceAllowMask

* ✅ returns correct value

### withdrawLimit

* ✅ returns correct value

### supportsInterface

* ✅ returns true for IProtocolGovernance interface (0xca11fe03)
* ✅ access control: allowed: any address
* ✅ edge cases: when contract does not support the given interface returns false

### stageValidator

* ✅ emits ValidatorStaged event

*Access control*

* ✅ allowed: admin
* ✅ denied: deployer
* ✅ denied: random address

*Edge cases*

* ✅ when attempting to stage grant to zero address reverts with AZ when target has zero address
* ✅ when attempting to stage grant to zero address reverts with AZ when validator has zero address

### rollbackStagedValidators

* ✅ rolls back all staged validators
* ✅ emits AllStagedValidatorsRolledBack event

*Access control*

* ✅ allowed: admin
* ✅ denied: deployer
* ✅ denied: random address

### commitValidator

* ✅ commits staged validators
* ✅ emits ValidatorCommitted event

*Access control*

* ✅ allowed: admin
* ✅ denied: deployer
* ✅ denied: random address

*Edge cases*

* ✅ when attempting to commit validator for zero address reverts with NULL
* ✅ when nothing is staged for the given address reverts with NULL
* ✅ when attempting to commit validator too early reverts with TS

### commitAllValidatorsSurpassedDelay

* ✅ emits ValidatorCommitted event

*Access control*

* ✅ allowed: admin
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ commits all staged validators
* ✅ commits all staged validators after delay

*Edge cases*

* ✅ when attempting to commit a single validator too early does not commit validator
* ✅ when attempting to commit multiple validators too early does not commit these validators

### revokeValidator

* ✅ emits ValidatorRevoked event

*Edge cases*

* ✅ when attempting to revoke from zero address reverts with NULL

### rollbackStagedPermissionGrants

* ✅ rolls back all staged permission grants
* ✅ emits AllStagedPermissionGrantsRolledBack event

*Access control*

* ✅ allowed: admin
* ✅ denied: deployer
* ✅ denied: random address

### commitPermissionGrants

* ✅ commits staged permission grants
* ✅ emits PermissionGrantsCommitted event

*Access control*

* ✅ allowed: admin
* ✅ denied: deployer
* ✅ denied: random address

*Edge cases*

* ✅ when attempting to commit permissions for zero address reverts with NULL
* ✅ when nothing is staged for the given address reverts with NULL
* ✅ when attempting to commit permissions too early reverts with TS

### commitAllPermissionGrantsSurpassedDelay

* ✅ emits PermissionGrantsCommitted event

*Access control*

* ✅ allowed: admin
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ commits all staged permission grants
* ✅ commits all staged permission grants after delay

*Edge cases*

* ✅ when attempting to commit a single permission too early does not commit permission
* ✅ when attempting to commit multiple permissions too early does not commit these permissions

### revokePermissions

* ✅ emits PermissionRevoked event

*Edge cases*

* ✅ when attempting to revoke from zero address reverts with NULL

### commitParams

* ✅ emits ParamsCommitted event

*Access control*

* ✅ allowed: protocol admin
* ✅ denied: deployer
* ✅ denied: random address

*Edge cases*

* ✅ when attempting to commit params too early reverts with TS
* ✅ when attempting to commit params without setting pending params reverts with NULL

### stagePermissionGrants

* ✅ emits PermissionGrantsStaged event

*Access control*

* ✅ allowed: admin
* ✅ denied: deployer
* ✅ denied: random address

*Edge cases*

* ✅ when attempting to stage grant to zero address reverts with NULL

### stageParams

* ✅ emits ParamsStaged event

*Access control*

* ✅ allowed: admin
* ✅ denied: random address

*Edge cases*

* ✅ when given invalid params when maxTokensPerVault is zero reverts with NULL
* ✅ when given invalid params when governanceDelay is zero reverts with NULL
* ✅ when given invalid params when governanceDelay exceeds MAX\_GOVERNANCE\_DELAY reverts with LIMO
* ✅ when given invalid params when withdrawLimit less than MIN\_WITHDRAW\_LIMIT reverts with LIMO

## UnitPricesGovernance

### constructor

### supportsInterface

### stageUnitPrice

### rollbackUnitPrice

### commitUnitPrice

## VaultRegistry

### constructor

* ✅ creates VaultRegistry
* ✅ initializes ProtocolGovernance address
* ✅ initializes ERC721 token name
* ✅ initializes ERC721 token symbol

### vaults

* ✅ returns all registered vaults
* ✅ access control: allowed: any address
* ✅ ount returns the number of registered vaults
* ✅ ount access control: allowed: any address
* ✅ ount properties @property: when N new vaults have been registered, vaults count will be increased by N

### vaultForNft

* ✅ resolves Vault address by VaultRegistry NFT
* ✅ access control: allowed: any address

*Edge cases*

* ✅ when Vault NFT is not registered in VaultRegistry returns zero address

### nftForVault

* ✅ resolves VaultRegistry NFT by Vault address
* ✅ access control: allowed: any address

*Edge cases*

* ✅ when Vault is not registered in VaultRegistry returns zero

### isLocked

* ✅ checks if token is locked (not transferable)
* ✅ access control: allowed: any address

*Edge cases*

* ✅ when VaultRegistry NFT is not registered in VaultRegistry returns false

### protocolGovernance

* ✅ returns ProtocolGovernance address
* ✅ access control: allowed: any address

### stagedProtocolGovernance

* ✅ returns ProtocolGovernance address staged for commit
* ✅ access control: allowed: any address
* ✅ imestamp returns timestamp after which #commitStagedProtocolGovernance can be called
* ✅ imestamp access control: allowed: any address
* ✅ imestamp edge cases when nothing is staged returns 0
* ✅ imestamp edge cases right after #commitStagedProtocolGovernance was called returns 0

*Edge cases*

* ✅ when nothing is staged returns zero address
* ✅ right after #commitStagedProtocolGovernance was called returns zero address

### stagedProtocolGovernanceTimestamp

* ✅ returns timestamp after which #commitStagedProtocolGovernance can be called
* ✅ access control: allowed: any address

*Edge cases*

* ✅ when nothing is staged returns 0
* ✅ right after #commitStagedProtocolGovernance was called returns 0

### vaultsCount

* ✅ returns the number of registered vaults
* ✅ access control: allowed: any address

*Properties*

* ✅ when N new vaults have been registered, vaults count will be increased by N

### supportsInterface

* ✅ returns true if this contract supports a certain interface
* ✅ access control: allowed: any address
* ✅ edge cases: when contract does not support the given interface returns false

### registerVault

* ✅ binds minted ERC721 NFT to Vault address and transfers minted NFT to owner specified in args
* ✅ emits VaultRegistered event
* ✅ access control: allowed: any account with Register Vault permissions
* ✅ access control: denied: any other address
* ✅ access control: denied: protocol governance admin

*Properties*

* ✅ minted NFT equals to vaultRegistry#vaultsCount

*Edge cases*

* ✅ when address doesn't conform to IVault interface (IERC165) reverts with INVI
* ✅ when vault has already been registered reverts with DUP
* ✅ when owner address is zero reverts with AZ

### stageProtocolGovernance

* ✅ stages new ProtocolGovernance for commit
* ✅ sets the stagedProtocolGovernanceTimestamp after which #commitStagedProtocolGovernance can be called
* ✅ access control: allowed: ProtocolGovernance Admin
* ✅ access control: denied: any other address
* ✅ access control: denied: deployer

*Edge cases*

* ✅ when new ProtocolGovernance is a zero address reverts with AZ

### commitStagedProtocolGovernance

* ✅ commits staged ProtocolGovernance
* ✅ resets staged ProtocolGovernanceTimestamp
* ✅ resets staged ProtocolGovernance
* ✅ access control: allowed: ProtocolGovernance Admin
* ✅ access control: denied: any other address

*Edge cases*

* ✅ when nothing is staged reverts with INIT
* ✅ when called before stagedProtocolGovernanceTimestamp reverts with TS
* ✅ when called before stagedProtocolGovernanceTimestamp reverts with TS

### lockNft

* ✅ locks NFT (disables any transfer)
* ✅ emits TokenLocked event
* ✅ access control: allowed: NFT owner
* ✅ access control: denied: any other address
* ✅ access control: denied: protocol admin

*Edge cases*

* ✅ when NFT has already been locked succeeds

## CommonLibrary

## ExceptionsLibrary

## PermissionIdsLibrary

## SemverLibrary

## ChainlinkOracle

### constructor

### hasOracle

* ✅ returns true if oracle is supported
* ✅ edge cases: when oracle is not supported returns false

### supportedTokens

* ✅ returns list of supported tokens

### priceX96

### supportsInterface

* ✅ returns true for ChainlinkOracle interface (0x8e3bd5d7)
* ✅ edge cases: when contract does not support the given interface returns false

### addChainlinkOracles

* ✅ emits OraclesAdded event
* ✅ when oracles have set by addChainLinkOracles function returns prices
* ✅ edge cases: when arrays have different lengths reverts with INV
* ✅ edge cases: when sender has no admin righs reverts with FRB

## MellowOracle

### constructor

### priceX96

### supportsInterface

* ✅ returns true for IUniV3Oracle interface (0x6d80125b)
* ✅ edge cases: when contract does not support the given interface returns false

## UniV2Oracle

### constructor

### priceX96

### supportsInterface

* ✅ returns true for IUniV2Oracle interface (0x2748645e)
* ✅ edge cases: when contract does not support the given interface returns false

## UniV3Oracle

### constructor

### priceX96

### supportsInterface

* ✅ returns true for IUniV3Oracle interface (0x2a3602d6)
* ✅ when contract does not support the given interface returns false

### addUniV3Pools

* ✅ when adding \[weth, usdc] pools with fee = 500 adds pools
* ✅ when adding \[weth, usdc] pools with fee = 3000 adds pools
* ✅ when adding \[weth, usdc] pools with fee = 10000 does not return prices

## HStrategy

### constructor

* ✅ deploys a new contract

### initialize

### createStrategy

* ✅ creates a new strategy and initializes it

### updateStrategyParams

### updateMintingParams

### updateOracleParams

### updateRatioParams

### updateSwapFees

### manualPull

* ✅ pulls token amounts from fromVault to toVault

### rebalance

* ✅ performs a rebalance according to strategy params

## LStrategy

### constructor

### getTargetPriceX96

### targetUniV3LiquidityRatio

### rebalanceERC20UniV3Vaults

### rebalanceUniV3Vaults

### postPreOrder

### signOrder

### resetCowswapAllowance

### collectUniFees

### manualPull

### updateTradingParams

### updateRatioParams

### updateOtherParams

## MStrategy

### constructor

* ✅ deploys a new contract

*Edge cases*

* ✅ when positionManager\_ address is zero reverts with AZ
* ✅ when router\_ address is zero passes

### getAverageTick

* ✅ returns average UniswapV3Pool price tick

### initialize

### createStrategy

* ✅ creates a new strategy and initializes it

*Access control*

* ✅ allowed: any address

*Edge cases*

* ✅ when tokens.length is not equal 2 reverts with INVL
* ✅ when erc20Vault vaultTokens do not match tokens\_ reverts with INVA
* ✅ when moneyVault vaultTokens do not match tokens\_ reverts with INVA
* ✅ when UniSwapV3 pool for tokens does not exist reverts with AZ

### rebalance

* ✅ performs a rebalance according to target ratios when token0/token1 ratio is greater than required
* ✅ performs a rebalance according to target ratios when token0/token1 ratio is less than required

*Access control*

* ✅ allowed: MStrategy admin
* ✅ allowed: MStrategy operator
* ✅ denied: any other address

*Edge cases*

* ✅ when absolute tick deviation >= oracle.maxTickDeviation reverts with INVA
* ✅ when tick is greater than tickMax - tickNeiborhood the upper bound of the interval is expanded by tickIncrease amount
* ✅ when tick is less than tickMin + tickNeiborhood the lower bound of the interval is expanded by tickIncrease amount
* ✅ when current tick has not deviated from the previous rebalance tick reverts with LIMU

### manualPull

* ✅ pulls token amounts from fromVault to toVault

*Access control*

* ✅ allowed: MStrategy admin
* ✅ denied: any other address

*Edge cases*

* ✅ when token pull amounts are 0 passes

### setOracleParams

* ✅ sets new params for oracle
* ✅ edge cases: when maxSlippageD is more than DENOMINATOR reverts with INVA

*Access control*

* ✅ allowed: MStrategy admin
* ✅ denied: any other address

### setRatioParams

* ✅ sets new ratio params
* ✅ edge cases: tickMin is greater than tickMax reverts with INVA
* ✅ edge cases: when erc20MoneyRatioD is more than DENOMINATOR reverts with INVA
* ✅ edge cases: when minErc20MoneyRatioDeviationD is more than DENOMINATOR reverts with INVA

*Access control*

* ✅ allowed: MStrategy admin
* ✅ denied: any other address

## MultiPoolHStrategy

### constructor

### initialize

### createStrategy

### updateMutableParams

### rebalance

* ✅ works correctly

### checkMutableParams

## PulseRouteStrategy

### constructor

### initialize

### updateMutableParams

### rebalance

### calculateNewInterval

### checkMutableParams

### checkImmutableParams

### checkTickDeviations

### calculateTargetRatioOfToken1

### calculateAmountsForSwap

### depositCallback

### withdrawCallback

## PulseStrategy

### constructor

### initialize

### updateMutableParams

### rebalance

### checkMutableParams

### checkImmutableParams

### checkTickDeviation

### calculateNewPosition

### calculateTargetRatioOfToken1

### calculateAmountsForSwap

### depositCallback

### withdrawCallback

## PulseStrategyV2

### constructor

### initialize

### setForceRebalanceFlag

### updateDesiredAmounts

### updateMutableParams

### rebalance

### checkMutableParams

### checkImmutableParams

### checkTickDeviation

### formPositionWithSpotTickInCenter

### calculateNewPosition

### calculateTargetRatioOfToken1

### calculateAmountsForSwap

### depositCallback

### withdrawCallback

## QuickPulseStrategy

### constructor

### initialize

### updateMutableParams

### rebalance

### checkMutableParams

### checkImmutableParams

### checkTickDeviation

### calculateNewPosition

### calculateTargetRatioOfToken1

### calculateAmountsForSwap

### depositCallback

### withdrawCallback

### onERC721Received

## SinglePositionQuickSwapStrategy

### constructor

### initialize

### updateMutableParams

### rebalance

### calculateNewInterval

### checkMutableParams

### checkImmutableParams

### checkTickDeviations

### calculateTargetRatioOfToken1

### calculateAmountsForSwap

### depositCallback

### withdrawCallback

## SinglePositionStrategy

### constructor

* ✅ creates contract

### initialize

### updateMutableParams

### rebalance

* ✅ works correctly

### calculateNewInterval

### checkMutableParams

### checkImmutableParams

### checkTickDeviations

### calculateTargetRatioOfToken1

### calculateAmountsForSwap

### depositCallback

### withdrawCallback

## BatchCall

### batchcall

* ✅ returns results
* ✅ edge cases: when arrays have different lengths reverts with INVL
* ✅ edge cases: when targets arrays not only of contracts reverts with "Address: delegate call to non-contract"

## ContractMeta

### contractName

### contractNameBytes

### contractVersion

### contractVersionBytes

## DefaultAccessControl

### constructor

### isAdmin

### isOperator

## DefaultAccessControlLateInit

### isAdmin

* ✅ returns `true` if sender is an admin, `false` otherwise

### isOperator

* ✅ returns `true` if sender is an operator, `false` otherwise

### init

## DefaultProxy

### constructor

## DefaultProxyAdmin

## ERC20RootVaultHelper

### getTvlToken0

## ERC20Token

### approve

* ✅ allows `sender` to transfer `spender` an `amount` and emits Approval

### transfer

* ✅ transfers `amount` from `msg.sender` to `to`
* ✅ rom transfers `amount` from `from` to `to` if allowed

### transferFrom

* ✅ transfers `amount` from `from` to `to` if allowed

### permit

* ✅ emits Approval
* ✅ edge cases: when deadline less than current timestamp reverts with TS
* ✅ edge cases: when incorrect signature reverts with FRB

## GearboxHelper

### setParameters

### verifyInstances

### calculateEarnedCvxAmountByEarnedCrvAmount

### calculateClaimableRewards

### calculateDesiredTotalValue

### calcConvexTokensToWithdraw

### calcRateRAY

### calculateAmountInMaximum

### createUniswapMulticall

### checkNecessaryDepositExchange

### claimRewards

### withdrawFromConvex

### depositToConvex

### adjustPosition

### swapExactOutput

### pullFromAddress

### openCreditAccount

## HStrategyHelper

### calculateExpectedRatios

### calculateMissingTokenAmounts

### calculateExtraTokenAmountsForUniV3Vault

### calculateExtraTokenAmountsForMoneyVault

### calculateExpectedTokenAmountsByExpectedRatios

### calculateCurrentTokenAmounts

### calculateCurrentCapitalInToken0

### calculateExpectedTokenAmountsInToken0

### swapNeeded

### tokenRebalanceNeeded

### calculateAndCheckDomainPositionParams

### checkSpotTickDeviationFromAverage

### calculateNewPositionTicks

### calculateExpectedTokenAmounts

## LStrategyHelper

### constructor

### checkOrder

### tickFromPriceX96

## MultiPoolHStrategyRebalancer

### constructor

### initialize

### createRebalancer

### getTvls

### processRebalance

### calculateExpectedAmounts

### calculateNewPosition

## PulseStrategyHelper

### getStrategyParams

### calculateAmountForSwap

## PulseStrategyV2Helper

### getStrategyParams

### calculateAmountForSwap

## QuickPulseStrategyHelper

### getStrategyParams

### calculateAmountForSwap

## QuickSwapHelper

### constructor

### calculateTvl

### liquidityToTokenAmounts

### tokenAmountsToLiquidity

### tokenAmountsToMaxLiquidity

### calculateLiquidityToPull

### increaseCumulative

### calculateInnerFeesGrow

### calculateCollectableRewards

### convertTokenToUnderlying

## SinglePositionStrategyHelper

### checkUniV3PoolState

### checkAlgebraPoolState

## UniV3Helper

### constructor

### liquidityToTokenAmounts

* ✅ returns correct vaulues for type(uint128).max

### tokenAmountsToLiquidity

### tokenAmountsToMaximalLiquidity

### getPoolByNft

### getFeesByNft

### calculateTvlBySqrtPriceX96

### calculateTvlByMinMaxPrices

### getTickDeviationForTimeSpan

* ✅ returns withFail=true if there is no observation in the pool that was not made before secondsAgo

### getPositionTokenAmountsByCapitalOfToken0

* ✅ test uniV3Helper, borders: -600 0
* ✅ test uniV3Helper, borders: 600 1200
* ✅ test uniV3Helper, borders: -600 600

## WhiteList

### constructor

### deposit

* ✅ works correctly
* ✅ reverts on wrong address

### updateRoot

## AllowAllValidator

### constructor

* ✅ deploys a new contract

### validate

* ✅ successful validate

## BaseValidator

### constructor

### stagedValidatorParams

### stagedValidatorParamsTimestamp

### validatorParams

### stageValidatorParams

### commitValidatorParams

## CowswapValidator

### constructor

* ✅ deploys a new contract

### validate

* ✅ successful validate
* ✅ edge cases: when selector is not 0xec6cb13f reverts with INVS

## CurveValidator

### constructor

* ✅ deploys a new contract

### validate

* ✅ successful validate
* ✅ edge cases: when selector is not 0x3df02124 reverts with INVS
* ✅ edge cases: when token ids are equal reverts with INV
* ✅ edge cases: when not a vault token reverts with INVTO
* ✅ edge cases: when pool has no approve permission reverts with FRB

## ERC20Validator

### constructor

* ✅ deploys a new contract

### validate

* ✅ successful validate, spender can approve
* ✅ successful validate, sender is trusted strategy
* ✅ edge cases: when value is not zero reverts with INV
* ✅ edge cases: when selector is not 0x095ea7b3 reverts with INVS
* ✅ edge cases: when no transfer permission reverts with FRB
* ✅ edge cases: when no approve permission reverts with FRB

## QuickSwapValidator

### constructor

### validate

## UniV2Validator

### constructor

* ✅ deploys a new contract

### validate

* ✅ selector is 0x7ff36ab5 or 0xfb3bdb41 successful validate
* ✅ selector is 0x7ff36ab5 or 0xfb3bdb41 edge cases: when addr is not swap reverts with INVTR
* ✅ selector is 0x7ff36ab5 or 0xfb3bdb41 edge cases: when selector is wrong reverts with INVS
* ✅ selector is 0x7ff36ab5 or 0xfb3bdb41 edge cases: when path is too small reverts with INVL
* ✅ selector is 0x7ff36ab5 or 0xfb3bdb41 edge cases: when not a vault token reverts with INVTO
* ✅ selector is 0x7ff36ab5 or 0xfb3bdb41 edge cases: when tokens are the same reverts with INVTO
* ✅ selector is 0x7ff36ab5 or 0xfb3bdb41 edge cases: when pool has no approve permission reverts with FRB
* ✅ selector is 0x7ff36ab5 or 0xfb3bdb41 edge cases: when sender is not a reciever reverts
* ✅ selector is one of: 0x4a25d94a, 0x18cbafe5, 0x38ed1739, 0x8803dbee successful validate
* ✅ selector is one of: 0x4a25d94a, 0x18cbafe5, 0x38ed1739, 0x8803dbee edge cases: when value is not zero reverts with INV
* ✅ selector is one of: 0x4a25d94a, 0x18cbafe5, 0x38ed1739, 0x8803dbee edge cases: when sender is not reciever reverts
* ✅ selector is one of: 0x4a25d94a, 0x18cbafe5, 0x38ed1739, 0x8803dbee edge cases: when path too small reverts with INVL
* ✅ selector is one of: 0x4a25d94a, 0x18cbafe5, 0x38ed1739, 0x8803dbee edge cases: when not a vault token reverts with INVTO
* ✅ selector is one of: 0x4a25d94a, 0x18cbafe5, 0x38ed1739, 0x8803dbee edge cases: when tokens are the same reverts with INVTO
* ✅ selector is one of: 0x4a25d94a, 0x18cbafe5, 0x38ed1739, 0x8803dbee edge cases: when pool has no approve permission reverts with FRB

## UniV3Validator

### constructor

* ✅ deploys a new contract

### validate

* ✅ edge cases: if addr is not swap reverts with INVTR
* ✅ edge cases: if value is not zero reverts with INV
* ✅ edge cases: if selector is wrong reverts with INVS
* ✅ selector is 0x414bf389 successful validate
* ✅ selector is 0x414bf389 edge cases: if recipient is not sender reverts with INVTR
* ✅ selector is 0x414bf389 edge cases: if not a vault token reverts with INVTO
* ✅ selector is 0x414bf389 edge cases: if tokens are the same reverts with INVTO
* ✅ selector is 0x414bf389 edge cases: if pool has no permisson reverts with FRB
* ✅ selector is 0xdb3e2198 successfull validate
* ✅ selector is 0xdb3e2198 edge cases: if recipient is not sender reverts with INVTR
* ✅ selector is 0xdb3e2198 edge cases: if not a vault token reverts with INVTO
* ✅ selector is 0xdb3e2198 edge cases: if tokens are the same reverts with INVTO
* ✅ selector is 0xdb3e2198 edge cases: if pool has no permisson reverts with FRB
* ✅ selector is 0xc04b8d59 successfull validate
* ✅ selector is 0xc04b8d59 edge cases: if recipient is not sender reverts with INVTR
* ✅ selector is 0xc04b8d59 edge cases: if tokens are the same reverts with INVTO
* ✅ selector is 0xc04b8d59 edge cases: if pool has no approve permission reverts with FRB
* ✅ selector is 0xc04b8d59 edge cases: if not a vault token reverts with INVTO
* ✅ selector is 0xf28c0498 successfull validate
* ✅ selector is 0xf28c0498 edge cases: if recipient is not sender reverts with INVTR
* ✅ selector is 0xf28c0498 edge cases: if tokens are the same reverts with INVTO
* ✅ selector is 0xf28c0498 edge cases: if pool has no approve permission reverts with FRB
* ✅ selector is 0xf28c0498 edge cases: if not a vault token reverts with INVTO

## Validator

### supportsInterface

## AaveVault

### tvl

* ✅ returns total value locked
* ✅ returns total value locked, no time passed from initialization
* ✅ edge cases: when there are no initial funds returns zeroes

### lendingPool

* ✅ returns ILendingPool
* ✅ access control: allowed: any address

### supportsInterface

* ✅ returns true if this contract supports 0x18026500 interface
* ✅ access control: allowed: any address
* ✅ returns true if this contract supports 0x7a63aa3a interface
* ✅ access control: allowed: any address
* ✅ edge cases: when contract does not support the given interface returns false

### updateTvls

* ✅ updates total value locked

### initialize

* ✅ emits Initialized event
* ✅ initializes contract successfully
* ✅ edge cases: when vault's nft is not 0 reverts with INIT
* ✅ edge cases: when tokens are not sorted reverts with INVA
* ✅ edge cases: when tokens are not unique reverts with INVA
* ✅ edge cases: when setting zero nft reverts with VZ
* ✅ edge cases: when setting token with address zero reverts with AZ
* ✅ edge cases: when token has no permission to become a vault token reverts with FRB

## AaveVaultGovernance

### constructor

* ✅ deploys a new contract
* ✅ initializes internalParams

*Edge cases*

* ✅ when lendingPool address is 0 reverts
* ✅ when estimatedAaveAPY is 0 reverts
* ✅ when estimatedAaaveAPY is larger than limit reverts
* ✅ when protocolGovernance address is 0 reverts
* ✅ when vaultRegistry address is 0 reverts

### delayedProtocolParams

* ✅ returns current DelayedProtocolParams

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ staging DelayedProtocolParams doesn't change delayedProtocolParams

*Edge cases*

* ✅ when no params were committed returns non-zero params initialized in constructor

### supportsInterface

* ✅ returns true if this contract supports 0x2f8c3ff3 interface
* ✅ access control: allowed: any address

### stagedDelayedProtocolParams

* ✅ returns DelayedProtocolParams staged for commit

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ always equals to params that were just staged

*Edge cases*

* ✅ when no params are staged for commit returns zero struct
* ✅ when params were just committed returns zero struct

### stageDelayedProtocolParams

* ✅ stages DelayedProtocolParams for commit
* ✅ sets delay for commit
* ✅ emits StageDelayedProtocolParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address

*Edge cases*

* ✅ when estimated Aave APY is larger than limit reverts
* ✅ when called twice succeeds with the last value
* ✅ when called with zero params reverts with zero params

### commitDelayedProtocolParams

* ✅ commits staged DelayedProtocolParams
* ✅ resets delay for commit
* ✅ emits CommitDelayedProtocolParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address
* ✅ reverts if called before the delay has elapsed
* ✅ succeeds if called after the delay has elapsed

*Edge cases*

* ✅ when called twice reverts
* ✅ when nothing is staged reverts
* ✅ when delay has not elapsed reverts

### createVault

* ✅ deploys a new vault
* ✅ registers vault with vault registry and issues nft
* ✅ the nft is owned by the owner from #createVault arguments
* ✅ vault is initialized with nft

*Access control*

* ✅ when permissionless allowed: any address
* ✅ when not permissionless allowed: protocol governance admin
* ✅ when not permissionless denied: any address

## AggregateVault

### subvaultNfts

### subvaultOneBasedIndex

### hasSubvault

### subvaultAt

### tvl

### supportsInterface

## ERC20RootVault

### depositorsAllowlist

* ✅ returns non zero length of depositorsAllowlist
* ✅ access control: allowed: any address

### supportsInterface

* ✅ returns true if this contract supports 0x23040f0a interface
* ✅ edge cases: when contract does not support the given interface returns false
* ✅ access control: allowed: any address

### addDepositorsToAllowlist

* ✅ adds depositor to allow list
* ✅ access control: allowed: admin
* ✅ access control: not allowed: deployer
* ✅ access control: not allowed: any address

### removeDepositorsFromAllowlist

* ✅ removes depositor to allow list
* ✅ access control: allowed: admin
* ✅ access control: not allowed: deployer
* ✅ access control: not allowed: any address

### initialize

* ✅ edge cases: when root vault is not owner of subvault nft reverts with FRB
* ✅ edge cases: when subVault index is 0 (rootVault has itself as subVaul) reverts with DUP
* ✅ edge cases: when subVault index index is 0 reverts with DUP

### deposit

* ✅ rsAllowlist returns non zero length of depositorsAllowlist
* ✅ rsAllowlist access control: allowed: any address
* ✅ emits Deposit event
* ✅ checking protocol fees charges fees
* ✅ edge cases: when performance fee is zero do not charge performance fees
* ✅ edge cases: when management fee is zero not charges management fees
* ✅ edge cases: when deposit is disabled reverts with FRB
* ✅ edge cases: when there is no depositor in allow list reverts with FRB
* ✅ edge cases: when there is a private vault in delayedStrategyParams reverts with FRB
* ✅ edge cases: when minLpTokens is greater than lpAmount reverts with LIMU
* ✅ edge cases: when tokenAmounts is less than or equal to FIRST\_DEPOSIT\_LIMIT reverts with LIMU
* ✅ edge cases: when depositCallback Address is set emits deposits callback called
* ✅ edge cases: when lpAmount is zero reverts with VZ
* ✅ edge cases: when sum of lpAmount and sender balance is greater than tokenLimitPerAddress reverts with LIMO
* ✅ edge cases: when sum of lpAmount and totalSupply is greater than tokenLimit reverts with LIMO
* ✅ access control: allowed: any address

### withdraw

* ✅ emits Withdraw event
* ✅ edge cases: when total supply is 0 reverts with VZ
* ✅ edge cases: when length of vaultsOptions and length of \_subvaultNfts are different reverts with INVL
* ✅ edge cases: when withdrawn is larger than protocol governance withdraw limit for vault token reverts with LIMO
* ✅ edge cases: When address of lpCallback is not null emits withdrawCallback
* ✅ edge cases: When address of lpCallback is not null and lpCallback throws empty error emits WithdrawCallbackLog
* ✅ edge cases: When address of lpCallback is not null and lpCallback throws non empty error emits WithdrawCallbackLog
* ✅ access control: allowed: any address

## ERC20RootVaultGovernance

### constructor

* ✅ deploys a new contract
* ✅ initializes internalParams

*Edge cases*

* ✅ when protocolGovernance address is 0 reverts
* ✅ when vaultRegistry address is 0 reverts

### delayedProtocolParams

* ✅ returns current DelayedProtocolParams

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ staging DelayedProtocolParams doesn't change delayedProtocolParams

*Edge cases*

* ✅ when no params were committed returns non-zero params initialized in constructor

### stagedDelayedProtocolParams

* ✅ returns DelayedProtocolParams staged for commit

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ always equals to params that were just staged

*Edge cases*

* ✅ when no params are staged for commit returns zero struct
* ✅ when params were just committed returns zero struct

### delayedProtocolPerVaultParams

* ✅ returns current DelayedProtocolPerVaultParams

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ staging DelayedProtocolPerVaultParams doesn't change delayedProtocolPerVaultParams

*Edge cases*

* ✅ when no params were committed returns zero params

### stagedDelayedProtocolPerVaultParams

* ✅ returns DelayedProtocolPerVaultParams staged for commit

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ always equals to params that were just staged

*Edge cases*

* ✅ when no params are staged for commit returns zero struct
* ✅ when params were just committed returns zero struct

### stagedDelayedStrategyParams

* ✅ returns DelayedStrategyParams staged for commit

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ always equals to params that were just staged

*Edge cases*

* ✅ when no params are staged for commit returns zero struct
* ✅ when params were just committed returns zero struct

### operatorParams

* ✅ returns operatorParams

*Access control*

* ✅ allowed: any address

*Edge cases*

* ✅ when operatorParams have not been set returns zero params

### delayedStrategyParams

* ✅ returns current DelayedStrategyParams

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ staging DelayedStrategyParams doesn't change delayedStrategyParams

*Edge cases*

* ✅ when no params were committed returns zero params

### strategyParams

### supportsInterface

* ✅ returns true if this contract supports 0x6a2c3330 interface
* ✅ access control: allowed: any address

### stageDelayedStrategyParams

* ✅ stages DelayedStrategyParams for commit
* ✅ sets zero delay for commit when #commitDelayedStrategyParams was called 0 times (init)
* ✅ sets governance delay for commit after #commitDelayedStrategyParams was called at least once
* ✅ emits StageDelayedStrategyParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ allowed: Vault NFT Approved (aka strategy)
* ✅ allowed: Vault NFT Owner (aka liquidity provider)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address

*Edge cases*

* ✅ when managementFee is exceeds MAX\_MANAGEMENT\_FEE reverts with LIMO
* ✅ when performnaceFee is exceeds MAX\_PERFORMANCE\_FEE reverts with LIMO
* ✅ when called twice succeeds with the last value
* ✅ when called with zero params succeeds with zero params

### commitDelayedStrategyParams

* ✅ commits staged DelayedStrategyParams
* ✅ resets delay for commit
* ✅ emits CommitDelayedStrategyParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ allowed: Vault NFT Owner (aka liquidity provider)
* ✅ allowed: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address
* ✅ reverts if called before the delay has elapsed (after commit was called initally)
* ✅ succeeds if called after the delay has elapsed

*Edge cases*

* ✅ when called twice reverts
* ✅ when nothing is staged reverts
* ✅ when delay has not elapsed (after initial commit call) reverts

### stageDelayedProtocolPerVaultParams

* ✅ stages DelayedProtocolPerVaultParams for commit
* ✅ sets delay for commit
* ✅ emits StageDelayedProtocolPerVaultParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address

*Edge cases*

* ✅ when called twice succeeds with the last value
* ✅ when called with zero params succeeds with zero params
* ✅ when protocol fee is greater than MAX\_PROTOCOL\_FEE reverts

### commitDelayedProtocolPerVaultParams

* ✅ commits staged DelayedProtocolPerVaultParams
* ✅ resets delay for commit
* ✅ emits CommitDelayedProtocolPerVaultParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address
* ✅ reverts if called before the delay has elapsed only if params have already been commited
* ✅ succeeds if called after the delay has elapsed

*Edge cases*

* ✅ when called twice reverts
* ✅ when nothing is staged reverts
* ✅ when delay has not elapsed and params have not been commited reverts
* ✅ when params have already been set and delay has not elapsed reverts

### setStrategyParams

### setOperatorParams

* ✅ sets new operatorParams
* ✅ access constrol allowed: ProtocolGovernance admin or Operator
* ✅ access constrol denied: any other address

*Properties*

* ✅ setting new oprator params overwrites old params immediately

### stageDelayedProtocolParams

* ✅ stages DelayedProtocolParams for commit
* ✅ sets delay for commit
* ✅ emits StageDelayedProtocolParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address

*Edge cases*

* ✅ when called twice succeeds with the last value
* ✅ when called with zero params reverts with zero params

### commitDelayedProtocolParams

* ✅ commits staged DelayedProtocolParams
* ✅ resets delay for commit
* ✅ emits CommitDelayedProtocolParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address
* ✅ reverts if called before the delay has elapsed
* ✅ succeeds if called after the delay has elapsed

*Edge cases*

* ✅ when called twice reverts
* ✅ when nothing is staged reverts
* ✅ when delay has not elapsed reverts

### createVault

* ✅ deploys a new vault
* ✅ registers vault with vault registry and issues nft
* ✅ the nft is owned by the owner from #createVault arguments
* ✅ vault is initialized with nft

*Access control*

* ✅ when permissionless allowed: any address
* ✅ when not permissionless allowed: protocol governance admin
* ✅ when not permissionless denied: any address

## ERC20Vault

### tvl

* ✅ returns total value locked
* ✅ edge cases: when there are no initial funds returns zeroes

### initialize

* ✅ emits Initialized event
* ✅ initializes contract successfully
* ✅ edge cases: when vault's nft is not 0 reverts with INIT
* ✅ edge cases: not initialized when vault's nft is 0 returns false
* ✅ edge cases: when tokens are not sorted reverts with INVA
* ✅ edge cases: when tokens are not unique reverts with INVA
* ✅ edge cases: when setting zero nft reverts with VZ
* ✅ edge cases: when setting empty tokens array reverts with INV
* ✅ edge cases: when token has no permission to become a vault token reverts with FRB

### supportsInterface

* ✅ returns true if this contract supports 0x7a63aa3a interface
* ✅ access control: allowed: any address
* ✅ edge cases: when contract does not support the given interface returns false

## ERC20VaultGovernance

### constructor

* ✅ deploys a new contract
* ✅ initializes internalParams

*Edge cases*

* ✅ when protocolGovernance address is 0 reverts
* ✅ when vaultRegistry address is 0 reverts

### createVault

* ✅ deploys a new vault
* ✅ registers vault with vault registry and issues nft
* ✅ the nft is owned by the owner from #createVault arguments
* ✅ vault is initialized with nft

*Access control*

* ✅ when permissionless allowed: any address
* ✅ when not permissionless allowed: protocol governance admin
* ✅ when not permissionless denied: any address

## GearboxRootVault

### depositorsAllowlist

### supportsInterface

### addDepositorsToAllowlist

### removeDepositorsFromAllowlist

### initialize

### deposit

### registerWithdrawal

### cancelWithdrawal

### invokeExecution

### withdraw

### shutdown

### reopen

## GearboxVault

### tvl

### supportsInterface

### getCreditAccount

### getAllAssetsOnCreditAccountValue

### getClaimableRewardsValue

### getMerkleProof

### initialize

### openCreditAccount

### adjustPosition

### setMerkleParameters

### updateTargetMarginalFactor

### multicall

### swap

### openCreditAccountInManager

## GearboxVaultGovernance

### constructor

### delayedProtocolParams

### supportsInterface

### stagedDelayedProtocolParams

### stagedDelayedProtocolPerVaultParams

### strategyParams

### delayedProtocolPerVaultParams

### stageDelayedProtocolParams

### commitDelayedProtocolParams

### stageDelayedProtocolPerVaultParams

### commitDelayedProtocolPerVaultParams

### setStrategyParams

### createVault

## IntegrationVault

### supportsInterface

### push

### transferAndPush

### pull

### reclaimTokens

### isValidSignature

### externalCall

## MellowVault

### tvl

### initialize

## MellowVaultGovernance

### constructor

### createVault

## QuickSwapVault

### constructor

### initialize

### onERC721Received

### openFarmingPosition

### burnFarmingPosition

### collectEarnings

### collectRewards

### tvl

### supportsInterface

### strategyParams

## QuickSwapVaultGovernance

### constructor

### strategyParams

### supportsInterface

### setStrategyParams

### createVault

## UniV3Vault

### tvl

* ✅ returns total value locked
* ✅ edge cases: when there are no initial funds returns zeroes
* ✅ edge cases: when push was made but there was no minted position returns zeroes

### supportsInterface

* ✅ returns true if this contract supports 0x88878d28 interface
* ✅ access control: allowed: any address
* ✅ returns true if this contract supports 0x7a63aa3a interface
* ✅ access control: allowed: any address
* ✅ edge cases: when contract does not support the given interface returns false

### positionManager

* ✅ returns INonfungiblePositionManager
* ✅ access control: allowed: any address

### liquidityToTokenAmounts

* ✅ returns tokenAmounts corresponding to liquidity

### tokenAmountsToLiquidity

* ✅ returns zero in case of zero amounts
* ✅ returns more than zero in case of non-zero amounts
* ✅ returns proportionally correct
* ✅ returns correctly in case of tick being out of position by the left
* ✅ returns correctly in case of tick being out of position by the right

### initialize

* ✅ emits Initialized event
* ✅ initializes contract successfully
* ✅ edge cases: when vault's nft is not 0 reverts with INIT
* ✅ edge cases: when tokens are not sorted reverts with INVA
* ✅ edge cases: when tokens are not unique reverts with INVA
* ✅ edge cases: when tokens length is not equal to 2 reverts with INV
* ✅ edge cases: when setting zero nft reverts with VZ
* ✅ edge cases: when token has no permission to become a vault token reverts with FRB

### onERC721Received

* ✅ updates vault's uniV3Nft
* ✅ edge cases: when msg.sender is not a position manager reverts
* ✅ edge cases: when operator is not a strategy reverts
* ✅ edge cases: when UniV3 token is not valid reverts
* ✅ edge cases: prevent from adding nft while liquidity is not empty reverts
* ✅ access control: position manager: allowed
* ✅ access control: any other address: not allowed

### collectEarnings

* ✅ emits CollectedEarnings event
* ✅ collecting fees
* ✅ edge cases: when there is no minted position reverts
* ✅ access control: allowed: all addresses

## UniV3VaultGovernance

### constructor

* ✅ deploys a new contract
* ✅ initializes internalParams

*Edge cases*

* ✅ when positionManager address is 0 reverts
* ✅ when oracle address is 0 reverts
* ✅ when protocolGovernance address is 0 reverts
* ✅ when vaultRegistry address is 0 reverts

### delayedProtocolParams

* ✅ returns current DelayedProtocolParams

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ staging DelayedProtocolParams doesn't change delayedProtocolParams

*Edge cases*

* ✅ when no params were committed returns non-zero params initialized in constructor

### stagedDelayedProtocolParams

* ✅ returns DelayedProtocolParams staged for commit

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ always equals to params that were just staged

*Edge cases*

* ✅ when no params are staged for commit returns zero struct
* ✅ when params were just committed returns zero struct

### stagedDelayedStrategyParams

### delayedStrategyParams

### supportsInterface

* ✅ returns true if this contract supports 0xa2e9c513 interface
* ✅ access control: allowed: any address

### stageDelayedProtocolParams

* ✅ stages DelayedProtocolParams for commit
* ✅ sets delay for commit
* ✅ emits StageDelayedProtocolParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address

*Edge cases*

* ✅ when called twice succeeds with the last value
* ✅ when called with zero params reverts with zero params

### commitDelayedProtocolParams

* ✅ commits staged DelayedProtocolParams
* ✅ resets delay for commit
* ✅ emits CommitDelayedProtocolParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address
* ✅ reverts if called before the delay has elapsed
* ✅ succeeds if called after the delay has elapsed

*Edge cases*

* ✅ when called twice reverts
* ✅ when nothing is staged reverts
* ✅ when delay has not elapsed reverts

### stageDelayedStrategyParams

### commitDelayedStrategyParams

### createVault

* ✅ deploys a new vault
* ✅ registers vault with vault registry and issues nft
* ✅ the nft is owned by the owner from #createVault arguments
* ✅ vault is initialized with nft

*Access control*

* ✅ when permissionless allowed: any address
* ✅ when not permissionless allowed: protocol governance admin
* ✅ when not permissionless denied: any address

*Edge cases*

* ✅ when fee is not supported by uni v3 reverts

## Vault

### initialized

### isVaultToken

### vaultGovernance

### vaultTokens

### nft

### tvl

### pullExistentials

### supportsInterface

## VaultGovernance

### delayedStrategyParamsTimestamp

### delayedProtocolPerVaultParamsTimestamp

### delayedProtocolParamsTimestamp

### internalParamsTimestamp

### internalParams

### stagedInternalParams

### supportsInterface

### stageInternalParams

### commitInternalParams

## YearnVault

### yTokens

* ✅ returns list of yTokens

### tvl

* ✅ returns total value locked
* ✅ edge cases: when there are no initial funds returns zeroes

### supportsInterface

* ✅ returns true if this contract supports 0x073ab565 interface
* ✅ access control: allowed: any address
* ✅ returns true if this contract supports 0x7a63aa3a interface
* ✅ access control: allowed: any address
* ✅ edge cases: when contract does not support the given interface returns false

### initialize

* ✅ emits Initialized event
* ✅ initializes contract successfully
* ✅ edge cases: when vault's nft is not 0 reverts with INIT
* ✅ edge cases: when tokens are not sorted reverts with INVA
* ✅ edge cases: when tokens are not unique reverts with INVA
* ✅ edge cases: when setting zero nft reverts with VZ
* ✅ edge cases: when token has no permission to become a vault token reverts with FRB

## YearnVaultGovernance

### constructor

* ✅ deploys a new contract
* ✅ initializes internalParams

*Edge cases*

* ✅ when YearnVaultRegistry address is 0 reverts
* ✅ when protocolGovernance address is 0 reverts
* ✅ when vaultRegistry address is 0 reverts

### yTokenForToken

* ✅ returns yToken (yVault) in yToken overrides (set by #setYTokenForToken) or corresponding to ERC20 token in YearnVaultRegistry

*Access control*

* ✅ allowed: any address

*Edge cases*

* ✅ when yToken doesn't exist in overrides or YearnVaultRegistry returns 0
* ✅ when yToken was not overridden by #setYTokenForToken returns token from YearnVaultRegistry
* ✅ when yToken was overridden by #setYTokenForToken returns overridden token

### stagedDelayedProtocolParams

* ✅ returns DelayedProtocolParams staged for commit

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ always equals to params that were just staged

*Edge cases*

* ✅ when no params are staged for commit returns zero struct
* ✅ when params were just committed returns zero struct

### delayedProtocolParams

* ✅ returns current DelayedProtocolParams

*Access control*

* ✅ allowed: any address

*Properties*

* ✅ staging DelayedProtocolParams doesn't change delayedProtocolParams

*Edge cases*

* ✅ when no params were committed returns non-zero params initialized in constructor

### supportsInterface

* ✅ returns true if this contract supports 0x15482137 interface
* ✅ access control: allowed: any address

### stageDelayedProtocolParams

* ✅ stages DelayedProtocolParams for commit
* ✅ sets delay for commit
* ✅ emits StageDelayedProtocolParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address

*Edge cases*

* ✅ when called twice succeeds with the last value
* ✅ when called with zero params reverts with zero params

### commitDelayedProtocolParams

* ✅ commits staged DelayedProtocolParams
* ✅ resets delay for commit
* ✅ emits CommitDelayedProtocolParams event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Properties*

* ✅ cannot be called by random address
* ✅ reverts if called before the delay has elapsed
* ✅ succeeds if called after the delay has elapsed

*Edge cases*

* ✅ when called twice reverts
* ✅ when nothing is staged reverts
* ✅ when delay has not elapsed reverts

### setYTokenForToken

* ✅ sets a yToken override for a ERC20 token
* ✅ emits SetYToken event

*Access control*

* ✅ allowed: ProtocolGovernance admin
* ✅ denied: Vault NFT Owner (aka liquidity provider)
* ✅ denied: Vault NFT Approved (aka strategy)
* ✅ denied: deployer
* ✅ denied: random address

*Edge cases*

* ✅ when yToken is 0 succeeds
* ✅ when called twice succeeds

### createVault

* ✅ deploys a new vault
* ✅ registers vault with vault registry and issues nft
* ✅ the nft is owned by the owner from #createVault arguments
* ✅ vault is initialized with nft

*Access control*

* ✅ when permissionless allowed: any address
* ✅ when not permissionless allowed: protocol governance admin
* ✅ when not permissionless denied: any address


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mellow.finance/mellow-alm/overview/contracts-specs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
