diff --git a/.env.sepolia.example b/.env.sepolia.example index f8fcac66..9bfd6c72 100644 --- a/.env.sepolia.example +++ b/.env.sepolia.example @@ -1,3 +1,2 @@ -ETHERSCAN_API_KEY=... RPC_URL="https://eth-sepolia.g.alchemy.com/v2/xyz" ... diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f64897a..42eb62c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,6 @@ jobs: RPC_URL: ${{ secrets.RPC_URL }} DEPLOYER_PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }} LP_PRIVATE_KEY: ${{ secrets.LP_PRIVATE_KEY }} - ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} - name: "Lint" run: pnpm lint @@ -56,7 +55,6 @@ jobs: RPC_URL: ${{ secrets.RPC_URL }} DEPLOYER_PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }} LP_PRIVATE_KEY: ${{ secrets.LP_PRIVATE_KEY }} - ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }} - name: "Add test summary" @@ -99,7 +97,6 @@ jobs: RPC_URL: ${{ secrets.RPC_URL }} DEPLOYER_PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }} LP_PRIVATE_KEY: ${{ secrets.LP_PRIVATE_KEY }} - ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} publish-abis: name: "Publish Contract ABIs" @@ -136,7 +133,6 @@ jobs: RPC_URL: ${{ secrets.RPC_URL }} DEPLOYER_PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }} LP_PRIVATE_KEY: ${{ secrets.LP_PRIVATE_KEY }} - ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} - name: "Extract and package ABIs + Bytecode" run: | diff --git a/contracts/LiquidityOrchestrator.sol b/contracts/LiquidityOrchestrator.sol index d5060742..0ad31cd1 100644 --- a/contracts/LiquidityOrchestrator.sol +++ b/contracts/LiquidityOrchestrator.sol @@ -86,9 +86,6 @@ contract LiquidityOrchestrator is /// @notice Minibatch size for fulfill deposit and redeem processing uint8 public minibatchSize; - /// @notice Number of vault leaves folded into the commitment per StateCommitment upkeep step - uint8 public commitmentMinibatchSize; - /// @notice Upkeep phase LiquidityUpkeepPhase public currentPhase; @@ -111,9 +108,6 @@ contract LiquidityOrchestrator is /// @notice Live buffer amount [assets] uint256 public bufferAmount; - /// @notice Buffer snapshot captured at epoch start and used as deterministic proof input anchor [assets] - uint256 public initialEpochBufferAmount; - /// @notice Pending protocol fees [assets] uint256 public pendingProtocolFees; @@ -125,10 +119,8 @@ contract LiquidityOrchestrator is /// @notice Cached vaults hash from last full commitment build bytes32 private _cachedVaultsHash; - /// @notice Running vault leaf fold accumulator during StateCommitment phase - bytes32 private _partialVaultsHash; - /// @notice Number of vault leaves already folded this epoch - uint16 private _commitmentBatchIndex; + /// @notice Buffer snapshot captured at epoch start and used as deterministic proof input anchor [assets] + uint256 public initialEpochBufferAmount; /// @notice Epoch protocol fees to accrue when transitioning to ProcessVaultOperations. uint256 private _pendingEpochProtocolFees; @@ -152,6 +144,18 @@ contract LiquidityOrchestrator is /// @notice Current epoch state EpochState internal _currentEpoch; + /// @notice Address of the upgrade timelock that must authorise all implementation upgrades + address public upgradeTimelock; + + /// @notice Number of vault leaves folded into the commitment per StateCommitment upkeep step + uint8 public commitmentMinibatchSize; + + /// @notice Running vault leaf fold accumulator during StateCommitment phase + bytes32 private _partialVaultsHash; + + /// @notice Number of vault leaves already folded this epoch + uint16 private _commitmentBatchIndex; + /* -------------------------------------------------------------------------- */ /* MODIFIERS */ /* -------------------------------------------------------------------------- */ @@ -936,9 +940,6 @@ contract LiquidityOrchestrator is } } - /// @notice Address of the upgrade timelock that must authorise all implementation upgrades - address public upgradeTimelock; - /// @notice Sets the upgrade timelock address. /// @dev If no timelock is set yet, only the owner may call this. Once a timelock is active, /// only the timelock itself may replace it, preventing the owner from bypassing the delay. @@ -967,5 +968,5 @@ contract LiquidityOrchestrator is } /// @dev Storage gap to allow for future upgrades - uint256[50] private __gap; + uint256[47] private __gap; } diff --git a/contracts/OrionConfig.sol b/contracts/OrionConfig.sol index 49a3b941..ed35b7fd 100644 --- a/contracts/OrionConfig.sol +++ b/contracts/OrionConfig.sol @@ -89,6 +89,9 @@ contract OrionConfig is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, /// @notice Timestamp when new protocol fee rates become effective uint256 public newProtocolFeeRatesTimestamp; + /// @notice Address of the upgrade timelock that must authorise all implementation upgrades + address public upgradeTimelock; + modifier onlyFactories() { if (msg.sender != transparentVaultFactory) revert ErrorsLib.NotAuthorized(); _; @@ -536,9 +539,6 @@ contract OrionConfig is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, return tokenDecimals[token]; } - /// @notice Address of the upgrade timelock that must authorise all implementation upgrades - address public upgradeTimelock; - /// @notice Sets the upgrade timelock address. /// @dev If no timelock is set yet, only the owner may call this. Once a timelock is active, /// only the timelock itself may replace it, preventing the owner from bypassing the delay. @@ -567,5 +567,5 @@ contract OrionConfig is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, } /// @dev Storage gap to allow for future upgrades - uint256[50] private __gap; + uint256[49] private __gap; } diff --git a/contracts/factories/TransparentVaultFactory.sol b/contracts/factories/TransparentVaultFactory.sol index 73b83d5f..8b82252e 100644 --- a/contracts/factories/TransparentVaultFactory.sol +++ b/contracts/factories/TransparentVaultFactory.sol @@ -24,6 +24,9 @@ contract TransparentVaultFactory is Initializable, Ownable2StepUpgradeable, UUPS /// @notice UpgradeableBeacon for transparent vaults UpgradeableBeacon public vaultBeacon; + /// @notice Address of the upgrade timelock that must authorise all implementation upgrades + address public upgradeTimelock; + /// @notice Constructor that disables initializers for the implementation contract /// @custom:oz-upgrades-unsafe-allow constructor // solhint-disable-next-line use-natspec @@ -113,9 +116,6 @@ contract TransparentVaultFactory is Initializable, Ownable2StepUpgradeable, UUPS emit EventsLib.VaultBeaconUpdated(newVaultBeacon); } - /// @notice Address of the upgrade timelock that must authorise all implementation upgrades - address public upgradeTimelock; - /// @notice Sets the upgrade timelock address. /// @dev If no timelock is set yet, only the owner may call this. Once a timelock is active, /// only the timelock itself may replace it, preventing the owner from bypassing the delay. @@ -144,5 +144,5 @@ contract TransparentVaultFactory is Initializable, Ownable2StepUpgradeable, UUPS } /// @dev Storage gap to allow for future upgrades - uint256[50] private __gap; + uint256[49] private __gap; } diff --git a/contracts/interfaces/IOrionVault.sol b/contracts/interfaces/IOrionVault.sol index 559e726b..8a9cbc23 100644 --- a/contracts/interfaces/IOrionVault.sol +++ b/contracts/interfaces/IOrionVault.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.34; import "@openzeppelin/contracts/interfaces/IERC4626.sol"; import "./IOrionConfig.sol"; -import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; /// @title IOrionVault /// @notice Interface for Orion vaults @@ -53,17 +52,6 @@ interface IOrionVault is IERC4626 { /// @param sharesBurned The number of shares burned for the user. event Redeem(address indexed user, uint256 indexed redeemAmount, uint256 indexed sharesBurned); - /// @notice Transfer to the redeemer failed (e.g. USDC denylist); funds are held until claimed. - /// @param user The address of the recipient whose transfer failed. - /// @param amount The underlying amount that could not be transferred. - /// @param shares The number of shares that could not be redeemed. - event RedemptionFailed(address indexed user, uint256 indexed amount, uint256 indexed shares); - - /// @notice A previously failed redemption transfer has been claimed by the user. - /// @param user The address of the claimer. - /// @param amount The underlying amount claimed. - event RedemptionClaimed(address indexed user, uint256 indexed amount); - /// @notice Fees have been accrued. /// @param managementFee The amount of management fees accrued. /// @param performanceFee The amount of performance fees accrued. @@ -124,13 +112,13 @@ interface IOrionVault is IERC4626 { /// @return The currently active fee model function activeFeeModel() external view returns (FeeModel memory); - /// --------- CONFIG FUNCTIONS --------- + // --------- CONFIG FUNCTIONS --------- /// @notice Override intent to 100% underlying asset for decommissioning /// @dev Can only be called by the OrionConfig contract function overrideIntentForDecommissioning() external; - /// --------- LP FUNCTIONS --------- + // --------- LP FUNCTIONS --------- /// @notice Submit an asynchronous deposit request. /// @dev No share tokens are minted immediately. The specified amount of underlying tokens @@ -158,10 +146,6 @@ interface IOrionVault is IERC4626 { /// @param shares The amount of share tokens to recover. function cancelRedeemRequest(uint256 shares) external; - /// @notice Claim underlying funds from a previously failed redemption transfer. - /// @dev Called by the user after the transfer blocker (e.g. denylist) has been resolved. - function claimUnderlying() external; - // --------- MANAGER AND STRATEGIST FUNCTIONS --------- /// @notice Update the strategist address @@ -189,7 +173,7 @@ interface IOrionVault is IERC4626 { /// to ensure the deposit access control is capable of performing its duties. function setDepositAccessControl(address newDepositAccessControl) external; - /// --------- LIQUIDITY ORCHESTRATOR FUNCTIONS --------- + // --------- LIQUIDITY ORCHESTRATOR FUNCTIONS --------- /// @notice Get total pending deposit amount across all users /// @param fulfillBatchSize The maximum number of requests to process per fulfill call @@ -221,10 +205,6 @@ interface IOrionVault is IERC4626 { uint256 fulfillBatchSize ) external view returns (address[] memory users, uint256[] memory shares); - /// @notice Total underlying assets owed to users whose redemption transfer failed - /// @return total Sum of all pending underlying claims across all users - function totalPendingUnderlyingClaims() external view returns (uint256 total); - /// @notice Process all pending deposit requests and mint shares to depositors /// @param depositTotalAssets The total assets associated with the deposit requests function fulfillDeposit(uint256 depositTotalAssets) external; diff --git a/contracts/price/ERC4626PriceAdapter.sol b/contracts/price/ERC4626PriceAdapter.sol index e204e9da..03ca2def 100644 --- a/contracts/price/ERC4626PriceAdapter.sol +++ b/contracts/price/ERC4626PriceAdapter.sol @@ -60,11 +60,16 @@ contract ERC4626PriceAdapter is IPriceAdapter { address vaultUnderlying = vault.asset(); uint8 vaultAssetDecimals = IERC20Metadata(vaultAsset).decimals(); - uint256 precisionAmount = 10 ** (PRICE_DECIMALS + vaultAssetDecimals); + uint256 totalAssets = vault.totalAssets(); + uint256 totalSupply = vault.totalSupply(); - // Floor rounding here, previewMint uses ceil in execution, - // buffer to deal with negligible truncation and rounding errors. - uint256 vaultUnderlyingAssetAmount = vault.convertToAssets(precisionAmount); + if (totalSupply == 0) { + return (0, PRICE_DECIMALS + CONFIG.getTokenDecimals(vaultUnderlying)); + } + + uint8 effectiveShareDecimals = _effectiveShareDecimals(totalAssets, totalSupply, vaultAssetDecimals); + uint256 precisionAmount = 10 ** (PRICE_DECIMALS + effectiveShareDecimals); + uint256 vaultUnderlyingAssetAmount = Math.mulDiv(totalAssets, precisionAmount, totalSupply); if (vaultUnderlying == address(UNDERLYING_ASSET)) { return (vaultUnderlyingAssetAmount, PRICE_DECIMALS + UNDERLYING_ASSET_DECIMALS); @@ -78,4 +83,61 @@ contract ERC4626PriceAdapter is IPriceAdapter { return (vaultPrice, PRICE_DECIMALS + CONFIG.getTokenDecimals(vaultUnderlying)); } + + /// @notice Resolves share scale for pricing when reported vault decimals understate per-share value. + /// @dev Most vaults return `vaultAssetDecimals` after a single mulDiv. High-supply / low-asset + /// vaults (decimal offset) need a larger scale: `vaultDecimals + digitCount(totalSupply / totalAssets)`. + /// @param totalAssets Vault total assets in underlying wei. + /// @param totalSupply Vault total supply in share wei. + /// @param vaultAssetDecimals IERC20Metadata(vault).decimals(). + /// @return effectiveShareDecimals Exponent used in 10**effectiveShareDecimals share units. + function _effectiveShareDecimals( + uint256 totalAssets, + uint256 totalSupply, + uint8 vaultAssetDecimals + ) private pure returns (uint8 effectiveShareDecimals) { + uint256 shareUnit = 10 ** uint256(vaultAssetDecimals); + uint256 perShare = Math.mulDiv(totalAssets, shareUnit, totalSupply); + + if (perShare > 1 || totalAssets == 0) { + return vaultAssetDecimals; + } + + if (perShare == 1) { + // Distinguish true ~1 wei/share from a truncated larger value. + uint256 probePerShare = Math.mulDiv(totalAssets, shareUnit * 10, totalSupply); + if (probePerShare <= 10) { + return vaultAssetDecimals; + } + } + + uint256 supplyToAssetsRatio = Math.mulDiv(totalSupply, 1, totalAssets); + uint8 extraDecimals = _decimalDigits(supplyToAssetsRatio); + uint256 adjusted = uint256(vaultAssetDecimals) + uint256(extraDecimals); + + if (adjusted > 38) { + return 38; + } + + return uint8(adjusted); + } + + /// @notice Returns the number of decimal digits in `value` (minimum 1 when `value` > 0). + /// @param value The integer to measure. + /// @return digits The count of decimal digits in `value`. + function _decimalDigits(uint256 value) private pure returns (uint8) { + if (value == 0) { + return 0; + } + + uint8 digits = 1; + while (value > 9) { + value /= 10; + unchecked { + ++digits; + } + } + + return digits; + } } diff --git a/contracts/price/PriceAdapterRegistry.sol b/contracts/price/PriceAdapterRegistry.sol index 736ceb09..e0a52802 100644 --- a/contracts/price/PriceAdapterRegistry.sol +++ b/contracts/price/PriceAdapterRegistry.sol @@ -31,6 +31,9 @@ contract PriceAdapterRegistry is Initializable, IPriceAdapterRegistry, Ownable2S /// @notice Mapping of asset addresses to their corresponding price adapters mapping(address => IPriceAdapter) public adapterOf; + /// @notice Address of the upgrade timelock that must authorise all implementation upgrades + address public upgradeTimelock; + modifier onlyConfig() { if (msg.sender != configAddress) revert ErrorsLib.NotAuthorized(); _; @@ -83,9 +86,6 @@ contract PriceAdapterRegistry is Initializable, IPriceAdapterRegistry, Ownable2S return normalizedPrice; } - /// @notice Address of the upgrade timelock that must authorise all implementation upgrades - address public upgradeTimelock; - /// @notice Sets the upgrade timelock address. /// @dev If no timelock is set yet, only the owner may call this. Once a timelock is active, /// only the timelock itself may replace it, preventing the owner from bypassing the delay. @@ -114,5 +114,5 @@ contract PriceAdapterRegistry is Initializable, IPriceAdapterRegistry, Ownable2S } /// @dev Storage gap to allow for future upgrades - uint256[50] private __gap; + uint256[49] private __gap; } diff --git a/contracts/test/TestFixedRatioERC4626.sol b/contracts/test/TestFixedRatioERC4626.sol new file mode 100644 index 00000000..7c8e26c9 --- /dev/null +++ b/contracts/test/TestFixedRatioERC4626.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.34; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; + +/// @notice ERC-4626 vault with fixed totalAssets/totalSupply for ratio-based price adapter tests. +contract TestFixedRatioERC4626 is ERC4626 { + using Math for uint256; + uint8 private immutable _shareDecimals; + uint256 private immutable _fixedTotalAssets; + uint256 private immutable _fixedTotalSupply; + + constructor( + ERC20 underlyingAsset_, + string memory name_, + string memory symbol_, + uint8 shareDecimals_, + uint256 fixedTotalAssets_, + uint256 fixedTotalSupply_ + ) ERC20(name_, symbol_) ERC4626(underlyingAsset_) { + _shareDecimals = shareDecimals_; + _fixedTotalAssets = fixedTotalAssets_; + _fixedTotalSupply = fixedTotalSupply_; + } + + function decimals() public view override returns (uint8) { + return _shareDecimals; + } + + function totalAssets() public view override returns (uint256) { + return _fixedTotalAssets; + } + + function totalSupply() public view override(ERC20, IERC20) returns (uint256) { + return _fixedTotalSupply; + } + + function convertToAssets(uint256 shares) public view override returns (uint256) { + return shares.mulDiv(_fixedTotalAssets, _fixedTotalSupply); + } +} diff --git a/contracts/vaults/OrionVault.sol b/contracts/vaults/OrionVault.sol index 967f0fe3..4460a227 100644 --- a/contracts/vaults/OrionVault.sol +++ b/contracts/vaults/OrionVault.sol @@ -92,9 +92,6 @@ abstract contract OrionVault is Initializable, ERC4626Upgradeable, ReentrancyGua /// @dev When true, intent is overridden to 100% underlying asset bool public isDecommissioning; - /// @notice Underlying amount owed to a user whose redemption transfer failed - EnumerableMap.AddressToUintMap private _pendingUnderlyingClaims; - /// @dev Restricts function to only vault manager modifier onlyManager() { if (msg.sender != manager) revert ErrorsLib.NotAuthorized(); @@ -571,16 +568,6 @@ abstract contract OrionVault is Initializable, ERC4626Upgradeable, ReentrancyGua return (users, shares); } - /// @inheritdoc IOrionVault - function totalPendingUnderlyingClaims() external view returns (uint256 total) { - uint256 length = _pendingUnderlyingClaims.length(); - for (uint256 i = 0; i < length; ++i) { - // slither-disable-next-line unused-return - (, uint256 amount) = _pendingUnderlyingClaims.at(i); - total += amount; - } - } - /// @inheritdoc IOrionVault function accrueVaultFees(uint256 managementFee, uint256 performanceFee) external onlyLiquidityOrchestrator { if (managementFee == 0 && performanceFee == 0) return; @@ -667,29 +654,12 @@ abstract contract OrionVault is Initializable, ERC4626Upgradeable, ReentrancyGua ); processedShares += userShares; - try liquidityOrchestrator.transferRedemptionFunds(user, underlyingAmount) { - emit Redeem(user, underlyingAmount, userShares); - } catch { - // slither-disable-next-line unused-return - (, uint256 pendingAmount) = _pendingUnderlyingClaims.tryGet(user); - // slither-disable-next-line unused-return - _pendingUnderlyingClaims.set(user, pendingAmount + underlyingAmount); - emit RedemptionFailed(user, underlyingAmount, userShares); - } + liquidityOrchestrator.transferRedemptionFunds(user, underlyingAmount); + emit Redeem(user, underlyingAmount, userShares); } _burn(address(this), processedShares); } - /// @inheritdoc IOrionVault - function claimUnderlying() external nonReentrant { - (bool hasClaim, uint256 amount) = _pendingUnderlyingClaims.tryGet(msg.sender); - if (!hasClaim || amount == 0) revert ErrorsLib.InsufficientAmount(); - // slither-disable-next-line unused-return - _pendingUnderlyingClaims.remove(msg.sender); - liquidityOrchestrator.transferRedemptionFunds(msg.sender, amount); - emit RedemptionClaimed(msg.sender, amount); - } - /// @dev Storage gap to allow for future upgrades uint256[50] private __gap; } diff --git a/hardhat.config.ts b/hardhat.config.ts index 47c919c6..d36e4986 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -2,14 +2,13 @@ import * as dotenv from "dotenv"; import { defineConfig } from "hardhat/config"; import hardhatToolboxMochaEthers from "@nomicfoundation/hardhat-toolbox-mocha-ethers"; import hardhatTypechain from "@nomicfoundation/hardhat-typechain"; -import hardhatVerify from "@nomicfoundation/hardhat-verify"; dotenv.config({ quiet: true }); const useMainnetFork = process.env.FORK_MAINNET === "true" && Boolean(process.env.MAINNET_RPC_URL); const config = defineConfig({ - plugins: [hardhatToolboxMochaEthers, hardhatTypechain, hardhatVerify], + plugins: [hardhatToolboxMochaEthers, hardhatTypechain], paths: { tests: { solidity: "test/solidity", @@ -73,10 +72,6 @@ const config = defineConfig({ } : {}), }, - - etherscan: { - apiKey: process.env.ETHERSCAN_API_KEY ?? "", - }, }); export default config; diff --git a/package.json b/package.json index 7f29289a..56820110 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@orion-finance/protocol", "description": "Orion Finance Protocol", - "version": "2.3.5", + "version": "2.4.0", "type": "module", "engines": { "node": ">=22.13.0" @@ -30,9 +30,7 @@ "docgen": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile && node scripts/run-docgen.mjs", "prettier:check": "prettier --check \"**/*.{js,json,md,sol,ts,yml}\"", "prettier:write": "prettier --write \"**/*.{js,json,md,sol,ts,yml}\"", - "slither": "bash scripts/run-slither.sh", - "verify:vault": "hardhat run protocol-ops/verify-vault.ts --network sepolia", - "storage-layout": "hardhat run scripts/check-storage-layout.ts" + "slither": "bash scripts/run-slither.sh" }, "devDependencies": { "@eslint/eslintrc": "^3.3.5", @@ -43,30 +41,29 @@ "@nomicfoundation/hardhat-ethers-chai-matchers": "^3.0.9", "@nomicfoundation/hardhat-ignition": "^3.1.6", "@nomicfoundation/hardhat-ignition-ethers": "^3.1.5", - "@nomicfoundation/hardhat-keystore": "^3.0.10", + "@nomicfoundation/hardhat-keystore": "^3.0.11", "@nomicfoundation/hardhat-mocha": "^3.0.20", "@nomicfoundation/hardhat-network-helpers": "^3.0.9", "@nomicfoundation/hardhat-toolbox-mocha-ethers": "^3.0.6", - "@nomicfoundation/hardhat-typechain": "^3.0.9", - "@nomicfoundation/hardhat-verify": "^3.0.18", + "@nomicfoundation/hardhat-typechain": "^3.1.0", + "@nomicfoundation/hardhat-verify": "3.0.18", "@nomicfoundation/ignition-core": "^3.1.6", - "@openzeppelin/hardhat-upgrades": "^3.9.1", "@typechain/ethers-v6": "^0.5.1", "@types/chai": "^5.2.3", "@types/mocha": "^10.0.10", "@types/node": "^25.9.1", - "@typescript-eslint/eslint-plugin": "^8.59.4", - "@typescript-eslint/parser": "^8.59.4", + "@typescript-eslint/eslint-plugin": "^8.60.0", + "@typescript-eslint/parser": "^8.60.0", "@zama-fhe/oracle-solidity": "^0.2.0", "@zama-fhe/relayer-sdk": "^0.4.3", "chai": "^6.2.2", "chai-as-promised": "^8.0.1", "cross-env": "^10.1.0", "dotenv": "^17.4.2", - "eslint": "^10.4.0", + "eslint": "^10.4.1", "eslint-config-prettier": "^10.1.8", "ethers": "^6.15.0", - "hardhat": "^3.5.1", + "hardhat": "^3.7.0", "hardhat-deploy": "^2.0.8", "mocha": "^11.7.6", "prettier": "^3.8.3", @@ -92,6 +89,7 @@ }, "pnpm": { "overrides": { + "@nomicfoundation/hardhat-verify": "3.0.18", "@openzeppelin/contracts-upgradeable@>=4.3.0 <4.8.3": "^4.9.6", "@openzeppelin/contracts@>=4.3.0 <4.8.3": "^4.9.6", "lodash": "^4.17.21", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35ea4c90..a9104e28 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: + '@nomicfoundation/hardhat-verify': 3.0.18 '@openzeppelin/contracts-upgradeable@>=4.3.0 <4.8.3': ^4.9.6 '@openzeppelin/contracts@>=4.3.0 <4.8.3': ^4.9.6 lodash: ^4.17.21 @@ -46,49 +47,46 @@ importers: version: 3.3.5 '@eslint/js': specifier: ^10.0.1 - version: 10.0.1(eslint@10.4.0) + version: 10.0.1(eslint@10.4.1) '@fhevm/hardhat-plugin': specifier: ^0.4.2 - version: 0.4.2(@fhevm/mock-utils@0.4.2(@zama-fhe/relayer-sdk@0.4.3)(ethers@6.16.0)(typescript@6.0.3))(@fhevm/solidity@0.11.1)(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@zama-fhe/relayer-sdk@0.4.3)(encrypted-types@0.0.4)(ethers@6.16.0)(hardhat@3.5.1) + version: 0.4.2(@fhevm/mock-utils@0.4.2(@zama-fhe/relayer-sdk@0.4.3)(ethers@6.16.0)(typescript@6.0.3))(@fhevm/solidity@0.11.1)(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@zama-fhe/relayer-sdk@0.4.3)(encrypted-types@0.0.4)(ethers@6.16.0)(hardhat@3.7.0) '@fhevm/mock-utils': specifier: 0.4.2 version: 0.4.2(@zama-fhe/relayer-sdk@0.4.3)(ethers@6.16.0)(typescript@6.0.3) '@nomicfoundation/hardhat-ethers': specifier: ^4.0.12 - version: 4.0.12(hardhat@3.5.1) + version: 4.0.12(hardhat@3.7.0) '@nomicfoundation/hardhat-ethers-chai-matchers': specifier: ^3.0.9 - version: 3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(chai@6.2.2)(ethers@6.16.0)(hardhat@3.5.1) + version: 3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(chai@6.2.2)(ethers@6.16.0)(hardhat@3.7.0) '@nomicfoundation/hardhat-ignition': specifier: ^3.1.6 - version: 3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(hardhat@3.5.1) + version: 3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(hardhat@3.7.0) '@nomicfoundation/hardhat-ignition-ethers': specifier: ^3.1.5 - version: 3.1.5(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-ignition@3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(@nomicfoundation/ignition-core@3.1.6)(ethers@6.16.0)(hardhat@3.5.1) + version: 3.1.5(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@nomicfoundation/hardhat-ignition@3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(hardhat@3.7.0))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(@nomicfoundation/ignition-core@3.1.6)(ethers@6.16.0)(hardhat@3.7.0) '@nomicfoundation/hardhat-keystore': - specifier: ^3.0.10 - version: 3.0.10(hardhat@3.5.1) + specifier: ^3.0.11 + version: 3.0.11(hardhat@3.7.0) '@nomicfoundation/hardhat-mocha': specifier: ^3.0.20 - version: 3.0.20(hardhat@3.5.1)(mocha@11.7.6) + version: 3.0.20(hardhat@3.7.0)(mocha@11.7.6) '@nomicfoundation/hardhat-network-helpers': specifier: ^3.0.9 - version: 3.0.9(hardhat@3.5.1) + version: 3.0.9(hardhat@3.7.0) '@nomicfoundation/hardhat-toolbox-mocha-ethers': specifier: ^3.0.6 - version: 3.0.6(6427341b890770f5d9a08b8a2bf9da56) + version: 3.0.6(1e55c586e87f306150f261219144bd66) '@nomicfoundation/hardhat-typechain': - specifier: ^3.0.9 - version: 3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(ethers@6.16.0)(hardhat@3.5.1)(typescript@6.0.3) + specifier: ^3.1.0 + version: 3.1.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(ethers@6.16.0)(hardhat@3.7.0)(typescript@6.0.3) '@nomicfoundation/hardhat-verify': - specifier: ^3.0.18 - version: 3.0.18(hardhat@3.5.1) + specifier: 3.0.18 + version: 3.0.18(hardhat@3.7.0) '@nomicfoundation/ignition-core': specifier: ^3.1.6 version: 3.1.6 - '@openzeppelin/hardhat-upgrades': - specifier: ^3.9.1 - version: 3.9.1(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(ethers@6.16.0)(hardhat@3.5.1) '@typechain/ethers-v6': specifier: ^0.5.1 version: 0.5.1(ethers@6.16.0)(typechain@8.3.2(typescript@6.0.3))(typescript@6.0.3) @@ -102,14 +100,14 @@ importers: specifier: ^25.9.1 version: 25.9.1 '@typescript-eslint/eslint-plugin': - specifier: ^8.59.4 - version: 8.59.4(@typescript-eslint/parser@8.59.4(eslint@10.4.0)(typescript@6.0.3))(eslint@10.4.0)(typescript@6.0.3) + specifier: ^8.60.0 + version: 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1)(typescript@6.0.3))(eslint@10.4.1)(typescript@6.0.3) '@typescript-eslint/parser': - specifier: ^8.59.4 - version: 8.59.4(eslint@10.4.0)(typescript@6.0.3) + specifier: ^8.60.0 + version: 8.60.0(eslint@10.4.1)(typescript@6.0.3) '@zama-fhe/oracle-solidity': specifier: ^0.2.0 - version: 0.2.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(@openzeppelin/defender-deploy-client-cli@0.0.1-alpha.10)(@openzeppelin/upgrades-core@1.44.2)(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3) + version: 0.2.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(@openzeppelin/defender-deploy-client-cli@0.0.1-alpha.10)(@openzeppelin/upgrades-core@1.44.2)(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3) '@zama-fhe/relayer-sdk': specifier: ^0.4.3 version: 0.4.3 @@ -126,20 +124,20 @@ importers: specifier: ^17.4.2 version: 17.4.2 eslint: - specifier: ^10.4.0 - version: 10.4.0 + specifier: ^10.4.1 + version: 10.4.1 eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@10.4.0) + version: 10.1.8(eslint@10.4.1) ethers: specifier: ^6.15.0 version: 6.16.0 hardhat: - specifier: ^3.5.1 - version: 3.5.1 + specifier: ^3.7.0 + version: 3.7.0 hardhat-deploy: specifier: ^2.0.8 - version: 2.0.8(@rocketh/node@0.19.4(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76))(typescript@6.0.3)(zod@3.25.76))(hardhat@3.5.1)(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76)) + version: 2.0.8(@rocketh/node@0.19.4(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76))(typescript@6.0.3)(zod@3.25.76))(hardhat@3.7.0)(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76)) mocha: specifier: ^11.7.6 version: 11.7.6 @@ -160,7 +158,7 @@ importers: version: 0.1.0(prettier-plugin-solidity@2.3.1(prettier@3.8.3))(prettier@3.8.3) solidity-docgen: specifier: 0.6.0-beta.36 - version: 0.6.0-beta.36(hardhat@3.5.1) + version: 0.6.0-beta.36(hardhat@3.7.0) ts-generator: specifier: ^0.1.1 version: 0.1.1 @@ -532,8 +530,8 @@ packages: resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.7.1': - resolution: {integrity: sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==} + '@eslint/plugin-kit@0.7.2': + resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@ethereumjs/rlp@5.0.2': @@ -834,6 +832,12 @@ packages: '@nomicfoundation/hardhat-errors@3.0.13': resolution: {integrity: sha512-h0nWNzKbmP6XhINMgSUfGixevzksT8BQPK08KNnsr/8kQORAeYzsv6bf0CLUD8mZfmBEP45m4QMlNP6xcoc0Ow==} + '@nomicfoundation/hardhat-errors@3.0.14': + resolution: {integrity: sha512-IlBQlJZmKLaGjhr8NX8wI1vjhOaquTxj+Boq0oOMGAVVkpvtaDtLsFu2tBTIjnP8TgazwR4uNFHsNlsDvsd76A==} + + '@nomicfoundation/hardhat-errors@3.0.15': + resolution: {integrity: sha512-h3r32RzpmWEcB2bz6aqZKlKOP8tzyvHLkPFleFFqwVvjO5AUfSoMUxm8OjaTuNgPF35mXPYRISh+kNCwmsKVOA==} + '@nomicfoundation/hardhat-ethers-chai-matchers@3.0.9': resolution: {integrity: sha512-jrb9tLL5c0BmaODWqhk4EFHIfLVOjpt13T6qJWMGpwxYBqO1RkBlPc0e44pDFwwlfkJNgiQNSWVbiXAh0hBCnA==} peerDependencies: @@ -852,7 +856,7 @@ packages: peerDependencies: '@nomicfoundation/hardhat-ethers': ^4.0.0 '@nomicfoundation/hardhat-ignition': ^3.1.2 - '@nomicfoundation/hardhat-verify': ^3.0.0 + '@nomicfoundation/hardhat-verify': 3.0.18 '@nomicfoundation/ignition-core': ^3.0.7 ethers: ^6.14.0 hardhat: ^3.4.0 @@ -860,11 +864,11 @@ packages: '@nomicfoundation/hardhat-ignition@3.1.6': resolution: {integrity: sha512-u9IX7H6HMrXx0neS1uYaihArRd7aR1Fsz7Uuptm06Vo2mZhbi7gDYp4ih/lkioB4jDyGuKRDA52WFt0BkzqHXQ==} peerDependencies: - '@nomicfoundation/hardhat-verify': ^3.0.0 + '@nomicfoundation/hardhat-verify': 3.0.18 hardhat: ^3.4.0 - '@nomicfoundation/hardhat-keystore@3.0.10': - resolution: {integrity: sha512-HjIHpy6OC2yE5e3Z/P3XmhvhNddKHPbsiHECAoNZbBgbBUAx//JWdkdaHkTG9T3VKgGYlHETPVrOrYSadDE/Tg==} + '@nomicfoundation/hardhat-keystore@3.0.11': + resolution: {integrity: sha512-JUhd+0ElK7S71aDFMf632Ozhs4aTgMWoEGXjgBL1b5DpzK+ahS0Y08tNanlQ0VPZc5EOKh9X5Vuyotx8R5r7ig==} peerDependencies: hardhat: ^3.0.0 @@ -890,26 +894,26 @@ packages: '@nomicfoundation/hardhat-mocha': ^3.0.0 '@nomicfoundation/hardhat-network-helpers': ^3.0.0 '@nomicfoundation/hardhat-typechain': ^3.0.0 - '@nomicfoundation/hardhat-verify': ^3.0.0 + '@nomicfoundation/hardhat-verify': 3.0.18 '@nomicfoundation/ignition-core': ^3.0.0 chai: '>=5.1.2 <7' ethers: ^6.14.0 hardhat: ^3.4.0 mocha: ^11.0.0 - '@nomicfoundation/hardhat-typechain@3.0.9': - resolution: {integrity: sha512-u77/lhXGi1JL8sz971yLZaFt0gI5ZFMYsuCdAZTPfVQXCErA2+2rfrdBc5FcLZX18FEFA4hNUNdJDnxPMpN3jQ==} + '@nomicfoundation/hardhat-typechain@3.1.0': + resolution: {integrity: sha512-HRMAXcdROB+DCu4+PV9RFdbfgEISYkyoQI4Tph3lJTCkuk3oB6ApZY4qzTAbOtDVROTYyWeE/Mv6fgncxA22vg==} peerDependencies: '@nomicfoundation/hardhat-ethers': ^4.0.0 ethers: ^6.14.0 - hardhat: ^3.4.0 - - '@nomicfoundation/hardhat-utils@4.1.1': - resolution: {integrity: sha512-yKUMIhwzNlrl9wfe0WlAjXjRPfHh8JdCu6Iv4o+oi6Q9ovyCGj+66JzFsALNIMBo6L19Nf40DFICqUZef02Yrg==} + hardhat: ^3.6.0 '@nomicfoundation/hardhat-utils@4.1.2': resolution: {integrity: sha512-jUQfbyIoTLHmSua+BMhIqUIk7uDwL2bhTtJgfwRoVooM3TTvm5rIdRK+eNkvZcZR/wAL/SBQOq/r9yOekj4Unw==} + '@nomicfoundation/hardhat-utils@4.1.3': + resolution: {integrity: sha512-SYDKX6SCdzs/5mC/S1D+AjNSQJrhxevHTI24TIouIjO0Xs0dB0+S4cYCqHWOgvnHLshrcrJ7XGUjS7+apWa1Tw==} + '@nomicfoundation/hardhat-vendored@3.0.4': resolution: {integrity: sha512-RO8Otj1FvRvxJmXzkxh1vTwK/+cqSVPYLqY6RrWkmzHEEcxnAwAFsBYdW7xyTEyW/pVbSSNd2gs3aoGdGZaoNA==} @@ -918,11 +922,6 @@ packages: peerDependencies: hardhat: ^3.4.0 - '@nomicfoundation/hardhat-zod-utils@3.0.4': - resolution: {integrity: sha512-yCiycXDEEjbNgNVQaUoGYOee6+ljYUnIOWMtYc/dYDuwlHutWr9xg/KgkgMkiZZ1R2WrZAEqsSaeZTnH7Oyz9Q==} - peerDependencies: - zod: ^3.23.8 - '@nomicfoundation/hardhat-zod-utils@3.0.5': resolution: {integrity: sha512-A1G9Jcizf/vYcGMtqkf+st94zBPTDB+bXXlojOMu77gmBZYbywY0k7hdRM2B4uJY+8nM0oe0sNVGVkARITXdcw==} peerDependencies: @@ -1024,25 +1023,13 @@ packages: hasBin: true peerDependencies: '@nomicfoundation/hardhat-ethers': ^3.0.0 - '@nomicfoundation/hardhat-verify': ^2.0.0 + '@nomicfoundation/hardhat-verify': 3.0.18 ethers: ^6.6.0 hardhat: ^2.0.2 peerDependenciesMeta: '@nomicfoundation/hardhat-verify': optional: true - '@openzeppelin/hardhat-upgrades@3.9.1': - resolution: {integrity: sha512-pSDjlOnIpP+PqaJVe144dK6VVKZw2v6YQusyt0OOLiCsl+WUzfo4D0kylax7zjrOxqy41EK2ipQeIF4T+cCn2A==} - hasBin: true - peerDependencies: - '@nomicfoundation/hardhat-ethers': ^3.0.6 - '@nomicfoundation/hardhat-verify': ^2.0.14 - ethers: ^6.6.0 - hardhat: ^2.24.1 - peerDependenciesMeta: - '@nomicfoundation/hardhat-verify': - optional: true - '@openzeppelin/upgrades-core@1.44.2': resolution: {integrity: sha512-m6iorjyhPK9ow5/trNs7qsBC/SOzJCO51pvvAF2W9nOiZ1t0RtCd+rlRmRmlWTv4M33V0wzIUeamJ2BPbzgUXA==} hasBin: true @@ -1501,63 +1488,63 @@ packages: '@types/secp256k1@4.0.7': resolution: {integrity: sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw==} - '@typescript-eslint/eslint-plugin@8.59.4': - resolution: {integrity: sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==} + '@typescript-eslint/eslint-plugin@8.60.0': + resolution: {integrity: sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.59.4 + '@typescript-eslint/parser': ^8.60.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.59.4': - resolution: {integrity: sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==} + '@typescript-eslint/parser@8.60.0': + resolution: {integrity: sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.59.4': - resolution: {integrity: sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==} + '@typescript-eslint/project-service@8.60.0': + resolution: {integrity: sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.59.4': - resolution: {integrity: sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==} + '@typescript-eslint/scope-manager@8.60.0': + resolution: {integrity: sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.59.4': - resolution: {integrity: sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==} + '@typescript-eslint/tsconfig-utils@8.60.0': + resolution: {integrity: sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.59.4': - resolution: {integrity: sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==} + '@typescript-eslint/type-utils@8.60.0': + resolution: {integrity: sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.59.4': - resolution: {integrity: sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==} + '@typescript-eslint/types@8.60.0': + resolution: {integrity: sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.59.4': - resolution: {integrity: sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==} + '@typescript-eslint/typescript-estree@8.60.0': + resolution: {integrity: sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.59.4': - resolution: {integrity: sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==} + '@typescript-eslint/utils@8.60.0': + resolution: {integrity: sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.59.4': - resolution: {integrity: sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==} + '@typescript-eslint/visitor-keys@8.60.0': + resolution: {integrity: sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@uniswap/lib@4.0.1-alpha': @@ -1795,6 +1782,9 @@ packages: brace-expansion@2.1.0: resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==} + brace-expansion@2.1.1: + resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} + brace-expansion@5.0.6: resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} @@ -2170,8 +2160,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.4.0: - resolution: {integrity: sha512-loXy6bWOoP3EP6JA7jo6p5jMpBJmHmsNZM5SFRHLdh1MGOPurMnNBj4ZlAbaqUAaQWbCr7jHV4P7gzAyryZWkQ==} + eslint@10.4.1: + resolution: {integrity: sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -2451,8 +2441,8 @@ packages: typescript: optional: true - hardhat@3.5.1: - resolution: {integrity: sha512-QHODwpchwo7tqUnG51pT1A7aYYd70ssPpJ0jX4+P/XVglFnlX9rBcQslET/ipq+SwIPPIBgp4CGtj0xCgv64QQ==} + hardhat@3.7.0: + resolution: {integrity: sha512-dbz5wbN7sTkTjUicCX1qSAwrBQBklEl+j5gjiykzQa9JZx/RZ9OtlY9SvOOEV/2IrlgKhUqy30nGCU9MtOObSw==} hasBin: true has-flag@3.0.0: @@ -2922,8 +2912,8 @@ packages: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} - ox@0.14.22: - resolution: {integrity: sha512-nb5msL8qWbPglhIfZbGJAfw3cqiJjFMiWmACt7kgyWtLib12tcctbHufMT9Hb0Lr6Pt4k9I3dbpueTpbhvbqvA==} + ox@0.14.25: + resolution: {integrity: sha512-8DoibKtxE8yw63Y2jjMhlbjaURev6WCx4QR4MWLusl2/qIaeTzMJMBIYIDl1KOF45+8H1Ur6eLTdPlUoO8PlRw==} peerDependencies: typescript: '>=5.4.0' peerDependenciesMeta: @@ -3456,8 +3446,8 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - tinyglobby@0.2.16: - resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} tkms@0.12.8: @@ -3535,6 +3525,11 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tsx@4.22.4: + resolution: {integrity: sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -3597,6 +3592,10 @@ packages: resolution: {integrity: sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==} engines: {node: '>=18.17'} + undici@6.26.0: + resolution: {integrity: sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==} + engines: {node: '>=18.17'} + unfetch@4.2.0: resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} @@ -3626,8 +3625,8 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - viem@2.50.4: - resolution: {integrity: sha512-rf98F4s3Vlb+uJZEKfay3IbBw3CNCbVtx5Y3UIljlO2tSX420g/J0WQSYsjzBSasUFgxgsXabji14O9kGbiqgg==} + viem@2.51.3: + resolution: {integrity: sha512-DA4EbrsvatzzLo6MwcWWiv6kI6dIr3I9HH9B6qsJaClN/s0AjIDUz5RIxl+VmGrovIUCcIvG8744yuGH7d37zw==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -4235,9 +4234,9 @@ snapshots: '@esbuild/win32-x64@0.28.0': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.4.0)': + '@eslint-community/eslint-utils@4.9.1(eslint@10.4.1)': dependencies: - eslint: 10.4.0 + eslint: 10.4.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -4272,13 +4271,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@10.0.1(eslint@10.4.0)': + '@eslint/js@10.0.1(eslint@10.4.1)': optionalDependencies: - eslint: 10.4.0 + eslint: 10.4.1 '@eslint/object-schema@3.0.5': {} - '@eslint/plugin-kit@0.7.1': + '@eslint/plugin-kit@0.7.2': dependencies: '@eslint/core': 1.2.1 levn: 0.4.1 @@ -4555,18 +4554,18 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fhevm/hardhat-plugin@0.4.2(@fhevm/mock-utils@0.4.2(@zama-fhe/relayer-sdk@0.4.3)(ethers@6.16.0)(typescript@6.0.3))(@fhevm/solidity@0.11.1)(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@zama-fhe/relayer-sdk@0.4.3)(encrypted-types@0.0.4)(ethers@6.16.0)(hardhat@3.5.1)': + '@fhevm/hardhat-plugin@0.4.2(@fhevm/mock-utils@0.4.2(@zama-fhe/relayer-sdk@0.4.3)(ethers@6.16.0)(typescript@6.0.3))(@fhevm/solidity@0.11.1)(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@zama-fhe/relayer-sdk@0.4.3)(encrypted-types@0.0.4)(ethers@6.16.0)(hardhat@3.7.0)': dependencies: '@fhevm/host-contracts': 0.10.0 '@fhevm/mock-utils': 0.4.2(@zama-fhe/relayer-sdk@0.4.3)(ethers@6.16.0)(typescript@6.0.3) '@fhevm/solidity': 0.11.1 - '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.5.1) + '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.7.0) '@zama-fhe/relayer-sdk': 0.4.3 debug: 4.4.3(supports-color@8.1.1) dotenv: 16.6.1 encrypted-types: 0.0.4 ethers: 6.16.0 - hardhat: 3.5.1 + hardhat: 3.7.0 picocolors: 1.1.1 resolve: 1.22.12 transitivePeerDependencies: @@ -4729,117 +4728,125 @@ snapshots: '@nomicfoundation/hardhat-errors@3.0.12': dependencies: - '@nomicfoundation/hardhat-utils': 4.1.1 + '@nomicfoundation/hardhat-utils': 4.1.3 '@nomicfoundation/hardhat-errors@3.0.13': dependencies: '@nomicfoundation/hardhat-utils': 4.1.2 - '@nomicfoundation/hardhat-ethers-chai-matchers@3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(chai@6.2.2)(ethers@6.16.0)(hardhat@3.5.1)': + '@nomicfoundation/hardhat-errors@3.0.14': dependencies: - '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.5.1) + '@nomicfoundation/hardhat-utils': 4.1.3 + + '@nomicfoundation/hardhat-errors@3.0.15': + dependencies: + '@nomicfoundation/hardhat-utils': 4.1.3 + + '@nomicfoundation/hardhat-ethers-chai-matchers@3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(chai@6.2.2)(ethers@6.16.0)(hardhat@3.7.0)': + dependencies: + '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.7.0) '@nomicfoundation/hardhat-utils': 4.1.2 '@types/chai-as-promised': 8.0.2 chai: 6.2.2 chai-as-promised: 8.0.2(chai@6.2.2) deep-eql: 5.0.2 ethers: 6.16.0 - hardhat: 3.5.1 + hardhat: 3.7.0 - '@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1)': + '@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0)': dependencies: '@nomicfoundation/hardhat-errors': 3.0.13 '@nomicfoundation/hardhat-utils': 4.1.2 ethereum-cryptography: 2.2.1 ethers: 6.16.0 - hardhat: 3.5.1 + hardhat: 3.7.0 transitivePeerDependencies: - bufferutil - utf-8-validate - '@nomicfoundation/hardhat-ignition-ethers@3.1.5(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-ignition@3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(@nomicfoundation/ignition-core@3.1.6)(ethers@6.16.0)(hardhat@3.5.1)': + '@nomicfoundation/hardhat-ignition-ethers@3.1.5(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@nomicfoundation/hardhat-ignition@3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(hardhat@3.7.0))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(@nomicfoundation/ignition-core@3.1.6)(ethers@6.16.0)(hardhat@3.7.0)': dependencies: '@nomicfoundation/hardhat-errors': 3.0.12 - '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.5.1) - '@nomicfoundation/hardhat-ignition': 3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(hardhat@3.5.1) - '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.5.1) + '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.7.0) + '@nomicfoundation/hardhat-ignition': 3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(hardhat@3.7.0) + '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.7.0) '@nomicfoundation/ignition-core': 3.1.6 ethers: 6.16.0 - hardhat: 3.5.1 + hardhat: 3.7.0 - '@nomicfoundation/hardhat-ignition@3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(hardhat@3.5.1)': + '@nomicfoundation/hardhat-ignition@3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(hardhat@3.7.0)': dependencies: '@nomicfoundation/hardhat-errors': 3.0.13 '@nomicfoundation/hardhat-utils': 4.1.2 - '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.5.1) + '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.7.0) '@nomicfoundation/ignition-core': 3.1.6 '@nomicfoundation/ignition-ui': 3.1.2 - hardhat: 3.5.1 + hardhat: 3.7.0 json5: 2.2.3 prompts: 2.4.2 transitivePeerDependencies: - bufferutil - utf-8-validate - '@nomicfoundation/hardhat-keystore@3.0.10(hardhat@3.5.1)': + '@nomicfoundation/hardhat-keystore@3.0.11(hardhat@3.7.0)': dependencies: '@noble/ciphers': 1.2.1 '@noble/hashes': 1.7.1 - '@nomicfoundation/hardhat-errors': 3.0.13 - '@nomicfoundation/hardhat-utils': 4.1.2 + '@nomicfoundation/hardhat-errors': 3.0.14 + '@nomicfoundation/hardhat-utils': 4.1.3 '@nomicfoundation/hardhat-zod-utils': 3.0.5(zod@3.25.76) - hardhat: 3.5.1 + hardhat: 3.7.0 zod: 3.25.76 - '@nomicfoundation/hardhat-mocha@3.0.20(hardhat@3.5.1)(mocha@11.7.6)': + '@nomicfoundation/hardhat-mocha@3.0.20(hardhat@3.7.0)(mocha@11.7.6)': dependencies: '@nomicfoundation/hardhat-errors': 3.0.13 '@nomicfoundation/hardhat-utils': 4.1.2 '@nomicfoundation/hardhat-zod-utils': 3.0.5(zod@3.25.76) - hardhat: 3.5.1 + hardhat: 3.7.0 mocha: 11.7.6 tsx: 4.22.3 zod: 3.25.76 - '@nomicfoundation/hardhat-network-helpers@3.0.9(hardhat@3.5.1)': + '@nomicfoundation/hardhat-network-helpers@3.0.9(hardhat@3.7.0)': dependencies: '@nomicfoundation/hardhat-errors': 3.0.13 '@nomicfoundation/hardhat-utils': 4.1.2 - hardhat: 3.5.1 - - '@nomicfoundation/hardhat-toolbox-mocha-ethers@3.0.6(6427341b890770f5d9a08b8a2bf9da56)': - dependencies: - '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.5.1) - '@nomicfoundation/hardhat-ethers-chai-matchers': 3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(chai@6.2.2)(ethers@6.16.0)(hardhat@3.5.1) - '@nomicfoundation/hardhat-ignition': 3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(hardhat@3.5.1) - '@nomicfoundation/hardhat-ignition-ethers': 3.1.5(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-ignition@3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(@nomicfoundation/ignition-core@3.1.6)(ethers@6.16.0)(hardhat@3.5.1) - '@nomicfoundation/hardhat-keystore': 3.0.10(hardhat@3.5.1) - '@nomicfoundation/hardhat-mocha': 3.0.20(hardhat@3.5.1)(mocha@11.7.6) - '@nomicfoundation/hardhat-network-helpers': 3.0.9(hardhat@3.5.1) - '@nomicfoundation/hardhat-typechain': 3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(ethers@6.16.0)(hardhat@3.5.1)(typescript@6.0.3) - '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.5.1) + hardhat: 3.7.0 + + '@nomicfoundation/hardhat-toolbox-mocha-ethers@3.0.6(1e55c586e87f306150f261219144bd66)': + dependencies: + '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.7.0) + '@nomicfoundation/hardhat-ethers-chai-matchers': 3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(chai@6.2.2)(ethers@6.16.0)(hardhat@3.7.0) + '@nomicfoundation/hardhat-ignition': 3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(hardhat@3.7.0) + '@nomicfoundation/hardhat-ignition-ethers': 3.1.5(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@nomicfoundation/hardhat-ignition@3.1.6(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(hardhat@3.7.0))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(@nomicfoundation/ignition-core@3.1.6)(ethers@6.16.0)(hardhat@3.7.0) + '@nomicfoundation/hardhat-keystore': 3.0.11(hardhat@3.7.0) + '@nomicfoundation/hardhat-mocha': 3.0.20(hardhat@3.7.0)(mocha@11.7.6) + '@nomicfoundation/hardhat-network-helpers': 3.0.9(hardhat@3.7.0) + '@nomicfoundation/hardhat-typechain': 3.1.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(ethers@6.16.0)(hardhat@3.7.0)(typescript@6.0.3) + '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.7.0) '@nomicfoundation/ignition-core': 3.1.6 chai: 6.2.2 ethers: 6.16.0 - hardhat: 3.5.1 + hardhat: 3.7.0 mocha: 11.7.6 - '@nomicfoundation/hardhat-typechain@3.0.9(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(ethers@6.16.0)(hardhat@3.5.1)(typescript@6.0.3)': + '@nomicfoundation/hardhat-typechain@3.1.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(ethers@6.16.0)(hardhat@3.7.0)(typescript@6.0.3)': dependencies: - '@nomicfoundation/hardhat-errors': 3.0.12 - '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.5.1) - '@nomicfoundation/hardhat-utils': 4.1.1 - '@nomicfoundation/hardhat-zod-utils': 3.0.4(zod@3.25.76) + '@nomicfoundation/hardhat-errors': 3.0.14 + '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.7.0) + '@nomicfoundation/hardhat-utils': 4.1.3 + '@nomicfoundation/hardhat-zod-utils': 3.0.5(zod@3.25.76) '@typechain/ethers-v6': 0.5.1(ethers@6.16.0)(typechain@8.3.2(typescript@6.0.3))(typescript@6.0.3) ethers: 6.16.0 - hardhat: 3.5.1 + hardhat: 3.7.0 typechain: 8.3.2(typescript@6.0.3) zod: 3.25.76 transitivePeerDependencies: - supports-color - typescript - '@nomicfoundation/hardhat-utils@4.1.1': + '@nomicfoundation/hardhat-utils@4.1.2': dependencies: '@streamparser/json-node': 0.0.22 env-paths: 2.2.1 @@ -4849,7 +4856,7 @@ snapshots: rfdc: 1.4.1 undici: 6.25.0 - '@nomicfoundation/hardhat-utils@4.1.2': + '@nomicfoundation/hardhat-utils@4.1.3': dependencies: '@streamparser/json-node': 0.0.22 env-paths: 2.2.1 @@ -4857,30 +4864,24 @@ snapshots: fast-equals: 5.4.0 json-stream-stringify: 3.1.6 rfdc: 1.4.1 - undici: 6.25.0 + undici: 6.26.0 '@nomicfoundation/hardhat-vendored@3.0.4': {} - '@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1)': + '@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0)': dependencies: '@ethersproject/abi': 5.8.0 - '@nomicfoundation/hardhat-errors': 3.0.13 - '@nomicfoundation/hardhat-utils': 4.1.2 + '@nomicfoundation/hardhat-errors': 3.0.15 + '@nomicfoundation/hardhat-utils': 4.1.3 '@nomicfoundation/hardhat-zod-utils': 3.0.5(zod@3.25.76) cbor2: 1.12.0 - hardhat: 3.5.1 - zod: 3.25.76 - - '@nomicfoundation/hardhat-zod-utils@3.0.4(zod@3.25.76)': - dependencies: - '@nomicfoundation/hardhat-errors': 3.0.12 - '@nomicfoundation/hardhat-utils': 4.1.1 + hardhat: 3.7.0 zod: 3.25.76 '@nomicfoundation/hardhat-zod-utils@3.0.5(zod@3.25.76)': dependencies: - '@nomicfoundation/hardhat-errors': 3.0.13 - '@nomicfoundation/hardhat-utils': 4.1.2 + '@nomicfoundation/hardhat-errors': 3.0.14 + '@nomicfoundation/hardhat-utils': 4.1.3 zod: 3.25.76 '@nomicfoundation/ignition-core@3.1.6': @@ -4955,9 +4956,9 @@ snapshots: '@openzeppelin/defender-deploy-client-cli@0.0.1-alpha.10': dependencies: - '@openzeppelin/defender-sdk-base-client': 2.7.1(debug@4.4.3) - '@openzeppelin/defender-sdk-deploy-client': 2.7.1(debug@4.4.3) - '@openzeppelin/defender-sdk-network-client': 2.7.1(debug@4.4.3) + '@openzeppelin/defender-sdk-base-client': 2.7.1 + '@openzeppelin/defender-sdk-deploy-client': 2.7.1 + '@openzeppelin/defender-sdk-network-client': 2.7.1 dotenv: 16.6.1 minimist: 1.2.8 transitivePeerDependencies: @@ -4972,7 +4973,7 @@ snapshots: transitivePeerDependencies: - encoding - '@openzeppelin/defender-sdk-base-client@2.7.1(debug@4.4.3)': + '@openzeppelin/defender-sdk-base-client@2.7.1': dependencies: '@aws-sdk/client-lambda': 3.985.0 amazon-cognito-identity-js: 6.3.16 @@ -4992,9 +4993,9 @@ snapshots: - debug - encoding - '@openzeppelin/defender-sdk-deploy-client@2.7.1(debug@4.4.3)': + '@openzeppelin/defender-sdk-deploy-client@2.7.1': dependencies: - '@openzeppelin/defender-sdk-base-client': 2.7.1(debug@4.4.3) + '@openzeppelin/defender-sdk-base-client': 2.7.1 axios: 1.13.5(debug@4.4.3) lodash: 4.18.1 transitivePeerDependencies: @@ -5011,9 +5012,9 @@ snapshots: - debug - encoding - '@openzeppelin/defender-sdk-network-client@2.7.1(debug@4.4.3)': + '@openzeppelin/defender-sdk-network-client@2.7.1': dependencies: - '@openzeppelin/defender-sdk-base-client': 2.7.1(debug@4.4.3) + '@openzeppelin/defender-sdk-base-client': 2.7.1 axios: 1.13.5(debug@4.4.3) lodash: 4.18.1 transitivePeerDependencies: @@ -5026,9 +5027,9 @@ snapshots: '@openzeppelin/defender-deploy-client-cli': 0.0.1-alpha.10 '@openzeppelin/upgrades-core': 1.44.2 - '@openzeppelin/hardhat-upgrades@3.5.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(ethers@6.15.0)(hardhat@2.28.6(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3))': + '@openzeppelin/hardhat-upgrades@3.5.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(ethers@6.15.0)(hardhat@2.28.6(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3))': dependencies: - '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.5.1) + '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.7.0) '@openzeppelin/defender-sdk-base-client': 1.15.2 '@openzeppelin/defender-sdk-deploy-client': 1.15.2(debug@4.4.3) '@openzeppelin/defender-sdk-network-client': 1.15.2(debug@4.4.3) @@ -5041,29 +5042,8 @@ snapshots: proper-lockfile: 4.1.2 undici: 6.23.0 optionalDependencies: - '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.5.1) - transitivePeerDependencies: - - encoding - - supports-color - - '@openzeppelin/hardhat-upgrades@3.9.1(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(ethers@6.16.0)(hardhat@3.5.1)': - dependencies: - '@nomicfoundation/hardhat-ethers': 4.0.12(hardhat@3.5.1) - '@openzeppelin/defender-sdk-base-client': 2.7.1(debug@4.4.3) - '@openzeppelin/defender-sdk-deploy-client': 2.7.1(debug@4.4.3) - '@openzeppelin/defender-sdk-network-client': 2.7.1(debug@4.4.3) - '@openzeppelin/upgrades-core': 1.44.2 - chalk: 4.1.2 - debug: 4.4.3(supports-color@8.1.1) - ethereumjs-util: 7.1.5 - ethers: 6.16.0 - hardhat: 3.5.1 - proper-lockfile: 4.1.2 - undici: 6.23.0 - optionalDependencies: - '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.5.1) + '@nomicfoundation/hardhat-verify': 3.0.18(hardhat@3.7.0) transitivePeerDependencies: - - aws-crt - encoding - supports-color @@ -5167,7 +5147,7 @@ snapshots: abitype: 1.2.4(typescript@6.0.3)(zod@3.25.76) eip-1193: 0.6.5 named-logs: 0.4.1 - viem: 2.50.4(typescript@6.0.3)(zod@3.25.76) + viem: 2.51.3(typescript@6.0.3)(zod@3.25.76) transitivePeerDependencies: - bufferutil - typescript @@ -5186,8 +5166,8 @@ snapshots: named-logs-console: 0.5.1 prompts: 2.4.2 rocketh: 0.19.4(typescript@6.0.3)(zod@3.25.76) - tsx: 4.22.3 - viem: 2.50.4(typescript@6.0.3)(zod@3.25.76) + tsx: 4.22.4 + viem: 2.51.3(typescript@6.0.3)(zod@3.25.76) transitivePeerDependencies: - bufferutil - typescript @@ -5680,15 +5660,15 @@ snapshots: dependencies: '@types/node': 25.9.1 - '@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@10.4.0)(typescript@6.0.3))(eslint@10.4.0)(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1)(typescript@6.0.3))(eslint@10.4.1)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.59.4(eslint@10.4.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.59.4 - '@typescript-eslint/type-utils': 8.59.4(eslint@10.4.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.4(eslint@10.4.0)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.4 - eslint: 10.4.0 + '@typescript-eslint/parser': 8.60.0(eslint@10.4.1)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/type-utils': 8.60.0(eslint@10.4.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.60.0(eslint@10.4.1)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.60.0 + eslint: 10.4.1 ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -5696,79 +5676,79 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.59.4(eslint@10.4.0)(typescript@6.0.3)': + '@typescript-eslint/parser@8.60.0(eslint@10.4.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.59.4 - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.4 + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.60.0 debug: 4.4.3(supports-color@8.1.1) - eslint: 10.4.0 + eslint: 10.4.1 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.59.4(typescript@6.0.3)': + '@typescript-eslint/project-service@8.60.0(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@6.0.3) - '@typescript-eslint/types': 8.59.4 + '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@6.0.3) + '@typescript-eslint/types': 8.60.0 debug: 4.4.3(supports-color@8.1.1) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.59.4': + '@typescript-eslint/scope-manager@8.60.0': dependencies: - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/visitor-keys': 8.59.4 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/visitor-keys': 8.60.0 - '@typescript-eslint/tsconfig-utils@8.59.4(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.60.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.59.4(eslint@10.4.0)(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.60.0(eslint@10.4.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.4(eslint@10.4.0)(typescript@6.0.3) + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.60.0(eslint@10.4.1)(typescript@6.0.3) debug: 4.4.3(supports-color@8.1.1) - eslint: 10.4.0 + eslint: 10.4.1 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.59.4': {} + '@typescript-eslint/types@8.60.0': {} - '@typescript-eslint/typescript-estree@8.59.4(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.60.0(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.59.4(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@6.0.3) - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/visitor-keys': 8.59.4 + '@typescript-eslint/project-service': 8.60.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@6.0.3) + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/visitor-keys': 8.60.0 debug: 4.4.3(supports-color@8.1.1) minimatch: 10.2.5 semver: 7.8.1 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.59.4(eslint@10.4.0)(typescript@6.0.3)': + '@typescript-eslint/utils@8.60.0(eslint@10.4.1)(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0) - '@typescript-eslint/scope-manager': 8.59.4 - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) - eslint: 10.4.0 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.1) + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@6.0.3) + eslint: 10.4.1 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.59.4': + '@typescript-eslint/visitor-keys@8.60.0': dependencies: - '@typescript-eslint/types': 8.59.4 + '@typescript-eslint/types': 8.60.0 eslint-visitor-keys: 5.0.1 '@uniswap/lib@4.0.1-alpha': {} @@ -5787,13 +5767,13 @@ snapshots: '@uniswap/v3-core': 1.0.1 base64-sol: 1.0.1 - '@zama-fhe/oracle-solidity@0.2.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(@openzeppelin/defender-deploy-client-cli@0.0.1-alpha.10)(@openzeppelin/upgrades-core@1.44.2)(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3)': + '@zama-fhe/oracle-solidity@0.2.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(@openzeppelin/defender-deploy-client-cli@0.0.1-alpha.10)(@openzeppelin/upgrades-core@1.44.2)(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3)': dependencies: '@fhevm/solidity': 0.8.0 '@openzeppelin/contracts': 5.1.0 '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) '@openzeppelin/foundry-upgrades': 0.3.8(@openzeppelin/defender-deploy-client-cli@0.0.1-alpha.10)(@openzeppelin/upgrades-core@1.44.2) - '@openzeppelin/hardhat-upgrades': 3.5.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.5.1))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.5.1))(ethers@6.15.0)(hardhat@2.28.6(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3)) + '@openzeppelin/hardhat-upgrades': 3.5.0(@nomicfoundation/hardhat-ethers@4.0.12(hardhat@3.7.0))(@nomicfoundation/hardhat-verify@3.0.18(hardhat@3.7.0))(ethers@6.15.0)(hardhat@2.28.6(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3)) ethers: 6.15.0 hardhat: 2.28.6(ts-node@10.9.2(@types/node@25.9.1)(typescript@6.0.3))(typescript@6.0.3) hardhat-deploy: 0.11.45 @@ -6016,6 +5996,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@2.1.1: + dependencies: + balanced-match: 1.0.2 + brace-expansion@5.0.6: dependencies: balanced-match: 4.0.4 @@ -6388,9 +6372,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.4.0): + eslint-config-prettier@10.1.8(eslint@10.4.1): dependencies: - eslint: 10.4.0 + eslint: 10.4.1 eslint-scope@9.1.2: dependencies: @@ -6405,14 +6389,14 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.4.0: + eslint@10.4.1: dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.1) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 '@eslint/config-helpers': 0.6.0 '@eslint/core': 1.2.1 - '@eslint/plugin-kit': 0.7.1 + '@eslint/plugin-kit': 0.7.2 '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -6808,12 +6792,12 @@ snapshots: - supports-color - utf-8-validate - hardhat-deploy@2.0.8(@rocketh/node@0.19.4(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76))(typescript@6.0.3)(zod@3.25.76))(hardhat@3.5.1)(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76)): + hardhat-deploy@2.0.8(@rocketh/node@0.19.4(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76))(typescript@6.0.3)(zod@3.25.76))(hardhat@3.7.0)(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76)): dependencies: '@nomicfoundation/hardhat-zod-utils': 3.0.5(zod@3.25.76) '@rocketh/node': 0.19.4(rocketh@0.19.4(typescript@6.0.3)(zod@3.25.76))(typescript@6.0.3)(zod@3.25.76) commander: 14.0.3 - hardhat: 3.5.1 + hardhat: 3.7.0 named-logs: 0.4.1 named-logs-console: 0.5.1 rocketh: 0.19.4(typescript@6.0.3)(zod@3.25.76) @@ -6874,11 +6858,11 @@ snapshots: - supports-color - utf-8-validate - hardhat@3.5.1: + hardhat@3.7.0: dependencies: '@nomicfoundation/edr': 0.12.0-next.33 - '@nomicfoundation/hardhat-errors': 3.0.13 - '@nomicfoundation/hardhat-utils': 4.1.2 + '@nomicfoundation/hardhat-errors': 3.0.14 + '@nomicfoundation/hardhat-utils': 4.1.3 '@nomicfoundation/hardhat-vendored': 3.0.4 '@nomicfoundation/hardhat-zod-utils': 3.0.5(zod@3.25.76) '@nomicfoundation/solidity-analyzer': 0.1.2 @@ -6891,7 +6875,7 @@ snapshots: p-map: 7.0.4 resolve.exports: 2.0.3 semver: 7.8.1 - tsx: 4.22.3 + tsx: 4.22.4 ws: 8.21.0 zod: 3.25.76 transitivePeerDependencies: @@ -7201,7 +7185,7 @@ snapshots: minimatch@5.1.9: dependencies: - brace-expansion: 2.1.0 + brace-expansion: 2.1.1 minimatch@9.0.9: dependencies: @@ -7341,7 +7325,7 @@ snapshots: os-tmpdir@1.0.2: {} - ox@0.14.22(typescript@6.0.3)(zod@3.25.76): + ox@0.14.25(typescript@6.0.3)(zod@3.25.76): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -7779,10 +7763,10 @@ snapshots: solidity-comments-win32-ia32-msvc: 0.0.2 solidity-comments-win32-x64-msvc: 0.0.2 - solidity-docgen@0.6.0-beta.36(hardhat@3.5.1): + solidity-docgen@0.6.0-beta.36(hardhat@3.7.0): dependencies: handlebars: 4.7.9 - hardhat: 3.5.1 + hardhat: 3.7.0 solidity-ast: 0.4.61 source-map-support@0.5.21: @@ -7880,7 +7864,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - tinyglobby@0.2.16: + tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 @@ -7966,6 +7950,12 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tsx@4.22.4: + dependencies: + esbuild: 0.28.0 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -8019,6 +8009,8 @@ snapshots: undici@6.25.0: {} + undici@6.26.0: {} + unfetch@4.2.0: {} universalify@0.1.2: {} @@ -8037,7 +8029,7 @@ snapshots: v8-compile-cache-lib@3.0.1: {} - viem@2.50.4(typescript@6.0.3)(zod@3.25.76): + viem@2.51.3(typescript@6.0.3)(zod@3.25.76): dependencies: '@noble/curves': 1.9.1 '@noble/hashes': 1.8.0 @@ -8045,7 +8037,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@6.0.3)(zod@3.25.76) isows: 1.0.7(ws@8.21.0) - ox: 0.14.22(typescript@6.0.3)(zod@3.25.76) + ox: 0.14.25(typescript@6.0.3)(zod@3.25.76) ws: 8.21.0 optionalDependencies: typescript: 6.0.3 diff --git a/test/PriceAdapterTruncation.test.ts b/test/PriceAdapterTruncation.test.ts index 160da46c..5faf389f 100644 --- a/test/PriceAdapterTruncation.test.ts +++ b/test/PriceAdapterTruncation.test.ts @@ -99,13 +99,14 @@ describe("Price Adapter Truncation", function () { }); it("should demonstrate ERC4626 getPriceData preserves precision and avoids truncation", async function () { - // ERC4626PriceAdapter uses: precisionAmount = 10^(PRICE_DECIMALS + vaultDecimals), then - // vaultPrice = convertToAssets(precisionAmount).mulDiv(underlyingPrice, 10^priceAdapterDecimals) - // Replicate that formula for expected price. + // ERC4626PriceAdapter uses mulDiv(totalAssets, 10^(PRICE_DECIMALS + effectiveShareDecimals), totalSupply) + // then composes with underlying price. Replicate that formula for expected price. const vaultDecimals = await vault.decimals(); + const totalAssets = await vault.totalAssets(); + const totalSupply = await vault.totalSupply(); const precisionAmount = 10n ** BigInt(10 + Number(vaultDecimals)); // PRICE_DECIMALS (10) + vault decimals (18) = 10^28 - const vaultUnderlyingAssetAmount = await vault.convertToAssets(precisionAmount); + const vaultUnderlyingAssetAmount = (totalAssets * precisionAmount) / totalSupply; const priceRegistry = await ethers.getContractAt("PriceAdapterRegistry", await orionConfig.priceAdapterRegistry()); const underlyingPriceInUSDC = await priceRegistry.getPrice(await vaultUnderlying.getAddress()); diff --git a/test/crossAsset/ERC4626PriceAdapter.test.ts b/test/crossAsset/ERC4626PriceAdapter.test.ts index cc16ba64..a446e55a 100644 --- a/test/crossAsset/ERC4626PriceAdapter.test.ts +++ b/test/crossAsset/ERC4626PriceAdapter.test.ts @@ -166,20 +166,25 @@ describe("ERC4626PriceAdapter - Coverage Tests", function () { expect(vaultPrice).to.be.closeTo(expectedPrice, expectedPrice / 100n); // Within 1% }); - //#todo: Fix WBTC whale funding on fork it("Should handle vault with different underlying decimals (WBTC - 8 decimals)", async function () { - // Deploy a WBTC vault - const MockERC4626Factory = await ethers.getContractFactory("MockERC4626Asset"); - const wbtcVault = await MockERC4626Factory.deploy(MAINNET.WBTC, "WBTC Vault", "vWBTC"); + await orionConfig.setTokenDecimals(MAINNET.WBTC, 8); + + const MockVaultFactory = await ethers.getContractFactory("TestFixedRatioERC4626"); + const totalAssets = 100_000_000n; // 1 WBTC (8 decimals) + const totalSupply = ethers.parseUnits("1", 18); + const wbtcVault = await MockVaultFactory.deploy( + MAINNET.WBTC, + "WBTC Vault", + "vWBTC", + 18, + totalAssets, + totalSupply, + ); await wbtcVault.waitForDeployment(); - // Register in config - const mockConfig = await ethers.getContractAt("MockOrionConfig", await orionConfig.getAddress()); - await mockConfig.setTokenDecimals(await wbtcVault.getAddress(), 18); - const [vaultPrice, priceDecimals] = await vaultPriceAdapter.getPriceData(await wbtcVault.getAddress()); - expect(priceDecimals).to.equal(28); // PRICE_DECIMALS (10) + getTokenDecimals(WETH) (18) + expect(priceDecimals).to.equal(18); // PRICE_DECIMALS (10) + WBTC decimals (8) expect(vaultPrice).to.be.gt(0); console.log(` WBTC vault price: ${ethers.formatUnits(vaultPrice, 14)} USDC per share`); diff --git a/test/crossAsset/ERC4626PriceAdapterHighSupply.test.ts b/test/crossAsset/ERC4626PriceAdapterHighSupply.test.ts new file mode 100644 index 00000000..2cbb498e --- /dev/null +++ b/test/crossAsset/ERC4626PriceAdapterHighSupply.test.ts @@ -0,0 +1,153 @@ +/** + * ERC4626PriceAdapter high-supply / decimal-offset vault pricing tests. + */ + +import { expect } from "chai"; +import { ethers } from "../helpers/hh"; +import type { + ERC4626PriceAdapter, + TestFixedRatioERC4626, + MockUnderlyingAsset, + OrionConfig, + MockExecutionAdapter, +} from "../../typechain-types"; +import { resetNetwork } from "../helpers/resetNetwork"; +import { deployUpgradeableProtocol } from "../helpers/deployUpgradeable"; + +const PRICE_DECIMALS = 10; + +// vfUSDC mainnet snapshot (Varlamore Falcon USDC) +const VF_USDC_TOTAL_ASSETS = 41_875_623_172n; +const VF_USDC_TOTAL_SUPPLY = 37_863_307_763_348_816n; +const VF_USDC_VAULT_DECIMALS = 6; + +const MAINNET = { + VF_USDC: "0xa9b23B28621CFB32e0ebf50b572aFAC671fCc17B", +}; + +describe("ERC4626PriceAdapter - High Supply Vaults", function () { + let protocolUnderlying: MockUnderlyingAsset; + let priceAdapter: ERC4626PriceAdapter; + let orionConfig: OrionConfig; + + before(async function () { + await resetNetwork(); + }); + + beforeEach(async function () { + const [deployer] = await ethers.getSigners(); + + const MockUnderlyingAssetFactory = await ethers.getContractFactory("MockUnderlyingAsset"); + protocolUnderlying = (await MockUnderlyingAssetFactory.deploy(6)) as unknown as MockUnderlyingAsset; + await protocolUnderlying.waitForDeployment(); + + const deployed = await deployUpgradeableProtocol(deployer, protocolUnderlying); + orionConfig = deployed.orionConfig; + + const ERC4626PriceAdapterFactory = await ethers.getContractFactory("ERC4626PriceAdapter"); + priceAdapter = (await ERC4626PriceAdapterFactory.deploy( + await orionConfig.getAddress(), + )) as unknown as ERC4626PriceAdapter; + await priceAdapter.waitForDeployment(); + }); + + async function registerVault(vault: TestFixedRatioERC4626) { + const MockExecutionAdapterFactory = await ethers.getContractFactory("MockExecutionAdapter"); + const executionAdapter = (await MockExecutionAdapterFactory.deploy()) as unknown as MockExecutionAdapter; + await executionAdapter.waitForDeployment(); + + await orionConfig.addWhitelistedAsset( + await vault.getAddress(), + await priceAdapter.getAddress(), + await executionAdapter.getAddress(), + ); + } + + it("preserves per-share precision for vfUSDC-like high-supply USDC vaults", async function () { + const MockVaultFactory = await ethers.getContractFactory("TestFixedRatioERC4626"); + const vault = (await MockVaultFactory.deploy( + await protocolUnderlying.getAddress(), + "vfUSDC Mock", + "mvfUSDC", + VF_USDC_VAULT_DECIMALS, + VF_USDC_TOTAL_ASSETS, + VF_USDC_TOTAL_SUPPLY, + )) as unknown as TestFixedRatioERC4626; + await vault.waitForDeployment(); + await registerVault(vault); + + const [price, priceDecimals] = await priceAdapter.getPriceData(await vault.getAddress()); + + expect(priceDecimals).to.equal(PRICE_DECIMALS + 6); + + const underlyingPerShare = price / 10n ** BigInt(PRICE_DECIMALS); + + // Effective share scale is 12 for this ratio; naive 10^vaultDecimals truncates to 1. + const expectedPerShare = (VF_USDC_TOTAL_ASSETS * 10n ** 12n) / VF_USDC_TOTAL_SUPPLY; + const naivePerShare = (VF_USDC_TOTAL_ASSETS * 10n ** BigInt(VF_USDC_VAULT_DECIMALS)) / VF_USDC_TOTAL_SUPPLY; + + expect(naivePerShare).to.equal(1n); + expect(underlyingPerShare).to.be.closeTo(expectedPerShare, 1n); + expect(underlyingPerShare).to.be.gt(1_000_000n); + }); + + it("does not change pricing for standard 18-decimal appreciating vaults", async function () { + const MockVaultFactory = await ethers.getContractFactory("TestFixedRatioERC4626"); + const totalAssets = ethers.parseUnits("1000", 18); + const totalSupply = ethers.parseUnits("950", 18); + const vault = (await MockVaultFactory.deploy( + await protocolUnderlying.getAddress(), + "18d Vault", + "v18", + 18, + totalAssets, + totalSupply, + )) as unknown as TestFixedRatioERC4626; + await vault.waitForDeployment(); + await registerVault(vault); + + const [price] = await priceAdapter.getPriceData(await vault.getAddress()); + const underlyingPerShare = price / 10n ** BigInt(PRICE_DECIMALS); + const expectedPerShare = (totalAssets * 10n ** 18n) / totalSupply; + + expect(underlyingPerShare).to.equal(expectedPerShare); + }); + + describe("mainnet vfUSDC fork", function () { + before(function () { + if (!(process.env.FORK_MAINNET === "true" && process.env.MAINNET_RPC_URL)) { + this.skip(); + } + }); + + it("reports ~1.1 USDC per share for vfUSDC", async function () { + const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; + + const vault = await ethers.getContractAt( + "@openzeppelin/contracts/interfaces/IERC4626.sol:IERC4626", + MAINNET.VF_USDC, + ); + const vaultToken = await ethers.getContractAt("IERC20Metadata", MAINNET.VF_USDC); + + const totalAssets = await vault.totalAssets(); + const totalSupply = await vault.totalSupply(); + const vaultDecimals = await vaultToken.decimals(); + + const [deployer] = await ethers.getSigners(); + const deployed = await deployUpgradeableProtocol(deployer, USDC); + const forkAdapter = await ( + await ethers.getContractFactory("ERC4626PriceAdapter") + ).deploy(await deployed.orionConfig.getAddress()); + + const [price] = await forkAdapter.getPriceData(MAINNET.VF_USDC); + const underlyingPerShare = price / 10n ** BigInt(PRICE_DECIMALS); + + const naivePerShare = (totalAssets * 10n ** BigInt(vaultDecimals)) / totalSupply; + const highPrecisionPerShare = (totalAssets * 10n ** 12n) / totalSupply; + + expect(naivePerShare).to.be.lte(1n); + expect(underlyingPerShare).to.be.closeTo(highPrecisionPerShare, 2n); + expect(underlyingPerShare).to.be.gt(1_000_000n); + }); + }); +});