From 05e201473c172108752a4ec56915fab9ae1ac40f Mon Sep 17 00:00:00 2001 From: Aalavandhan <6264334+aalavandhan@users.noreply.github.com> Date: Thu, 20 Jun 2024 23:14:37 -0400 Subject: [PATCH] v4.0.0 (#211) * spot subgraph update (#207) * Removed fixed per-tranche mint cap (#206) * updated per-tranche mint cap * removed redundant constant * added dr to the spot and vault interface * added mintedSupplyPerTranche cleanup * updated rounding * updated unit test * renamed constants in rollover vault to keep consistant with perp * Bill broker (#203) * bill broker * BB Internal audit fixes (#210) * internal audit fixes * code review fixes * Update spot-vaults/contracts/_interfaces/BillBrokerErrors.sol Co-authored-by: Brandon Iles --------- Co-authored-by: Brandon Iles --------- Co-authored-by: Brandon Iles * updated yarn lock * bumped up ci version --------- Co-authored-by: Brandon Iles * ci config update * Peck audit changes (#212) * pve001 * pve002 * using msg.sender instead of _msgSender * Perp upgrade and bill-broker deployment (#213) * perp min-cap upgrade deployed to testnet * mock contracts for testnet * tasks to interact with bb * oz testnet deployment * updated yarn lock * removed todo comment * upgraded perp on mainnet * bb mainnet deployment * minor task updates * Delete spot-contracts/notes.txt deleted unused file --------- Co-authored-by: Brandon Iles --- .github/workflows/nightly.yml | 11 +- .github/workflows/test.yml | 5 +- .nvmrc | 2 +- package.json | 4 +- spot-contracts/.openzeppelin/mainnet.json | 391 ++ spot-contracts/.openzeppelin/sepolia.json | 391 ++ spot-contracts/contracts/PerpetualTranche.sol | 152 +- spot-contracts/contracts/RolloverVault.sol | 27 +- .../_interfaces/IPerpetualTranche.sol | 3 + .../contracts/_interfaces/IRolloverVault.sol | 3 + spot-contracts/deployments/mainnet.json | 16 +- spot-contracts/deployments/sepolia.json | 5 +- .../PerpetualTrancheV1.json | 1699 ++++++++ spot-contracts/hardhat.config.ts | 1 - spot-contracts/tasks/ops/perp.ts | 21 +- spot-contracts/tasks/scripts/mainnet.sh | 1 - spot-contracts/tasks/upgrade/index.ts | 4 +- spot-contracts/test/perp/PerpetualTranche.ts | 45 +- .../test/perp/PerpetualTranche_deposit.ts | 68 +- spot-staking-subgraph/.gitignore | 2 + spot-staking-subgraph/.prettierrc | 7 + spot-staking-subgraph/README.md | 15 + spot-staking-subgraph/abis/CharmVault.json | 1 + spot-staking-subgraph/abis/ERC20.json | 222 + spot-staking-subgraph/abis/RebasingERC20.json | 344 ++ spot-staking-subgraph/abis/UniV3Pool.json | 1 + spot-staking-subgraph/package.json | 26 + spot-staking-subgraph/schema.graphql | 47 + spot-staking-subgraph/src/mappings.ts | 214 + spot-staking-subgraph/subgraph.yaml | 38 + spot-subgraph/{.eslintrc => .eslintrc.js} | 0 spot-subgraph/.prettierrc | 2 +- spot-subgraph/README.md | 6 +- .../modified-artifacts/PerpetualTranche.json | 1166 ++++++ spot-subgraph/modified-artifacts/notes.txt | 1 + spot-subgraph/schema.graphql | 213 +- spot-subgraph/scripts/deploy.sh | 9 +- spot-subgraph/src/data/bondIssuer.ts | 4 - spot-subgraph/src/data/buttonTranche.ts | 73 +- spot-subgraph/src/data/perpetualTranche.ts | 166 +- spot-subgraph/src/data/rolloverVault.ts | 193 +- spot-subgraph/src/mappings/bondController.ts | 21 +- spot-subgraph/src/mappings/bondIssuer.ts | 1 - .../src/mappings/perpetualTranche.ts | 99 +- spot-subgraph/src/mappings/rebasingToken.ts | 35 +- spot-subgraph/src/mappings/rolloverVault.ts | 155 +- spot-subgraph/src/utils.ts | 97 +- spot-subgraph/subgraph.template.yaml | 129 +- spot-vaults/.eslintignore | 4 + spot-vaults/.eslintrc.js | 46 + spot-vaults/.eslintrc.yaml | 0 spot-vaults/.gitignore | 14 + spot-vaults/.openzeppelin/mainnet.json | 331 ++ spot-vaults/.openzeppelin/sepolia.json | 331 ++ spot-vaults/.prettierignore | 12 + spot-vaults/.prettierrc | 17 + spot-vaults/.solcover.js | 3 + spot-vaults/.solhint.json | 10 + spot-vaults/.solhintignore | 1 + spot-vaults/README.md | 44 + spot-vaults/contracts/BillBroker.sol | 791 ++++ .../_interfaces/BillBrokerErrors.sol | 29 + .../contracts/_interfaces/BillBrokerTypes.sol | 48 + .../IBillBrokerPricingStrategy.sol | 22 + .../contracts/_interfaces/external/IAMPL.sol | 8 + .../_interfaces/external/IAmpleforth.sol | 7 + .../external/IAmpleforthOracle.sol | 8 + .../_interfaces/external/IChainlinkOracle.sol | 17 + .../contracts/_strategies/SpotAppraiser.sol | 214 + spot-vaults/contracts/_test/DMock.sol | 52 + spot-vaults/contracts/_test/MockCLOracle.sol | 26 + spot-vaults/contracts/_test/MockCPIOracle.sol | 21 + spot-vaults/contracts/_test/MockERC20.sol | 24 + .../contracts/_test/PerpTestArtifacts.sol | 5 + .../contracts/_test/TrancheTestArtifacts.sol | 8 + .../_test/UFragmentsTestArtifacts.sol | 11 + spot-vaults/hardhat.config.ts | 80 + spot-vaults/package.json | 78 + spot-vaults/tasks/deploy.ts | 93 + spot-vaults/tasks/info.ts | 125 + spot-vaults/tasks/ops.ts | 300 ++ spot-vaults/tasks/scripts/mainnet.sh | 48 + spot-vaults/tasks/scripts/sepolia.sh | 41 + spot-vaults/tasks/tools.ts | 63 + spot-vaults/test/BillBroker.ts | 637 +++ spot-vaults/test/BillBroker_deposit_redeem.ts | 903 ++++ spot-vaults/test/BillBroker_swap.ts | 1103 +++++ spot-vaults/test/SpotAppraiser.ts | 242 ++ spot-vaults/test/helpers.ts | 79 + spot-vaults/tsconfig.json | 11 + yarn.lock | 3643 +++++++++++------ 91 files changed, 13911 insertions(+), 1775 deletions(-) create mode 100644 spot-contracts/exported-artifacts/PerpetualTrancheV1.json create mode 100644 spot-staking-subgraph/.gitignore create mode 100644 spot-staking-subgraph/.prettierrc create mode 100644 spot-staking-subgraph/README.md create mode 100644 spot-staking-subgraph/abis/CharmVault.json create mode 100644 spot-staking-subgraph/abis/ERC20.json create mode 100644 spot-staking-subgraph/abis/RebasingERC20.json create mode 100644 spot-staking-subgraph/abis/UniV3Pool.json create mode 100644 spot-staking-subgraph/package.json create mode 100644 spot-staking-subgraph/schema.graphql create mode 100644 spot-staking-subgraph/src/mappings.ts create mode 100644 spot-staking-subgraph/subgraph.yaml rename spot-subgraph/{.eslintrc => .eslintrc.js} (100%) create mode 100644 spot-subgraph/modified-artifacts/PerpetualTranche.json create mode 100644 spot-subgraph/modified-artifacts/notes.txt create mode 100644 spot-vaults/.eslintignore create mode 100644 spot-vaults/.eslintrc.js create mode 100644 spot-vaults/.eslintrc.yaml create mode 100644 spot-vaults/.gitignore create mode 100644 spot-vaults/.openzeppelin/mainnet.json create mode 100644 spot-vaults/.openzeppelin/sepolia.json create mode 100644 spot-vaults/.prettierignore create mode 100644 spot-vaults/.prettierrc create mode 100644 spot-vaults/.solcover.js create mode 100644 spot-vaults/.solhint.json create mode 100644 spot-vaults/.solhintignore create mode 100644 spot-vaults/README.md create mode 100644 spot-vaults/contracts/BillBroker.sol create mode 100644 spot-vaults/contracts/_interfaces/BillBrokerErrors.sol create mode 100644 spot-vaults/contracts/_interfaces/BillBrokerTypes.sol create mode 100644 spot-vaults/contracts/_interfaces/IBillBrokerPricingStrategy.sol create mode 100644 spot-vaults/contracts/_interfaces/external/IAMPL.sol create mode 100644 spot-vaults/contracts/_interfaces/external/IAmpleforth.sol create mode 100644 spot-vaults/contracts/_interfaces/external/IAmpleforthOracle.sol create mode 100644 spot-vaults/contracts/_interfaces/external/IChainlinkOracle.sol create mode 100644 spot-vaults/contracts/_strategies/SpotAppraiser.sol create mode 100644 spot-vaults/contracts/_test/DMock.sol create mode 100644 spot-vaults/contracts/_test/MockCLOracle.sol create mode 100644 spot-vaults/contracts/_test/MockCPIOracle.sol create mode 100644 spot-vaults/contracts/_test/MockERC20.sol create mode 100644 spot-vaults/contracts/_test/PerpTestArtifacts.sol create mode 100644 spot-vaults/contracts/_test/TrancheTestArtifacts.sol create mode 100644 spot-vaults/contracts/_test/UFragmentsTestArtifacts.sol create mode 100644 spot-vaults/hardhat.config.ts create mode 100644 spot-vaults/package.json create mode 100644 spot-vaults/tasks/deploy.ts create mode 100644 spot-vaults/tasks/info.ts create mode 100644 spot-vaults/tasks/ops.ts create mode 100644 spot-vaults/tasks/scripts/mainnet.sh create mode 100644 spot-vaults/tasks/scripts/sepolia.sh create mode 100644 spot-vaults/tasks/tools.ts create mode 100644 spot-vaults/test/BillBroker.ts create mode 100644 spot-vaults/test/BillBroker_deposit_redeem.ts create mode 100644 spot-vaults/test/BillBroker_swap.ts create mode 100644 spot-vaults/test/SpotAppraiser.ts create mode 100644 spot-vaults/test/helpers.ts create mode 100644 spot-vaults/tsconfig.json diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 766ec403..35c75393 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16.x] + node-version: [20.x] os: [ubuntu-latest] steps: @@ -34,3 +34,12 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: "./spot-contracts/coverage/lcov.info" + + - name: spot-vaults run coverage + run: yarn workspace @ampleforthorg/spot-vaults run coverage + + - name: spot-vaults report coverage + uses: coverallsapp/github-action@v2.2.3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: "./spot-vaults/coverage/lcov.info" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b4842eae..12ef3ba9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,15 +4,16 @@ on: push: branches: [main] pull_request: - branches: [main] + branches: [main,dev] jobs: test: runs-on: ${{ matrix.os }} strategy: + fail-fast: true matrix: - node-version: [16.x] + node-version: [20.x] os: [ubuntu-latest] steps: diff --git a/.nvmrc b/.nvmrc index b6a7d89c..209e3ef4 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16 +20 diff --git a/package.json b/package.json index cd67320c..3aa79c82 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "packageManager": "yarn@3.2.1", "workspaces": [ "spot-contracts", - "spot-subgraph" + "spot-vaults", + "spot-subgraph", + "spot-staking-subgraph" ] } diff --git a/spot-contracts/.openzeppelin/mainnet.json b/spot-contracts/.openzeppelin/mainnet.json index b417140d..e139eb59 100644 --- a/spot-contracts/.openzeppelin/mainnet.json +++ b/spot-contracts/.openzeppelin/mainnet.json @@ -2449,6 +2449,397 @@ }, "namespaces": {} } + }, + "812d4eb2dcd362a6d0f952775faf9957f5a27979ddeb62f7da074968b20a0690": { + "address": "0x5Dc5488B35C34a43fE19bA9dE38b63806FAb4b23", + "txHash": "0x621ea9c5ed7008d05eb1d430c1bb6834bb18598527c0614df2fa366f21ed73ca", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_balances", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:40" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:42" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "53", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "_name", + "offset": 0, + "slot": "54", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:46" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "55", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "56", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:376" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC20BurnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol:51" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "201", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "_status", + "offset": 0, + "slot": "251", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:88" + }, + { + "label": "_decimals", + "offset": 0, + "slot": "301", + "type": "t_uint8", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:122" + }, + { + "label": "keeper", + "offset": 1, + "slot": "301", + "type": "t_address", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:128" + }, + { + "label": "feePolicy", + "offset": 0, + "slot": "302", + "type": "t_contract(IFeePolicy)11570", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:132" + }, + { + "label": "_pricingStrategy_DEPRECATED", + "offset": 0, + "slot": "303", + "type": "t_address", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:138" + }, + { + "label": "_discountStrategy_DEPRECATED", + "offset": 0, + "slot": "304", + "type": "t_address", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:146" + }, + { + "label": "bondIssuer", + "offset": 0, + "slot": "305", + "type": "t_contract(IBondIssuer)11490", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:150" + }, + { + "label": "_depositBond", + "offset": 0, + "slot": "306", + "type": "t_contract(IBondController)12129", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:153" + }, + { + "label": "minTrancheMaturitySec", + "offset": 0, + "slot": "307", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:157" + }, + { + "label": "maxTrancheMaturitySec", + "offset": 0, + "slot": "308", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:161" + }, + { + "label": "_matureValueTargetPerc_DEPRECATED", + "offset": 0, + "slot": "309", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:169" + }, + { + "label": "maxSupply", + "offset": 0, + "slot": "310", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:172" + }, + { + "label": "maxDepositTrancheValuePerc", + "offset": 0, + "slot": "311", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:176" + }, + { + "label": "_mintedSupplyPerTranche_DEPRECATED", + "offset": 0, + "slot": "312", + "type": "t_mapping(t_contract(ITranche)12156,t_uint256)", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:182" + }, + { + "label": "_appliedDiscounts_DEPRECATED", + "offset": 0, + "slot": "313", + "type": "t_mapping(t_contract(IERC20Upgradeable)1205,t_uint256)", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:189" + }, + { + "label": "_reserves", + "offset": 0, + "slot": "314", + "type": "t_struct(AddressSet)4926_storage", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:195" + }, + { + "label": "_matureTrancheBalance_DEPRECATED", + "offset": 0, + "slot": "316", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:201" + }, + { + "label": "vault", + "offset": 0, + "slot": "317", + "type": "t_contract(IRolloverVault)11853", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:209" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IBondController)12129": { + "label": "contract IBondController", + "numberOfBytes": "20" + }, + "t_contract(IBondIssuer)11490": { + "label": "contract IBondIssuer", + "numberOfBytes": "20" + }, + "t_contract(IERC20Upgradeable)1205": { + "label": "contract IERC20Upgradeable", + "numberOfBytes": "20" + }, + "t_contract(IFeePolicy)11570": { + "label": "contract IFeePolicy", + "numberOfBytes": "20" + }, + "t_contract(IRolloverVault)11853": { + "label": "contract IRolloverVault", + "numberOfBytes": "20" + }, + "t_contract(ITranche)12156": { + "label": "contract ITranche", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_contract(IERC20Upgradeable)1205,t_uint256)": { + "label": "mapping(contract IERC20Upgradeable => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_contract(ITranche)12156,t_uint256)": { + "label": "mapping(contract ITranche => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)4926_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)4611_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)4611_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/spot-contracts/.openzeppelin/sepolia.json b/spot-contracts/.openzeppelin/sepolia.json index 9a8fda8a..1abd075a 100644 --- a/spot-contracts/.openzeppelin/sepolia.json +++ b/spot-contracts/.openzeppelin/sepolia.json @@ -1086,6 +1086,397 @@ }, "namespaces": {} } + }, + "812d4eb2dcd362a6d0f952775faf9957f5a27979ddeb62f7da074968b20a0690": { + "address": "0xAbB9046413479575DEA9c14E79847939B6AA039A", + "txHash": "0x0922dc22c1653dfd85785d2316a7f0d024010685e7838c12bbc77f9ab4ca1c44", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_balances", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:40" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:42" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "53", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "_name", + "offset": 0, + "slot": "54", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:46" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "55", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "56", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:376" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC20BurnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol:51" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "201", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "_status", + "offset": 0, + "slot": "251", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:88" + }, + { + "label": "_decimals", + "offset": 0, + "slot": "301", + "type": "t_uint8", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:122" + }, + { + "label": "keeper", + "offset": 1, + "slot": "301", + "type": "t_address", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:128" + }, + { + "label": "feePolicy", + "offset": 0, + "slot": "302", + "type": "t_contract(IFeePolicy)11570", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:132" + }, + { + "label": "_pricingStrategy_DEPRECATED", + "offset": 0, + "slot": "303", + "type": "t_address", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:138" + }, + { + "label": "_discountStrategy_DEPRECATED", + "offset": 0, + "slot": "304", + "type": "t_address", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:146" + }, + { + "label": "bondIssuer", + "offset": 0, + "slot": "305", + "type": "t_contract(IBondIssuer)11490", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:150" + }, + { + "label": "_depositBond", + "offset": 0, + "slot": "306", + "type": "t_contract(IBondController)12129", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:153" + }, + { + "label": "minTrancheMaturitySec", + "offset": 0, + "slot": "307", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:157" + }, + { + "label": "maxTrancheMaturitySec", + "offset": 0, + "slot": "308", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:161" + }, + { + "label": "_matureValueTargetPerc_DEPRECATED", + "offset": 0, + "slot": "309", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:169" + }, + { + "label": "maxSupply", + "offset": 0, + "slot": "310", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:172" + }, + { + "label": "maxDepositTrancheValuePerc", + "offset": 0, + "slot": "311", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:176" + }, + { + "label": "_mintedSupplyPerTranche_DEPRECATED", + "offset": 0, + "slot": "312", + "type": "t_mapping(t_contract(ITranche)12156,t_uint256)", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:182" + }, + { + "label": "_appliedDiscounts_DEPRECATED", + "offset": 0, + "slot": "313", + "type": "t_mapping(t_contract(IERC20Upgradeable)1205,t_uint256)", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:189" + }, + { + "label": "_reserves", + "offset": 0, + "slot": "314", + "type": "t_struct(AddressSet)4926_storage", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:195" + }, + { + "label": "_matureTrancheBalance_DEPRECATED", + "offset": 0, + "slot": "316", + "type": "t_uint256", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:201" + }, + { + "label": "vault", + "offset": 0, + "slot": "317", + "type": "t_contract(IRolloverVault)11853", + "contract": "PerpetualTranche", + "src": "contracts/PerpetualTranche.sol:209" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IBondController)12129": { + "label": "contract IBondController", + "numberOfBytes": "20" + }, + "t_contract(IBondIssuer)11490": { + "label": "contract IBondIssuer", + "numberOfBytes": "20" + }, + "t_contract(IERC20Upgradeable)1205": { + "label": "contract IERC20Upgradeable", + "numberOfBytes": "20" + }, + "t_contract(IFeePolicy)11570": { + "label": "contract IFeePolicy", + "numberOfBytes": "20" + }, + "t_contract(IRolloverVault)11853": { + "label": "contract IRolloverVault", + "numberOfBytes": "20" + }, + "t_contract(ITranche)12156": { + "label": "contract ITranche", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_contract(IERC20Upgradeable)1205,t_uint256)": { + "label": "mapping(contract IERC20Upgradeable => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_contract(ITranche)12156,t_uint256)": { + "label": "mapping(contract ITranche => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)4926_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)4611_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)4611_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/spot-contracts/contracts/PerpetualTranche.sol b/spot-contracts/contracts/PerpetualTranche.sol index 7450cddd..960dfc8e 100644 --- a/spot-contracts/contracts/PerpetualTranche.sol +++ b/spot-contracts/contracts/PerpetualTranche.sol @@ -5,7 +5,7 @@ import { IERC20MetadataUpgradeable } from "@openzeppelin/contracts-upgradeable/t import { IERC20Upgradeable, IPerpetualTranche, IBondIssuer, IFeePolicy, IBondController, ITranche } from "./_interfaces/IPerpetualTranche.sol"; import { IRolloverVault } from "./_interfaces/IRolloverVault.sol"; import { TokenAmount, RolloverData, SubscriptionParams } from "./_interfaces/CommonTypes.sol"; -import { UnauthorizedCall, UnauthorizedTransferOut, UnexpectedDecimals, UnexpectedAsset, UnacceptableParams, UnacceptableRollover, ExceededMaxSupply, ExceededMaxMintPerTranche, ReserveCountOverLimit } from "./_interfaces/ProtocolErrors.sol"; +import { UnauthorizedCall, UnauthorizedTransferOut, UnexpectedDecimals, UnexpectedAsset, UnacceptableParams, UnacceptableRollover, ExceededMaxSupply, ExceededMaxMintPerTranche, ReserveCountOverLimit, InvalidPerc } from "./_interfaces/ProtocolErrors.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; @@ -107,9 +107,10 @@ contract PerpetualTranche is // //------------------------------------------------------------------------- // Constants & Immutables - // Number of decimals for a multiplier of 1.0x (i.e. 100%) - uint8 public constant FEE_POLICY_DECIMALS = 8; - uint256 public constant FEE_ONE = (10 ** FEE_POLICY_DECIMALS); + + /// @dev Internal percentages are fixed point numbers with {PERC_DECIMALS} places. + uint8 public constant PERC_DECIMALS = 8; + uint256 public constant ONE = (10 ** PERC_DECIMALS); // 1.0 or 100% /// @dev The maximum number of reserve assets that can be held by perp. uint8 public constant MAX_RESERVE_COUNT = 11; @@ -170,11 +171,15 @@ contract PerpetualTranche is /// @notice The maximum supply of perps that can exist at any given time. uint256 public maxSupply; - /// @notice The max number of perps that can be minted using the senior tranche in the minting bond. - uint256 public maxMintAmtPerTranche; + /// @notice Enforced maximum percentage of reserve value in the deposit tranche. + /// @custom:oz-upgrades-renamed-from maxMintAmtPerTranche + uint256 public maxDepositTrancheValuePerc; - /// @notice The total number of perps that have been minted using a given tranche. - mapping(ITranche => uint256) public mintedSupplyPerTranche; + /// @notice DEPRECATED. + /// @dev This used to store the number of perps minted using each deposit tranche. + /// @custom:oz-upgrades-renamed-from mintedSupplyPerTranche + // solhint-disable-next-line var-name-mixedcase + mapping(ITranche => uint256) private _mintedSupplyPerTranche_DEPRECATED; /// @notice DEPRECATED. /// @dev This used to store the discount factor applied on each reserve token. @@ -266,7 +271,8 @@ contract PerpetualTranche is updateBondIssuer(bondIssuer_); updateTolerableTrancheMaturity(1, type(uint256).max); - updateMintingLimits(type(uint256).max, type(uint256).max); + updateMaxSupply(type(uint256).max); + updateMaxDepositTrancheValuePerc(ONE); } //-------------------------------------------------------------------------- @@ -296,7 +302,7 @@ contract PerpetualTranche is /// @notice Update the reference to the fee policy contract. /// @param feePolicy_ New strategy address. function updateFeePolicy(IFeePolicy feePolicy_) public onlyOwner { - if (feePolicy_.decimals() != FEE_POLICY_DECIMALS) { + if (feePolicy_.decimals() != PERC_DECIMALS) { revert UnexpectedDecimals(); } feePolicy = feePolicy_; @@ -346,12 +352,20 @@ contract PerpetualTranche is _unpause(); } - /// @notice Update parameters controlling the perp token mint limits. + /// @notice Updates the maximum supply. /// @param maxSupply_ New max total supply. - /// @param maxMintAmtPerTranche_ New max total for per tranche in minting bond. - function updateMintingLimits(uint256 maxSupply_, uint256 maxMintAmtPerTranche_) public onlyKeeper { + function updateMaxSupply(uint256 maxSupply_) public onlyKeeper { maxSupply = maxSupply_; - maxMintAmtPerTranche = maxMintAmtPerTranche_; + } + + /// @notice Updates the enforced maximum percentage value of deposit tranches. + /// @dev Stored as a fixed point number with {PERC_DECIMALS} places. + /// @param maxDepositTrancheValuePerc_ New max percentage. + function updateMaxDepositTrancheValuePerc(uint256 maxDepositTrancheValuePerc_) public onlyKeeper { + if (maxDepositTrancheValuePerc_ > ONE) { + revert InvalidPerc(); + } + maxDepositTrancheValuePerc = maxDepositTrancheValuePerc_; } //-------------------------------------------------------------------------- @@ -380,7 +394,6 @@ contract PerpetualTranche is _mint(msg.sender, perpAmtMint); // post-deposit checks - mintedSupplyPerTranche[trancheIn] += perpAmtMint; _enforceMintCaps(trancheIn); return perpAmtMint; @@ -491,7 +504,14 @@ contract PerpetualTranche is ITranche tranche = ITranche(address(token)); IBondController parentBond = IBondController(tranche.bond()); - return _computeReserveTrancheValue(tranche, parentBond, _reserveAt(0), tranche.balanceOf(address(this)), true); + return + _computeReserveTrancheValue( + tranche, + parentBond, + _reserveAt(0), + tranche.balanceOf(address(this)), + MathUpgradeable.Rounding.Up + ); } /// @inheritdoc IPerpetualTranche @@ -566,6 +586,18 @@ contract PerpetualTranche is return _computeRolloverAmt(trancheIn, tokenOut, trancheInAmtAvailable); } + /// @inheritdoc IPerpetualTranche + function deviationRatio() external override afterStateUpdate nonReentrant returns (uint256) { + return + feePolicy.computeDeviationRatio( + SubscriptionParams({ + perpTVL: _reserveValue(), + vaultTVL: vault.getTVL(), + seniorTR: _depositBond.getSeniorTrancheRatio() + }) + ); + } + //-------------------------------------------------------------------------- // Public methods @@ -681,8 +713,11 @@ contract PerpetualTranche is // Removes tranche from reserve set. _reserves.remove(address(token)); - // Frees up minted supply. - delete mintedSupplyPerTranche[ITranche(address(token))]; + // Frees up storage slot used by existing tranches in the system. + // NOTE: This variable in the process of being `DEPRECATED`, and the following line + // can be removed once all storage used by all the current tranches are zeroed out + // as they are removed from the reserve. + delete _mintedSupplyPerTranche_DEPRECATED[ITranche(address(token))]; } return balance; @@ -690,7 +725,13 @@ contract PerpetualTranche is /// @dev Computes the fee adjusted perp mint amount for given amount of tranche tokens deposited into the reserve. function _computeMintAmt(ITranche trancheIn, uint256 trancheInAmt) private view returns (uint256) { - uint256 valueIn = _computeReserveTrancheValue(trancheIn, _depositBond, _reserveAt(0), trancheInAmt, false); + uint256 valueIn = _computeReserveTrancheValue( + trancheIn, + _depositBond, + _reserveAt(0), + trancheInAmt, + MathUpgradeable.Rounding.Down + ); //----------------------------------------------------------------------------- // We charge no mint fee when interacting with other callers within the system. @@ -706,7 +747,7 @@ contract PerpetualTranche is // The mint fees are settled by simply minting fewer perps. if (feePerc > 0) { - perpAmtMint = perpAmtMint.mulDiv(FEE_ONE - feePerc, FEE_ONE); + perpAmtMint = perpAmtMint.mulDiv(ONE - feePerc, ONE); } return perpAmtMint; @@ -733,7 +774,7 @@ contract PerpetualTranche is // The burn fees are settled by simply redeeming for fewer tranches. if (feePerc > 0) { - reserveTokens[i].amount = reserveTokens[i].amount.mulDiv(FEE_ONE - feePerc, FEE_ONE); + reserveTokens[i].amount = reserveTokens[i].amount.mulDiv(ONE - feePerc, ONE); } } @@ -767,7 +808,13 @@ contract PerpetualTranche is // with the same number of decimals. IERC20Upgradeable underlying_ = _reserveAt(0); uint256 unitTokenAmt = (10 ** _decimals); - uint256 trancheInPrice = _computeReserveTrancheValue(trancheIn, _depositBond, underlying_, unitTokenAmt, false); + uint256 trancheInPrice = _computeReserveTrancheValue( + trancheIn, + _depositBond, + underlying_, + unitTokenAmt, + MathUpgradeable.Rounding.Down + ); uint256 tokenOutPrice = unitTokenAmt; if (tokenOut != underlying_) { ITranche trancheOut = ITranche(address(tokenOut)); @@ -776,7 +823,7 @@ contract PerpetualTranche is IBondController(trancheOut.bond()), underlying_, unitTokenAmt, - true + MathUpgradeable.Rounding.Up ); } @@ -800,12 +847,12 @@ contract PerpetualTranche is // A positive fee percentage implies that perp charges rotators by // offering tranchesOut for a premium, i.e) more tranches in. if (feePerc > 0) { - r.trancheInAmt = r.trancheInAmt.mulDiv(FEE_ONE, FEE_ONE - feePerc.toUint256(), MathUpgradeable.Rounding.Up); + r.trancheInAmt = r.trancheInAmt.mulDiv(ONE, ONE - feePerc.toUint256(), MathUpgradeable.Rounding.Up); } // A negative fee percentage (or a reward) implies that perp pays the rotators by // offering tranchesOut at a discount, i.e) fewer tranches in. else if (feePerc < 0) { - r.trancheInAmt = r.trancheInAmt.mulDiv(FEE_ONE, FEE_ONE + feePerc.abs(), MathUpgradeable.Rounding.Up); + r.trancheInAmt = r.trancheInAmt.mulDiv(ONE, ONE + feePerc.abs(), MathUpgradeable.Rounding.Up); } //----------------------------------------------------------------------------- @@ -822,13 +869,13 @@ contract PerpetualTranche is // accepting tranchesIn at a discount, i.e) fewer tokens out. // This results in perp enrichment. if (feePerc > 0) { - r.tokenOutAmt = r.tokenOutAmt.mulDiv(FEE_ONE - feePerc.abs(), FEE_ONE); + r.tokenOutAmt = r.tokenOutAmt.mulDiv(ONE - feePerc.abs(), ONE); } // A negative fee percentage (or a reward) implies that perp pays the rotators by // accepting tranchesIn at a premium, i.e) more tokens out. // This results in perp debasement. else if (feePerc < 0) { - r.tokenOutAmt = r.tokenOutAmt.mulDiv(FEE_ONE + feePerc.abs(), FEE_ONE); + r.tokenOutAmt = r.tokenOutAmt.mulDiv(ONE + feePerc.abs(), ONE); } } @@ -887,17 +934,41 @@ contract PerpetualTranche is } /// @dev Enforces the total supply and per tranche mint cap. To be invoked AFTER the mint operation. - function _enforceMintCaps(ITranche trancheIn) private view { - // checks if supply minted using the given tranche is within the cap - if (mintedSupplyPerTranche[trancheIn] > maxMintAmtPerTranche) { - revert ExceededMaxMintPerTranche(); - } - - // checks if new total supply is within the max supply cap + function _enforceMintCaps(ITranche depositTranche) private view { + // Checks if new total supply is within the max supply cap uint256 newSupply = totalSupply(); if (newSupply > maxSupply) { revert ExceededMaxSupply(); } + + // Checks if the value of deposit tranche relative to the other tranches in the reserve + // is no higher than the defined limit. + // + // NOTE: We consider the tranches which are up for rollover and mature collateral (if any), + // to be part of the deposit tranche, as given enough time + // they will be eventually rolled over into the deposit tranche. + IERC20Upgradeable underlying_ = _reserveAt(0); + uint256 totalVal = underlying_.balanceOf(address(this)); + uint256 depositTrancheValue = totalVal; + uint8 reserveCount = uint8(_reserves.length()); + for (uint8 i = 1; i < reserveCount; ++i) { + ITranche tranche = ITranche(address(_reserveAt(i))); + uint256 trancheValue = _computeReserveTrancheValue( + tranche, + IBondController(tranche.bond()), + underlying_, + tranche.balanceOf(address(this)), + MathUpgradeable.Rounding.Up + ); + if (tranche == depositTranche || _isTimeForRollout(tranche)) { + depositTrancheValue += trancheValue; + } + totalVal += trancheValue; + } + uint256 depositTrancheValuePerc = depositTrancheValue.mulDiv(ONE, totalVal, MathUpgradeable.Rounding.Up); + if (depositTrancheValuePerc > maxDepositTrancheValuePerc) { + revert ExceededMaxMintPerTranche(); + } } /// @dev Fetches the reserve token by index. @@ -924,7 +995,7 @@ contract PerpetualTranche is parentBond, underlying_, tranche.balanceOf(address(this)), - true + MathUpgradeable.Rounding.Up ); } return totalVal; @@ -938,7 +1009,7 @@ contract PerpetualTranche is IBondController parentBond, IERC20Upgradeable collateralToken, uint256 trancheAmt, - bool roundUp + MathUpgradeable.Rounding rounding ) private view returns (uint256) { // NOTE: As an optimization here, we assume that the reserve tranche is immature and has the most senior claim. uint256 parentBondCollateralBalance = collateralToken.balanceOf(address(parentBond)); @@ -946,14 +1017,7 @@ contract PerpetualTranche is uint256 trancheClaim = MathUpgradeable.min(trancheSupply, parentBondCollateralBalance); // Tranche supply is zero (its parent bond has no deposits yet); // the tranche's CDR is assumed 1.0. - return - (trancheSupply > 0) - ? trancheClaim.mulDiv( - trancheAmt, - trancheSupply, - roundUp ? MathUpgradeable.Rounding.Up : MathUpgradeable.Rounding.Down - ) - : trancheAmt; + return (trancheSupply > 0) ? trancheClaim.mulDiv(trancheAmt, trancheSupply, rounding) : trancheAmt; } /// @dev Checks if the given token is the underlying collateral token. diff --git a/spot-contracts/contracts/RolloverVault.sol b/spot-contracts/contracts/RolloverVault.sol index d166993a..75970182 100644 --- a/spot-contracts/contracts/RolloverVault.sol +++ b/spot-contracts/contracts/RolloverVault.sol @@ -74,10 +74,6 @@ contract RolloverVault is //------------------------------------------------------------------------- // Constants - /// @dev Number of decimals for a multiplier of 1.0x (i.e. 100%) - uint8 public constant FEE_POLICY_DECIMALS = 8; - uint256 public constant FEE_ONE = (10 ** FEE_POLICY_DECIMALS); - /// @dev Internal percentages are fixed point numbers with {PERC_DECIMALS} places. uint8 public constant PERC_DECIMALS = 8; uint256 public constant ONE = (10 ** PERC_DECIMALS); // 1.0 or 100% @@ -207,7 +203,7 @@ contract RolloverVault is /// @notice Update the reference to the fee policy contract. /// @param feePolicy_ New strategy address. function updateFeePolicy(IFeePolicy feePolicy_) public onlyOwner { - if (feePolicy_.decimals() != FEE_POLICY_DECIMALS) { + if (feePolicy_.decimals() != PERC_DECIMALS) { revert UnexpectedDecimals(); } feePolicy = feePolicy_; @@ -521,7 +517,12 @@ contract RolloverVault is } //-------------------------------------------------------------------------- - // External & Public methods + // External & Public compute methods + + /// @inheritdoc IRolloverVault + function deviationRatio() external override nonReentrant returns (uint256) { + return feePolicy.computeDeviationRatio(_querySubscriptionState(perp)); + } /// @inheritdoc IRolloverVault function computeUnderlyingToPerpSwapAmt( @@ -545,10 +546,10 @@ contract RolloverVault is //----------------------------------------------------------------------------- // Calculate perp fee share to be paid by the vault - uint256 perpFeeAmtToBurn = perpAmtOut.mulDiv(perpFeePerc, FEE_ONE, MathUpgradeable.Rounding.Up); + uint256 perpFeeAmtToBurn = perpAmtOut.mulDiv(perpFeePerc, ONE, MathUpgradeable.Rounding.Up); // We deduct fees by transferring out fewer perp tokens - perpAmtOut = perpAmtOut.mulDiv(FEE_ONE - (perpFeePerc + vaultFeePerc), FEE_ONE); + perpAmtOut = perpAmtOut.mulDiv(ONE - (perpFeePerc + vaultFeePerc), ONE); return (perpAmtOut, perpFeeAmtToBurn, s); } @@ -579,10 +580,10 @@ contract RolloverVault is //----------------------------------------------------------------------------- // Calculate perp fee share to be paid by the vault - uint256 perpFeeAmtToBurn = perpAmtIn.mulDiv(perpFeePerc, FEE_ONE, MathUpgradeable.Rounding.Up); + uint256 perpFeeAmtToBurn = perpAmtIn.mulDiv(perpFeePerc, ONE, MathUpgradeable.Rounding.Up); // We deduct fees by transferring out fewer underlying tokens - underlyingAmtOut = underlyingAmtOut.mulDiv(FEE_ONE - (perpFeePerc + vaultFeePerc), FEE_ONE); + underlyingAmtOut = underlyingAmtOut.mulDiv(ONE - (perpFeePerc + vaultFeePerc), ONE); return (underlyingAmtOut, perpFeeAmtToBurn, s); } @@ -603,7 +604,7 @@ contract RolloverVault is : (underlyingAmtIn * INITIAL_RATE); // The mint fees are settled by simply minting fewer vault notes. - notes = notes.mulDiv(FEE_ONE - feePerc, FEE_ONE); + notes = notes.mulDiv(ONE - feePerc, ONE); return notes; } @@ -625,7 +626,7 @@ contract RolloverVault is token: underlying_, amount: underlying_.balanceOf(address(this)).mulDiv(noteAmtBurnt, noteSupply) }); - redemptions[0].amount = redemptions[0].amount.mulDiv(FEE_ONE - feePerc, FEE_ONE); + redemptions[0].amount = redemptions[0].amount.mulDiv(ONE - feePerc, ONE); for (uint8 i = 1; i < assetCount_; ++i) { // tranche token share to be redeemed @@ -636,7 +637,7 @@ contract RolloverVault is }); // deduct redemption fee - redemptions[i].amount = redemptions[i].amount.mulDiv(FEE_ONE - feePerc, FEE_ONE); + redemptions[i].amount = redemptions[i].amount.mulDiv(ONE - feePerc, ONE); // in case the redemption amount is just dust, we skip if (redemptions[i].amount < TRANCHE_DUST_AMT) { diff --git a/spot-contracts/contracts/_interfaces/IPerpetualTranche.sol b/spot-contracts/contracts/_interfaces/IPerpetualTranche.sol index 7d37a4e6..4b64fc01 100644 --- a/spot-contracts/contracts/_interfaces/IPerpetualTranche.sol +++ b/spot-contracts/contracts/_interfaces/IPerpetualTranche.sol @@ -138,4 +138,7 @@ interface IPerpetualTranche is IERC20Upgradeable { /// @notice Updates time dependent storage state. function updateState() external; + + /// @return The system's current deviation ratio. + function deviationRatio() external returns (uint256); } diff --git a/spot-contracts/contracts/_interfaces/IRolloverVault.sol b/spot-contracts/contracts/_interfaces/IRolloverVault.sol index dea92298..0b6c4742 100644 --- a/spot-contracts/contracts/_interfaces/IRolloverVault.sol +++ b/spot-contracts/contracts/_interfaces/IRolloverVault.sol @@ -32,4 +32,7 @@ interface IRolloverVault is IVault { function computePerpToUnderlyingSwapAmt( uint256 perpAmtIn ) external returns (uint256, uint256, SubscriptionParams memory); + + /// @return The system's current deviation ratio. + function deviationRatio() external returns (uint256); } diff --git a/spot-contracts/deployments/mainnet.json b/spot-contracts/deployments/mainnet.json index 3ddc46f4..03ee64ae 100644 --- a/spot-contracts/deployments/mainnet.json +++ b/spot-contracts/deployments/mainnet.json @@ -4,20 +4,20 @@ "ampl": "0xD46bA6D942050d489DBd938a2C909A5d5039A161", "bondFactory": "0x17550f48c61915A67F216a083ced89E04d91fD54", "bondIssuer": "0x5613Fc36A431c9c2746763B80C1DD89e03593871", - "spot": "0xC1f33e0cf7e40a67375007104B929E49a581bafE", + "perpetualTranche": "0xC1f33e0cf7e40a67375007104B929E49a581bafE", "rolloverVault": "0x82A91a0D599A45d8E9Af781D67f695d7C72869Bd", "proxyAdmin": "0x2978B4103985A6668CE345555b0febdE64Fb092F", "router": "0xCe2878d1f2901EFaF48cd456E586B470C145d1BC", "feePolicy": "0xE22977381506bF094CB3ed50CB8834E358F7ef6c", "previousIssuers": [ - "0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2", - "0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66", - "0x2E2E49eDCd5ce08677Bab6d791C863f1361B52F2", - "0x85d1BA777Eb3FCBb10C82cdf3aAa8231e21B6777" + [0, "0x9443b779d4AedF97d2B93D7CDa5fA0BB6312DfF2"], + [1, "0xD64FA63dc5E8fcB743457E47E4d522E11Ff1AD66"], + [2, "0x2E2E49eDCd5ce08677Bab6d791C863f1361B52F2"], + [3, "0x85d1BA777Eb3FCBb10C82cdf3aAa8231e21B6777"] ], "previousBondFactories": [ - "0x2b135C839d61808E1eC6F84151CD9429B0920374", - "0x72799FFD1F4CCF92eA2b1eE0CADa16a5461c4d96", - "0x71868D38Ea3b3eB5e4db9a45ee355548B46c82E0" + [0, "0x2b135C839d61808E1eC6F84151CD9429B0920374"], + [1, "0x72799FFD1F4CCF92eA2b1eE0CADa16a5461c4d96"], + [2, "0x71868D38Ea3b3eB5e4db9a45ee355548B46c82E0"] ] } diff --git a/spot-contracts/deployments/sepolia.json b/spot-contracts/deployments/sepolia.json index ddef753b..4f5f4d05 100644 --- a/spot-contracts/deployments/sepolia.json +++ b/spot-contracts/deployments/sepolia.json @@ -5,9 +5,10 @@ "bondFactory": "0x25BcaEd6377CEAA345f12C2005a42e669B8a29fC", "bondIssuer": "0x3838C8d4D092d40Cb27DD22Dafc6E1A81ea2DB60", "previousIssuers": [], + "previousBondFactories": [], "proxyAdmin": "0x0584042677d469C0B95775368cF1EFfe9cc222F5", "feePolicy": "0x2DdF288F26490D1147296cC0FA2B3c4da5E15f10", - "spot": "0xdcCef9065876fD654bAddeBAa778FDA43E0bfC1F", - "vault": "0x107614c6602A8e602952Da107B8fE62b5Ab13b04", + "perpetualTranche": "0xdcCef9065876fD654bAddeBAa778FDA43E0bfC1F", + "rolloverVault": "0x107614c6602A8e602952Da107B8fE62b5Ab13b04", "router": "0x5B59915E5754C62C40Ba5e7467382ced958F8559" } diff --git a/spot-contracts/exported-artifacts/PerpetualTrancheV1.json b/spot-contracts/exported-artifacts/PerpetualTrancheV1.json new file mode 100644 index 00000000..212588b6 --- /dev/null +++ b/spot-contracts/exported-artifacts/PerpetualTrancheV1.json @@ -0,0 +1,1699 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PerpetualTranche", + "sourceName": "contracts/PerpetualTranche.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "matureValuePerc", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "matureValueTargetPerc", + "type": "uint256" + } + ], + "name": "BelowMatureValueTargetPerc", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmtForCurrentTranche", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxMintAmtPerTranche", + "type": "uint256" + } + ], + "name": "ExceededMaxMintPerTranche", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentMaxSupply", + "type": "uint256" + } + ], + "name": "ExceededMaxSupply", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "perpSupply", + "type": "uint256" + } + ], + "name": "ExpectedSupplyReduction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "invalidCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingCollateral", + "type": "address" + } + ], + "name": "InvalidCollateral", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "InvalidPerc", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "decimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expectDecimals", + "type": "uint256" + } + ], + "name": "InvalidStrategyDecimals", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minTrancheMaturitySec", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTrancheMaturitySec", + "type": "uint256" + } + ], + "name": "InvalidTrancheMaturityBounds", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestedBurnAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "perpSupply", + "type": "uint256" + } + ], + "name": "UnacceptableBurnAmt", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "contract IBondController", + "name": "depositBond", + "type": "address" + } + ], + "name": "UnacceptableDepositTranche", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "perpAmtMint", + "type": "uint256" + } + ], + "name": "UnacceptableMintAmt", + "type": "error" + }, + { + "inputs": [], + "name": "UnacceptableReference", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "tokenOut", + "type": "address" + } + ], + "name": "UnacceptableRollover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "trancheOutAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rolloverAmt", + "type": "uint256" + } + ], + "name": "UnacceptableRolloverAmt", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "authorizedCaller", + "type": "address" + } + ], + "name": "UnauthorizedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "UnauthorizedTransferOut", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "discount", + "type": "uint256" + } + ], + "name": "DiscountApplied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "ReserveSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IBondIssuer", + "name": "issuer", + "type": "address" + } + ], + "name": "UpdatedBondIssuer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IBondController", + "name": "bond", + "type": "address" + } + ], + "name": "UpdatedDepositBond", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IDiscountStrategy", + "name": "strategy", + "type": "address" + } + ], + "name": "UpdatedDiscountStrategy", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IFeeStrategy", + "name": "strategy", + "type": "address" + } + ], + "name": "UpdatedFeeStrategy", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "prevKeeper", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newKeeper", + "type": "address" + } + ], + "name": "UpdatedKeeper", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "matureTrancheBalance", + "type": "uint256" + } + ], + "name": "UpdatedMatureTrancheBalance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "matureValueTargetPerc", + "type": "uint256" + } + ], + "name": "UpdatedMatureValueTargetPerc", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxMintAmtPerTranche", + "type": "uint256" + } + ], + "name": "UpdatedMintingLimits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IPricingStrategy", + "name": "strategy", + "type": "address" + } + ], + "name": "UpdatedPricingStrategy", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "min", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "UpdatedTolerableTrancheMaturity", + "type": "event" + }, + { + "inputs": [], + "name": "DISCOUNT_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HUNDRED_PERC", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERC_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRICE_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNIT_DISCOUNT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNIT_PERC", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNIT_PRICE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bondIssuer", + "outputs": [ + { + "internalType": "contract IBondIssuer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "collateral", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "computeDiscount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + } + ], + "name": "computeMintAmt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "computePrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "perpAmtBurnt", + "type": "uint256" + } + ], + "name": "computeRedemptionAmts", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable[]", + "name": "", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "trancheInAmtAvailable", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenOutAmtRequested", + "type": "uint256" + } + ], + "name": "computeRolloverAmt", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "perpRolloverAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenOutAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "trancheOutAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "remainingTrancheInAmt", + "type": "uint256" + } + ], + "internalType": "struct IPerpetualTranche.RolloverPreview", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "discountStrategy", + "outputs": [ + { + "internalType": "contract IDiscountStrategy", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeStrategy", + "outputs": [ + { + "internalType": "contract IFeeStrategy", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAvgPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getDepositBond", + "outputs": [ + { + "internalType": "contract IBondController", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getMatureTrancheBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "i", + "type": "uint256" + } + ], + "name": "getReserveAt", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getReserveCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getReserveTokensUpForRollover", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "tranche", + "type": "address" + } + ], + "name": "getReserveTrancheBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "inReserve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "collateral_", + "type": "address" + }, + { + "internalType": "contract IBondIssuer", + "name": "bondIssuer_", + "type": "address" + }, + { + "internalType": "contract IFeeStrategy", + "name": "feeStrategy_", + "type": "address" + }, + { + "internalType": "contract IPricingStrategy", + "name": "pricingStrategy_", + "type": "address" + }, + { + "internalType": "contract IDiscountStrategy", + "name": "discountStrategy_", + "type": "address" + } + ], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "tokenOut", + "type": "address" + } + ], + "name": "isAcceptableRollover", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "keeper", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "matureValueTargetPerc", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxMintAmtPerTranche", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxTrancheMaturitySec", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minTrancheMaturitySec", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "", + "type": "address" + } + ], + "name": "mintedSupplyPerTranche", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "perpERC20", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pricingStrategy", + "outputs": [ + { + "internalType": "contract IPricingStrategy", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolFeeCollector", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "perpAmtBurnt", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "trancheInAmtAvailable", + "type": "uint256" + } + ], + "name": "rollover", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IBondIssuer", + "name": "bondIssuer_", + "type": "address" + } + ], + "name": "updateBondIssuer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IDiscountStrategy", + "name": "discountStrategy_", + "type": "address" + } + ], + "name": "updateDiscountStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IFeeStrategy", + "name": "feeStrategy_", + "type": "address" + } + ], + "name": "updateFeeStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newKeeper", + "type": "address" + } + ], + "name": "updateKeeper", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "matureValueTargetPerc_", + "type": "uint256" + } + ], + "name": "updateMatureValueTargetPerc", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxSupply_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxMintAmtPerTranche_", + "type": "uint256" + } + ], + "name": "updateMintingLimits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPricingStrategy", + "name": "pricingStrategy_", + "type": "address" + } + ], + "name": "updatePricingStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minTrancheMaturitySec_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTrancheMaturitySec_", + "type": "uint256" + } + ], + "name": "updateTolerableTrancheMaturity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60806040523480156200001157600080fd5b5061f8aa80620000226000396000f3fe608060405234801561001057600080fd5b50600436106104125760003560e01c8063850a150111610220578063beed49b811610130578063ddebf795116100b8578063ef98f88411610087578063ef98f88414610c67578063f01e66ec14610c98578063f1a640f814610cb6578063f20b4fdf14610cd4578063f2fde38b14610cf257610412565b8063ddebf79514610bdf578063e8821b8914610c0f578063eca05e9614610c2b578063ee95e04814610c4957610412565b8063cd3293de116100ff578063cd3293de14610b39578063d5abeb0114610b57578063d8dfeb4514610b75578063db006a7514610b93578063dd62ed3e14610baf57610412565b8063beed49b814610ab3578063c34b96fc14610ad1578063c5706b2014610b01578063c876a2a714610b1d57610412565b806397790217116101b3578063a9059cbb11610182578063a9059cbb14610a0d578063aced166114610a3d578063adf84ca314610a5b578063afa40bbd14610a79578063b4abecc714610a9757610412565b8063977902171461098757806399806546146109a35780639db5dbe4146109c1578063a457c2d7146109dd57610412565b806392a18b44116101ef57806392a18b4414610913578063949b22ae1461092f57806395a074951461094d57806395d89b411461096957610412565b8063850a15011461089b578063876853aa146108b95780638da5cb5b146108d75780638fb69c4b146108f557610412565b806347e7ef2411610326578063715018a6116102ae57806379cc67901161027d57806379cc67901461081b5780637cb6eb6b146108375780637daa0050146108555780638456cb5914610873578063846e7e9f1461087d57610412565b8063715018a6146107b7578063729256eb146107c157806375d5179f146107df57806378b99c24146107fd57610412565b80635ec57251116102f55780635ec57251146106eb57806361902ffc14610709578063647846a514610739578063679556e81461075757806370a082311461078757610412565b806347e7ef241461066557806357c3ee83146106815780635c975abb1461069d5780635dcc45b7146106bb57610412565b80632cff15ce116103a9578063364d22fc11610378578063364d22fc146105c157806336852f4f146105df578063395093511461060f5780633f4ba83a1461063f57806342966c681461064957610412565b80632cff15ce146105395780632e5d55e114610555578063311705aa14610585578063313ce567146105a357610412565b806318160ddd116103e557806318160ddd146104c55780631d8557d7146104e357806323b872dd146104ed5780632bf8f1a51461051d57610412565b806306fdde0314610417578063095ea7b314610435578063107c041814610465578063151b499c14610495575b600080fd5b61041f610d0e565b60405161042c919061d533565b60405180910390f35b61044f600480360381019061044a919061d5fd565b610da0565b60405161045c919061d658565b60405180910390f35b61047f600480360381019061047a919061d673565b610dc3565b60405161048c919061d6ff565b60405180910390f35b6104af60048036038101906104aa919061d796565b610f11565b6040516104bc919061d874565b60405180910390f35b6104cd61106b565b6040516104da919061d89e565b60405180910390f35b6104eb611075565b005b6105076004803603810190610502919061d8b9565b611b5e565b604051610514919061d658565b60405180910390f35b6105376004803603810190610532919061d90c565b611b8d565b005b610553600480360381019061054e919061d95f565b612404565b005b61056f600480360381019061056a919061d99f565b6126b0565b60405161057c919061d89e565b60405180910390f35b61058d6126c9565b60405161059a919061d89e565b60405180910390f35b6105ab6126da565b6040516105b8919061d9e8565b60405180910390f35b6105c9612776565b6040516105d6919061dac1565b60405180910390f35b6105f960048036038101906105f4919061dae3565b612e4d565b604051610606919061d89e565b60405180910390f35b6106296004803603810190610624919061d5fd565b613024565b604051610636919061d658565b60405180910390f35b61064761305b565b005b610663600480360381019061065e919061d673565b6132e3565b005b61067f600480360381019061067a919061db10565b6132f7565b005b61069b6004803603810190610696919061db8e565b613c6f565b005b6106a5614117565b6040516106b2919061d658565b60405180910390f35b6106d560048036038101906106d0919061dae3565b61412e565b6040516106e2919061d658565b60405180910390f35b6106f361427c565b604051610700919061d89e565b60405180910390f35b610723600480360381019061071e919061db10565b614283565b604051610730919061d89e565b60405180910390f35b6107416143d3565b60405161074e919061d6ff565b60405180910390f35b610771600480360381019061076c919061dbbb565b6144f0565b60405161077e919061d658565b60405180910390f35b6107a1600480360381019061079c919061dbfb565b614640565b6040516107ae919061d89e565b60405180910390f35b6107bf614689565b005b6107c961469d565b6040516107d6919061dc49565b60405180910390f35b6107e76146c4565b6040516107f4919061d9e8565b60405180910390f35b6108056146c9565b604051610812919061dc85565b60405180910390f35b6108356004803603810190610830919061d5fd565b6146f0565b005b61083f614710565b60405161084c919061d89e565b60405180910390f35b61085d614857565b60405161086a919061dcc1565b60405180910390f35b61087b61487e565b005b610885614b06565b604051610892919061d89e565b60405180910390f35b6108a3614b23565b6040516108b0919061dceb565b60405180910390f35b6108c1614bb6565b6040516108ce919061d89e565b60405180910390f35b6108df614bbd565b6040516108ec919061dceb565b60405180910390f35b6108fd614be7565b60405161090a919061dd27565b60405180910390f35b61092d6004803603810190610928919061dd80565b614d4e565b005b61093761522c565b604051610944919061ddce565b60405180910390f35b6109676004803603810190610962919061de27565b615253565b005b6109716156fb565b60405161097e919061d533565b60405180910390f35b6109a1600480360381019061099c919061dbfb565b61578d565b005b6109ab615ab2565b6040516109b8919061d89e565b60405180910390f35b6109db60048036038101906109d6919061de54565b615bfd565b005b6109f760048036038101906109f2919061d5fd565b615ed5565b604051610a04919061d658565b60405180910390f35b610a276004803603810190610a22919061d5fd565b615f4c565b604051610a34919061d658565b60405180910390f35b610a45615f6f565b604051610a52919061dceb565b60405180910390f35b610a63615f96565b604051610a70919061d89e565b60405180910390f35b610a81615f9d565b604051610a8e919061d89e565b60405180910390f35b610ab16004803603810190610aac919061d95f565b615fae565b005b610abb616137565b604051610ac8919061d89e565b60405180910390f35b610aeb6004803603810190610ae6919061dae3565b616148565b604051610af8919061d89e565b60405180910390f35b610b1b6004803603810190610b16919061e01a565b6163cc565b005b610b376004803603810190610b32919061e0f4565b616b03565b005b610b41616da5565b604051610b4e919061dceb565b60405180910390f35b610b5f616e31565b604051610b6c919061d89e565b60405180910390f35b610b7d616e38565b604051610b8a919061d6ff565b60405180910390f35b610bad6004803603810190610ba8919061d673565b616ecd565b005b610bc96004803603810190610bc4919061e121565b61769e565b604051610bd6919061d89e565b60405180910390f35b610bf96004803603810190610bf4919061dae3565b617725565b604051610c06919061d89e565b60405180910390f35b610c296004803603810190610c24919061d673565b61790e565b005b610c33617b71565b604051610c40919061d89e565b60405180910390f35b610c51617b78565b604051610c5e919061d6ff565b60405180910390f35b610c816004803603810190610c7c919061d673565b617c04565b604051610c8f92919061e210565b60405180910390f35b610ca0617d55565b604051610cad919061d89e565b60405180910390f35b610cbe617f20565b604051610ccb919061d9e8565b60405180910390f35b610cdc617f25565b604051610ce9919061d9e8565b60405180910390f35b610d0c6004803603810190610d07919061dbfb565b617f2a565b005b606060368054610d1d9061e276565b80601f0160208091040260200160405190810160405280929190818152602001828054610d499061e276565b8015610d965780601f10610d6b57610100808354040283529160200191610d96565b820191906000526020600020905b815481529060010190602001808311610d7957829003601f168201915b5050505050905090565b600080610dab617fad565b9050610db8818585617fb5565b600191505092915050565b6000610df17f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b610e1d7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b610e497f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b610e51611075565b610e7d7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b610ea97f05152c8e9de07acd46b31fc73fe403ba35b8914ba5173fbb9dc2978d543cc8ae60001b61817e565b610ed57fa79894200a7b639a6a55fb2b9f046a1dd296afde640c8cde5e4bd1cad214f08f60001b61817e565b610f017f61b1bf511a3a2792b48a4fe1e5ee75d4dc2d5456d7f42a4c9adca89d7f3e80a860001b61817e565b610f0a82618181565b9050919050565b610f1961d474565b610f457f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b610f717fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b610f9d7f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b610fa5611075565b610fd17f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b610ffd7fd1beafed999679274ff3b75856b494cd1df921d78f4df9a8b91976f69bb92e6760001b61817e565b6110297f48e8ec20aa70feef399a559d1762c3530611cee44c31808aa067b15cee081a5660001b61817e565b6110557f755c2763ca4bf9d42a46db3c9f01fd52ec1c6a511a92ff294839ff1a5caf03cc60001b61817e565b61106185858585618223565b9050949350505050565b6000603554905090565b6110a17fbe971f136eca38d79383c8a21f3e6818e5d03fe4a4a1c417bee4667c881ef35260001b61817e565b6110cd7fc44856c05594420e74d5e03916909f82d9ecf907900d3dd1ba98e9b12055a96260001b61817e565b6110f97f3779ae423c8b6554aa8dea7be3fc01d4923ef9fbd86e81e7829868dbe2775d4560001b61817e565b600061013160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d5eb27a16040518163ffffffff1660e01b81526004016020604051808303816000875af115801561116b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118f919061e2e5565b90506111bd7fbc8669b813247b48a64854f00bbe9709cd252834ec0484887e5e3d62b95084b260001b61817e565b6111e97fc70a89aa2f909e25431a4787db4d0a334dd5559631ac38dbc634bc4936b91a3c60001b61817e565b8073ffffffffffffffffffffffffffffffffffffffff1661013260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415801561124d575061124c81618db6565b5b156113ac5761127e7f41fe4f85e70e841952c036cd431b23cacbb1ec00af34ab8eab8ac855ce9ee25260001b61817e565b6112aa7fba55735fa52c5726585ccde4c5f8933b3412f2ffa71d6d61c746185907db69a660001b61817e565b6112d67fce3f91541dd4a6c5af8fe71670f8b25a684bd7ed53b1bb43634f11304a9b744660001b61817e565b8061013260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506113447f70894150fe69156bba557d7ccc95b0d10c387e67114a67f7977536415067286060001b61817e565b6113707f7dbc88702f5b80cc570ad13b5c1806156dae7540697dd4c00894a013446614d360001b61817e565b7f63e01b6b930f6bd3789aab43a62005627cb8a43517cd0569f997fd6b343b80238160405161139f919061dd27565b60405180910390a16113d9565b6113d87f1089d9c00752b2cabbd4532663303a9800eb122ae33669d6837212e1f2ed9a2e60001b61817e565b5b6114057f4a7b1f132e5df5cb3e9794e1f398564f406853c51f7f2962c942648b49ab286a60001b61817e565b6114317f7c12376140aa37197956e326bce38e7542eaeee5c486847dab645a60a826db7b60001b61817e565b600061143b618f82565b90506114697f2cbf64c9deff76adaee1fca44e44c6873b721627363b6b63150011c40fae8f1060001b61817e565b6114957f4d79bb21290ec3eeb1fdc254baf3d961e0eb681d0a62dcfad37dd388622699c360001b61817e565b60006001826114a4919061e341565b90505b6000811115611aee576114dc7f17280846d8d52c6d88fdcd2314f908709b2ae3979e5e19f45bfab676ad76249660001b61817e565b6115087f6fc9e01fe69f70994e4aa683aa2fbd1e14e8c3e4e2064f3ca0080edc5b08331560001b61817e565b600061151382618181565b90506115417fd975004bc9af5fbe029ab32d3625349599d45b9dba39e2502c3566bd1135dde760001b61817e565b61156d7fabf53a256c3b0ef70d85c1b33fab72a1f27471d32eab51b512ebd0c7cd45376060001b61817e565b60008173ffffffffffffffffffffffffffffffffffffffff166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115de919061e38a565b905061160c7f15194ca9f89f979958e99eb466e82279da7fcbb4efad96b62aafa4d4a3fa940f60001b61817e565b6116387f90eea24149eeae04a7afb6110e7bc4e6c36c2546953f4ba9b4b6fb34b714a82a60001b61817e565b60006116598273ffffffffffffffffffffffffffffffffffffffff16619018565b11156116be5761168b7f33891fd60c32d87ac44e24b2a4bcf97cf1b98a557ba95dfa0d83179d377b55cd60001b61817e565b6116b77f9d2c7f14896d711439656e1438221a2e76b5e2a92f042621c79074d87a87bb0360001b61817e565b5050611adb565b6116ea7f4243f88579f2bcb16b6d0d4ea128dc6d7ece250c3b59199fcd8de99512b5ec4460001b61817e565b6117167f2c40423fc9ab5175df0f30738346c339aace298ca5127e8ea788b4a8ca08049460001b61817e565b6117427f0d599ddb8eeeab15045eb7eb6ccf49bb4741065a2f55c343635756f0bca9f44a60001b61817e565b8073ffffffffffffffffffffffffffffffffffffffff1663ae4e7fdf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561178d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b1919061e3e3565b61189e576117e17fb4f53a8f3d08cda2c6b5bf86bd62724635684a54a338f6a543f972b4951f1f3f60001b61817e565b61180d7f630509c1c193f41e414cdf0024b48d202734d2dfe440b35f599f673ac37723b960001b61817e565b6118397f222b432495a4cc5bbc6bdded0b5a460c78dbae9fe48c5b6a457de696964a745960001b61817e565b8073ffffffffffffffffffffffffffffffffffffffff166387b652076040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561188157600080fd5b505af1158015611895573d6000803e3d6000fd5b505050506118cb565b6118ca7f99102f5253a56bcdc8962760ce83246bbc01438476842eb601ddd941d48c7a9260001b61817e565b5b6118f77f20b9fa97e04c86f7f9ccb0598acd9be250c7b8bb64114edebd975d964299020160001b61817e565b6119237f7d94097dd501a602d472abe9a9ec9f515e13b496adda69b78495e76b51bf4b0560001b61817e565b600061192e8361918c565b905061195c7fcaef6532b5d983273e038d9d15a3627a16fa50268a34aa4f27341c8dbfc1b21260001b61817e565b6119887f04de80ed6e0bd41956a07422627fc6bfad908985e099df7b3ffa19a827e0840760001b61817e565b8173ffffffffffffffffffffffffffffffffffffffff166333d20e3484836040518363ffffffff1660e01b81526004016119c392919061e410565b600060405180830381600087803b1580156119dd57600080fd5b505af11580156119f1573d6000803e3d6000fd5b50505050611a217f4c3f13c54ac0ad494dc7a5482df89bc0cbb51f0497980ba5796a40b4843417d260001b61817e565b611a4d7fcfebbef3f9a7e39aa7af2b884f3f08ff4505367195a3e630e03fe44969cc9d7b60001b61817e565b611a568361929a565b50611a837f9d64b93fddfdc6c99bfbfbc3a2364cf0429b9eed37afad0a114b916b2857219860001b61817e565b611aaf7f5cb624a68c63aaa064689304dd76e75b3a650f5c148f28c19de26164cfd18bd160001b61817e565b611ad7611ac482611abf86612e4d565b61994e565b61013c54611ad2919061e439565b619a00565b5050505b8080611ae69061e46d565b9150506114a7565b50611b1b7f26a58e80bbff6dc10c443831bed01573e0259ebde61e613868cf169a023ba38160001b61817e565b611b477f0c515450c06a0937f2ef637c0009eb8825392c2054220f6eeab6539ee3cc0f8760001b61817e565b611b59611b546000618181565b61929a565b505050565b600080611b69617fad565b9050611b76858285619b1e565b611b81858585619baa565b60019150509392505050565b600260fb5403611bd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc99061e4e2565b60405180910390fd5b600260fb81905550611be2619e2c565b611c0e7f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b611c3a7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b611c667f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b611c6e611075565b611c9a7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b611cc67f18d19f877d7d519c7ef65e1a1d2f6ed034f1bd48b1c6d6aa66aae75521ce2cd660001b61817e565b611cf27fdb59fe5adc43a98e001314ca5e0a4d8cae10bfeb901d38182002acf0f9ceb53b60001b61817e565b611d1e7f267b7e88f868650640484f59316a84466508382c047a36ab4aeb7502c7cde83560001b61817e565b611d288383619e76565b611dc357611d587fd073da7260828e1ba80a40b3daa21aecbf35f54e588654dbd27f7ed7ccb72dc260001b61817e565b611d847f182eaf0688cd47c932d57b570bd628a9e3805feac4965bc621924f4fbcc0123b60001b61817e565b82826040517f3f4316bd000000000000000000000000000000000000000000000000000000008152600401611dba92919061e523565b60405180910390fd5b611def7fb6767f143bfd1ec7de6c6bb1ba3e477e5f6d30df47f2fe25c366f89a821da99960001b61817e565b611e1b7fb66af0810c9853e0fc48b8e80c948beccb984337c63604c1f42b70b47231769360001b61817e565b611e477f1ba721d16499424ae25c7e521601df32bee7d2b8adf21e9dc098fa697ab9cf6c60001b61817e565b6000611e758484847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618223565b9050611ea37f77dd970ee68b7b6853f6baaf564b6b2aa09a87aed50702ad055c7852d8c8c35760001b61817e565b611ecf7fdfab4295f48e3dbdefe66dab5fd69faf385908a27209a3ceb1fb7f97d07dadbc60001b61817e565b600081606001511480611ee6575060008160200151145b80611ef5575060008160000151145b15611f9f57611f267f3c3c5a506df63881d9c194ed8b26f4c573d4df926a61a6c77bd665e281aaf18d60001b61817e565b611f527f56ebcf545abea369cd2c970c5a6b3ddee7c52358e5b87ab6ac0c0328b976bb1b60001b61817e565b8060600151816020015182600001516040517f1c44ac5b000000000000000000000000000000000000000000000000000000008152600401611f969392919061e54c565b60405180910390fd5b611fcb7fb2fb5e4b760ae823f11801d83ed358861f8483a96d9318b85de6c63db9a5c45860001b61817e565b611ff77f58a8c2a8cb3cd9ff1a06f01a132206091e5aabb7f0eb7b98c2e27b63e557879d60001b61817e565b6120237f9e25b642a176cb0676c8e9e088fa509be1ce83f6787bfa9f0887525db11d95a960001b61817e565b60008061012e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c212ded484600001516040518263ffffffff1660e01b8152600401612086919061d89e565b6040805180830381865afa1580156120a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c6919061e5ce565b915091506120f67fac6e02ce452a8bdbba21ec3de51d811e3389b9caa27f8d506ad7ba5802c1e1ce60001b61817e565b6121227f6364a4fff4fe879705e703fa466bfb556b01614d0ed719005a4c44a0ea58a66860001b61817e565b6121313387856060015161a33b565b5061215e7f40a72df5e5a62dd2280765fb8a647cd206f2b4b03d0c8b33768e43842255cb2660001b61817e565b61218a7fe66adad8d4a6aa47d74a7c2c9a38330edb938b430669b427fbafa997f15a3e5960001b61817e565b61219533838361a45f565b6121c17f5702af68b90c771f3cf965d4148e2dc20f3ef1de580d3a22dbd379df898ceb3f60001b61817e565b6121ed7f7d724e1c8987285473c688435109ee055fca5c5215d414b75a7e752213f2651260001b61817e565b6121f68561a83d565b1561229f576122277fc0cdb0874f983b49e27376562cfdc1bbc5dc6ce9d5c7a4b38db701b4352562d160001b61817e565b6122537f4c5b0dab83ca31fb1badf242a8183b6a455b66f8dc57a513d9bc71876f14c0fc60001b61817e565b61227f7f0406b4da42b8d84e9505065263cc6398eae95d8a79e9635a431cfbd785f9fe3e60001b61817e565b61229a836040015161013c54612295919061e341565b619a00565b6122cc565b6122cb7f93948cdf6d98fbf4e66ce502af08e6ce075f0aed3502ea52854b5db36697949660001b61817e565b5b6122f87f2074c777071aed0f22a20c901552b73d7281bd6ae626702702ffffc470ab778360001b61817e565b6123247f2cee4cb04b53746cf80d9b13ba5b2b8697331ac66d80134165e3026ae4e9c55a60001b61817e565b6123333386856020015161a902565b506123607fe182f8cc6655119317553855eb102904d65f73ebfc9b1d24a707453755f022fc60001b61817e565b61238c7fa02858af716cd958ed02a10e8b0c114deb5951630744edb9acb7e18a77e739ef60001b61817e565b61239461aa1d565b6123c07f23279c07a84c0a40e9670804a1076b915101514a82d2e7f1ee58ba533637d08060001b61817e565b6123ec7fc587290490da7439cc82f4afd7eb204c28f66d2e1b536cf972be343900ea732b60001b61817e565b6123f461ac85565b505050600160fb81905550505050565b61240c61ae41565b6124387fbc530f0fe2c2324bbbc409ee5d4f96af34bf189f39a748a260dc603c427c436a60001b61817e565b6124647f28c72fcf41a25690e52daeec9668e2305e17a76790b24766035199820e9f82ed60001b61817e565b6124907fb2558e7a252c090244939ec7d8287747ad4a59e7f67c6118d62e6b4cf90a485060001b61817e565b8082111561252f576124c47f7d42e9d63f90bc1494eed37d69e4bb34c7cf9fdc3c875676b053110a3549e49560001b61817e565b6124f07f303cacb664359ea37ce26e233144e6195cf881e70c8639c35eccec561d31878a60001b61817e565b81816040517f4e1deae400000000000000000000000000000000000000000000000000000000815260040161252692919061e60e565b60405180910390fd5b61255b7faf200d1935169726d4e3017b04dad3bfd42bbbc048b7907e9d069118b6a713bb60001b61817e565b6125877fd96bfbc278ab29ced855027d2fbca2a1121a7e71687eb197de48d1afa6cd493b60001b61817e565b6125b37fb35c4356aa1c2ccd4bba2070619c5ad55f67b3eb3893cd4bb7f82e684b8bdc3260001b61817e565b81610133819055506125e77f24c7fd657900fdc2129f73c3590c919b039f4a18b0da3c7f39c498ddfc1fe0e660001b61817e565b6126137fe98957c320f10c6e62795105e99cdbed4d495b60ac8911d1eb9b1d4dbbfae8a560001b61817e565b80610134819055506126477fba35e8dba51344975bf53df0cfe8a6cc97e3a7da4057438373161ef3f911831860001b61817e565b6126737fc54342af06fef892a4a132f2ae3de9aaccce09133df3d1b16df295c04dd30d1060001b61817e565b7fa40bc974b2b7304c66b9d01fc43100ec5b6171732d074da0bda432a2f33530ea82826040516126a492919061e60e565b60405180910390a15050565b6101386020528060005260406000206000915090505481565b6006600a6126d7919061e76a565b81565b60006127087f51a4f32684dd7ebaff422024acf478115290ff79a3a325a887ad192f4a6bf79660001b61817e565b6127347f90343db7ab7d16eb48710471fe77472743d53f6c7ff7418714f451a7c666b6e360001b61817e565b6127607fe5e6c074134ab6a1d8b3a211ec97366728c8db256f61cd4aafb2b0f2c496371560001b61817e565b61012d60009054906101000a900460ff16905090565b60606127a47f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b6127d07fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b6127fc7f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b612804611075565b6128307f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b61285c7f092223749b24d0ae4dc94cabd418968917f03a12fedaaa55fc9576fbbfddacce60001b61817e565b6128887f5e62a24f8fc2ecfbe42c4071284edfeb31af697bf46db7e5958fb111e30b657f60001b61817e565b6128b47f26d49ec6f02d5b3a3230e76aa9cb7b791c7c6f93d4557d1db6cbc72f4123f46b60001b61817e565b60006128be618f82565b90506128ec7f65f20508451acc0dc8d48226f20b9527b7e604541582d5b4bee776aeefad1eee60001b61817e565b6129187fb1867f8fa317b7b053c6ba31799a35483a8ea27b9adfa0ee94465f3013fcc63b60001b61817e565b60008167ffffffffffffffff8111156129345761293361deb1565b5b6040519080825280602002602001820160405280156129625781602001602082028036833780820191505090505b5090506129917ffc9f7f0a23905ae4995aeb9d4c16d105975cd6b3e91a5cbabb62a6548cd29a1360001b61817e565b6129bd7fd3d7f8ccc8feb24a230853e8ca677716ee38150ff8a1ca036ada58f17067724d60001b61817e565b600061013c541115612aaa576129f57f8dfd20b12130afc206823e3fea7ccdacbc2730f31b42235f5b1479dc4a28dc8360001b61817e565b612a217f573e1a1d1845e5ee08e98928dcdb44b1a4142441f6455dcd96f979bda124178360001b61817e565b612a4d7fa671992a56bbefef0363ebdeb491d348f92884c1f458bc514a251203b805288060001b61817e565b612a576000618181565b81600081518110612a6b57612a6a61e7b5565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050612ad7565b612ad67f3acf819921bd33d64b3cf499135599ce50bc15dec15227262bbb9c8c75c78c8d60001b61817e565b5b612b037fb7365bcf82c7313ed6794862db5bc70999544ca510516a7fe1761baa885ced6160001b61817e565b612b2f7fa3c3ef6db28f1a4edb70e42cf211f417f8acdb95fbec00fd784fbca7065384a260001b61817e565b6000600190505b82811015612dec57612b6a7fa1fbe0137f670d2c2f2d0f271839fd1037a1f116af936e45d78e974769e0e0c660001b61817e565b612b967f73a96998af86407f83215adf4a5eaae836497dec6b3d675863df0214f81fa6a760001b61817e565b6000612ba182618181565b9050612bcf7fd29e5cab001d2813566f6f831686c896b6d808ba915fd3e3523ccb0bf2916f4360001b61817e565b612bfb7fc82ddb491a5bc34b2a0c55a8f6827c78ae2129022e5391f31399be1d37c91e0b60001b61817e565b60008173ffffffffffffffffffffffffffffffffffffffff166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6c919061e38a565b9050612c9a7ff728048bda3d61859d283a08a315c3458521a65fb97b633552bc4ce8310b672860001b61817e565b612cc67f530be2ab01942dc74d509fe5e4d6ed899241bb85a8f929cd351bfd2733d077b860001b61817e565b612ccf81618db6565b612daa57612cff7f8d2dd2ea261902d13d8505480dcf6be6fc99fd576a11899f96e55e58827833c160001b61817e565b612d2b7f6fda49310517fc588bc8a27ce956de790e4543ad6f7ed1c98a4cfc6afc6a676060001b61817e565b612d577ff17a7fa21784d1de098367b86aabfff09f8672326fc9ede2a6ed268236757cc160001b61817e565b81848481518110612d6b57612d6a61e7b5565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050612dd7565b612dd67f0950ff4fbe5479819990f106321c598e6a8025128db27bb5f236e8ce220705d060001b61817e565b5b50508080612de49061e7e4565b915050612b36565b50612e197fcf9ac3dc4a3f811d1fdce964202a110b59e52de0806ad8b6afa48f53eb78ea5a60001b61817e565b612e457f38ad1e4e7f995a451da45aa1ccf3d96f07a347d294a68103423de984916ede3960001b61817e565b809250505090565b6000612e7b7f81af453d683887c7bba9bdc71c4d5bbf2c4ac9ff22494c700e8817af28a601b360001b61817e565b612ea77f9d1c67e4b85376071647eb5fd50e674ebd797c8eb09e6fdcf3ed4fa7fdb62c1460001b61817e565b612ed37fa86bb394e35f2fc57802d2225b17f22e8c955a20fe8701ba7005c0c552e4134260001b61817e565b600061013960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050612f447f0f823ef9ca619d21b13c899339430da2729fbd371cde565fe99932e4f1c92e3860001b61817e565b612f707f468556883ba4274d3bc3638aac909bb3b46f2eb68185e73667258f6c29f3e6cb60001b61817e565b6000811161301a5761013060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166317d9b034846040518263ffffffff1660e01b8152600401612fd4919061d6ff565b602060405180830381865afa158015612ff1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613015919061e82c565b61301c565b805b915050919050565b60008061302f617fad565b9050613050818585613041858961769e565b61304b919061e439565b617fb5565b600191505092915050565b6130877f1e14cdc4c7716496573268ca5b4ef259b5f7c8b8bda8b8a7a8efcf9ba073cf2f60001b61817e565b6130b37fd6a407369739847083101930563077e546ee9f7c872018eb2513aa09d0f19c5960001b61817e565b6130df7f20f61c7a67db2e1c2faa39453e55cde7c06d872a74c6e45e6df213ccef9978e960001b61817e565b6130e7617fad565b73ffffffffffffffffffffffffffffffffffffffff1661012d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146131fd576131687fded2da8dd4c4b6def231b4bd1c098e35b6234df8bc1e48bcb85d877fec8f95b360001b61817e565b6131947fe5d4d315da5a7959bc022df06ff0738f8577d7c9c36514b504f95aa7df0c679760001b61817e565b61319c617fad565b61012d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f91658dbc0000000000000000000000000000000000000000000000000000000081526004016131f492919061e859565b60405180910390fd5b6132297f4c65e525359bea4c3e996ced72e74fe235c3c863b4878c9b5020db342d8778c360001b61817e565b6132557f8f37792c7a5e33878ef23dbbab5969721379d8c07f358f52bd0f4f2f6ae074dc60001b61817e565b6132817f2acd680e8b26b33f98b2542c2ab97f877fbf325f9e9d3a750b0d047f847ec92260001b61817e565b6132ad7f0e8c86bf8233c044b9f6f8a0224f9b91cbb5b8e27a77af7656a6569597272c9a60001b61817e565b6132d97fc8c0cd3dacb2fdc0b7f7adaba8ca2f4bffde9033f7faa211f4ddd22416d93b7360001b61817e565b6132e161aebf565b565b6132f46132ee617fad565b8261af22565b50565b600260fb540361333c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133339061e4e2565b60405180910390fd5b600260fb8190555061334c619e2c565b6133787f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b6133a47fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b6133d07f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b6133d8611075565b6134047f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b6134307fe6a9b3c7d774e5f6c5b3b47fee2c576a6c7c15ef42a9b227ce9dd3c80c1c490a60001b61817e565b61345c7fdec2b5d7da0d7cf60d233547cfc5d6d35d72bfc432083c5349dec020156911f060001b61817e565b6134887feef248673933b54f36da9a959c7b444a5db9d57d909eaaa4c2b662d212657c4760001b61817e565b60008273ffffffffffffffffffffffffffffffffffffffff166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f9919061e38a565b90506135277fd370433679a7c89fa4e236f4bd69e3c95865e671acaa1afbf0a04aadcc59787c60001b61817e565b6135537f7050cf46e9849d84931263ed6f78b16f9316cd8bd1c802ac7097a9fcd2ef0abe60001b61817e565b61013260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166320e8e89e846040518263ffffffff1660e01b81526004016135af919061e882565b602060405180830381865afa1580156135cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f0919061e3e3565b158061364b575061013260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b1561370a5761367c7fc0c033cd43d0f8e179c2e00883077b8e844fd55d120792b3b1febe159ddbd05660001b61817e565b6136a87f58054db75e64856389e1699e08ecde8e52d63943487983f24e413dd98aa6228460001b61817e565b8261013260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517ff81af68300000000000000000000000000000000000000000000000000000000815260040161370192919061e89d565b60405180910390fd5b6137367fa33df73b788494570475026d51293af49df7a943e33ee5a752f9f073b6cbc2dc60001b61817e565b6137627f55d3b2362badb9de42307d482efb3ccdcd3c179498632c30c34b8a4892add67360001b61817e565b61378e7f6f663fe8db1321d32b6524662c786b1220870e5e46284cd175f79cd2ebab100a60001b61817e565b600061379a848461b0fa565b90506137c87fec93ec419766bf91597875d8125e72b9d3a9b3e4bdf4f9871b6aaf6325ebc61a60001b61817e565b6137f47fac5591029fddf2d94cce41a1d6789c105abb86a1820fad8612c9ea04146bb31b60001b61817e565b60008314806138035750600081145b1561389f576138347f83a413f93d41fa5aa4eeb78226e727d0f525c4115047a9ce5be83af3e6bfc1be60001b61817e565b6138607f32adec0f07ded8adbf1dc555ab7f7f9f7c33f45e7641b38e09e4aa644e312a8660001b61817e565b82816040517fedffabb900000000000000000000000000000000000000000000000000000000815260040161389692919061e60e565b60405180910390fd5b6138cb7f47b98058cb153db972936761e6dfafd7110ca70c8673eb985b640a7e6ff939bb60001b61817e565b6138f77f8613d1743ff6994979573d284d100160d5977716b1576e68c859109cd83e878a60001b61817e565b6139237f886b23e5c6ae15059a7b6dbda63a54ce4e82b186318a4120884be681977faa5660001b61817e565b60008061012e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ccbbe510846040518263ffffffff1660e01b8152600401613982919061d89e565b6040805180830381865afa15801561399e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139c2919061e5ce565b915091506139f27f30b4c9159611bcd28f371a01aeb0a37b7bd68952cf212ce95689e4485b282b0a60001b61817e565b613a1e7f85c8546da4f1c341c836d89c3bf1ec287f0ea707b476cdfffc72e4bb97ea27cf60001b61817e565b613a2933878761a33b565b50613a567fab41acbe624a99d45bdedfd42dca5adf1cd8b8a97abc62d2f8d5bd7c75ea2c1a60001b61817e565b613a827f95105a0e641cb1d4f3ca7f14cc4a8ffbeba26da5d346ad9594257e49b072568960001b61817e565b613a8c338461b37a565b613ab87fc38827fd676ac372379552b0d7f094fff92f46dcf2bb4550b90f474f23a101b960001b61817e565b613ae47f67de296518fc6cd37fc736bad5f8097768c9fbda4f1911e9a92e9610aab9d8e660001b61817e565b613aef33838361a45f565b613b1b7f829092bc92f031a7158302ea43db43c2c92d0b3cf914461ded3ed12a9e551a4f60001b61817e565b613b477fd583c82eb47b49d90444d01967cbc88e55ea7423f2629d2d6f994a0445e5b5d360001b61817e565b8261013860008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613b97919061e439565b92505081905550613bca7f7636b58eddcdd3090ed6ccc9b5b471e0f8c034c7e8dc0754c3b1b397bec73fb860001b61817e565b613bf67f534b89c2c242c4a6301b73be149316ff98038717a0cc243f49b859e641d90c3b60001b61817e565b613bff8661b4da565b613c2b7f1f0b2594e2dd4184a80c81058584fa8dad97789d2be22e0e6d9b9e627450c17c60001b61817e565b613c577f925590089fcca209c66cce64e5e108d9a202ab5cc367fa405e54d7714b80c6d260001b61817e565b613c5f61ac85565b50505050600160fb819055505050565b613c7761ae41565b613ca37f95be776ef135c1c796920cf1d26ff6da56ebb2159e0f87195f5f72a0c0f3145760001b61817e565b613ccf7fb7af94b5088ec0f3f5b54d7f8239b4f9808ccd1ed66b6fef2ee15ea8ad12fa1260001b61817e565b613cfb7f35145c5fa3ee640c4f2df11fbf4ff65aca6abff6381095a23dc267509b3d3a6060001b61817e565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613db957613d5b7fed417902db99c0d6f2ef00df04613018f3717c565e61f4d718c59f1ad0362d0f60001b61817e565b613d877f433374e896d3fa70b7185774cfe11ac8e4442b0d3bc3c582208255e9d6d466ef60001b61817e565b6040517fe21d05d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613de57f5f5f07caba9f45ae7574895925463bf0bfb8014c1c2095a9663dc315848ddf4460001b61817e565b613e117f37966b57fd622042e317cef5ab413c9ba48b21cfbe0d8d1019757807fa8c50b760001b61817e565b613e3d7f6b9b06a2202d7da12be9925ceae0fb394ea3f1087073ece05122c594e9fd42bd60001b61817e565b600860ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613eb1919061e8f2565b60ff1614613fbf57613ee57faa4b05d3a18a04d3ecb810ce69ed3c94e2c13fe930b9696597aaeb462f4d698e60001b61817e565b613f117f9f893c8862288456c29bb446eb53ab2ec4ade82433febe1cadc7da29da607a0360001b61817e565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f80919061e8f2565b60086040517f1dd7cdcd000000000000000000000000000000000000000000000000000000008152600401613fb692919061e950565b60405180910390fd5b613feb7f9ca45637c26055a0d4fbd941729462799892c5db6c2f7e2756c102915f2f5b6e60001b61817e565b6140177f905f52496a5e34c7aee3b9f083825acaa77d65b793efaf75ea20618f804b692960001b61817e565b6140437f6343cdbfee6ce6b0dd698893a158073aac85a5892a704437678b300f8666737760001b61817e565b8061012f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506140b17f4209660529be46f2503f314f1fc6d1f1e36ca65cdf371c8b50232f1ceb12cf4860001b61817e565b6140dd7ffd3a5491b6783359c7aa108155c8ae7e63470e3228867e112c40ba9b66bc2af860001b61817e565b7ff523a7f068712cfe690e1d0ac9d9390f8053cded5617400d4004311bf0157c278160405161410c919061dc85565b60405180910390a150565b600060c960009054906101000a900460ff16905090565b600061415c7f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b6141887fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b6141b47f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b6141bc611075565b6141e87f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b6142147fdd0f7745a134d10ef551ddf4e7cd84cb98ef1f0e29d6ed2dbccf04564d851be360001b61817e565b6142407fc4c881fc861842463826ff09c552af44ddd9d2761d5a7463b40e734d7df8547360001b61817e565b61426c7f8955b7ddb95c744c65931d2273a55435ea7ae17083a71c58dfec74b70fcd795d60001b61817e565b6142758261b6b4565b9050919050565b6101335481565b60006142b17f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b6142dd7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b6143097f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b614311611075565b61433d7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b6143697f14a2ea735c237b94205bdccba207ffb37a3970e32a5c03730f220997a27f676b60001b61817e565b6143957f19355a773788aa75889c838fd47e38d55955e2ae2e920a33ec96f394db1abd2260001b61817e565b6143c17f09a56a99eac8efd65d6d2b28c663b403420e51d043b9a47b13fc08df9d812f1460001b61817e565b6143cb838361b0fa565b905092915050565b60006144017f68cce6a5787c02d2d2714f1e573e7feaffb3a2d61df7cabed960193da431b7d560001b61817e565b61442d7f50e4c2ec614658efdfe4d86b20ea471dae50c6b76c26919e85fe90c42cc28ed760001b61817e565b6144597fdd5924b27251da8405eae8f3584e2d9da7e3604db1589d1c4f215d7c76290a1860001b61817e565b61012e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663647846a56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156144c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144eb919061e98e565b905090565b600061451e7f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b61454a7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b6145767f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b61457e611075565b6145aa7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b6145d67fe7203ba330617f2c29a0d456207e25f5083726514f00e26ab001210d7cadabeb60001b61817e565b6146027fde4baa4a8c9e836a1560537ba9a35da408227ad7061e1c6ea899d0562f56a14c60001b61817e565b61462e7fbe16bfc74399fc95ab0e49fa73c3d12476d2d906c98b5bf06248cd119099789d60001b61817e565b6146388383619e76565b905092915050565b6000603360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b61469161ae41565b61469b600061b756565b565b61013160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600681565b61012f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b614702826146fc617fad565b83619b1e565b61470c828261af22565b5050565b600061473e7f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b61476a7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b6147967f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b61479e611075565b6147ca7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b6147f67f20ffa425816a05359daf280e666d57265fbeef55cc51419ae4ca63afc6577b7a60001b61817e565b6148227f0f9ca9003624e7a854ba95b6daedd22bcb958e7dafcede6eb16c5da6223b433c60001b61817e565b61484e7f6d9ab7ac33e82927c4a38d34a6463df8de0f1b02a636f607265e299d7036eb1860001b61817e565b61013c54905090565b61013060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6148aa7f1e14cdc4c7716496573268ca5b4ef259b5f7c8b8bda8b8a7a8efcf9ba073cf2f60001b61817e565b6148d67fd6a407369739847083101930563077e546ee9f7c872018eb2513aa09d0f19c5960001b61817e565b6149027f20f61c7a67db2e1c2faa39453e55cde7c06d872a74c6e45e6df213ccef9978e960001b61817e565b61490a617fad565b73ffffffffffffffffffffffffffffffffffffffff1661012d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614a205761498b7fded2da8dd4c4b6def231b4bd1c098e35b6234df8bc1e48bcb85d877fec8f95b360001b61817e565b6149b77fe5d4d315da5a7959bc022df06ff0738f8577d7c9c36514b504f95aa7df0c679760001b61817e565b6149bf617fad565b61012d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f91658dbc000000000000000000000000000000000000000000000000000000008152600401614a1792919061e859565b60405180910390fd5b614a4c7f4c65e525359bea4c3e996ced72e74fe235c3c863b4878c9b5020db342d8778c360001b61817e565b614a787f8f37792c7a5e33878ef23dbbab5969721379d8c07f358f52bd0f4f2f6ae074dc60001b61817e565b614aa47f9773ae104382084c29b002190a630bc7a4836ac5311e0c5cf8d35a39247792e960001b61817e565b614ad07fbc679052196500558fdf799fab8b6df07577006956ece4d9549b186eda15626060001b61817e565b614afc7ff27b84414b9f9ebb60515e4f1d6c464d2f828f5c3705a5d23087861db6d5b51260001b61817e565b614b0461b81c565b565b6006600a614b14919061e76a565b6064614b20919061e9bb565b81565b6000614b517fc87bda01cfe03b18bbeab628e635f38b9087e9ce3e9970db00e3d0fb7fc2ff8860001b61817e565b614b7d7f746d7d881f1c7a275336b9031097d23799ee5d1ed0b8a2181ec448075c335f4c60001b61817e565b614ba97fe7bf1d62983b150ba9d615b67efa81f0307c8e2b24ee9cc8b13fc0ceeef5020760001b61817e565b614bb1614bbd565b905090565b6101375481565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000614c157f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b614c417fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b614c6d7f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b614c75611075565b614ca17f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b614ccd7f1aef930e33af6eec3984713525721fa8f21904631bd493291982f897e7e4649360001b61817e565b614cf97f9b19f3ef2658c9377b9f85d8f2653b53d3c793c7dd194ace3b412ce41a30022260001b61817e565b614d257f0ae6d86e3d60e5b5f082ea6353baef409587e6b8b89e3e15b3cef186a1899dff60001b61817e565b61013260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b614d5661ae41565b614d827fba87ec40593aea2c54a447c850030d14786bdbca34c90b018eb932c90b1aadc860001b61817e565b614dae7fd124e438d672cf3bce9141bc05024c2ab3f69792eedfcc5daebab70f09e32afb60001b61817e565b614dda7f99349b6fe831d85fcfd01d700bd3a37011e6abd834d1fbd9bcdf575bf82b6b5a60001b61817e565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603614e9857614e3a7f4d8861453c937574a403300b315c7ea5a6a2aa146a5b4cc4452c5c1fc590e31060001b61817e565b614e667f0f07584d59e5386db9490690b970b4f8ee4fe4414fde678b5d3e5f734a20359460001b61817e565b6040517fe21d05d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614ec47fb7eb26ac35891d30c75443cf86626d0efae65e4c1df46bc5803f52823152007660001b61817e565b614ef07f6876494ed8f966b4dc1464f5fb2eb4795aefdaa6c139b44dfb2d20035cf0c24c60001b61817e565b614f1c7fa77927e01c57f222a21d13ae9ddbbb1d5d5d749fa8a8b67d1a254a87d729cc0160001b61817e565b8073ffffffffffffffffffffffffffffffffffffffff1663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015614f67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f8b919061e38a565b73ffffffffffffffffffffffffffffffffffffffff16614fab6000618181565b73ffffffffffffffffffffffffffffffffffffffff16146150d457614ff27f7ab84510cd5571e342a6f8de2c0ad62c93f58dfc12e1b30b048f10ef7afeb7a560001b61817e565b61501e7fafe409c2408fa740d745e4badfcdc35b951ca152df1923f855d613f0da3f71e460001b61817e565b8073ffffffffffffffffffffffffffffffffffffffff1663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015615069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061508d919061e38a565b6150976000618181565b6040517f077602540000000000000000000000000000000000000000000000000000000081526004016150cb92919061e859565b60405180910390fd5b6151007fa2299638d2bceba42bc69e2534fce912334b7b897b5d888a662777ff31a84e4860001b61817e565b61512c7f2413ab98990eedfdc258453c0353a7ab3a86ea325e0493e3b84d9e3ae736fc1a60001b61817e565b6151587f4d77580f766c79be8ca1c5182c0b8cb61e8a0116c4a3826811af25276cff0ab460001b61817e565b8061013160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506151c67f8897e5dbab9f7dfe710553e6e07c9a7b323c9b8186e116a342c0d701d9c46e7460001b61817e565b6151f27f2489714a76f2af6356ce06d79e0e8e49cf2055c5e5163b6008348cf0892bfc8760001b61817e565b7fce2d1e798d2ce42e86a515798c5267d8a0775f0c6c0d724bb7bc91e24d3cce9781604051615221919061dc49565b60405180910390a150565b61012e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61525b61ae41565b6152877f564d7153724f1ccb809f921e405836acb9b4956a66d97c09db91679c901eae9a60001b61817e565b6152b37f879142ce630896bfa07db0cf653eaec59a2cb47cecb908bf24eb4e5bc773b64e60001b61817e565b6152df7fc406e672493722e2e70441f8510b88ced70053e3e61fcb8020448512e376986f60001b61817e565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361539d5761533f7f8b92b302b1e99b285a300f671da633c9813f3b0c5f843dfb843159bc66069f5860001b61817e565b61536b7f9fbe16e9fed3c7b5d704b021908aef6f875435d31b0a9b82d67b4ccfdbe0d59660001b61817e565b6040517fe21d05d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6153c97f4ffd22688241783f60ea50745160b1091dbd2a421438da4156f749df1b544ad060001b61817e565b6153f57f86351a7eb7470b54c73b0692417796e7f91cb1dc5cec6771192fce132deb701360001b61817e565b6154217f3f7a9bb35607a8a5b17894c79e9427b541d2b887de6b3f911df7c4bae1f1484b60001b61817e565b601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015615471573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615495919061e8f2565b60ff16146155a3576154c97f333ba19af90954fce35170a7305ed62693773872dff379fdcbeb0b72ec5b19f360001b61817e565b6154f57f8985fc724d4312b9967b01937599a32ea602524bb0f3b6f758ef603b26cc1e8d60001b61817e565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015615540573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615564919061e8f2565b60126040517f1dd7cdcd00000000000000000000000000000000000000000000000000000000815260040161559a92919061e950565b60405180910390fd5b6155cf7fec213db3e343c71eb4cfe7befcba7480b2660996acab3aff0233310cae917ade60001b61817e565b6155fb7f80fb2a2b2d4e8b2519e1052b8abe64e073a3e972f7b0cfd37dea2277f85a9c7260001b61817e565b6156277f6ef58174d5e4c8de3cf13eaa64b098e93d004308065dcd64be428f5840259ecc60001b61817e565b8061013060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506156957fcdd5f9e474e1ab323e1db7d9da017f22b5443696e03523b57f6ca4b71261fdd560001b61817e565b6156c17f04e6bf760b89e9dd5b8a89f3ccc61dbd750d5b7b48aab7a18576cb6a3516b17160001b61817e565b7f2b42f26d9e3870f84933cb34c05b2463a97259bf9adf3582d70d6bd06e832aec816040516156f0919061dcc1565b60405180910390a150565b60606037805461570a9061e276565b80601f01602080910402602001604051908101604052809291908181526020018280546157369061e276565b80156157835780601f1061575857610100808354040283529160200191615783565b820191906000526020600020905b81548152906001019060200180831161576657829003601f168201915b5050505050905090565b61579561ae41565b6157c17f44ed09e6306b0e6e275b01040473e19632565fc08c404e113f810c9a1b51104760001b61817e565b6157ed7f8e5c825f0198d3b2c7efc147cd5045d8394654e6d73a3fcaaad71b2565c7aae260001b61817e565b6158197f76f491cd3c052cfc046119e52a524fada9d124900403a95c1e318fc9861da5d060001b61817e565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036158d7576158797f43cc95d5442d16db6ae0bf8230cfe462648f3b63f80a7c2c2543ee126da7bdaf60001b61817e565b6158a57f55752d16eb523b0d186af324df96f0ab38e7e9fbf5a2e09ac75889d85cf1ed3d60001b61817e565b6040517fe21d05d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6159037f9b324718242f5ec1d0a2987dfcac0eab739941ae3c26687118aa97e3ae9f430960001b61817e565b61592f7f19a3f9d4891cf241ca893f492debda9feb653fd511bd9f6b56be8b4e6d8bc2bf60001b61817e565b61595b7f68e406fd44d866b1a912daa323ee51196874d41e9cfb1667500de84d23955bbc60001b61817e565b600061012d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506159af7f7e5590ac14597e4796a6ab48824785a9b9a22ccecf79cfccbea80d9dc8d63ce360001b61817e565b6159db7f0508ec84836445c67c4cedb7cbaa4d7244dd4fc2abea7c6ec8e2140e9c004ff560001b61817e565b8161012d60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550615a497ff4db8ee8abd940b5a22572c25b8dd2c6c9b3499adcd0a631901e9ef7921ec63e60001b61817e565b615a757fa3c3badc8dc72d090c3a0f8142c34de6dccd4919ff59420ff8061930f30eb92d60001b61817e565b7f60ed9ffad04b70bf58c43b18d1f0e54642250116c1137ac1cc483144912435088183604051615aa692919061e859565b60405180910390a15050565b6000615ae07f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b615b0c7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b615b387f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b615b40611075565b615b6c7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b615b987feb4d68d5d27dec10c145b0549f3377e9e96852b6b044d19012bd55f97ccfd80860001b61817e565b615bc47f0c0b850270a8f966879fbd29c6dbcfeaad4499840f0044b1a2a35028e795703c60001b61817e565b615bf07fbc5c11f483f789dd3015c867eddd5abaec5cf187c13ec2e5d54e8518ff597a0660001b61817e565b615bf8618f82565b905090565b615c297f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b615c557fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b615c817f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b615c89611075565b615cb57f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b615cbd61ae41565b615ce97f7879219e6e53e3841461e468b8c8ce5f3c205d41ae74cfce834570983e20a21760001b61817e565b615d157f9ed5ef3c911073d6d1a666692c2e260a7600fc89feccec2727449486b8bffd5f60001b61817e565b615d417f26351d057dac1fa9598ff9f39da6f3bbb7ad31b835c62f6162153402d0c661b760001b61817e565b615d4a8361b6b4565b80615d8757508273ffffffffffffffffffffffffffffffffffffffff16615d6f6143d3565b73ffffffffffffffffffffffffffffffffffffffff16145b15615e2157615db87f7f37e05c935b0239f95c986426972d8b6bc6f9c29a7e99270c9809896d6699fc60001b61817e565b615de47f761d7225be01c202a52aa03e21e9635a8f78ada7cfc6e69323a5250c39a8f8e760001b61817e565b826040517f97f05cc5000000000000000000000000000000000000000000000000000000008152600401615e18919061d6ff565b60405180910390fd5b615e4d7f77102d80692e76d575e2d300e475daf7483358f04c0fe1509ff0d0d6a811963d60001b61817e565b615e797f37a28f212167f201898948dbd866240c40d5f0acfb6250439f716842e11925d860001b61817e565b615ea57f30c5330db84258a8b86bfe09cb75133488612ef0769574c0427798b6e1286c7f60001b61817e565b615ed082828573ffffffffffffffffffffffffffffffffffffffff1661b87f9092919063ffffffff16565b505050565b600080615ee0617fad565b90506000615eee828661769e565b905083811015615f33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401615f2a9061ea6f565b60405180910390fd5b615f408286868403617fb5565b60019250505092915050565b600080615f57617fad565b9050615f64818585619baa565b600191505092915050565b61012d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6101355481565b6008600a615fab919061e76a565b81565b615fb661ae41565b615fe27fa835fb038809d4d6bcbe410cfc2603a0c7f0d0a5031107b287859e0e9698274560001b61817e565b61600e7f31a8791bc67412144ae95ac469158a944950609b36808834fbbfbbadad29791960001b61817e565b61603a7f3083f18a1c5d3578c76d324d9f3ac1aa741679772de9a8013be653849e758c2860001b61817e565b816101368190555061606e7f0dcb89cd7cd7a901013fe9a2b31f5345bbeb5dd0a9331f0e3876221d48ad325560001b61817e565b61609a7f64cf2fbb7d575b74a72322eba92a1ee782ba2bf5434755704cfe5a7dcdc3fffb60001b61817e565b80610137819055506160ce7f9d48256c11a2e58e6c0c46ecc163af5702334e0c99624d960105bfce2780086860001b61817e565b6160fa7f1540a7b44ddd32353585fa6b183d0334b1cca8fb38b2bb80af13130445ca9d4260001b61817e565b7f020bf23f373ccabbafa51024353ff2a1475f224779d55f4d18f8ccc5c7ecfaed828260405161612b92919061e60e565b60405180910390a15050565b6012600a616145919061e76a565b81565b60006161767f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b6161a27fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b6161ce7f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b6161d6611075565b6162027f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b61622e7f6bdaba3e379257962243fb73d01a5a9287580804524c820176480c228e7b107960001b61817e565b61625a7fa164d65a033c0d54de108124861c98e7dd7020f4df858f3ce5f21e0fca1bb0af60001b61817e565b6162867fb7ef44037acc72ad58706274702719545939d321889c1c7e8006edc783b4321560001b61817e565b61628f8261b6b4565b616320576162bf7f25f962b40563aba4ce30dd09ba9431d55c42e91f114b1818a4ee3d838f029a3b60001b61817e565b6162eb7f96eb4551a5d3d6eef922da2c6c865960a4176313f4a62ad2c7eb1a9d059e746860001b61817e565b6163177f6685e7705c236da755b2b3c075d8fdd56fbff2e1c9639b70911d1eac029f9fdc60001b61817e565b600090506163c7565b61634c7f04822522cc1a57c8d671fc4f81996107e7004d8f8a2a3d3158829b386ac2d12960001b61817e565b6163787f26d5801040aa25149c8b1c94c5dc65bc8c672ff4eeeb24c6fcea0ed55631bc6a60001b61817e565b6163a47f1002202a7b889577cd95265e3432438b3e9ba895697afb959191bf0ad9f37d1c60001b61817e565b6163ad8261a83d565b6163bf576163ba8261918c565b6163c4565b61013c545b90505b919050565b60008060019054906101000a900460ff161590508080156163fd5750600160008054906101000a900460ff1660ff16105b8061642a575061640c3061b905565b1580156164295750600160008054906101000a900460ff1660ff16145b5b616469576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016164609061eb01565b60405180910390fd5b60016000806101000a81548160ff021916908360ff16021790555080156164a6576001600060016101000a81548160ff0219169083151502179055505b6164d27f7a10b7a2a72f7bb26aae26c9a7144bed7c16a7adb85bc3fc06d0eee535fbdbb260001b61817e565b6164fe7f7eb7f86c145323db75e9d1c59576dfeccca6bac58f383da76e810f0e8a42fc1f60001b61817e565b61652a7fb82d1144d125134bdb6c8ad2bfa23615f67ea38f8a04d392da40234c058a61a160001b61817e565b616534888861b928565b6165607f51a34d4014ed0388e3e3774ffec69073e7797946461997b68bb4851025dd859e60001b61817e565b61658c7f27add12d71c217e4429c0b530f56cac7908e06660eae36c53f3bfb3aa4aea88b60001b61817e565b61659461b985565b6165c07f6fcc0e7ad926b0061dfae76cfc682ee29340e5dfbf38a66856d44838e4f125e960001b61817e565b6165ec7f89de7b3a6c6677e048993855ee5b49fbafeaceac90c43929725ba5d46fcd428260001b61817e565b8573ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015616637573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061665b919061e8f2565b61012d60006101000a81548160ff021916908360ff1602179055506166a27ff756a3682fd154199bed4a312faec08a887a5faf46daaed416cae5ab0041d2b760001b61817e565b6166ce7f51c0cc499005e5155e3e31b15cf25c2a808e8196b12c3ce0780207bc93e5027760001b61817e565b6166e38661013a61b9de90919063ffffffff16565b506167107f3272b6845d8d68874832456598bef754fd5d6db196bd5d93e77862fc6bc8b2b460001b61817e565b61673c7ff10f7082676448b59512b439bc6c38c33c9aad132d0588d039ca0b315d5153d760001b61817e565b6167458661929a565b506167727f154d66acf78bf30a87d935eefd3275e25a9e464ad6de14ee5d1c391d88e5186a60001b61817e565b61679e7fe70fee723cee76f3b5229777ff9922f84ba8259daf224829d6a74b649f4f6d0460001b61817e565b6167b5866012600a6167b0919061e76a565b61ba0e565b6167e17fc8253148f06ab7d74fddcefb1b2ba8ba1d3f1b54db181abe79d84d36137cfef060001b61817e565b61680d7f2164ff5b0353b4a36b2843a42231d8b6595c2627b928f2d4dcbc910d856c973c60001b61817e565b61681685614d4e565b6168427f945d91cfbeb1f84a8c6993f364c4a7a6afad311886c6f639baf31a4933c698c760001b61817e565b61686e7fef59e71783438eac6c1f1de6d4f9fca1164a117fe2521ba8594fa0e2b7add4b560001b61817e565b61687784616b03565b6168a37fa231b035b01a434e8c97567cf484d0f86c28e56370c8b0d9de5329bdc6f64d2760001b61817e565b6168cf7f8549ed59c9c05ec06caa874e08816a9eb465e511f3df71db6b614b21e80ad45d60001b61817e565b6168d883613c6f565b6169047fff5a19b4e74032d881cfb5ad2b4ea6a480e04d880326889416ce2265da4b5c0a60001b61817e565b6169307f672eb7826dbca8faaa6d14e69e1f0d494c240cc6a7f48c3e6a24d220abebd6ce60001b61817e565b61693982615253565b6169657fdcee329f65a490bc3e5254b3914e3cd8bedf6f6e40afdf13253c6b44e636021460001b61817e565b6169917f8c4ae27c825e1306a5fca5c4f709a670f638a050da1ba1cf3de361632807852d60001b61817e565b6169bc60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612404565b6169e87f674a8a4e5af1fed72b98376a0717fd5c51dd00f1e8b6bc4aaae57ef6fe7a7df260001b61817e565b616a147f0e2f1ea06ba522da3beca59a1a725496600583fb85b9cee12029894752824d5760001b61817e565b616a3e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80615fae565b616a6a7f59094eaffd8af45ef73912f2f1f81ebbfcd7c5c41763864b00813a6fa3b61e8360001b61817e565b616a967fdfbd9d1950f84ff934da26ed2618977f48edf762e3081c47a5b9b1b264a324fe60001b61817e565b616aa0600061790e565b8015616af95760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024986001604051616af0919061eb5c565b60405180910390a15b5050505050505050565b616b0b61ae41565b616b377fa86ff0f8461233a00abedaa2a5f62f7562d06ec14ce13689f4830ce9247bf6ae60001b61817e565b616b637fc998d6ab5ff6290a515862c29f05cf99f25d587bb4db244ff3dc75899969343860001b61817e565b616b8f7ffe8a4756e84c38b5704ba23862d199fd17d978492055b0c1f87a27576f510ad560001b61817e565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603616c4d57616bef7fc30e99f53b0c7eb8b1b5aa524f0052947d31555e079a2d1c28ffdb6964c41ea860001b61817e565b616c1b7f5882d438953cf2efa0b42fb14cb5f1b78bf1f4081015c003b27dd0105701ad6560001b61817e565b6040517fe21d05d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b616c797f76bcb1fd0da2e56634cb14821094090d08cc26bf24e4fc3a1b284a433fa437cb60001b61817e565b616ca57ff6799c9d46e09a6c042ca0e874c5802ea1dab082ed3e822b6ed7ad231f6d50a560001b61817e565b616cd17f31dc26bfe7e8fcf74ec52ee320973c4b407c0848aca5fa5cd4e7e07257c2d73560001b61817e565b8061012e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550616d3f7fd8abfc46cda2424384e4728e7304728e08cd9dcbcfda98f5ac8ee891a8c0f0a960001b61817e565b616d6b7f4dabfc9d89cf5ebb11dd706a5863c786dd4f3c80ec027118119fb1d0a478eef260001b61817e565b7fe3c5028b6066630edda64ff80edd17ecbaf6db73936adf66833b8eac3f46603b81604051616d9a919061ddce565b60405180910390a150565b6000616dd37f668be87fd30b79acd1753d7ff8bd568f68ee0642be93c62ae7761b0beca921e360001b61817e565b616dff7f343fcd9b2cb0ec3e67e741b30d34720ac2a74faa4991e089cde7992fed74f5cb60001b61817e565b616e2b7fd623d74f730a52903c5036915d5c9016139fc0abd6cf5409d54470538bbecaba60001b61817e565b30905090565b6101365481565b6000616e667f652adef71a3de8a77f51893ad556564178b4c8dfabc3b4f308d7b9450fde250a60001b61817e565b616e927fa9c124b5195c19b2902ad933f99aeb4d314cca35beedf2e31ea726e1d6a7819360001b61817e565b616ebe7f8ecc475684715c2970e0304d8f07f84ad9de5876bfc0b987b4f3e355a4a1023f60001b61817e565b616ec86000618181565b905090565b600260fb5403616f12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401616f099061e4e2565b60405180910390fd5b600260fb81905550616f22619e2c565b616f4e7f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b616f7a7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b616fa67f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b616fae611075565b616fda7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b6170067f75c61aa90a7dce0a8177d3a79e7f546ffc7e516ef2edff8bdff2a79360d176d260001b61817e565b6170327fdf1e9051e3de6c9c6dc274e6515034423ac9d1f97898b097aabb93eb42b3ac6b60001b61817e565b61705e7f70c4c1be5f7e2cf850eda0b58b67f4e3c903fff0e5625cce4abb4613db63bb6560001b61817e565b600061706861106b565b90506170967fba4785474cac433ed535ae31434008ce522cf3b702143bc5ede306248b73df4460001b61817e565b6170c27f6f168f5494cbc2b1f9d3b5a90174fe3aa2d916d3bcbd78435b6bd00b0d7cb9f460001b61817e565b60008214806170d057508082115b1561716c576171017fca8e90451e8fdb1b5c0565b5c48d6a307f608f6d5fe3769464d3cafd2a32ed3760001b61817e565b61712d7fa25f16ee9ebcc250d1e10eee6c7fc45ec0f41c5de79bc4a9ea6917ac2f5bf13a60001b61817e565b81816040517fa520f62300000000000000000000000000000000000000000000000000000000815260040161716392919061e60e565b60405180910390fd5b6171987f84d4d3d391b1104db2ffc3b6271aa3fb443ef8d732dc6ff5b7bf869105c3219560001b61817e565b6171c47fc7be6900629344e095eb23e52f60d30b70576bef42280e0fa67b4cc490958d5b60001b61817e565b6171f07ffd4be61e6a89916f18bef032048680f2a9bf192b6337d311582947f6e81c28f560001b61817e565b6000806171fc8461bc9b565b9150915061722c7f6235b6b7ca1dc0c0a6da93878b3b45a63d10dc848a4a46bbe859a0dcb6fdec1f60001b61817e565b6172587f2c52ac3f69464591c35f4c0504d604281ffaf438c6dbc289e120aaa1f721ba3b60001b61817e565b60008061012e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcc30919876040518263ffffffff1660e01b81526004016172b7919061d89e565b6040805180830381865afa1580156172d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906172f7919061e5ce565b915091506173267e48326e4b1034c9e8da887bd26d31af1e75419ef1bde96ac743f7411e3e27a660001b61817e565b6173527f6096d740fbae36cbff085152d6156571ef6af1e8a0a795528bb398554b5fdcef60001b61817e565b61737f858787617362919061e341565b61013c54617370919061e9bb565b61737a919061eba6565b619a00565b6173ab7ff534fe261271ff878a1191284b9d322b09de57daa97e48f68921a16ea838363c60001b61817e565b6173d77ff995801e10e74aa8a4a0f20678d0829d2c9fd86b02ee26f8a296ea92e66f352760001b61817e565b6173e233838361a45f565b61740e7f9e5579e97601365266afd9a16c7790f735a13db4c70b873444fd91cdfae9b0f860001b61817e565b61743a7ffd0af3af56014df6188378f9a6889c7fdad6b6c88fd2223bc8c3612f54128e3860001b61817e565b617444338761af22565b6174707f8e984fb5359b7646dd4915272b6145cbc259bb6a744eb09275ab5cfc466b2e0660001b61817e565b61749c7f7847ce030c3a1126e89fa394dcf56f1615251d40c9d689a909cda692c3a2f4f460001b61817e565b60005b845181101561762c576174d47fd8b5f3ea54396e02600c3ee0ee3967c04c6583eb9887efea29ac89b660b3184460001b61817e565b6175007f9324a8fbe0a13ed32e63542d114dfa3b08f22658175456e6514e7e1b3121469b60001b61817e565b60008482815181106175155761751461e7b5565b5b602002602001015111156175ec5761754f7fb24494c279a765f283d1e3bdace5a28be00fd2bdfc474de97138b97b0ce6f6e860001b61817e565b61757b7fd7a3371f0496ce08b4bb1f90a414399bba064777c60127374d73cc58ef104b3560001b61817e565b6175a77fe133544b43909e07fd4b37fbcdb9de775be910ca1ac0009d7b7a58ad8785ed0160001b61817e565b6175e6338683815181106175be576175bd61e7b5565b5b60200260200101518684815181106175d9576175d861e7b5565b5b602002602001015161a902565b50617619565b6176187fceeb9c946cfaa29b47b5ccffc729dcde29b7f8064fc09d1e9c84694dbb12c7a760001b61817e565b5b80806176249061e7e4565b91505061749f565b506176597f7c9a61e55e1381fa65e0161623804e29d3404fbe9dea6b5d6062297fd4e2ba0c60001b61817e565b6176857f9d8339b35944191637d04094d09c57bfb9c02c10483012a3bf9f76841852a07760001b61817e565b61768e8561c128565b5050505050600160fb8190555050565b6000603460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60006177537f053205fb42c2af8c5162d21b964b51a671ffecb23c9d1be35da0fdbd318d756760001b61817e565b61777f7fa37a6ee92cdf610d9096426457d0f30a95b11ea463aa4a4deaa493d5c4176bff60001b61817e565b6177ab7f889c683ff2e70d3616cde73a8f49c80ce89b98f1ac3164cf6eed6ce94df9df7b60001b61817e565b6177b48261a83d565b61785a5761012f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c061e080836040518263ffffffff1660e01b8152600401617814919061e882565b602060405180830381865afa158015617831573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190617855919061e82c565b617907565b61012f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663233f953e836178a38561918c565b61013c546040518463ffffffff1660e01b81526004016178c59392919061ebd7565b602060405180830381865afa1580156178e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190617906919061e82c565b5b9050919050565b61791661ae41565b6179427ff326cdb8ab9227f45228b50a174fb27cc6dc89e364c1b1a2bf07f5e0116ec1da60001b61817e565b61796e7f6b4f5011e02ffccabe4ef12111dbc2b9f97a76df2ca405cdee2aee0b39bc7ab860001b61817e565b61799a7ffe1f5c72b7f352371d91a077edcf1672197b0eb15bf410321a1282d731d399d960001b61817e565b6006600a6179a8919061e76a565b60646179b4919061e9bb565b811115617a50576179e77ff1abe02a2db6412d513d785fed3c332439f7288aae29010fdbd88e2b730208b660001b61817e565b617a137f6b70cf6ff5c4bfef5802878c657ca540f25e3460b740cf0733701f25f0cd94e360001b61817e565b806040517fc18bc93a000000000000000000000000000000000000000000000000000000008152600401617a47919061d89e565b60405180910390fd5b617a7c7f84fa7b8100dfc6b27c72ef8e948aae6c779b167367a75b51f936f6d2d73ac51160001b61817e565b617aa87f816631dc93dd11467dcb9cb47025312f82fbd6d7be487e3a067c563d4c68e87660001b61817e565b617ad47f38a9fe58cd6395b0e59ce2a0f190659e9e69c71af83a6aa0d56f5e685dffb3be60001b61817e565b8061013581905550617b087f0c771acc0c521cedec3ee4d4c90bb0ab3ce803116bfe98fd4ae98330446447c360001b61817e565b617b347fa2dc9275e3694df57e9edb8490af201afc5009b3c870a23c83ae99ecd5afb7f860001b61817e565b7fc7cffa4415f19fda37aaf051c84a1126b4968fb93a228c99cee161bd2258c5e961013554604051617b66919061d89e565b60405180910390a150565b6101345481565b6000617ba67f5d02c59985b18da06aad93b8b554e1da28966990a15d1a528ed9d747066b9d9160001b61817e565b617bd27fd8ba9b8edddd00abacc7e2c4e55826d14dadabf423c89e56de7c42eb2ba1863960001b61817e565b617bfe7f4f484ef50b590710e0561f7d7993e3c79f03e5aa8755775f4c48a18f45fac9b660001b61817e565b30905090565b606080617c337f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b617c5f7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b617c8b7f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b617c93611075565b617cbf7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b617ceb7ff673be39189f88dd7a6aff51a04c58ff09edecb3bb020c99cf2d38fc070124d960001b61817e565b617d177ffa0f3fe9f84c5e512cf8fce293ff2fa01f90b1ead7e3a1d5d5b9f9f93ec4d93e60001b61817e565b617d437f619bff111bb613dafd7bf8b3bfe9155ea45871da2d6737f7a6aec2755be40cf260001b61817e565b617d4c8361bc9b565b91509150915091565b6000617d837f551f7d7b36bbf8cd2411279d4dc173fc1ba16ee22507b9d15cf27bca000667d060001b61817e565b617daf7fdfc0a0225b0d9b7d9038e08c5a92c1431d86b907d9b917a6e29e81e38230852a60001b61817e565b617ddb7f303030a167d48149392978fe67462d1c9fc379ccfbb49d6065a176f4045d4f3260001b61817e565b617de3611075565b617e0f7f5a4af93e7fe97872f29b54286f62ecef301c636454ee430f63a47953722f64d660001b61817e565b617e3b7f605a2ba61a8ecdb417dce57ea53ccb41fa61a4cb84d5c4d426c5ebadc4ebc39460001b61817e565b617e677faa99ce6014d84febbd136e8d7155fc65befb525e281194895cb0f4c04d859d2b60001b61817e565b617e937fa2e7601b9f8cfe0f757f137003355b30b51ef07a4dcb7bbbffe4668d2b20c89760001b61817e565b6000617e9d61106b565b9050617ecb7f39d9bfead6eeb38e0ce315335c0cbf6b28ad417a967022f67079a667d66c903c60001b61817e565b617ef77fcbcb091e6b1f9a53c05ae78b2f33c01250fcee9f14560006f4c4f0f6290f1c4360001b61817e565b60008111617f06576000617f1a565b80617f0f61c2de565b617f19919061eba6565b5b91505090565b600881565b601281565b617f3261ae41565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603617fa1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401617f989061ec80565b60405180910390fd5b617faa8161b756565b50565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603618024576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161801b9061ed12565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603618093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161808a9061eda4565b60405180910390fd5b80603460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051618171919061d89e565b60405180910390a3505050565b50565b60006181af7f25bd61ecf5d3bad55c67d2562fb53eb8f56612ab95890c24920fa450eab14cb360001b61817e565b6181db7fa479fb045cc0b4fb3ce21831cb4975ab4cddd9e170520265efd6bfbd12b499e060001b61817e565b6182077f958f63451061ca922134675926c947c2921e203c65c0394f8ce9acf9ef94885260001b61817e565b61821c8261013a61c5bf90919063ffffffff16565b9050919050565b61822b61d474565b6182577faca784b367a41ab80d92fa9133bc7858e5173e138ba869e0dadfd0c8f5f0b20c60001b61817e565b6182837ffd70e1924225cd3f27bb9b237286d802be81db25ed29d9dc3d320f5c09a349ca60001b61817e565b6182af7f303c6792d53654a44cbbc2e9b9bce2604769944cf929f41523693d7571ed855660001b61817e565b6182b761d474565b6182e37fb56b207879956bc6a8add7f832719ac83872783d93a23a6ab98b9f067171bc5360001b61817e565b61830f7f0d0b39af3f93a8bc5fcf3797d18afecab3c8285f5fcffd94138f5dca40e7854960001b61817e565b600061831a87612e4d565b90506183487f91ca9fd7bcd2a2b867483400709bfbf654694c3fd05d9bf36a3fe5b68bc247a260001b61817e565b6183747fccda20b5730b9b4291441dabc9617f43129c58da5cd3c7d3bc5ea9a99d85bbfe60001b61817e565b600061837f87612e4d565b90506183ad7f0c73c4b1dc302b26c2a48975e9d5f40e5a1798c5b76821bc199347a060c22e4060001b61817e565b6183d97f496c76aadfa9fc8d47808e6a1ef64b895111603e88da52a0badadc484a68ff7560001b61817e565b60006183e489617725565b90506184127f74a5626eccdc9b36cf6bf820c0892e05b921dc13fe946749c347fc5e98ee10ac60001b61817e565b61843e7f3f35d582c868d63af27f95f01f09a2b6b42ef7ecefa33356ad3ac4bed74478c760001b61817e565b600061844989617725565b90506184777f7b752c850de6d0a09719e55952905825e6efcf4929c1bd4f0bf9873996335ddd60001b61817e565b6184a37f1120914b6d30f59c0c2db07de17a479a888847554dcf442b5151b54c9560343460001b61817e565b60006184ae8a61918c565b90506184dc7f91bce1b09e8ba6c7492db99a245970950b88720e2e91ac0d287cb737358a323660001b61817e565b6185087ff5cfa818dc2a36deda092fdcbf7a93f7694a9fa37b6d6919d053869af0aed54560001b61817e565b618512888261c5d9565b97506185407f5e1a128c951141c2908f77f880d34e1d65e0f53666892b19c8cfa64d1498ab0960001b61817e565b61856c7f7114a6dd09badacf34d87708b7f9cb59a7f1e0f7066f3326d04b56dda6d29be960001b61817e565b600085148061857b5750600084145b806185865750600083145b806185915750600082145b1561868a576185c27f4e49e8e263c9c102778c02bf4d6b4df9e2a86a08f783c3bc903755ebe354588860001b61817e565b6185ee7f3bd000b451b98b0687037eed4c6772cf38869d04a13698bf193775ddf1637fd660001b61817e565b61861a7f4554a2e18b262923424b2a3dc2dd7c670108f3ab4dcb76b4a6dbd46c69f3a9d860001b61817e565b888660800181815250506186507f7efb1af68cb876669ab7e2cecb41592a7dff960f883d0b3457e3be5a40bb3d3c60001b61817e565b61867c7f987ddbce3caab65e0cf458f2201086a513b0d373ac0eb5724ed5abf7e6dca89060001b61817e565b859650505050505050618dae565b6186b67fd9d32972b59531b6f53b30cfb55c3581d65ee012220d755751e376d885d1630360001b61817e565b6186e27f5168a401c9d9ea3fb27cc9d555b41358f0e8754576a27f854e82b69b1fc98e0160001b61817e565b61870e7f7f7bec02090c5c9fdfea206010459b52d2b299274e9070073643d3b2144d352260001b61817e565b888660600181815250506187447f11bbe788d328ac48e68ce974501f5dcfc3874f2e7c86f95ae4db6c2fa83274e560001b61817e565b6187707f997e0171e633a03c01b559a1d6885ff1d893eeeca9615ace74d9209afcd317a060001b61817e565b600061877c8a8761994e565b90506187aa7f93fb88123825ea3260d0f7e1e59d444a42ca114d29dfeb7a2d852997e609e9bf60001b61817e565b6187d67f06cf6c518b92e4051ecdad7cb84ade388e03d88538dc1783bfc6464bfbf2b4c460001b61817e565b60008385836187e5919061e9bb565b6187ef919061eba6565b905061881d7f8a2aa45bf08f9a807838bd085d157362d76827dd6af6dd4c0f7c65601d9831f360001b61817e565b6188497fc5715f051dfb3926a12f6eb27416a1cd5d5552652ff3433c7d244aad14d2875360001b61817e565b618853818761c5f2565b8860400181815250506188887f5dc87af37d915d4579780d770542cb818f161c1e8bd4113261b44ff8a141c20e60001b61817e565b6188b47f198ca67ad4cfc88c72f1534a75ff911d5c3551f0320ebfcd49f28bbc3cc0074860001b61817e565b60006188bf8d61a83d565b90506188ed7fb90a7de98a81a164bf7dae84bcd2d1ce3a13b26cf7f7aa43acddfbb2a500b60d60001b61817e565b6189197f625a59527a7efc2fe0448aad3e2aff6acfad32a2983f5ab088bd12b6832c520f60001b61817e565b80618928578860400151618947565b61013c5489604001518561893c919061e9bb565b618946919061eba6565b5b89602001818152505061897c7fe3a242f682843eff05e556d0bd922ea6a5a4d3e17eb163cfdb098253333f42c760001b61817e565b6189a87f8c422bdf75d9ac68a3d44591662cef526a0b8d8b17acb7b318ed668159f098fa60001b61817e565b8a89602001511115618c1a576189e07f0b770251f3afaeace58c1c3754851d75370d8ead7c708f362ce966c6e9c8d9b460001b61817e565b618a0c7fe334e91570f5d97d979ffccc4d183d77bc1e6a858a3f1bdfb5bafd78d0307c5460001b61817e565b618a387f663487e2f264cd1b2e36889d02d0809964b274f7620012a3859c669fcec82eaf60001b61817e565b8a896020018181525050618a6e7f60272ff7c115c8d708fa4d83756f91023beaac33bc1e4eb16c3847caff19cd4260001b61817e565b618a9a7fabee65dd61c5c7b37cef7fcce43deae56851a56afe8bb552e46c374887e5212860001b61817e565b80618aa9578860200151618ac8565b83896020015161013c54618abd919061e9bb565b618ac7919061eba6565b5b896040018181525050618afd7ffd8e00bbbb9220e7655a88d04e2300180051e9f96dbac57b684c0ceac2bf932a60001b61817e565b618b297fb3f82b828b641e379631f840704f35c0baf196309a2531e7b691d39e2001967660001b61817e565b618b3789604001518861994e565b9150618b657fb98a0c9bbc6c038f73db64039dd27be52f8377770e2241b738b4f794e3063dd960001b61817e565b618b917f41a7c5f726f8db46cc162f9e140f0ba12f15b3ae3f6140d28f22a92f22488f7d60001b61817e565b858583618b9e919061e9bb565b618ba8919061eba6565b9250618bd67fe484620ca5a361ca4dad8320d04d925ad760564bba50ef5e4e3232f1a69cee5d60001b61817e565b618c027fe4c3158f8244be6e1b1289fec958c2a2ac2cde24fce8b2ccf69808fa17a08e1760001b61817e565b618c0c838961c5f2565b896060018181525050618c47565b618c467f35af4519171f473fef5a4c3c125a6b279abe5b3ffdfc150be4a6453bc9d7cb6860001b61817e565b5b618c737f9ffe00bc74723bea7dcd9868593cf68a2d13107e033b236b9c1f3ae56944036360001b61817e565b618c9f7fbd33996db3b73820c987fd63e7b4d219d977e21568c338e5b9100b9c8be377ff60001b61817e565b618ca761c2de565b618caf61106b565b8684618cbb919061e9bb565b618cc5919061e9bb565b618ccf919061eba6565b896000018181525050618d047fb60d24656ebc7ef1560363d17fd922423c1bfcaee5843948347be1c063a6d9b360001b61817e565b618d307f96dfb56c16c77c462cbfc023370d0bbc598a47b7aa43e8f916bd953d837706fe60001b61817e565b88606001518c618d40919061e341565b896080018181525050618d757fc7d24197686d8a75c556d2781eb159c8d008b1905078f9952e1d50ccc5ef5b1660001b61817e565b618da17f119e23360136bb5b048cef47ef0fefe376edfa5caa6fa583f2437e9419f681fc60001b61817e565b8899505050505050505050505b949350505050565b6000618de47fb6e3efc2ae5e24627cbddafff57fe6dda47582314905eb97896700740cf8aa7360001b61817e565b618e107f92385b8d104b5b0c3ae76ce978d8aa5d9837718b4641578989260a20843d0fa160001b61817e565b618e3c7fbc153942e499ceb2192525284c4dbb6d8d1824b385b3d29d6ebdfe997aeeb50560001b61817e565b6000618e5d8373ffffffffffffffffffffffffffffffffffffffff16619018565b9050618e8b7f84fe6f27464da3d6138cff42d9b833038100fc4fd6a238b41dc7ea24e01a9b7560001b61817e565b618eb77f3e5eab018865ecb6648436657e1723907aed4e110c0ec97b34d78052664906a360001b61817e565b8273ffffffffffffffffffffffffffffffffffffffff1663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015618f02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190618f26919061e38a565b73ffffffffffffffffffffffffffffffffffffffff16618f466000618181565b73ffffffffffffffffffffffffffffffffffffffff16148015618f6c5750610133548110155b8015618f7a57506101345481105b915050919050565b6000618fb07fa97ee7395a1b0050c048354f060a29fa2baa6f3d9a1dafff6c795f2f2074898460001b61817e565b618fdc7f0d5052dd14d58ddc089722ff8c9535697f6f8eb3087a990c2eea84f54a173f8b60001b61817e565b6190087f4aafbaa0b3a47343c2a14af236196d258d0f482afdbb19d9c66a528e98bf592c60001b61817e565b61901361013a61c6a4565b905090565b60006190467fb7f980168adc791d818af53e590c23f006d7e5ed6b098cd2338990d0e381b97a60001b61c6b9565b6190727fda2d029e690305abc6022e9bf0e3de413840bc957d7b761738b0f0add5696dc660001b61c6b9565b61909e7f36b958f4355042548ea4504d68cc4ae0d2d8951f7a336c87c46426eb5208315660001b61c6b9565b60008273ffffffffffffffffffffffffffffffffffffffff1663d59624b46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156190eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061910f919061e82c565b905061913d7fbc2b64ef0e340446a027823b2633d7a6cacfffccddaf2ae11229a1f0bc666ced60001b61c6b9565b6191697f817e224b63dbc11b6f0af28ff2a2771056b1c1d76cffd9de34224c644804f42d60001b61c6b9565b428111619177576000619184565b4281619183919061e341565b5b915050919050565b60006191ba7ff28581cfbd1f650811ab2d7db123c935c21fb4db07526ce3e99f8a088bd88eff60001b61817e565b6191e67fec992c5ad162835bd7e28b3050d2fbbf12ce2881d7742320b73e5479970c863c60001b61817e565b6192127fea32b2835eff5ef4aab09502015fa1aca9f720359c9546ff7eb48a36bc2230a660001b61817e565b8173ffffffffffffffffffffffffffffffffffffffff166370a08231619236616da5565b6040518263ffffffff1660e01b8152600401619252919061dceb565b602060405180830381865afa15801561926f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190619293919061e82c565b9050919050565b60006192c87fec4ffddf040ca1e71797fd29d29dbd668c76ffd2dfe2121f35b5c23121a050e760001b61817e565b6192f47f5598f813497fe21b3436acd155b9471b240644b91da4d74e4aa106897b454f7360001b61817e565b61931f7e98bfe2d4f10cf33f7ec6d56ecb81e3b1541157bb45bfa06228777ec85d83a160001b61817e565b600061932a8361918c565b90506193587f03e0757eb7c1d7ceb8ca7978ccfb01164723c715c2d750abb5002222852e5a5b60001b61817e565b6193847f12b5bcd9edc7da6403703e6db48ac246fb94cc51a5b12507f327c549f1d693f060001b61817e565b7fd1fbbd81a5fd46d869b5cd6883d99108cd295072be1b09d36381bbc78b68693983826040516193b592919061edc4565b60405180910390a16193e97fc28ee7c57c1b38b468979d2eb809a76c82f13d27eacda05d0d93bd996b13aace60001b61817e565b6194157f921a703207b7e2a74ede092d22703ebb5d8ad1f2e746303c3c197634fbca74a560001b61817e565b61941e8361a83d565b156194b05761944f7f2af30fe4e99cc916a050e072725e2de1852a55368fcebc5c9e660d400f495cc960001b61817e565b61947b7fa2201c154ee4dc3c35d88cebd04365489178d49719e23df3cdc99612d0fcc5ff60001b61817e565b6194a77f83fbd748dd46fddabb156721e3e204a0148649c7b3a1883d58769c66e865da2560001b61817e565b80915050619949565b6194dc7f43819dcd394b1902aba8c0a760308b4bf40cf5f9b3c8a2e510121c4304fb373e60001b61817e565b6195087f9055fcf0c05bee6135bdcc7360f16fad0ab9b303dd92a133415428bec7e8972c60001b61817e565b6195347f7a96f33d349f7406c1dc1a94ce8b0266b1460258aabe7a3d261c8e78aa445aa160001b61817e565b600061953f8461b6b4565b905061956d7f6618740f4a3f95da5dc8b257c636e39b75c5e4cf18c0ceb9538ba7b9e61cddf860001b61817e565b6195997f13c834e23f4fee06af8beee4c0dd04edbf37eee99d58ed32708b13bdb4722fbd60001b61817e565b6000821180156195a7575080155b156196b5576195d87ffa8bfeead948e27f6a24742e4a99110ffa51847e4b54c8de36e05ef2637e0bbf60001b61817e565b6196047f29364c381a2289da3475a56e9a06c4d78000272c499d480327763b491b16d1ca60001b61817e565b6196307f6831d2c66cdce84626e5e178f46c6b29c5287e7ba03eabd8bda826bf47d393e860001b61817e565b6196458461013a61b9de90919063ffffffff16565b506196727f7f1d50cdcb898a8782ecc002e4dc8779ed3ffa32002f0ff3620795f3ac8ccbed60001b61817e565b61969e7f9d540d7e3bc932ea6f5d94669fbee6edbc488b3c0a1799a8407d14ce09ffa38560001b61817e565b6196b0846196ab86612e4d565b61ba0e565b6196e2565b6196e17fd6ca80b93719dbc0439e34f0c2295355cc9b123635e629ce1e243fd3178c475f60001b61817e565b5b61970e7f455cf4a108722bdc4ce13b5167b39963e83e45c8b50f9abbacae4739211d9b6460001b61817e565b61973a7f07d99b486e946c683817523d08c4a09013add4a2e159e64542d2efec9ddc30b560001b61817e565b6000821480156197475750805b156198be576197787f4585a37914b28cf37351c30d00a4dad64fbb8e58c3adbd0ce0c05c5b34f6f6e360001b61817e565b6197a47fa9d6dbf3047eb065cca3c8434ec255dc72982e70e87d085853ad0d33efeeb11360001b61817e565b6197d07fbc0ee343df23593e9ec3e033372afeb8121a0f903b8b5be400b15e790f58dcb760001b61817e565b6197e58461013a61c6bc90919063ffffffff16565b506198127f38b663c9cd764d9454e911783cc4524ec85e5c837e36dbef25758b39a0633fca60001b61817e565b61983e7f77e72570412254b8aba8c2473c47f16af71a0a794d8b2557096f4a13880123b360001b61817e565b61984984600061ba0e565b6198757f0f8c65bf9744f6bf116f53aa9662ffe67ee240467e92efe1cb36ecbaa62369f660001b61817e565b61013860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090556198eb565b6198ea7f460e8d0e4e0cac69d9deb417cad3ab8ed6bf719d92c4d7e70f973aa62b35149360001b61817e565b5b6199177f11d41a3432409458c68277ade9d8421a8b0a7971230fe1aa90e750773a5fc73260001b61817e565b6199437ffd37bcd8ca2508dc9ccdf6bb8feb744be698aa19ca17a29aaa74448522a18f2f60001b61817e565b81925050505b919050565b600061997c7fd3f4d4e9f7f7114e34dec1b603b95cb0fe8740cca16a678d789090e2a586846760001b61817e565b6199a87ff84dca655a548895cd657e995df7c02b3ad67c761b05e12b92f6d70e6e35edd360001b61817e565b6199d47ffda4c5999a7a5728f9ab71deb827c20ad8724de0202e620b30fce7aa3faf42d460001b61817e565b6012600a6199e2919061e76a565b82846199ee919061e9bb565b6199f8919061eba6565b905092915050565b619a2c7fe57450373c34c0d547092b6a9550c646dc83396fc35a9f833e669148747b7ff760001b61817e565b619a587f0e1672ae4eeafacf1b58af7fab44cf009a98574353bbcb0ab9ce708329654c1d60001b61817e565b619a847f437d6bcf31a3e4dfe065610363b058161eb36b257ed113c7e755bc6da27c9ffe60001b61817e565b8061013c81905550619ab87fc25e7304613f3596a597a775ca2507c2b6db27b93d2b4ab6f5d418f2b59eba0e60001b61817e565b619ae47f06b0bdfc6be9551866d9e486110ce6cb9595d0d1caf22877d5fe809f3505dd0e60001b61817e565b7f9cc737f332356ffc0bee94f3125342b67a356a00505e0f85891ff6f662c5103181604051619b13919061d89e565b60405180910390a150565b6000619b2a848461769e565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114619ba45781811015619b96576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401619b8d9061ee39565b60405180910390fd5b619ba38484848403617fb5565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603619c19576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401619c109061eecb565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603619c88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401619c7f9061ef5d565b60405180910390fd5b619c9383838361c6ec565b6000603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015619d1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401619d119061efef565b60405180910390fd5b818103603360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254619daf919061e439565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051619e13919061d89e565b60405180910390a3619e2684848461c6f1565b50505050565b619e34614117565b15619e74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401619e6b9061f05b565b60405180910390fd5b565b6000619ea47fd00f4ecb349cd471acae2bef825c8ac13bb0cbb1aeb0385f79aa4a4ce6a5ea6860001b61817e565b619ed07f0cbb054943c121e1ddfb30983afe20467f129d136c6a652ae62b759c632ec7b760001b61817e565b619efc7f3f0e93e7baa8b4b3940080ad0be28f2c9c4c9e0c6adab95b1b138bb50c5d93c260001b61817e565b60008373ffffffffffffffffffffffffffffffffffffffff166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015619f49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190619f6d919061e38a565b9050619f9b7f9a95db065af9be4e69f2ea1194d47180590dea564c938f1b77aa0031340ef74c60001b61817e565b619fc77f830822fac61b5cded1dcac3eb1f5a26f53c0594d2ee16c70581877683ec63e2260001b61817e565b619fd08361a83d565b1561a0b35761a0017fe9d2d9a56f32bea19b6c3c9e5a00fa9747130901531c91eeb198cdd2506a5e7960001b61817e565b61a02d7f1359e7b1ec2fdca8172f01dbe37598b83e4e77653d3224e6f6adb4b69155018a60001b61817e565b61a0597f443960a60a0742b01ee81abaaffdd00eb5c4c33b00056c288f6f7b872b15086b60001b61817e565b61013260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161491505061a335565b61a0df7f2635d8226025aaa070aab5493790b2a704929b64349ce1a3eff79bb2f41cbee860001b61817e565b61a10b7fb38f89fb4548631130d144ea251971db9c04144a47501d019e7a44d449a578c260001b61817e565b61a1377fdd70c0fa5bed715617a82026af054f2c2630021a4f04825409ba5ad2184f233560001b61817e565b600083905061a1687fc862e3040a9ef605e1c5d8fb1781e41086c9d28b2a58f18163fde1da0d5e105a60001b61817e565b61a1947fd14ad362877b2aa3fdef19f1e61ceccad8fa7c4fbff4349fdf4e6c83415285be60001b61817e565b60008173ffffffffffffffffffffffffffffffffffffffff166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561a1e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061a205919061e38a565b905061a2337fe100f567220f2e41470f684b0b94a65b732c01568196527a3eb662724126771f60001b61817e565b61a25f7f80a2441c942128007ca27d8116b60370bffb63e836996f7eac29abcd0ca2bd6760001b61817e565b61013260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614801561a30c575061013260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561a31d575061a31c8261b6b4565b5b801561a32f575061a32d81618db6565b155b93505050505b92915050565b600061a3697f634fab3bac0b896d4287ee3df5267d76ebbcf79c600fb6183f97ffcad07b05fc60001b61817e565b61a3957f5fd00702aad48bdab3d4ae77012839d5300f00088b6bedf94b7e3b053af5af4660001b61817e565b61a3c17fd4a7b3da8aa62cf5969c179d07ab0ae79ad85663fe54ad07469437e4c82cd60660001b61817e565b61a3f58461a3cd616da5565b848673ffffffffffffffffffffffffffffffffffffffff1661c6f6909392919063ffffffff16565b61a4217fd7a229f78d2032f7c86cc5f930f80b02771c6333100bbe781939862c88a461df60001b61817e565b61a44d7f1c66b741f8dd6b95bb451516cda465e70f565bb1aa397b964303abca4ce61fdb60001b61817e565b61a4568361929a565b90509392505050565b61a48b7f406b880321af53c0daba78c95862414e7870d0ae6bf52d9572e397b26f5574b460001b61817e565b61a4b77f63efcb8f2339bdd7c1ebe9620abf08d301efbe31b3d690e84eab24e8117865e160001b61817e565b61a4e37f61b7aa73778b463919c8b2fe34b7a4887b89daf2d80ef11ab66c469d4bb7867c60001b61817e565b600061a4ee8361c77f565b905061a51c7fc996545b598a47e7a0d3ed9c3506edfb5c8728f3e37f6a17f691b52049a08f2160001b61817e565b61a5487f2aeae6ed08279e55760073d5819422f321e435a3a5301aed70af2a4b6e88071a60001b61817e565b600083131561a5ec5761a57d7ffe21aac626e6988051304f8384e0633f862ad9c7242d143157208bcc38b79e4860001b61817e565b61a5a97f8e0f58a7fea970ceb347729e3a1d0b7b15f60b74d0761907d17eb3fedef23a0660001b61817e565b61a5d57f4c7c407a569c8c15338df01a95fb98749e72d9fbed47031bb8d37232accc11eb60001b61817e565b61a5e78461a5e1616da5565b8361c79b565b61a70e565b61a6187fc23319a667ba51fe7d595fb0a7ecfe3fa6fb713510bb64d072954a89df4eaf6c60001b61817e565b61a6447f071cbea46793a545d4faf792bfcfcf12ae824024e5a607259b9dc1994a993ddb60001b61817e565b600083121561a6e05761a6797f1ae849f9305b16243a688f6b53b4ebe0b85ebdcfe120175bcdd6ce745e77d9ee60001b61817e565b61a6a57f689f8dd7d2cf80a2fffa100be0a079f00b35609def108186ef25e725f6b8078c60001b61817e565b61a6d17f3b97b96ca69e52a985d9a01c71e2d6b9ba1056be9c6f742fd21e1f0b9704944b60001b61817e565b61a6db848261ca67565b61a70d565b61a70c7ff058bad544b3c836c63d6cce2ef15647441081e025d44c48cdbc8e5133a56aeb60001b61817e565b5b5b61a73a7fa88a311c31b417b40367ab7b27f7790f36f11e922b37171764786318669b37a360001b61817e565b61a7667f2bacc7cbd66b6d73c50e78cad4abb804a63cd1de4b46ab59824cada80eedfc8e60001b61817e565b600082111561a80a5761a79b7f7c11a7f150069c70cea049ce0e207849840eb30c021892a9db39e2b88a83229e60001b61817e565b61a7c77fed295807e3f4d2965b6c509ebea45961b9fbfbdaeee2dfe826373d311ea55a0660001b61817e565b61a7f37f77f5c3012d688d05ebb944a07ba1e128068a359a6590a637b47c107b7f31f75460001b61817e565b61a8058461a7ff614b23565b8461c79b565b61a837565b61a8367f569d65c58a4951e9c6642e291b0066be3d8fd76ce73361367920e6fa186b294360001b61817e565b5b50505050565b600061a86b7ff8fba7a47dd65d8540c4753546ea9d1a86313c432a7eb5263d6208dcd46d854360001b61817e565b61a8977f9b494ce01a664d63f773505816e8ac8929eecfdae638ea1c397b5a6dcc60590f60001b61817e565b61a8c37f8086cb3aa1a6305dacf93544099cf2ef92c5778c1a6a895ed338c2bb53323b4b60001b61817e565b61a8cd6000618181565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b600061a9307f3727ada4132eff29832679c8f165e437aa25a9318ba0676ffd0120fdbed0f1d660001b61817e565b61a95c7fd02973341cddbe6ac79abc59d319d340f19646ba8bdbe79d20bbbe656ce11f7f60001b61817e565b61a9887f72425880e86be2fc3f9eb6d1666dbf73aa5ef524b62f7621fbe9fafaa082c4ee60001b61817e565b61a9b384838573ffffffffffffffffffffffffffffffffffffffff1661b87f9092919063ffffffff16565b61a9df7f9e37ec9bbeb13f9583bf036d36768208d8e5ff4bc2dbe10609c9059739096b7160001b61817e565b61aa0b7f9f3c9f814ecd80f794c4c58fb5924e4e71d5a074ff3ae3b0271bfdcc8b4314db60001b61817e565b61aa148361929a565b90509392505050565b61aa497fd0416ffd7d9bc9f41d42945e2a002b30bca6a42aaac3cedd468ecde2e1b1f44660001b61817e565b61aa757f74be75e7968a92c52d2e5cfa564493d5e46a2415fbd799742ccce9f79cf0c6ad60001b61817e565b61aaa17f3e1cd593bf26c5eaa1150aa9e3f18a9dfce576e2352aa87233983661f2197a1c60001b61817e565b600061aab561aab06000618181565b617725565b61013c5461aac3919061e9bb565b905061aaf17fdd39f444747e8b87e36039d80f076b982e244d7234b02b7674bed312dc12328860001b61817e565b61ab1d7f190a77c2698bc5ab5a2b798dba35625843bc6550800f9c8e993d6cb14cc60e2e60001b61817e565b600061ab2761c2de565b6006600a61ab35919061e76a565b606461ab41919061e9bb565b8361ab4c919061e9bb565b61ab56919061eba6565b905061ab847f4dff9bedf15d19b267b3dc5a47c4d75ac2c370416f42867d170343a708bae67b60001b61817e565b61abb07fa583e19faf510e17a4dff3c1406e50d36d697c89236d022efc59d667c0a2c7e460001b61817e565b6101355481101561ac555761abe77f420d53b7601d35a780dacdff51cccf967be6355d538907e70ab684a6e03f449a60001b61817e565b61ac137f7fab65726e4ea36039edbe8dda5dcc7138c226c10dd52cf0f502945de75710e960001b61817e565b80610135546040517f25ba9b1600000000000000000000000000000000000000000000000000000000815260040161ac4c92919061e60e565b60405180910390fd5b61ac817fcc08208db10d8e365484717e6dc892d6a18b8c445a75482187df8045e9af5e5660001b61817e565b5050565b61acb17f392aadc528a433f934e0f1724536a75b3a26130ed98efa1a8338768cc5d7e68260001b61817e565b61acdd7f4290f72e477b379260c613ebbd84c6566ccd984633a6ddece59607f4f3b58ecc60001b61817e565b61ad097f9fc94d0f3b316b8f4cf449395e57adda06f3c670cdd4878d7d6b62567728e08760001b61817e565b600061ad1361106b565b905061ad417f92bf2a33b0fce0c8d8bf141c9b3cfff90317afd47568aa2dc563ab5b2c47eefd60001b61817e565b61ad6d7fb09d32c7624f27ffd8e6e18ea4e5625b06d239165a98f65cd719fa2bce363e7460001b61817e565b6101365481111561ae125761ada47f3195da66c72a5df9a42ad8af2e2d6d1f18feb530eaf54c11c6af9c5801c0d47960001b61817e565b61add07fedbd70501c4e50bd8ba8d9b728230706fa1981e9262c2775e242a82e1ccd8cb760001b61817e565b80610136546040517f23b53af800000000000000000000000000000000000000000000000000000000815260040161ae0992919061e60e565b60405180910390fd5b61ae3e7fa87b631b4a26b19e3b33a5b0ad016603eece1ab307dc3a2c75ab2c7ee20961b860001b61817e565b50565b61ae49617fad565b73ffffffffffffffffffffffffffffffffffffffff1661ae67614bbd565b73ffffffffffffffffffffffffffffffffffffffff161461aebd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161aeb49061f0c7565b60405180910390fd5b565b61aec761ceea565b600060c960006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61af0b617fad565b60405161af18919061dceb565b60405180910390a1565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361af91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161af889061f159565b60405180910390fd5b61af9d8260008361c6ec565b6000603360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561b024576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161b01b9061f1eb565b60405180910390fd5b818103603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816035600082825461b07c919061e341565b92505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161b0e1919061d89e565b60405180910390a361b0f58360008461c6f1565b505050565b600061b1287f6ba6c09f658fca66c867f8b44fe95671b775bafde18811debbe53901ddcf31c460001b61817e565b61b1547f5806a9a9aaa1ae9ef73d842788c2949955316863d84aa96958caf6dfecb8b70160001b61817e565b61b1807f6c95172faa467dc758f4d4bdf0a60577580c0f507bce2dfe35fd891d881f4ccc60001b61817e565b600061b18a61106b565b905061b1b87febeef2272c49baf3e4ac5bc756cf78eb96f7a80aef680019959833350534950660001b61817e565b61b1e47f53e3e5e09ff490f6707725922ba92f1a3ce4887e4a2bad715816e239c35d8a6360001b61817e565b600061b1f88461b1f387612e4d565b61994e565b905061b2267f09c12d07f59eb9894b678f85696bb63978c8a52495e558dbd899bb90a845d12a60001b61817e565b61b2527fa5300afa99bcba0476988dae7492cf3f6d1c3a5d49e2985f1d1346289a3ddfe960001b61817e565b600061b25d86617725565b905061b28b7fea68ed567ddbc9ed13759ebf0ad38424ec58856bf6b677b5f490811f0b14dc8360001b61817e565b61b2b77f3d9e69d91860c35fefe7e307e552d689142327108adb19a2af8b1038114a6e5f60001b61817e565b600080841161b2e9576008600a61b2ce919061e76a565b828461b2da919061e9bb565b61b2e4919061eba6565b61b313565b61b2f161c2de565b84838561b2fe919061e9bb565b61b308919061e9bb565b61b312919061eba6565b5b905061b3417fc8e5b0c07e6fe97eefafd9a3756f3d6f3d67bf8d48c4189d17b9da65aab9ca8e60001b61817e565b61b36d7f0ad395cd3c81b27e610cc24345ac0c478fdb4137a4902e79be73f07908cab7d060001b61817e565b8094505050505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361b3e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161b3e09061f257565b60405180910390fd5b61b3f56000838361c6ec565b806035600082825461b407919061e439565b9250508190555080603360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461b45d919061e439565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161b4c2919061d89e565b60405180910390a361b4d66000838361c6f1565b5050565b61b5067f848277dbafb970884efe661be8b078946bf808900c9fb7139071378f4538684860001b61817e565b61b5327f41514a19547b95b178011cc3c198ee6df9282139050387b72069086f2932053360001b61817e565b61b55e7faacd86a6a2af44c1d03b422cb56fcda47a6d13d80e439224149e186b484b895c60001b61817e565b6101375461013860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054111561b6855761b5d57f22d93e0a5e890a3e777bc2b5d76bc21cd893988f54c44addf25083955761883c60001b61817e565b61b6017ff3011b8068499c9eed3982bbe70a01547ad7daf35402081ad8f624d53459ce6c60001b61817e565b8061013860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610137546040517f22e4089f00000000000000000000000000000000000000000000000000000000815260040161b67c9392919061f277565b60405180910390fd5b61b6b17f7b497268fbd6ff0e939aeb8a8da90c4f4066f40b42f2129c40d29e3d759dfbca60001b61817e565b50565b600061b6e27f1e214cab3749f68bb6799489cad507404cd0c35e0b7a397596ec193d9dfa63fe60001b61817e565b61b70e7f1272e4b5413680ce09a6109e866c133f66a80fb5406597c2049c7fc4bfbd7e6560001b61817e565b61b73a7f134a547eb86266715a3cea2d1315e7db9d3bc5802ccec562b6d9c43e2e2f60bf60001b61817e565b61b74f8261013a61cf3390919063ffffffff16565b9050919050565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081609760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61b824619e2c565b600160c960006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861b868617fad565b60405161b875919061dceb565b60405180910390a1565b61b9008363a9059cbb60e01b848460405160240161b89e92919061e410565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061cf63565b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff1661b977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161b96e9061f320565b60405180910390fd5b61b981828261d02a565b5050565b600060019054906101000a900460ff1661b9d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161b9cb9061f320565b60405180910390fd5b61b9dc61d09d565b565b600061ba06836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61d0fe565b905092915050565b61ba3a7f5582c9672008c8668ac17a1705637307f05204a542ab2f58e621034eef32801b60001b61817e565b61ba667f248e518f6a76bc43fa50b1f0950aca2922c4f7b0c7f3a6f7647251e340c9bdac60001b61817e565b61ba927ff72bf42d6a21aa7586397b62dd7657a0f6973e396a3a723a46e219ec0f21774f60001b61817e565b600081111561bb695761bac77f333120fe0e0f8fc6bd8665443ee2e99e63d0ed02410e873d49da16c191302f4060001b61817e565b61baf37f5b5730603531ff2ca15d54f3938c61cf0f455f216fc6c8048d8a6a0cb36a6a9060001b61817e565b61bb1f7f7666560604adb98c1f98d802d5489307d6208ebd1c927f55321f6622fc9de0dd60001b61817e565b8061013960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061bc06565b61bb957f30331d34298b2c59f62603c73ba8b76b53645e60fc0963bb303cbf044ba4a3d260001b61817e565b61bbc17fba3492672b8328627d5c2be9325b11ee8b8290e6b8ff6a3184c95a2f3905961f60001b61817e565b61013960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b61bc327fcf0554ccb491e538236050dab400a331932821a414501aa55780803bb802770360001b61817e565b61bc5e7f0e43f9c10db66c1b7e9dcf6fd86584e25a3553399cb47ec6c1ae8c9a8909503e60001b61817e565b7f06399d5691a131b9ea716df732acdd7df7a4223509ae80d3bbf84f525d917b69828260405161bc8f92919061edc4565b60405180910390a15050565b60608061bcca7fd8516f983f0bb4f253d287b56e9cb28efd630e8b5af2b4ebf80a71a4be174da460001b61817e565b61bcf67f3c3dd6352c1d2cf87b64b3351b18e70696f9a6200d9bf270625884da06bee30a60001b61817e565b61bd227f7762436f8297a583309de2955b09b867bcd8ab9d37c7c5f71d8d7f95db9e438460001b61817e565b600061bd2c61106b565b905061bd5a7f26b3628ff0442ef15aa36968976ff61f5f2a452212a23611606ad50f4e3a64f460001b61817e565b61bd867f1d67aead9a72660bf8bedaa194ac8f3243a41d47999e583364bb095645d25ad860001b61817e565b600061bd90618f82565b905061bdbe7f399ca3bc182d7d091e2a48ff46335ec657dcfae57818c0e60279ab8d5f83a85960001b61817e565b61bdea7f1c41e87b4c865207d0c6c9f680f28717e638b021d3444b7cd2c694837387657a60001b61817e565b60008167ffffffffffffffff81111561be065761be0561deb1565b5b60405190808252806020026020018201604052801561be345781602001602082028036833780820191505090505b50905061be637fc85490b6b3aed37c18b9fcfba513ec918c620bac058a3956d8da55516a80ab0360001b61817e565b61be8f7f8572113ff484249679485335fa364c59d5a6fce236697031e82e92d08bd6912860001b61817e565b60008267ffffffffffffffff81111561beab5761beaa61deb1565b5b60405190808252806020026020018201604052801561bed95781602001602082028036833780820191505090505b50905061bf087f0f30023855c1c1f2d70089b58c9556c87b872f25b33e506f8643fb9b06de7cf960001b61817e565b61bf347ff22099ff52fea2f186299ecd036cf7a946736eeb3070399de6f179b93703a52560001b61817e565b60005b8381101561c0c05761bf6b7f52873f778ca4c6774d41965c838c83e2f3ed13107f77e5488393658bd489bfaa60001b61817e565b61bf977fa5d114a852415a745ad5efe586b522254c4ad50824605ff9b3b7ab44abd05ced60001b61817e565b61bfa081618181565b83828151811061bfb35761bfb261e7b5565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061c0197f23babd2d68317fdb58bf753a2e62f4180989f59f25acf58ff6a0da654f30158e60001b61817e565b61c0457f2745d7cd6fbe03e118bfe1db4d0ba1c491b10a3b73e88fb18e72f98d54a7c6e460001b61817e565b6000851161c05457600061c08e565b848861c07985848151811061c06c5761c06b61e7b5565b5b602002602001015161918c565b61c083919061e9bb565b61c08d919061eba6565b5b82828151811061c0a15761c0a061e7b5565b5b602002602001018181525050808061c0b89061e7e4565b91505061bf37565b5061c0ed7f91eb6a4c2f1ab00ef55f8453e828c5d9ad34d81982669b927d760d539210a55360001b61817e565b61c1197f4cca870ec3d24492c31d30dbad2d2fb7d0b715fb9e6d7d4a02733db8152cdfaf60001b61817e565b81819550955050505050915091565b61c1547f66a077f53bd95ff45eeb1c39591f63e04461f77d17d49df3fa7d665ba15148e960001b61817e565b61c1807f31d839eae1fca926d9947874bfefcd023cc1a3a16bf81ac269eed80435c933c460001b61817e565b61c1ac7f368c17b2312ead9f88c22165bf5d494f717ef00d5b7945d1b6097e1d9b14036660001b61817e565b600061c1b661106b565b905061c1e47f0cb5a0c95b483f140fef3b63860c05a77128ee6f40c412354cd913c6ee05914f60001b61817e565b61c2107f56a5c61821679595e9149d13b3d7c8ebaa8e0f0920ec2a9930a81e4eb1e953b860001b61817e565b81811061c2ae5761c2437fad6f3d79c3225f522cacfc95e2e06d7d4c1db74693ce51624250cc6ec771f81060001b61817e565b61c26f7f1a185365c67aee292d88c46b732a5d54c865ead0c40abb7df521fd377ce1d0a960001b61817e565b80826040517f1790876600000000000000000000000000000000000000000000000000000000815260040161c2a592919061e60e565b60405180910390fd5b61c2da7f69fa6a1e187ac58a87604a78558a314e617df67fd2773ec9d2553d3b1d93f4f860001b61817e565b5050565b600061c30c7f8bc4e19f088a81699b04bd566cb3ba6cb8488c675d11dac7af401a128623317660001b61817e565b61c3387f2a1775fec90c51e4069badfbb6ae3cfb78c0c738de3e3cbff1bfbce01997a71860001b61817e565b61c3647fef46b0a9afc22acf7b26c1896d8f73a28d763e9cde24eb6831c0743047182df460001b61817e565b600061c37861c3736000618181565b617725565b61013c5461c386919061e9bb565b905061c3b47f7119286d2685e445aed037030f10184c0f3ed8f6d3b3df6968e5659d015c255360001b61817e565b61c3e07fd1f080162d4b30661ae81d2ee2e646c88c1756c409cb78e54977f2638d2ae2fb60001b61817e565b6000600190505b61c3ef618f82565b81101561c55f5761c4227fd3c874e9acf063fd065e4b8c1201a117cc62a516988ed19b69e2770875c4854d60001b61817e565b61c44e7f979f6e2d152015a9107b77be0169dd03d9c1cd16a412bc9b241e158abc023b3160001b61817e565b600061c45982618181565b905061c4877fac6f1b78d3e3f37c3aaea842e28966d078a5e17a842183c303b1b6e420594a5b60001b61817e565b61c4b37fcb3718a2bcfd45b505907881bf7b30e0efd9ff99ac7608f3a6244ba709afb1f960001b61817e565b600061c4cf61c4c18361918c565b61c4ca84612e4d565b61994e565b905061c4fd7feb2d140e7971914a003527c1cbb7c53dd24219c169f483452e35b6f3d87f53ba60001b61817e565b61c5297f6002140a4f357b2f8d5c4c0e6107f89292cc14d947a17a4a9db64dd80df23a9260001b61817e565b61c53282617725565b8161c53d919061e9bb565b8461c548919061e439565b93505050808061c5579061e7e4565b91505061c3e7565b5061c58c7fc4045c4c7cace628abd816945e9e50d6d3c2c95ae268be64f35277f2a8008ad960001b61817e565b61c5b87f980f71996b6dc40608255e597f092af0456998a14a6cf455203a5fd22f8c827c60001b61817e565b8091505090565b600061c5ce836000018361d16e565b60001c905092915050565b600081831061c5e8578161c5ea565b825b905092915050565b600061c6207f40514dfdb5cb5066b3deef6d60e662d7638c6a53aef51ae6bc8b2d4137aca04760001b61817e565b61c64c7f5e69e4a79a3e7b06e4fd1fa26c3d32de96eac9bbdc53a043d32848090c1ff33260001b61817e565b61c6787f4778b01816ca247f557dfd188491bd460135c342ca2bc70dc4df59e70204c76c60001b61817e565b816012600a61c687919061e76a565b8461c692919061e9bb565b61c69c919061eba6565b905092915050565b600061c6b28260000161d199565b9050919050565b50565b600061c6e4836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61d1aa565b905092915050565b505050565b505050565b61c779846323b872dd60e01b85858560405160240161c7179392919061f340565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061cf63565b50505050565b60008082121561c792578160000361c794565b815b9050919050565b61c7c77ff5a83f59cc3137f0a206a0540202b4198ddab55c54fd623bedd338007edd8d6d60001b61817e565b61c7f37f90bbc6f27ad7a65ff37b26d87f984ec74f6a736b064dfb8fe69406471af865cb60001b61817e565b61c81f7f6d772f910c3672045215a866870b88c410ecd06da1f0b07d7a70846396a3ecd060001b61817e565b600061c8296143d3565b905061c8577f5da1ae01a564d20000b191023c26d1f82ac062d2b79ded38e3dad0f3a5375ccc60001b61817e565b61c8837f9a2914c82c6da691b755b5a8be2860fd058f87ec8d596f45aa0d3f86ef9c86e560001b61817e565b600061c88d617b78565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061c8e97f2f177e056be1b74ad1f21688932fd4606aaee230a4652abc1745c958f41cd8c060001b61817e565b61c9157f662700a77afd41b7d45ec1701ea7fcc11cd82ed14b11c6272a410fcd10a9069960001b61817e565b801561c9af5761c9477fdf7dd35978671da3bb89de4d77c6baca57267a5496f11abd9e512f14d94f002b60001b61817e565b61c9737fcb3711a2c905c461ba12a4984ce6198eac434491257889b78812f26e3dd1a98b60001b61817e565b61c99f7f6cc1bcc5dafcce44a88e878f8ef4c8ed6dbd04623090f55898bda39ca2818bcc60001b61817e565b61c9a98484615f4c565b5061ca60565b61c9db7f39ef87ef8bf44c7153b4dc86ca011d311373f7593aed162f9f517d43b809279160001b61817e565b61ca067e4c8799bd9d2957c4ee6ba16706a461d0586c20255554dd84eb3bdae87b656c60001b61817e565b61ca327fc4d30b63a666a92735a5fc780dc8e6e6e61f8aaece3142bacab79dc38e48195c60001b61817e565b61ca5f8585858573ffffffffffffffffffffffffffffffffffffffff1661c6f6909392919063ffffffff16565b5b5050505050565b61ca937fc2b39400da071dc497b9fa274edd758bcafa4eadc1c86c198051affa1f1ee40660001b61817e565b61cabe7e72268b85dbff689839982aeb8b6e9485ee982a5ec174d15dff20ca83de037560001b61817e565b61caea7feae5e45282bccff15a259c53d8f2995c8deb7b88e051f533a76def7f1b363be860001b61817e565b600061caf46143d3565b905061cb227feddd8422808cba26b9169e50ff6b452b658885c2cfc9514e1f8eae8c9d33dd7960001b61817e565b61cb4e7f75b223667844d3cf3e3d89414d1a41574fb19b3c18af9797afe0bb5fff6e9c7a60001b61817e565b600061cb58617b78565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061cbb47ffa6273fdb2a1631d902eeb8ec6ae10f71891043813140da7c360c4dbab022a2e60001b61817e565b61cbe07f26469f5e0ce09f71b7ede83e333458fd0134e649248532e44aff60d2b7c85ca160001b61817e565b801561ce345761cc127f5d8e8da70e3c91945e1fde087f38093b7cc38ba3af5ef44bf1bb54149e52755c60001b61817e565b61cc3e7f880c8a173c77067e5e62a16a63f66dede4444e47e088f783945a45ea4ac5939960001b61817e565b61cc6a7f4dafad54c96e042b855da5ff508e238518622f8cd292847a2a500990fa254c6d60001b61817e565b600061cc758361918c565b905061cca37fe8ef47454ba2c59d013244bffb7acdabccceaf1a170178fe85b1bdeac983b12860001b61817e565b61cccf7ff136ed2a7050f342d992812974602cbcb5e17221e26b4106bfbcee2eea30776260001b61817e565b61cd038561ccdd868461c5d9565b8573ffffffffffffffffffffffffffffffffffffffff1661b87f9092919063ffffffff16565b61cd2f7f070f8c63695947637571286767de7482e084f646b4451f1e7dc33d5a40bbf61c60001b61817e565b61cd5b7fe64c8e6c6c7faceffb3838eb1e04812c9d7e34b3c2f4b9d89a55d175813d85ed60001b61817e565b8381101561ce015761cd8f7fad0a51a1f6b0ae7fd33a807139f1fa67253a8b10cea8f89bcd4b27cfabba605b60001b61817e565b61cdbb7faeb6d08e2cfd90420931855ff57cc6ed925b1982ebc7f5093d1833f7e8bb8e0a60001b61817e565b61cde77ffc72cfa8bc6cb8c4c93b8061dd8121d89d38501b3871aa9b75ca89b47777dbf560001b61817e565b61cdfc85828661cdf7919061e341565b61b37a565b61ce2e565b61ce2d7f37a8cc7265988abb8a58e64e957665af948b4addf2e85266f335d9a57083d2fd60001b61817e565b5b5061cee4565b61ce607f321440236a1195aaa7b40bdb2d635741a96d25b0cae352ef89dbea3b3b0cd99760001b61817e565b61ce8c7f54040d8ec3a02e07ef598f027985f126f7bac8c629f48182fc1a318cd686176d60001b61817e565b61ceb87fe0f1da1130df3a547e7a4e81d567b67eb73b11ef444d24a73df2cad2b3ee235860001b61817e565b61cee384848473ffffffffffffffffffffffffffffffffffffffff1661b87f9092919063ffffffff16565b5b50505050565b61cef2614117565b61cf31576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161cf289061f3c3565b60405180910390fd5b565b600061cf5b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61d2be565b905092915050565b600061cfc5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661d2e19092919063ffffffff16565b905060008151111561d025578080602001905181019061cfe5919061e3e3565b61d024576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161d01b9061f455565b60405180910390fd5b5b505050565b600060019054906101000a900460ff1661d079576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161d0709061f320565b60405180910390fd5b816036908161d088919061f617565b50806037908161d098919061f617565b505050565b600060019054906101000a900460ff1661d0ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161d0e39061f320565b60405180910390fd5b61d0fc61d0f7617fad565b61b756565b565b600061d10a838361d2be565b61d16357826000018290806001815401808255809150506001900390600052602060002001600090919091909150558260000180549050836001016000848152602001908152602001600020819055506001905061d168565b600090505b92915050565b600082600001828154811061d1865761d18561e7b5565b5b9060005260206000200154905092915050565b600081600001805490509050919050565b6000808360010160008481526020019081526020016000205490506000811461d2b257600060018261d1dc919061e341565b905060006001866000018054905061d1f4919061e341565b905081811461d26357600086600001828154811061d2155761d21461e7b5565b5b906000526020600020015490508087600001848154811061d2395761d23861e7b5565b5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061d2775761d27661f6e9565b5b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061d2b8565b60009150505b92915050565b600080836001016000848152602001908152602001600020541415905092915050565b606061d2f0848460008561d2f9565b90509392505050565b60608247101561d33e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161d3359061f78a565b60405180910390fd5b61d3478561b905565b61d386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161d37d9061f7f6565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161d3af919061f85d565b60006040518083038185875af1925050503d806000811461d3ec576040519150601f19603f3d011682016040523d82523d6000602084013e61d3f1565b606091505b509150915061d40182828661d40d565b92505050949350505050565b6060831561d41d5782905061d46d565b60008351111561d4305782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161d464919061d533565b60405180910390fd5b9392505050565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561d4dd57808201518184015260208101905061d4c2565b60008484015250505050565b6000601f19601f8301169050919050565b600061d5058261d4a3565b61d50f818561d4ae565b935061d51f81856020860161d4bf565b61d5288161d4e9565b840191505092915050565b6000602082019050818103600083015261d54d818461d4fa565b905092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061d5948261d569565b9050919050565b61d5a48161d589565b811461d5af57600080fd5b50565b60008135905061d5c18161d59b565b92915050565b6000819050919050565b61d5da8161d5c7565b811461d5e557600080fd5b50565b60008135905061d5f78161d5d1565b92915050565b6000806040838503121561d6145761d61361d55f565b5b600061d6228582860161d5b2565b925050602061d6338582860161d5e8565b9150509250929050565b60008115159050919050565b61d6528161d63d565b82525050565b600060208201905061d66d600083018461d649565b92915050565b60006020828403121561d6895761d68861d55f565b5b600061d6978482850161d5e8565b91505092915050565b6000819050919050565b600061d6c561d6c061d6bb8461d569565b61d6a0565b61d569565b9050919050565b600061d6d78261d6aa565b9050919050565b600061d6e98261d6cc565b9050919050565b61d6f98161d6de565b82525050565b600060208201905061d714600083018461d6f0565b92915050565b600061d7258261d589565b9050919050565b61d7358161d71a565b811461d74057600080fd5b50565b60008135905061d7528161d72c565b92915050565b600061d7638261d589565b9050919050565b61d7738161d758565b811461d77e57600080fd5b50565b60008135905061d7908161d76a565b92915050565b6000806000806080858703121561d7b05761d7af61d55f565b5b600061d7be8782880161d743565b945050602061d7cf8782880161d781565b935050604061d7e08782880161d5e8565b925050606061d7f18782880161d5e8565b91505092959194509250565b61d8068161d5c7565b82525050565b60a08201600082015161d822600085018261d7fd565b50602082015161d835602085018261d7fd565b50604082015161d848604085018261d7fd565b50606082015161d85b606085018261d7fd565b50608082015161d86e608085018261d7fd565b50505050565b600060a08201905061d889600083018461d80c565b92915050565b61d8988161d5c7565b82525050565b600060208201905061d8b3600083018461d88f565b92915050565b60008060006060848603121561d8d25761d8d161d55f565b5b600061d8e08682870161d5b2565b935050602061d8f18682870161d5b2565b925050604061d9028682870161d5e8565b9150509250925092565b60008060006060848603121561d9255761d92461d55f565b5b600061d9338682870161d743565b935050602061d9448682870161d781565b925050604061d9558682870161d5e8565b9150509250925092565b6000806040838503121561d9765761d97561d55f565b5b600061d9848582860161d5e8565b925050602061d9958582860161d5e8565b9150509250929050565b60006020828403121561d9b55761d9b461d55f565b5b600061d9c38482850161d743565b91505092915050565b600060ff82169050919050565b61d9e28161d9cc565b82525050565b600060208201905061d9fd600083018461d9d9565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61da388161d6de565b82525050565b600061da4a838361da2f565b60208301905092915050565b6000602082019050919050565b600061da6e8261da03565b61da78818561da0e565b935061da838361da1f565b8060005b8381101561dab457815161da9b888261da3e565b975061daa68361da56565b92505060018101905061da87565b5085935050505092915050565b6000602082019050818103600083015261dadb818461da63565b905092915050565b60006020828403121561daf95761daf861d55f565b5b600061db078482850161d781565b91505092915050565b6000806040838503121561db275761db2661d55f565b5b600061db358582860161d743565b925050602061db468582860161d5e8565b9150509250929050565b600061db5b8261d589565b9050919050565b61db6b8161db50565b811461db7657600080fd5b50565b60008135905061db888161db62565b92915050565b60006020828403121561dba45761dba361d55f565b5b600061dbb28482850161db79565b91505092915050565b6000806040838503121561dbd25761dbd161d55f565b5b600061dbe08582860161d743565b925050602061dbf18582860161d781565b9150509250929050565b60006020828403121561dc115761dc1061d55f565b5b600061dc1f8482850161d5b2565b91505092915050565b600061dc338261d6cc565b9050919050565b61dc438161dc28565b82525050565b600060208201905061dc5e600083018461dc3a565b92915050565b600061dc6f8261d6cc565b9050919050565b61dc7f8161dc64565b82525050565b600060208201905061dc9a600083018461dc76565b92915050565b600061dcab8261d6cc565b9050919050565b61dcbb8161dca0565b82525050565b600060208201905061dcd6600083018461dcb2565b92915050565b61dce58161d589565b82525050565b600060208201905061dd00600083018461dcdc565b92915050565b600061dd118261d6cc565b9050919050565b61dd218161dd06565b82525050565b600060208201905061dd3c600083018461dd18565b92915050565b600061dd4d8261d589565b9050919050565b61dd5d8161dd42565b811461dd6857600080fd5b50565b60008135905061dd7a8161dd54565b92915050565b60006020828403121561dd965761dd9561d55f565b5b600061dda48482850161dd6b565b91505092915050565b600061ddb88261d6cc565b9050919050565b61ddc88161ddad565b82525050565b600060208201905061dde3600083018461ddbf565b92915050565b600061ddf48261d589565b9050919050565b61de048161dde9565b811461de0f57600080fd5b50565b60008135905061de218161ddfb565b92915050565b60006020828403121561de3d5761de3c61d55f565b5b600061de4b8482850161de12565b91505092915050565b60008060006060848603121561de6d5761de6c61d55f565b5b600061de7b8682870161d781565b935050602061de8c8682870161d5b2565b925050604061de9d8682870161d5e8565b9150509250925092565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61dee98261d4e9565b810181811067ffffffffffffffff8211171561df085761df0761deb1565b5b80604052505050565b600061df1b61d555565b905061df27828261dee0565b919050565b600067ffffffffffffffff82111561df475761df4661deb1565b5b61df508261d4e9565b9050602081019050919050565b82818337600083830152505050565b600061df7f61df7a8461df2c565b61df11565b90508281526020810184848401111561df9b5761df9a61deac565b5b61dfa684828561df5d565b509392505050565b600082601f83011261dfc35761dfc261dea7565b5b813561dfd384826020860161df6c565b91505092915050565b600061dfe78261d589565b9050919050565b61dff78161dfdc565b811461e00257600080fd5b50565b60008135905061e0148161dfee565b92915050565b600080600080600080600060e0888a03121561e0395761e03861d55f565b5b600088013567ffffffffffffffff81111561e0575761e05661d564565b5b61e0638a828b0161dfae565b975050602088013567ffffffffffffffff81111561e0845761e08361d564565b5b61e0908a828b0161dfae565b965050604061e0a18a828b0161d781565b955050606061e0b28a828b0161dd6b565b945050608061e0c38a828b0161e005565b93505060a061e0d48a828b0161db79565b92505060c061e0e58a828b0161de12565b91505092959891949750929550565b60006020828403121561e10a5761e10961d55f565b5b600061e1188482850161e005565b91505092915050565b6000806040838503121561e1385761e13761d55f565b5b600061e1468582860161d5b2565b925050602061e1578582860161d5b2565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061e199838361d7fd565b60208301905092915050565b6000602082019050919050565b600061e1bd8261e161565b61e1c7818561e16c565b935061e1d28361e17d565b8060005b8381101561e20357815161e1ea888261e18d565b975061e1f58361e1a5565b92505060018101905061e1d6565b5085935050505092915050565b6000604082019050818103600083015261e22a818561da63565b9050818103602083015261e23e818461e1b2565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061e28e57607f821691505b60208210810361e2a15761e2a061e247565b5b50919050565b600061e2b28261d589565b9050919050565b61e2c28161e2a7565b811461e2cd57600080fd5b50565b60008151905061e2df8161e2b9565b92915050565b60006020828403121561e2fb5761e2fa61d55f565b5b600061e3098482850161e2d0565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061e34c8261d5c7565b915061e3578361d5c7565b925082820390508181111561e36f5761e36e61e312565b5b92915050565b60008151905061e3848161d59b565b92915050565b60006020828403121561e3a05761e39f61d55f565b5b600061e3ae8482850161e375565b91505092915050565b61e3c08161d63d565b811461e3cb57600080fd5b50565b60008151905061e3dd8161e3b7565b92915050565b60006020828403121561e3f95761e3f861d55f565b5b600061e4078482850161e3ce565b91505092915050565b600060408201905061e425600083018561dcdc565b61e432602083018461d88f565b9392505050565b600061e4448261d5c7565b915061e44f8361d5c7565b925082820190508082111561e4675761e46661e312565b5b92915050565b600061e4788261d5c7565b91506000820361e48b5761e48a61e312565b5b600182039050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061e4cc601f8361d4ae565b915061e4d78261e496565b602082019050919050565b6000602082019050818103600083015261e4fb8161e4bf565b9050919050565b600061e50d8261d6cc565b9050919050565b61e51d8161e502565b82525050565b600060408201905061e538600083018561e514565b61e545602083018461d6f0565b9392505050565b600060608201905061e561600083018661d88f565b61e56e602083018561d88f565b61e57b604083018461d88f565b949350505050565b6000819050919050565b61e5968161e583565b811461e5a157600080fd5b50565b60008151905061e5b38161e58d565b92915050565b60008151905061e5c88161d5d1565b92915050565b6000806040838503121561e5e55761e5e461d55f565b5b600061e5f38582860161e5a4565b925050602061e6048582860161e5b9565b9150509250929050565b600060408201905061e623600083018561d88f565b61e630602083018461d88f565b9392505050565b60008160011c9050919050565b6000808291508390505b600185111561e68e5780860481111561e66a5761e66961e312565b5b600185161561e6795780820291505b808102905061e6878561e637565b945061e64e565b94509492505050565b60008261e6a7576001905061e763565b8161e6b5576000905061e763565b816001811461e6cb576002811461e6d55761e704565b600191505061e763565b60ff84111561e6e75761e6e661e312565b5b8360020a91508482111561e6fe5761e6fd61e312565b5b5061e763565b5060208310610133831016604e8410600b841016171561e7395782820a90508381111561e7345761e73361e312565b5b61e763565b61e746848484600161e644565b9250905081840481111561e75d5761e75c61e312565b5b81810290505b9392505050565b600061e7758261d5c7565b915061e7808361d9cc565b925061e7ad7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848461e697565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061e7ef8261d5c7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361e8215761e82061e312565b5b600182019050919050565b60006020828403121561e8425761e84161d55f565b5b600061e8508482850161e5b9565b91505092915050565b600060408201905061e86e600083018561dcdc565b61e87b602083018461dcdc565b9392505050565b600060208201905061e897600083018461e514565b92915050565b600060408201905061e8b2600083018561e514565b61e8bf602083018461dd18565b9392505050565b61e8cf8161d9cc565b811461e8da57600080fd5b50565b60008151905061e8ec8161e8c6565b92915050565b60006020828403121561e9085761e90761d55f565b5b600061e9168482850161e8dd565b91505092915050565b600061e93a61e93561e9308461d9cc565b61d6a0565b61d5c7565b9050919050565b61e94a8161e91f565b82525050565b600060408201905061e965600083018561e941565b61e972602083018461e941565b9392505050565b60008151905061e9888161d76a565b92915050565b60006020828403121561e9a45761e9a361d55f565b5b600061e9b28482850161e979565b91505092915050565b600061e9c68261d5c7565b915061e9d18361d5c7565b925082820261e9df8161d5c7565b9150828204841483151761e9f65761e9f561e312565b5b5092915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b600061ea5960258361d4ae565b915061ea648261e9fd565b604082019050919050565b6000602082019050818103600083015261ea888161ea4c565b9050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b600061eaeb602e8361d4ae565b915061eaf68261ea8f565b604082019050919050565b6000602082019050818103600083015261eb1a8161eade565b9050919050565b6000819050919050565b600061eb4661eb4161eb3c8461eb21565b61d6a0565b61d9cc565b9050919050565b61eb568161eb2b565b82525050565b600060208201905061eb71600083018461eb4d565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061ebb18261d5c7565b915061ebbc8361d5c7565b92508261ebcc5761ebcb61eb77565b5b828204905092915050565b600060608201905061ebec600083018661d6f0565b61ebf9602083018561d88f565b61ec06604083018461d88f565b949350505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061ec6a60268361d4ae565b915061ec758261ec0e565b604082019050919050565b6000602082019050818103600083015261ec998161ec5d565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b600061ecfc60248361d4ae565b915061ed078261eca0565b604082019050919050565b6000602082019050818103600083015261ed2b8161ecef565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b600061ed8e60228361d4ae565b915061ed998261ed32565b604082019050919050565b6000602082019050818103600083015261edbd8161ed81565b9050919050565b600060408201905061edd9600083018561d6f0565b61ede6602083018461d88f565b9392505050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b600061ee23601d8361d4ae565b915061ee2e8261eded565b602082019050919050565b6000602082019050818103600083015261ee528161ee16565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b600061eeb560258361d4ae565b915061eec08261ee59565b604082019050919050565b6000602082019050818103600083015261eee48161eea8565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b600061ef4760238361d4ae565b915061ef528261eeeb565b604082019050919050565b6000602082019050818103600083015261ef768161ef3a565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b600061efd960268361d4ae565b915061efe48261ef7d565b604082019050919050565b6000602082019050818103600083015261f0088161efcc565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600061f04560108361d4ae565b915061f0508261f00f565b602082019050919050565b6000602082019050818103600083015261f0748161f038565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061f0b160208361d4ae565b915061f0bc8261f07b565b602082019050919050565b6000602082019050818103600083015261f0e08161f0a4565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b600061f14360218361d4ae565b915061f14e8261f0e7565b604082019050919050565b6000602082019050818103600083015261f1728161f136565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b600061f1d560228361d4ae565b915061f1e08261f179565b604082019050919050565b6000602082019050818103600083015261f2048161f1c8565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b600061f241601f8361d4ae565b915061f24c8261f20b565b602082019050919050565b6000602082019050818103600083015261f2708161f234565b9050919050565b600060608201905061f28c600083018661e514565b61f299602083018561d88f565b61f2a6604083018461d88f565b949350505050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b600061f30a602b8361d4ae565b915061f3158261f2ae565b604082019050919050565b6000602082019050818103600083015261f3398161f2fd565b9050919050565b600060608201905061f355600083018661dcdc565b61f362602083018561dcdc565b61f36f604083018461d88f565b949350505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b600061f3ad60148361d4ae565b915061f3b88261f377565b602082019050919050565b6000602082019050818103600083015261f3dc8161f3a0565b9050919050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b600061f43f602a8361d4ae565b915061f44a8261f3e3565b604082019050919050565b6000602082019050818103600083015261f46e8161f432565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261f4d77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261f49a565b61f4e1868361f49a565b95508019841693508086168417925050509392505050565b600061f51461f50f61f50a8461d5c7565b61d6a0565b61d5c7565b9050919050565b6000819050919050565b61f52e8361f4f9565b61f54261f53a8261f51b565b84845461f4a7565b825550505050565b600090565b61f55761f54a565b61f56281848461f525565b505050565b5b8181101561f5865761f57b60008261f54f565b60018101905061f568565b5050565b601f82111561f5cb5761f59c8161f475565b61f5a58461f48a565b8101602085101561f5b4578190505b61f5c861f5c08561f48a565b83018261f567565b50505b505050565b600082821c905092915050565b600061f5ee6000198460080261f5d0565b1980831691505092915050565b600061f607838361f5dd565b9150826002028217905092915050565b61f6208261d4a3565b67ffffffffffffffff81111561f6395761f63861deb1565b5b61f643825461e276565b61f64e82828561f58a565b600060209050601f83116001811461f681576000841561f66f578287015190505b61f679858261f5fb565b86555061f6e1565b601f19841661f68f8661f475565b60005b8281101561f6b75784890151825560018201915060208501945060208101905061f692565b8683101561f6d4578489015161f6d0601f89168261f5dd565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061f77460268361d4ae565b915061f77f8261f718565b604082019050919050565b6000602082019050818103600083015261f7a38161f767565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600061f7e0601d8361d4ae565b915061f7eb8261f7aa565b602082019050919050565b6000602082019050818103600083015261f80f8161f7d3565b9050919050565b600081519050919050565b600081905092915050565b600061f8378261f816565b61f841818561f821565b935061f85181856020860161d4bf565b80840191505092915050565b600061f869828461f82c565b91508190509291505056fea26469706673582212200704ac00b00c6c5884542f293c7d994e119d8b3488da92a05f0642cb7f5208ad64736f6c63430008110033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/spot-contracts/hardhat.config.ts b/spot-contracts/hardhat.config.ts index 5d66ddf7..e0f1fb42 100644 --- a/spot-contracts/hardhat.config.ts +++ b/spot-contracts/hardhat.config.ts @@ -36,7 +36,6 @@ export default { accounts: { mnemonic: process.env.PROD_MNEMONIC || Wallet.createRandom().mnemonic.phrase, }, - gasMultiplier: 1.01, }, mainnet: { // url: `https://mainnet.infura.io/v3/${process.env.INFURA_SECRET}`, diff --git a/spot-contracts/tasks/ops/perp.ts b/spot-contracts/tasks/ops/perp.ts index e535e559..b3fc6569 100644 --- a/spot-contracts/tasks/ops/perp.ts +++ b/spot-contracts/tasks/ops/perp.ts @@ -10,6 +10,7 @@ task("ops:perp:info") const perp = await hre.ethers.getContractAt("PerpetualTranche", perpAddress); const perpDecimals = await perp.decimals(); + const percDecimals = await perp.PERC_DECIMALS(); const bondIssuer = await hre.ethers.getContractAt("BondIssuer", await perp.bondIssuer()); const latestBond = await hre.ethers.getContractAt("IBondController", await bondIssuer.callStatic.getLatestBond()); @@ -47,12 +48,12 @@ task("ops:perp:info") console.log("---------------------------------------------------------------"); console.log("feePolicy:", feePolicy.address); console.log("owner", await feePolicy.owner()); - console.log("perpMintFeePerc:", utils.formatUnits(await feePolicy.perpMintFeePerc(), 8)); - console.log("perpBurnFeePerc:", utils.formatUnits(await feePolicy.perpBurnFeePerc(), 8)); + console.log("perpMintFeePerc:", utils.formatUnits(await feePolicy.perpMintFeePerc(), percDecimals)); + console.log("perpBurnFeePerc:", utils.formatUnits(await feePolicy.perpBurnFeePerc(), percDecimals)); const r = await feePolicy.perpRolloverFee(); - console.log("perpRolloverFeeLower:", utils.formatUnits(r.lower, 8)); - console.log("perpRolloverFeeUpper:", utils.formatUnits(r.upper, 8)); - console.log("perpRolloverFeeGrowth:", utils.formatUnits(r.growth, 8)); + console.log("perpRolloverFeeLower:", utils.formatUnits(r.lower, percDecimals)); + console.log("perpRolloverFeeUpper:", utils.formatUnits(r.upper, percDecimals)); + console.log("perpRolloverFeeGrowth:", utils.formatUnits(r.growth, percDecimals)); console.log("---------------------------------------------------------------"); console.log("PerpetualTranche:", perp.address); @@ -65,20 +66,16 @@ task("ops:perp:info") console.log("---------------------------------------------------------------"); console.log(`maturityTolarance: [${await perp.minTrancheMaturitySec()}, ${await perp.maxTrancheMaturitySec()}]`); console.log("maxSupply:", utils.formatUnits(await perp.maxSupply(), await perp.decimals())); - console.log("maxMintAmtPerTranche:", utils.formatUnits(await perp.maxMintAmtPerTranche(), await perp.decimals())); - const t = await depositBond.tranches(0); console.log( - "availableCap:", - utils.formatUnits( - (await perp.maxMintAmtPerTranche()).sub(await perp.mintedSupplyPerTranche(t[0])), - await perp.decimals(), - ), + "maxDepositTrancheValuePerc:", + utils.formatUnits(await perp.maxDepositTrancheValuePerc(), percDecimals), ); console.log("---------------------------------------------------------------"); console.log("depositBond:", depositBond.address); console.log("issued:", issued); console.log("TotalSupply:", utils.formatUnits(perpSupply, perpDecimals)); console.log("TVL:", utils.formatUnits(perpTVL, perpDecimals)); + console.log("deviationRatio:", utils.formatUnits(await perp.callStatic.deviationRatio(), percDecimals)); console.log("---------------------------------------------------------------"); console.log("Reserve:"); const reserveCount = (await perp.callStatic.getReserveCount()).toNumber(); diff --git a/spot-contracts/tasks/scripts/mainnet.sh b/spot-contracts/tasks/scripts/mainnet.sh index d3330c6b..1b6107cf 100644 --- a/spot-contracts/tasks/scripts/mainnet.sh +++ b/spot-contracts/tasks/scripts/mainnet.sh @@ -103,7 +103,6 @@ yarn hardhat --network mainnet ops:trancheAndRollover \ --perp-address 0xC1f33e0cf7e40a67375007104B929E49a581bafE \ --collateral-amount 200 - yarn hardhat --network mainnet ops:vault:info 0x82A91a0D599A45d8E9Af781D67f695d7C72869Bd yarn hardhat --network mainnet ops:vault:deposit \ diff --git a/spot-contracts/tasks/upgrade/index.ts b/spot-contracts/tasks/upgrade/index.ts index b3677f7a..88d7ac4f 100644 --- a/spot-contracts/tasks/upgrade/index.ts +++ b/spot-contracts/tasks/upgrade/index.ts @@ -66,7 +66,9 @@ task("upgrade:testnet") console.log("Proxy", address); console.log("Current implementation", await getImplementationAddress(hre.ethers.provider, address)); - const impl = await hre.upgrades.upgradeProxy(address, Factory); + const impl = await hre.upgrades.upgradeProxy(address, Factory, { + unsafeAllowRenames: true, + }); await impl.deployed(); const newImpl = await getImplementationAddress(hre.ethers.provider, address); console.log("Updated implementation", newImpl); diff --git a/spot-contracts/test/perp/PerpetualTranche.ts b/spot-contracts/test/perp/PerpetualTranche.ts index 54909b3d..85a48f71 100644 --- a/spot-contracts/test/perp/PerpetualTranche.ts +++ b/spot-contracts/test/perp/PerpetualTranche.ts @@ -15,6 +15,7 @@ import { TimeHelpers, rebase, advancePerpQueueToRollover, + toPercFixedPtAmt, } from "../helpers"; use(smock.matchers); @@ -90,7 +91,7 @@ describe("PerpetualTranche", function () { expect(await perp.minTrancheMaturitySec()).to.eq(1); expect(await perp.maxTrancheMaturitySec()).to.eq(constants.MaxUint256); expect(await perp.maxSupply()).to.eq(constants.MaxUint256); - expect(await perp.maxMintAmtPerTranche()).to.eq(constants.MaxUint256); + expect(await perp.maxDepositTrancheValuePerc()).to.eq(toPercFixedPtAmt("1")); }); it("should NOT be paused", async function () { @@ -327,26 +328,58 @@ describe("PerpetualTranche", function () { }); }); - describe("#updateMintingLimits", function () { + describe("#updateMaxSupply", function () { + let tx: Transaction; + + describe("when triggered by non-keeper", function () { + it("should revert", async function () { + await expect(perp.connect(otherUser).updateMaxSupply(constants.MaxUint256)).to.be.revertedWithCustomError( + perp, + "UnauthorizedCall", + ); + }); + }); + + describe("when triggered by owner", function () { + beforeEach(async function () { + await perp.updateKeeper(await otherUser.getAddress()); + tx = perp.connect(otherUser).updateMaxSupply(toFixedPtAmt("100")); + await tx; + }); + it("should update reference", async function () { + expect(await perp.maxSupply()).to.eq(toFixedPtAmt("100")); + }); + }); + }); + + describe("#updateMaxDepositTrancheValuePerc", function () { let tx: Transaction; describe("when triggered by non-keeper", function () { it("should revert", async function () { await expect( - perp.connect(otherUser).updateMintingLimits(constants.MaxUint256, constants.MaxUint256), + perp.connect(otherUser).updateMaxDepositTrancheValuePerc(toPercFixedPtAmt("0.33")), ).to.be.revertedWithCustomError(perp, "UnauthorizedCall"); }); }); + describe("when invalid perc", function () { + it("should revert", async function () { + await perp.updateKeeper(await otherUser.getAddress()); + await expect( + perp.connect(otherUser).updateMaxDepositTrancheValuePerc(toPercFixedPtAmt("1.01")), + ).to.be.revertedWithCustomError(perp, "InvalidPerc"); + }); + }); + describe("when triggered by owner", function () { beforeEach(async function () { await perp.updateKeeper(await otherUser.getAddress()); - tx = perp.connect(otherUser).updateMintingLimits(toFixedPtAmt("100"), toFixedPtAmt("20")); + tx = perp.connect(otherUser).updateMaxDepositTrancheValuePerc(toPercFixedPtAmt("0.33")); await tx; }); it("should update reference", async function () { - expect(await perp.maxSupply()).to.eq(toFixedPtAmt("100")); - expect(await perp.maxMintAmtPerTranche()).to.eq(toFixedPtAmt("20")); + expect(await perp.maxDepositTrancheValuePerc()).to.eq(toPercFixedPtAmt("0.33")); }); }); }); diff --git a/spot-contracts/test/perp/PerpetualTranche_deposit.ts b/spot-contracts/test/perp/PerpetualTranche_deposit.ts index c6a860be..d42714e9 100644 --- a/spot-contracts/test/perp/PerpetualTranche_deposit.ts +++ b/spot-contracts/test/perp/PerpetualTranche_deposit.ts @@ -166,7 +166,7 @@ describe("PerpetualTranche", function () { describe("when the supply cap is exceeded", function () { beforeEach(async function () { - await perp.updateMintingLimits(toFixedPtAmt("499"), toFixedPtAmt("1000")); + await perp.updateMaxSupply(toFixedPtAmt("499")); }); it("should revert", async function () { @@ -180,7 +180,7 @@ describe("PerpetualTranche", function () { describe("when the supply cap is exceeded and existing supply > 0", function () { beforeEach(async function () { await perp.deposit(depositTrancheA.address, toFixedPtAmt("400")); - await perp.updateMintingLimits(toFixedPtAmt("499"), toFixedPtAmt("1000")); + await perp.updateMaxSupply(toFixedPtAmt("499")); }); it("should revert", async function () { @@ -191,29 +191,75 @@ describe("PerpetualTranche", function () { }); }); - describe("when the tranche mint limit is exceeded", function () { + describe("when the existing supply is zero", function () { beforeEach(async function () { - await perp.updateMintingLimits(toFixedPtAmt("1000"), toFixedPtAmt("499")); + await perp.updateMaxDepositTrancheValuePerc(toPercFixedPtAmt("0.5")); }); - - it("should revert", async function () { - await expect(perp.deposit(depositTrancheA.address, toFixedPtAmt("500"))).to.revertedWithCustomError( + it("should not revert", async function () { + await expect(perp.deposit(depositTrancheA.address, toFixedPtAmt("100"))).to.revertedWithCustomError( perp, "ExceededMaxMintPerTranche", ); }); }); + describe("when the tranche mint limit has not exceeded and existing supply > 0", function () { + beforeEach(async function () { + await perp.deposit(depositTrancheA.address, toFixedPtAmt("250")); + await advancePerpQueue(perp, 1200); + await perp.updateMaxDepositTrancheValuePerc(toPercFixedPtAmt("0.5")); + }); + + it("should NOT revert", async function () { + await mintCollteralToken(collateralToken, toFixedPtAmt("50"), deployer); + await collateralToken.transfer(perp.address, toFixedPtAmt("10")); + const newBond = await bondAt(await perp.callStatic.getDepositBond()); + await depositIntoBond(newBond, toFixedPtAmt("2000"), deployer); + const tranches = await getTranches(newBond); + const newTranche = tranches[0]; + await newTranche.approve(perp.address, toFixedPtAmt("500")); + await perp.deposit(newTranche.address, toFixedPtAmt("200")); + await expect(perp.deposit(newTranche.address, toFixedPtAmt("1"))).not.to.reverted; + }); + }); + + describe("when the tranche mint limit has exceeded and existing supply > 0", function () { + beforeEach(async function () { + await perp.deposit(depositTrancheA.address, toFixedPtAmt("250")); + await advancePerpQueue(perp, 1200); + await perp.updateMaxDepositTrancheValuePerc(toPercFixedPtAmt("0.5")); + }); + + it("should revert", async function () { + await mintCollteralToken(collateralToken, toFixedPtAmt("50"), deployer); + await collateralToken.transfer(perp.address, toFixedPtAmt("50")); + const newBond = await bondAt(await perp.callStatic.getDepositBond()); + await depositIntoBond(newBond, toFixedPtAmt("2000"), deployer); + const tranches = await getTranches(newBond); + const newTranche = tranches[0]; + await newTranche.approve(perp.address, toFixedPtAmt("500")); + await perp.deposit(newTranche.address, toFixedPtAmt("200")); + await expect(perp.deposit(newTranche.address, toFixedPtAmt("1"))).to.reverted; + }); + }); + describe("when the tranche mint limit is exceeded and existing supply > 0", function () { beforeEach(async function () { - await perp.deposit(depositTrancheA.address, toFixedPtAmt("400")); - await perp.updateMintingLimits(toFixedPtAmt("1000"), toFixedPtAmt("499")); + await perp.deposit(depositTrancheA.address, toFixedPtAmt("250")); + await advancePerpQueue(perp, 1200); + await perp.updateMaxDepositTrancheValuePerc(toPercFixedPtAmt("0.5")); }); it("should revert", async function () { - await expect(perp.deposit(depositTrancheA.address, toFixedPtAmt("100"))).to.revertedWithCustomError( + const newBond = await bondAt(await perp.callStatic.getDepositBond()); + await depositIntoBond(newBond, toFixedPtAmt("2000"), deployer); + const tranches = await getTranches(newBond); + const newTranche = tranches[0]; + await newTranche.approve(perp.address, toFixedPtAmt("500")); + await perp.deposit(newTranche.address, toFixedPtAmt("250")); + await expect(perp.deposit(newTranche.address, toFixedPtAmt("1"))).to.revertedWithCustomError( perp, - `ExceededMaxMintPerTranche`, + "ExceededMaxMintPerTranche", ); }); }); diff --git a/spot-staking-subgraph/.gitignore b/spot-staking-subgraph/.gitignore new file mode 100644 index 00000000..d42a8246 --- /dev/null +++ b/spot-staking-subgraph/.gitignore @@ -0,0 +1,2 @@ +build +generated \ No newline at end of file diff --git a/spot-staking-subgraph/.prettierrc b/spot-staking-subgraph/.prettierrc new file mode 100644 index 00000000..e02a9cfb --- /dev/null +++ b/spot-staking-subgraph/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": false, + "trailingComma": "all", + "singleQuote": true, + "bracketSpacing": true, + "printWidth": 99 +} diff --git a/spot-staking-subgraph/README.md b/spot-staking-subgraph/README.md new file mode 100644 index 00000000..5a04bb42 --- /dev/null +++ b/spot-staking-subgraph/README.md @@ -0,0 +1,15 @@ +# spot-staking-subgraph + +Ancillary subgraphs to keep track of spot staking. + + +``` +yarn codegen + +yarn build + +yarn graph deploy spot-staking \ + --node https://subgraphs.alchemy.com/api/subgraphs/deploy \ + --deploy-key $GRAPH_AUTH \ + --ipfs https://ipfs.satsuma.xyz +``` \ No newline at end of file diff --git a/spot-staking-subgraph/abis/CharmVault.json b/spot-staking-subgraph/abis/CharmVault.json new file mode 100644 index 00000000..56df03b3 --- /dev/null +++ b/spot-staking-subgraph/abis/CharmVault.json @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"feesToVault0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesToVault1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesToProtocol0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesToProtocol1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesToManager0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesToManager1","type":"uint256"}],"name":"CollectFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"CollectManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"CollectProtocol","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"tick","type":"int24"},{"indexed":false,"internalType":"uint256","name":"totalAmount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalAmount1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"}],"name":"Snapshot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"threshold","type":"int24"}],"name":"UpdateBaseThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"weight","type":"uint24"}],"name":"UpdateFullRangeWeight","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"threshold","type":"int24"}],"name":"UpdateLimitThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"manager","type":"address"}],"name":"UpdateManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"managerFee","type":"uint24"}],"name":"UpdateManagerFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxTotalSupply","type":"uint256"}],"name":"UpdateMaxTotalSupply","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"maxTwapDeviation","type":"int24"}],"name":"UpdateMaxTwapDeviation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"minTickMove","type":"int24"}],"name":"UpdateMinTickMove","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"manager","type":"address"}],"name":"UpdatePendingManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"period","type":"uint32"}],"name":"UpdatePeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"delegate","type":"address"}],"name":"UpdateRebalanceDelegate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"twapDuration","type":"uint32"}],"name":"UpdateTwapDuration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accruedManagerFees0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accruedManagerFees1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accruedProtocolFees0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accruedProtocolFees1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseLower","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseThreshold","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseUpper","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkCanRebalance","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"collectManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"collectProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Desired","type":"uint256"},{"internalType":"uint256","name":"amount1Desired","type":"uint256"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"liquidity","type":"uint128"}],"name":"emergencyBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract AlphaProVaultFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullLower","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullRangeWeight","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullUpper","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalance0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalance1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"}],"name":"getPositionAmounts","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAmounts","outputs":[{"internalType":"uint256","name":"total0","type":"uint256"},{"internalType":"uint256","name":"total1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTwap","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"uint24","name":"managerFee","type":"uint24"},{"internalType":"address","name":"rebalanceDelegate","type":"address"},{"internalType":"uint256","name":"maxTotalSupply","type":"uint256"},{"internalType":"int24","name":"baseThreshold","type":"int24"},{"internalType":"int24","name":"limitThreshold","type":"int24"},{"internalType":"uint24","name":"fullRangeWeight","type":"uint24"},{"internalType":"uint32","name":"period","type":"uint32"},{"internalType":"int24","name":"minTickMove","type":"int24"},{"internalType":"int24","name":"maxTwapDeviation","type":"int24"},{"internalType":"uint32","name":"twapDuration","type":"uint32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"internalType":"struct VaultParams","name":"_params","type":"tuple"},{"internalType":"address","name":"_factory","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTick","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitLower","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitThreshold","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitUpper","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managerFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTwapDeviation","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTickMove","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingManagerFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract IUniswapV3Pool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebalanceDelegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"_baseThreshold","type":"int24"}],"name":"setBaseThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_fullRangeWeight","type":"uint24"}],"name":"setFullRangeWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int24","name":"_limitThreshold","type":"int24"}],"name":"setLimitThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_pendingManagerFee","type":"uint24"}],"name":"setManagerFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTotalSupply","type":"uint256"}],"name":"setMaxTotalSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int24","name":"_maxTwapDeviation","type":"int24"}],"name":"setMaxTwapDeviation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int24","name":"_minTickMove","type":"int24"}],"name":"setMinTickMove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_period","type":"uint32"}],"name":"setPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rebalanceDelegate","type":"address"}],"name":"setRebalanceDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_twapDuration","type":"uint32"}],"name":"setTwapDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Upgradeable","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tickSpacing","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twapDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"uniswapV3MintCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/spot-staking-subgraph/abis/ERC20.json b/spot-staking-subgraph/abis/ERC20.json new file mode 100644 index 00000000..405d6b36 --- /dev/null +++ b/spot-staking-subgraph/abis/ERC20.json @@ -0,0 +1,222 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] diff --git a/spot-staking-subgraph/abis/RebasingERC20.json b/spot-staking-subgraph/abis/RebasingERC20.json new file mode 100644 index 00000000..09bb9cb7 --- /dev/null +++ b/spot-staking-subgraph/abis/RebasingERC20.json @@ -0,0 +1,344 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newScalar", + "type": "uint256" + } + ], + "name": "Rebase", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "LogRebase", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rebase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "scaledBalanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "scaledTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferAllFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/spot-staking-subgraph/abis/UniV3Pool.json b/spot-staking-subgraph/abis/UniV3Pool.json new file mode 100644 index 00000000..bd99dfb4 --- /dev/null +++ b/spot-staking-subgraph/abis/UniV3Pool.json @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"int24","name":"tickLower","type":"int24"},{"indexed":true,"internalType":"int24","name":"tickUpper","type":"int24"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"int24","name":"tickLower","type":"int24"},{"indexed":true,"internalType":"int24","name":"tickUpper","type":"int24"},{"indexed":false,"internalType":"uint128","name":"amount0","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"amount1","type":"uint128"}],"name":"Collect","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint128","name":"amount0","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"amount1","type":"uint128"}],"name":"CollectProtocol","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paid0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paid1","type":"uint256"}],"name":"Flash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"observationCardinalityNextOld","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"observationCardinalityNextNew","type":"uint16"}],"name":"IncreaseObservationCardinalityNext","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"indexed":false,"internalType":"int24","name":"tick","type":"int24"}],"name":"Initialize","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"int24","name":"tickLower","type":"int24"},{"indexed":true,"internalType":"int24","name":"tickUpper","type":"int24"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"feeProtocol0Old","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"feeProtocol1Old","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"feeProtocol0New","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"feeProtocol1New","type":"uint8"}],"name":"SetFeeProtocol","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"int256","name":"amount0","type":"int256"},{"indexed":false,"internalType":"int256","name":"amount1","type":"int256"},{"indexed":false,"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"indexed":false,"internalType":"uint128","name":"liquidity","type":"uint128"},{"indexed":false,"internalType":"int24","name":"tick","type":"int24"}],"name":"Swap","type":"event"},{"inputs":[{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"burn","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"amount0Requested","type":"uint128"},{"internalType":"uint128","name":"amount1Requested","type":"uint128"}],"name":"collect","outputs":[{"internalType":"uint128","name":"amount0","type":"uint128"},{"internalType":"uint128","name":"amount1","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint128","name":"amount0Requested","type":"uint128"},{"internalType":"uint128","name":"amount1Requested","type":"uint128"}],"name":"collectProtocol","outputs":[{"internalType":"uint128","name":"amount0","type":"uint128"},{"internalType":"uint128","name":"amount1","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeGrowthGlobal0X128","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeGrowthGlobal1X128","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"observationCardinalityNext","type":"uint16"}],"name":"increaseObservationCardinalityNext","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidity","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLiquidityPerTick","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"observations","outputs":[{"internalType":"uint32","name":"blockTimestamp","type":"uint32"},{"internalType":"int56","name":"tickCumulative","type":"int56"},{"internalType":"uint160","name":"secondsPerLiquidityCumulativeX128","type":"uint160"},{"internalType":"bool","name":"initialized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"secondsAgos","type":"uint32[]"}],"name":"observe","outputs":[{"internalType":"int56[]","name":"tickCumulatives","type":"int56[]"},{"internalType":"uint160[]","name":"secondsPerLiquidityCumulativeX128s","type":"uint160[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"positions","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"feeGrowthInside0LastX128","type":"uint256"},{"internalType":"uint256","name":"feeGrowthInside1LastX128","type":"uint256"},{"internalType":"uint128","name":"tokensOwed0","type":"uint128"},{"internalType":"uint128","name":"tokensOwed1","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFees","outputs":[{"internalType":"uint128","name":"token0","type":"uint128"},{"internalType":"uint128","name":"token1","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"feeProtocol0","type":"uint8"},{"internalType":"uint8","name":"feeProtocol1","type":"uint8"}],"name":"setFeeProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slot0","outputs":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint16","name":"observationIndex","type":"uint16"},{"internalType":"uint16","name":"observationCardinality","type":"uint16"},{"internalType":"uint16","name":"observationCardinalityNext","type":"uint16"},{"internalType":"uint8","name":"feeProtocol","type":"uint8"},{"internalType":"bool","name":"unlocked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"}],"name":"snapshotCumulativesInside","outputs":[{"internalType":"int56","name":"tickCumulativeInside","type":"int56"},{"internalType":"uint160","name":"secondsPerLiquidityInsideX128","type":"uint160"},{"internalType":"uint32","name":"secondsInside","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"int256","name":"amountSpecified","type":"int256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[{"internalType":"int256","name":"amount0","type":"int256"},{"internalType":"int256","name":"amount1","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int16","name":"","type":"int16"}],"name":"tickBitmap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tickSpacing","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"","type":"int24"}],"name":"ticks","outputs":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"uint256","name":"feeGrowthOutside0X128","type":"uint256"},{"internalType":"uint256","name":"feeGrowthOutside1X128","type":"uint256"},{"internalType":"int56","name":"tickCumulativeOutside","type":"int56"},{"internalType":"uint160","name":"secondsPerLiquidityOutsideX128","type":"uint160"},{"internalType":"uint32","name":"secondsOutside","type":"uint32"},{"internalType":"bool","name":"initialized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/spot-staking-subgraph/package.json b/spot-staking-subgraph/package.json new file mode 100644 index 00000000..8af2db64 --- /dev/null +++ b/spot-staking-subgraph/package.json @@ -0,0 +1,26 @@ +{ + "name": "@ampleforthorg/spot-staking-subgraph", + "version": "1.0.0", + "license": "GPL-3.0-or-later", + "scripts": { + "auth": "graph auth --studio", + "codegen": "graph codegen --output-dir ./generated", + "build": "graph build", + "lint": "yarn prettier --config .prettierrc --write '**/*.ts'", + "create-local": "graph create --node http://localhost:8020/ ampleforth/spot-staking", + "remove-local": "graph remove --node http://localhost:8020/ ampleforth/spot-staking", + "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 ampleforth/spot-staking", + "test": "echo 'TO_BE_IMPL'" + }, + "devDependencies": { + "@graphprotocol/graph-cli": "^0.21.1", + "@graphprotocol/graph-ts": "^0.20.0", + "@typescript-eslint/eslint-plugin": "^2.0.0", + "@typescript-eslint/parser": "^2.0.0", + "eslint": "^6.2.2", + "eslint-config-prettier": "^6.1.0", + "mustache": "^4.2.0", + "prettier": "^1.18.2", + "typescript": "^3.5.2" + } +} diff --git a/spot-staking-subgraph/schema.graphql b/spot-staking-subgraph/schema.graphql new file mode 100644 index 00000000..82f2139a --- /dev/null +++ b/spot-staking-subgraph/schema.graphql @@ -0,0 +1,47 @@ +type CharmVault @entity { + " the vault address " + id: ID! + pool: String! + name: String! + symbol: String! + decimals: BigInt! + token0: String! + token0Name: String! + token0Symbol: String! + token0Decimals: BigInt! + token1: String! + token1Name: String! + token1Symbol: String! + token1Decimals: BigInt! + token0Bal: BigDecimal! + token1Bal: BigDecimal! + token0BalIn: BigDecimal! + token1BalIn: BigDecimal! + token0Price: BigDecimal! + token1Price: BigDecimal! + tvl: BigDecimal! + valueIn: BigDecimal! + price: BigDecimal! + totalSupply: BigDecimal! + unusedToken0Bal: BigDecimal! + unusedToken1Bal: BigDecimal! + unusedTVL: BigDecimal! + dailyStats: [CharmVaultDailyStat!]! @derivedFrom(field: "vault") +} + +type CharmVaultDailyStat @entity { + "-" + id: ID! + vault: CharmVault! + timestamp: BigInt! + token0Bal: BigDecimal! + token1Bal: BigDecimal! + token0BalIn: BigDecimal! + token1BalIn: BigDecimal! + token0Price: BigDecimal! + token1Price: BigDecimal! + tvl: BigDecimal! + valueIn: BigDecimal! + price: BigDecimal! + totalSupply: BigDecimal! +} \ No newline at end of file diff --git a/spot-staking-subgraph/src/mappings.ts b/spot-staking-subgraph/src/mappings.ts new file mode 100644 index 00000000..d1430dc8 --- /dev/null +++ b/spot-staking-subgraph/src/mappings.ts @@ -0,0 +1,214 @@ +import { log, ethereum, BigInt, BigDecimal, Address } from '@graphprotocol/graph-ts' +import { Deposit, Withdraw, Snapshot } from '../generated/CharmVault/CharmVault' +import { CharmVault as CharmVaultABI } from '../generated/CharmVault/CharmVault' +import { UniV3Pool as UniV3PoolABI } from '../generated/CharmVault/UniV3Pool' +import { ERC20 as ERC20ABI } from '../generated/CharmVault/ERC20' +import { CharmVault, CharmVaultDailyStat } from '../generated/schema' + +let BIGINT_ZERO = BigInt.fromI32(0) +let BIGDECIMAL_ZERO = BigDecimal.fromString('0') +let BIGDECIMAL_ONE = BigDecimal.fromString('1') + +let BLOCK_UPDATE_INTERVAL = BigInt.fromI32(240) +let CHARM_VAULT_ID = '0x2dcaff0f75765d7867887fc402b71c841b3a4bfb' +let CHARM_VAULT_UPDATE_BLOCK = BigInt.fromI32(19798270) + +const dayTimestamp = (timestamp: BigInt): BigInt => { + return timestamp.minus(timestamp % BigInt.fromI32(24 * 3600)) +} +const stringToAddress = (id: string): Address => { + return Address.fromString(id) +} +const formatBalance = (wei: BigInt, decimals: BigInt): BigDecimal => { + return wei.toBigDecimal().div( + BigInt.fromI32(10) + .pow(decimals.toI32() as u8) + .toBigDecimal(), + ) +} + +// https://github.com/Uniswap/v3-subgraph/blob/main/src/utils/index.ts#L30 +function exponentToBigDecimal(decimals: BigInt): BigDecimal { + let resultString = '1' + for (let i = 0; i < decimals.toI32(); i++) { + resultString += '0' + } + return BigDecimal.fromString(resultString) +} +function safeDiv(amount0: BigDecimal, amount1: BigDecimal): BigDecimal { + if (amount1.equals(BIGDECIMAL_ZERO)) { + return BIGDECIMAL_ZERO + } else { + return amount0.div(amount1) + } +} +function sqrtPriceX96ToTokenPrices( + sqrtPriceX96: BigInt, + token0Decimals: BigInt, + token1Decimals: BigInt, +): BigDecimal[] { + let Q192 = BigInt.fromI32(2).pow(192 as u8) + let num = sqrtPriceX96.times(sqrtPriceX96).toBigDecimal() + let denom = BigDecimal.fromString(Q192.toString()) + let price1 = num + .div(denom) + .times(exponentToBigDecimal(token0Decimals)) + .div(exponentToBigDecimal(token1Decimals)) + let price0 = safeDiv(BigDecimal.fromString('1'), price1) + return [price0, price1] +} + +function fetchCharmVault(address: Address): CharmVault { + let id = address.toHexString() + let vault = CharmVault.load(id) + if (vault === null) { + vault = new CharmVault(id) + let vaultContract = CharmVaultABI.bind(address) + vault.pool = vaultContract.pool().toHexString() + vault.name = vaultContract.name() + vault.symbol = vaultContract.symbol() + vault.decimals = BigInt.fromI32(vaultContract.decimals()) + + let token0Address = vaultContract.token0() + let token0Contract = ERC20ABI.bind(token0Address) + vault.token0 = token0Address.toHexString() + vault.token0Name = token0Contract.name() + vault.token0Symbol = token0Contract.symbol() + vault.token0Decimals = BigInt.fromI32(token0Contract.decimals()) + + let token1Address = vaultContract.token1() + let token1Contract = ERC20ABI.bind(token1Address) + vault.token1 = token1Address.toHexString() + vault.token1Name = token1Contract.name() + vault.token1Symbol = token1Contract.symbol() + vault.token1Decimals = BigInt.fromI32(token1Contract.decimals()) + + vault.token0Bal = BIGDECIMAL_ZERO + vault.token1Bal = BIGDECIMAL_ZERO + vault.token0BalIn = BIGDECIMAL_ZERO + vault.token1BalIn = BIGDECIMAL_ZERO + vault.token0Price = BIGDECIMAL_ZERO + vault.token1Price = BIGDECIMAL_ZERO + vault.tvl = BIGDECIMAL_ZERO + vault.valueIn = BIGDECIMAL_ZERO + vault.price = BIGDECIMAL_ZERO + vault.totalSupply = BIGDECIMAL_ZERO + vault.unusedToken0Bal = BIGDECIMAL_ZERO + vault.unusedToken1Bal = BIGDECIMAL_ZERO + vault.unusedTVL = BIGDECIMAL_ZERO + vault.save() + } + return vault as CharmVault +} + +function fetchCharmVaultDailyStat(vault: CharmVault, timestamp: BigInt): CharmVaultDailyStat { + let id = vault.id.concat('-').concat(timestamp.toString()) + let dailyStat = CharmVaultDailyStat.load(id) + if (dailyStat === null) { + dailyStat = new CharmVaultDailyStat(id) + dailyStat.vault = vault.id + dailyStat.timestamp = timestamp + dailyStat.token0Bal = BIGDECIMAL_ZERO + dailyStat.token1Bal = BIGDECIMAL_ZERO + dailyStat.token0BalIn = BIGDECIMAL_ZERO + dailyStat.token1BalIn = BIGDECIMAL_ZERO + dailyStat.token0Price = BIGDECIMAL_ZERO + dailyStat.token1Price = BIGDECIMAL_ZERO + dailyStat.tvl = BIGDECIMAL_ZERO + dailyStat.valueIn = BIGDECIMAL_ZERO + dailyStat.price = BIGDECIMAL_ZERO + dailyStat.totalSupply = BIGDECIMAL_ZERO + dailyStat.save() + } + return dailyStat as CharmVaultDailyStat +} + +function refreshCharmVaultStats(vault: CharmVault, dailyStat: CharmVaultDailyStat): void { + let vaultContract = CharmVaultABI.bind(stringToAddress(vault.id)) + let tokenBals = vaultContract.getTotalAmounts() + let uniPoolContract = UniV3PoolABI.bind(stringToAddress(vault.pool)) + let slot0 = uniPoolContract.slot0() + let sqrtPrice = slot0.value0 + let prices = sqrtPriceX96ToTokenPrices(sqrtPrice, vault.token0Decimals, vault.token1Decimals) + + vault.token0Bal = formatBalance(tokenBals.value0, vault.token0Decimals) + vault.token1Bal = formatBalance(tokenBals.value1, vault.token1Decimals) + vault.token0Price = prices[0] + vault.token1Price = prices[1] + vault.tvl = vault.token0Bal.plus(vault.token1Bal.times(vault.token0Price)) + vault.totalSupply = formatBalance(vaultContract.totalSupply(), vault.decimals) + vault.price = vault.tvl.div(vault.totalSupply) + vault.unusedToken0Bal = formatBalance(vaultContract.getBalance0(), vault.token0Decimals) + vault.unusedToken1Bal = formatBalance(vaultContract.getBalance1(), vault.token1Decimals) + vault.unusedTVL = vault.unusedToken0Bal.plus(vault.unusedToken1Bal.times(vault.token0Price)) + vault.save() + + dailyStat.token0Bal = vault.token0Bal + dailyStat.token1Bal = vault.token1Bal + dailyStat.token0Price = vault.token0Price + dailyStat.token1Price = vault.token1Price + dailyStat.tvl = vault.tvl + dailyStat.totalSupply = vault.totalSupply + dailyStat.price = vault.price + dailyStat.save() +} + +export function handleDeposit(event: Deposit): void { + log.debug('triggered deposit', []) + let vault = fetchCharmVault(event.address) + let dailyStat = fetchCharmVaultDailyStat(vault, dayTimestamp(event.block.timestamp)) + refreshCharmVaultStats(vault, dailyStat) + vault.token0BalIn = vault.token0BalIn.plus( + formatBalance(event.params.amount0, vault.token0Decimals), + ) + vault.token1BalIn = vault.token1BalIn.plus( + formatBalance(event.params.amount1, vault.token1Decimals), + ) + vault.valueIn = vault.token0BalIn.plus(vault.token1BalIn.times(vault.token0Price)) + vault.save() + + dailyStat.token0BalIn = vault.token0BalIn + dailyStat.token1BalIn = vault.token1BalIn + dailyStat.valueIn = vault.valueIn + dailyStat.save() +} + +export function handleWithdraw(event: Withdraw): void { + log.debug('triggered withdraw', []) + let vault = fetchCharmVault(event.address) + let dailyStat = fetchCharmVaultDailyStat(vault, dayTimestamp(event.block.timestamp)) + refreshCharmVaultStats(vault, dailyStat) + vault.token0BalIn = vault.token0BalIn.minus( + formatBalance(event.params.amount0, vault.token0Decimals), + ) + vault.token1BalIn = vault.token1BalIn.minus( + formatBalance(event.params.amount1, vault.token1Decimals), + ) + vault.valueIn = vault.token0BalIn.plus(vault.token1BalIn.times(vault.token0Price)) + vault.save() + + dailyStat.token0BalIn = vault.token0BalIn + dailyStat.token1BalIn = vault.token1BalIn + dailyStat.valueIn = vault.valueIn + dailyStat.save() + dailyStat.save() +} + +export function handleSnapshot(event: Snapshot): void { + log.debug('triggered snapshot', []) + let vault = fetchCharmVault(event.address) + let dailyStat = fetchCharmVaultDailyStat(vault, dayTimestamp(event.block.timestamp)) + refreshCharmVaultStats(vault, dailyStat) +} + +export function refreshStore(block: ethereum.Block): void { + let timeForUpdate = + block.number.gt(CHARM_VAULT_UPDATE_BLOCK) && + block.number.mod(BLOCK_UPDATE_INTERVAL).equals(BIGINT_ZERO) + if (timeForUpdate) { + log.debug('triggered store refresh', []) + let vault = fetchCharmVault(stringToAddress(CHARM_VAULT_ID)) + let dailyStat = fetchCharmVaultDailyStat(vault, dayTimestamp(block.timestamp)) + refreshCharmVaultStats(vault, dailyStat) + } +} diff --git a/spot-staking-subgraph/subgraph.yaml b/spot-staking-subgraph/subgraph.yaml new file mode 100644 index 00000000..007875fc --- /dev/null +++ b/spot-staking-subgraph/subgraph.yaml @@ -0,0 +1,38 @@ +specVersion: 0.0.4 +description: Subgraph to keep track of spot staking +repository: http://github.com/ampleforth/spot +schema: + file: ./schema.graphql +dataSources: + - kind: ethereum/contract + name: CharmVault + network: mainnet + source: + address: "0x2dcaff0f75765d7867887fc402b71c841b3a4bfb" + abi: CharmVault + startBlock: 19792510 + mapping: + kind: ethereum/events + apiVersion: 0.0.4 + language: wasm/assemblyscript + entities: + - CharmVault + - UniV3Pool + - ERC20 + abis: + - name: CharmVault + file: ./abis/CharmVault.json + - name: UniV3Pool + file: ./abis/UniV3Pool.json + - name: ERC20 + file: ./abis/ERC20.json + eventHandlers: + - event: Deposit(indexed address,indexed address,uint256,uint256,uint256) + handler: handleDeposit + - event: Withdraw(indexed address,indexed address,uint256,uint256,uint256) + handler: handleWithdraw + - event: Snapshot(int24,uint256,uint256,uint256) + handler: handleSnapshot + blockHandlers: + - handler: refreshStore + file: ./src/mappings.ts \ No newline at end of file diff --git a/spot-subgraph/.eslintrc b/spot-subgraph/.eslintrc.js similarity index 100% rename from spot-subgraph/.eslintrc rename to spot-subgraph/.eslintrc.js diff --git a/spot-subgraph/.prettierrc b/spot-subgraph/.prettierrc index bd9e46e2..e02a9cfb 100644 --- a/spot-subgraph/.prettierrc +++ b/spot-subgraph/.prettierrc @@ -3,5 +3,5 @@ "trailingComma": "all", "singleQuote": true, "bracketSpacing": true, - "printWidth": 80 + "printWidth": 99 } diff --git a/spot-subgraph/README.md b/spot-subgraph/README.md index a5aa1ebf..12d43781 100644 --- a/spot-subgraph/README.md +++ b/spot-subgraph/README.md @@ -30,9 +30,9 @@ To build and deploy the subgraph to the graph hosted service: ``` # local deployment -./scripts/deploy-local.sh goerli ampleforth/spot-goerli +./scripts/deploy-local.sh sepolia ampleforth-spot-sepolia # prod deployment -./scripts/deploy.sh goerli ampleforth/spot-goerli -./scripts/deploy.sh mainnet ampleforth/spot +./scripts/deploy.sh sepolia ampleforth-spot-sepolia +./scripts/deploy.sh mainnet ampleforth-spot ``` \ No newline at end of file diff --git a/spot-subgraph/modified-artifacts/PerpetualTranche.json b/spot-subgraph/modified-artifacts/PerpetualTranche.json new file mode 100644 index 00000000..d12e1f64 --- /dev/null +++ b/spot-subgraph/modified-artifacts/PerpetualTranche.json @@ -0,0 +1,1166 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PerpetualTranche", + "sourceName": "contracts/PerpetualTranche.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ExceededMaxMintPerTranche", + "type": "error" + }, + { + "inputs": [], + "name": "ExceededMaxSupply", + "type": "error" + }, + { + "inputs": [], + "name": "ReserveCountOverLimit", + "type": "error" + }, + { + "inputs": [], + "name": "UnacceptableParams", + "type": "error" + }, + { + "inputs": [], + "name": "UnacceptableRollover", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedCall", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedTransferOut", + "type": "error" + }, + { + "inputs": [], + "name": "UnexpectedAsset", + "type": "error" + }, + { + "inputs": [], + "name": "UnexpectedDecimals", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "ReserveSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IBondController", + "name": "bond", + "type": "address" + } + ], + "name": "UpdatedDepositBond", + "type": "event" + }, + { + "inputs": [], + "name": "FEE_ONE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FEE_POLICY_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_RESERVE_COUNT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bondIssuer", + "outputs": [ + { + "internalType": "contract IBondIssuer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + } + ], + "name": "computeMintAmt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "perpAmtBurnt", + "type": "uint256" + } + ], + "name": "computeRedemptionAmts", + "outputs": [ + { + "components": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct TokenAmount[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "trancheInAmtAvailable", + "type": "uint256" + } + ], + "name": "computeRolloverAmt", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokenOutAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + } + ], + "internalType": "struct RolloverData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feePolicy", + "outputs": [ + { + "internalType": "contract IFeePolicy", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDepositBond", + "outputs": [ + { + "internalType": "contract IBondController", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getDepositTranche", + "outputs": [ + { + "internalType": "contract ITranche", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getDepositTrancheRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "i", + "type": "uint256" + } + ], + "name": "getReserveAt", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getReserveCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "getReserveTokenBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "getReserveTokenValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getReserveTokensUpForRollover", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTVL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "inReserve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "collateral_", + "type": "address" + }, + { + "internalType": "contract IBondIssuer", + "name": "bondIssuer_", + "type": "address" + }, + { + "internalType": "contract IFeePolicy", + "name": "feePolicy_", + "type": "address" + } + ], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "keeper", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxMintAmtPerTranche", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxTrancheMaturitySec", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minTrancheMaturitySec", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "", + "type": "address" + } + ], + "name": "mintedSupplyPerTranche", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "perpAmtBurnt", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITranche", + "name": "trancheIn", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "trancheInAmtAvailable", + "type": "uint256" + } + ], + "name": "rollover", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokenOutAmt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "trancheInAmt", + "type": "uint256" + } + ], + "internalType": "struct RolloverData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IBondIssuer", + "name": "bondIssuer_", + "type": "address" + } + ], + "name": "updateBondIssuer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IFeePolicy", + "name": "feePolicy_", + "type": "address" + } + ], + "name": "updateFeePolicy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeper_", + "type": "address" + } + ], + "name": "updateKeeper", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxSupply_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxMintAmtPerTranche_", + "type": "uint256" + } + ], + "name": "updateMintingLimits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minTrancheMaturitySec_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTrancheMaturitySec_", + "type": "uint256" + } + ], + "name": "updateTolerableTrancheMaturity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRolloverVault", + "name": "vault_", + "type": "address" + } + ], + "name": "updateVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vault", + "outputs": [ + { + "internalType": "contract IRolloverVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6146f080620000f36000396000f3fe608060405234801561001057600080fd5b50600436106103835760003560e01c8063729256eb116101de57806397b3fcaa1161010f578063d5abeb01116100ad578063eca05e961161007c578063eca05e961461076f578063ef98f88414610779578063f2fde38b1461078c578063fbfa77cf1461079f57600080fd5b8063d5abeb01146106f9578063db006a7514610703578063dd62ed3e14610723578063e7563f3f1461075c57600080fd5b8063a457c2d7116100e9578063a457c2d7146106a7578063a9059cbb146106ba578063aced1661146106cd578063b4abecc7146106e657600080fd5b806397b3fcaa14610684578063998065461461068c5780639db5dbe41461069457600080fd5b8063876853aa1161017c5780638fb69c4b116101565780638fb69c4b1461064e57806392a18b441461065657806395d89b4114610669578063977902171461067157600080fd5b8063876853aa1461062b5780638b539382146106355780638da5cb5b1461063d57600080fd5b806378f3ae74116101b857806378f3ae74146105e957806379cc6790146105fc578063825890381461060f5780638456cb591461062357600080fd5b8063729256eb146105ba57806376500c17146105ce57806377da7d8d146105d657600080fd5b806342966c68116102b85780636048d4911161025657806369f6f92c1161023057806369f6f92c1461056e5780636f307dc31461058157806370a0823114610589578063715018a6146105b257600080fd5b80636048d4911461054b578063614b4a431461055357806361902ffc1461055b57600080fd5b80634ce2f3ca116102925780634ce2f3ca146105105780635c975abb146105235780635dcc45b71461052e5780635ec572511461054157600080fd5b806342966c68146104d757806343cda19d146104ea57806347e7ef24146104fd57600080fd5b80632cff15ce11610325578063332d83d5116102ff578063332d83d51461049f578063364d22fc146104a757806339509351146104bc5780633f4ba83a146104cf57600080fd5b80632cff15ce146104515780632e5d55e114610464578063313ce5671461048557600080fd5b806318160ddd1161036157806318160ddd146103f45780631d8557d71461040657806323b872dd146104105780632bf8f1a51461042357600080fd5b806306fdde0314610388578063095ea7b3146103a6578063107c0418146103c9575b600080fd5b6103906107b3565b60405161039d9190613f8d565b60405180910390f35b6103b96103b4366004613fd5565b610845565b604051901515815260200161039d565b6103dc6103d7366004614001565b61085f565b6040516001600160a01b03909116815260200161039d565b6035545b60405190815260200161039d565b61040e61087a565b005b6103b961041e36600461401a565b610c08565b61043661043136600461401a565b610c2e565b6040805182518152602092830151928101929092520161039d565b61040e61045f36600461405b565b610d04565b6103f861047236600461407d565b6101386020526000908152604090205481565b61012d5460ff165b60405160ff909116815260200161039d565b6103dc610d3a565b6104af610d5f565b60405161039d919061409a565b6103b96104ca366004613fd5565b611007565b61040e611046565b61040e6104e5366004614001565b61107f565b6103f86104f836600461407d565b61108c565b6103f861050b366004613fd5565b611114565b61043661051e36600461401a565b6111d6565b60c95460ff166103b9565b6103b961053c36600461407d565b61122c565b6103f86101335481565b61048d600881565b6103f861123f565b6103f8610569366004613fd5565b61124e565b61040e61057c36600461407d565b611288565b6103dc61133b565b6103f861059736600461407d565b6001600160a01b031660009081526033602052604090205490565b61040e611347565b610131546103dc906001600160a01b031681565b61048d600b81565b6103f86105e436600461407d565b611359565b61040e6105f736600461418a565b61149c565b61040e61060a366004613fd5565b6116b6565b61012e546103dc906001600160a01b031681565b61040e6116cf565b6103f86101375481565b6103f8611708565b6097546001600160a01b03166103dc565b6103dc611728565b61040e61066436600461407d565b611743565b61039061180a565b61040e61067f36600461407d565b611819565b6103f8611861565b6103f8611873565b61040e6106a236600461401a565b611888565b6103b96106b5366004613fd5565b6118ea565b6103b96106c8366004613fd5565b611987565b61012d546103dc9061010090046001600160a01b031681565b61040e6106f436600461405b565b611995565b6103f86101365481565b610716610711366004614001565b6119d3565b60405161039d9190614228565b6103f8610731366004614280565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b61040e61076a36600461407d565b611af9565b6103f86101345481565b610716610787366004614001565b611b24565b61040e61079a36600461407d565b611b37565b61013d546103dc906001600160a01b031681565b6060603680546107c2906142b9565b80601f01602080910402602001604051908101604052809291908181526020018280546107ee906142b9565b801561083b5780601f106108105761010080835404028352916020019161083b565b820191906000526020600020905b81548152906001019060200180831161081e57829003601f168201915b5050505050905090565b600033610853818585611bad565b60019150505b92915050565b600061086961087a565b61087282611cd1565b90505b919050565b610882611cdf565b60c95460ff16610bfc57610131546040805163d5eb27a160e01b815290516000926001600160a01b03169163d5eb27a1916004808301926020929190829003018187875af11580156108d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108fc91906142f3565b610132549091506001600160a01b03808316911614801590610922575061092281611d38565b1561097a5761013280546001600160a01b0319166001600160a01b0383169081179091556040519081527f63e01b6b930f6bd3789aab43a62005627cb8a43517cd0569f997fd6b343b80239060200160405180910390a15b600061098761013a611fc5565b90506000610996600183614326565b90505b60ff811615610be55760006109b08260ff16611cd1565b90506000816001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1691906142f3565b90506000610a2c826001600160a01b0316611fcf565b1115610a39575050610bd3565b806001600160a01b031663ae4e7fdf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9b919061433f565b610af357806001600160a01b03166387b652076040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ada57600080fd5b505af1158015610aee573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b03808316916333d20e34918591908216906370a0823190602401602060405180830381865afa158015610b44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b689190614361565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610bae57600080fd5b505af1158015610bc2573d6000803e3d6000fd5b50505050610bcf8261204e565b5050505b80610bdd8161437a565b915050610999565b50610bf8610bf36000611cd1565b61204e565b5050505b610c06600160fb55565b565b600033610c168582856121b8565b610c2185858561224a565b60019150505b9392505050565b604080518082019091526000808252602082015261013d546001600160a01b03163314610c6e57604051637bf6a16f60e01b815260040160405180910390fd5b610c7661087a565b610c7e611cdf565b610c866123f5565b610c908484612448565b610cad57604051633c37540f60e21b815260040160405180910390fd5b6000610cba8585856124a4565b60208101519091501580610ccd57508051155b15610cd9579050610cfa565b610ce785826020015161292a565b50610cf684826000015161294a565b5090505b610c27600160fb55565b610d0c612960565b80821115610d2d57604051638d2e9ded60e01b815260040160405180910390fd5b6101339190915561013455565b6000610d4461087a565b61013254610d5a906001600160a01b03166129ba565b905090565b6060610d6961087a565b6000610d7661013a611fc5565b905060008160ff1667ffffffffffffffff811115610d9657610d966140e7565b604051908082528060200260200182016040528015610dbf578160200160208202803683370190505b509050600080610dcf6000611cd1565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3d9190614361565b1115610e7d578083600081518110610e5757610e57614397565b6001600160a01b039092166020928302919091019091015281610e79816143ad565b9250505b60015b8460ff168160ff161015610ef9576000610e9c8260ff16611cd1565b9050610ea781612a25565b15610ee85780858360ff1681518110610ec257610ec2614397565b6001600160a01b039092166020928302919091019091015283610ee4816143ad565b9450505b50610ef2816143ad565b9050610e80565b5060008260ff1667ffffffffffffffff811115610f1857610f186140e7565b604051908082528060200260200182016040528015610f41578160200160208202803683370190505b5090506000805b8660ff168160ff161015610ffb5760006001600160a01b0316868260ff1681518110610f7657610f76614397565b60200260200101516001600160a01b031614610feb57858160ff1681518110610fa157610fa1614397565b6020026020010151838380610fb5906143ad565b945060ff1681518110610fca57610fca614397565b60200260200101906001600160a01b031690816001600160a01b0316815250505b610ff4816143ad565b9050610f48565b50909550505050505090565b3360008181526034602090815260408083206001600160a01b038716845290915281205490919061085390829086906110419087906143cc565b611bad565b61012d5461010090046001600160a01b0316331461107757604051637bf6a16f60e01b815260040160405180910390fd5b610c06612aa6565b6110893382612af8565b50565b600061109661087a565b61109f82612c2c565b6110ab57506000919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a08231906024015b602060405180830381865afa1580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108729190614361565b600061111e61087a565b611126611cdf565b61112e6123f5565b61113783612c3a565b61115457604051632c88119960e11b815260040160405180910390fd5b60006111608484612c57565b905082158061116d575080155b1561117c5760009150506111cc565b611186848461292a565b506111913382612d7f565b6001600160a01b03841660009081526101386020526040812080548392906111ba9084906143cc565b909155506111c9905084612e40565b90505b610859600160fb55565b60408051808201909152600080825260208201526111f261087a565b6111fc8484612448565b61121957604051633c37540f60e21b815260040160405180910390fd5b6112248484846124a4565b949350505050565b600061123661087a565b61087282612c2c565b61124b6008600a6144c3565b81565b600061125861087a565b61126183612c3a565b61127e57604051632c88119960e11b815260040160405180910390fd5b610c278383612c57565b611290612960565b600860ff16816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f791906144d2565b60ff16146113185760405163c51d798560e01b815260040160405180910390fd5b61012e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610d5a6000611cd1565b61134f612960565b610c066000612eae565b600061136361087a565b61136c82612c2c565b61137857506000919050565b61138182612f00565b156113b2576040516370a0823160e01b81523060048201526001600160a01b038316906370a08231906024016110d3565b60008290506000816001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141b91906142f3565b9050611224828261142c6000611cd1565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a08231906024015b602060405180830381865afa158015611471573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114959190614361565b6001612f27565b600054610100900460ff16158080156114bc5750600054600160ff909116105b806114d65750303b1580156114d6575060005460ff166001145b61154d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015611570576000805461ff0019166101001790555b61157a8686613044565b6115826130a7565b61158a613100565b611592613161565b61159a6131c2565b836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc91906144d2565b61012d805460ff191660ff9290921691909117905561161d61013a85613223565b506116278461204e565b5061163d61067f6097546001600160a01b031690565b61164682611288565b61164f83611743565b61165c6001600019610d04565b61166860001980611995565b80156116ae576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6116c18233836121b8565b6116cb8282612af8565b5050565b61012d5461010090046001600160a01b0316331461170057604051637bf6a16f60e01b815260040160405180910390fd5b610c06613238565b600061171261087a565b61013254610d5a906001600160a01b0316613275565b600061173261087a565b50610132546001600160a01b031690565b61174b612960565b6117556000611cd1565b6001600160a01b0316816001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561179c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c091906142f3565b6001600160a01b0316146117e757604051632c88119960e11b815260040160405180910390fd5b61013180546001600160a01b0319166001600160a01b0392909216919091179055565b6060603780546107c2906142b9565b611821612960565b61012d80546001600160a01b03909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b600061186b61087a565b610d5a6132e0565b600061187d61087a565b610d5a61013a611fc5565b61189061087a565b611898611cdf565b6118a0612960565b6118a983612c2c565b156118c7576040516328071e2f60e11b815260040160405180910390fd5b6118db6001600160a01b0384168383613452565b6118e5600160fb55565b505050565b3360008181526034602090815260408083206001600160a01b03871684529091528120549091908381101561196f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401611544565b61197c8286868403611bad565b506001949350505050565b60003361085381858561224a565b61012d5461010090046001600160a01b031633146119c657604051637bf6a16f60e01b815260040160405180910390fd5b6101369190915561013755565b60606119dd61087a565b6119e5611cdf565b6119ed6123f5565b60008211611a3a576040805160008082526020820190925290611a32565b6040805180820190915260008082526020820152815260200190600190039081611a0b5790505b509050611aef565b6000611a45836134ca565b9050611a513384612af8565b805160005b8160ff168160ff161015611ae9576000838260ff1681518110611a7b57611a7b614397565b6020026020010151602001511115611ad957611ad7838260ff1681518110611aa557611aa5614397565b602002602001015160000151848360ff1681518110611ac657611ac6614397565b60200260200101516020015161294a565b505b611ae2816143ad565b9050611a56565b50909150505b610875600160fb55565b611b01612960565b61013d80546001600160a01b0319166001600160a01b0392909216919091179055565b6060611b2e61087a565b610872826134ca565b611b3f612960565b6001600160a01b038116611ba45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611544565b61108981612eae565b6001600160a01b038316611c0f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401611544565b6001600160a01b038216611c705760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401611544565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061087261013a83613750565b600260fb5403611d315760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611544565b600260fb55565b6000611d446000611cd1565b6001600160a01b0316826001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611daf91906142f3565b6001600160a01b0316148015611e265750816001600160a01b03166359eb82246040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e229190614361565b6002145b8015611e915750816001600160a01b03166324a9d8536040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8f9190614361565b155b8015611eb0575061013454611eae836001600160a01b0316611fcf565b105b8015611f3857506001600160a01b038216611ecc81600061375c565b6001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2d91906142f3565b6001600160a01b0316145b801561087257506001600160a01b038216611f5481600161375c565b6001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906142f3565b6001600160a01b03161492915050565b6000610872825490565b600080826001600160a01b031663d59624b46040518163ffffffff1660e01b8152600401602060405180830381865afa158015612010573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120349190614361565b9050428111612044576000610c27565b610c2742826144f5565b6040516370a0823160e01b815230600482015260009081906001600160a01b038416906370a0823190602401602060405180830381865afa158015612097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bb9190614361565b604080516001600160a01b0386168152602081018390529192507fd1fbbd81a5fd46d869b5cd6883d99108cd295072be1b09d36381bbc78b686939910160405180910390a161210983612f00565b156121145792915050565b600061211f84612c2c565b905060008211801561212f575080155b156121725761214061013a85613223565b50600b61214e61013a611fc5565b111561216d57604051630aadf0b960e41b815260040160405180910390fd5b6121aa565b8115801561217d5750805b156121aa5761218e61013a856137d1565b506001600160a01b038416600090815261013860205260408120555b5092915050565b600160fb55565b6001600160a01b03838116600090815260346020908152604080832093861683529290522054600019811461224457818110156122375760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401611544565b6122448484848403611bad565b50505050565b6001600160a01b0383166122ae5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401611544565b6001600160a01b0382166123105760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401611544565b6001600160a01b038316600090815260336020526040902054818110156123885760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401611544565b6001600160a01b0380851660008181526033602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906123e89086815260200190565b60405180910390a3612244565b60c95460ff1615610c065760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401611544565b600061245382612f00565b156124685761246183612c3a565b9050610859565b8161247284612c3a565b8015612482575061248281612c2c565b8015612494575061249281612c3a565b155b8015611224575061122481612a25565b604080518082019091526000808252602082015261012e5460408051606081019091526000916001600160a01b031690638b83535b9082906301356c8c90806124eb6132e0565b815261013d5460408051634bd9fe5560e11b815290516020938401936001600160a01b03909316926397b3fcaa92600480820193918290030181865afa158015612539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255d9190614361565b81526101325460209091019061257b906001600160a01b0316613275565b9052604080516001600160e01b031960e085901b16815282516004820152602083015160248201529101516044820152606401602060405180830381865afa1580156125cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ef9190614361565b6040518263ffffffff1660e01b815260040161260d91815260200190565b602060405180830381865afa15801561262a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264e9190614361565b9050600061265c6000611cd1565b61012d549091506000906126749060ff16600a6144c3565b610132549091506000906126959089906001600160a01b0316858585612f27565b9050816001600160a01b038881169085161461272357600088905061271f81826001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061271691906142f3565b87876001612f27565b9150505b6040516370a0823160e01b81523060048201526000906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614361565b905087158061279b575080155b806127a4575082155b806127ad575081155b156127d65760405180604001604052806000815260200160008152509650505050505050610c27565b60408051808201909152818152600090602081016127f784868860016137e6565b90529050600087131561284a576128406128136008600a6144c3565b61281c89613843565b6128286008600a6144c3565b61283291906144f5565b6020840151919060016137e6565b6020820152612887565b6000871215612887576128816128626008600a6144c3565b61286b89613899565b6128776008600a6144c3565b61283291906143cc565b60208201525b888160200151111561291c57602081018990526128a58985856138ac565b815260008713156128ee576128e76128bc88613899565b6128c86008600a6144c3565b6128d291906144f5565b6128de6008600a6144c3565b835191906138ac565b815261291c565b600087121561291c5761291961290388613899565b61290f6008600a6144c3565b6128d291906143cc565b81525b9a9950505050505050505050565b60006129416001600160a01b03841633308561399e565b610c278361204e565b60006129416001600160a01b0384163384613452565b6097546001600160a01b03163314610c065760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611544565b6040516313612cb160e11b8152600060048201819052906001600160a01b038316906326c25962906024016040805180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa9190614508565b600061013354612a9e836001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9091906142f3565b6001600160a01b0316611fcf565b111592915050565b612aae6139d6565b60c9805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216612b585760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401611544565b6001600160a01b03821660009081526033602052604090205481811015612bcc5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401611544565b6001600160a01b03831660008181526033602090815260408083208686039055603580548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b600061087261013a83613a28565b610132546000906001600160a01b0380841691611fb591166129ba565b610132546000908190612c809085906001600160a01b0316612c7884611cd1565b866000612f27565b61013d549091506000906001600160a01b03163314612d165761012e60009054906101000a90046001600160a01b03166001600160a01b0316630a98b70d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d119190614361565b612d19565b60005b90506000612d2660355490565b9050828115612d4657612d4382612d3b6132e0565b8391906138ac565b90505b8215612d7557612d7283612d5c6008600a6144c3565b612d6691906144f5565b612d3b6008600a6144c3565b90505b9695505050505050565b6001600160a01b038216612dd55760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401611544565b8060356000828254612de791906143cc565b90915550506001600160a01b0382166000818152603360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b610137546001600160a01b038216600090815261013860205260409020541115612e7d57604051630381ed1760e31b815260040160405180910390fd5b6000612e8860355490565b9050610136548111156116cb5760405163fb88d21560e01b815260040160405180910390fd5b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000612f0c6000611cd1565b6001600160a01b0316826001600160a01b0316149050919050565b6040516370a0823160e01b81526001600160a01b03858116600483015260009182918616906370a0823190602401602060405180830381865afa158015612f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f969190614361565b90506000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffc9190614361565b9050600061300a8284613a4a565b90506000821161301a5785613037565b61303786838761302b57600061302e565b60015b849291906137e6565b9998505050505050505050565b600054610100900460ff1661309d5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b6116cb8282613a60565b600054610100900460ff16610c065760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b600054610100900460ff166131595760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b610c06613ad2565b600054610100900460ff166131ba5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b610c06613b34565b600054610100900460ff1661321b5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b610c06613b99565b6000610c27836001600160a01b038416613bf2565b6132406123f5565b60c9805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612adb3390565b6040516313612cb160e11b8152600060048201819052906001600160a01b038316906326c25962906024016040805180830381865afa1580156132bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c279190614508565b6000806132ed6000611cd1565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613337573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061335b9190614361565b9050600061336a61013a611fc5565b905060015b8160ff168160ff16101561344957600061338b8260ff16611cd1565b90506000816001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f191906142f3565b6040516370a0823160e01b815230600482015290915061342a908390839089906001600160a01b038416906370a0823190602401611454565b61343490866143cc565b9450505080613442906143ad565b905061336f565b50909392505050565b6040516001600160a01b0383166024820152604481018290526118e590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152613c41565b606060006134d760355490565b61013d549091506000906001600160a01b0316331461356d5761012e60009054906101000a90046001600160a01b03166001600160a01b031663ca9cbcbe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613544573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135689190614361565b613570565b60005b9050600061357f61013a611fc5565b905060008160ff1667ffffffffffffffff81111561359f5761359f6140e7565b6040519080825280602002602001820160405280156135e457816020015b60408051808201909152600080825260208201528152602001906001900390816135bd5790505b50905060005b8260ff168160ff1610156137465760006136068260ff16611cd1565b6040805180820182526001600160a01b03831680825291516370a0823160e01b8152306004820152929350916020830191613690918c918b916370a0823190602401602060405180830381865afa158015613665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136899190614361565b91906138ac565b815250838360ff16815181106136a8576136a8614397565b602090810291909101015284156137355761370f856136c96008600a6144c3565b6136d391906144f5565b6136df6008600a6144c3565b858560ff16815181106136f4576136f4614397565b6020026020010151602001516138ac9092919063ffffffff16565b838360ff168151811061372457613724614397565b602002602001015160200181815250505b5061373f816143ad565b90506135ea565b5095945050505050565b6000610c278383613d29565b6040516313612cb160e11b815260ff821660048201526000906001600160a01b038416906326c25962906024016040805180830381865afa1580156137a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c99190614508565b509392505050565b6000610c27836001600160a01b038416613d53565b6000806137f48686866138ac565b9050600183600281111561380a5761380a614536565b1480156138275750600084806138225761382261454c565b868809115b1561383a576138376001826143cc565b90505b95945050505050565b6000808212156138955760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f7369746976656044820152606401611544565b5090565b6000808212156138955781600003610872565b60008080600019858709858702925082811083820303915050806000036138e6578382816138dc576138dc61454c565b0492505050610c27565b8084116139355760405162461bcd60e51b815260206004820152601560248201527f4d6174683a206d756c446976206f766572666c6f7700000000000000000000006044820152606401611544565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6040516001600160a01b03808516602483015283166044820152606481018290526122449085906323b872dd60e01b9060840161347e565b60c95460ff16610c065760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401611544565b6001600160a01b03811660009081526001830160205260408120541515610c27565b6000818310613a595781610c27565b5090919050565b600054610100900460ff16613ab95760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b6036613ac583826145a8565b5060376118e582826145a8565b600054610100900460ff16613b2b5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b610c0633612eae565b600054610100900460ff16613b8d5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b60c9805460ff19169055565b600054610100900460ff166121b15760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b6000818152600183016020526040812054613c3957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610859565b506000610859565b6000613c96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e469092919063ffffffff16565b9050805160001480613cb7575080806020019051810190613cb7919061433f565b6118e55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611544565b6000826000018281548110613d4057613d40614397565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613e3c576000613d776001836144f5565b8554909150600090613d8b906001906144f5565b9050818114613df0576000866000018281548110613dab57613dab614397565b9060005260206000200154905080876000018481548110613dce57613dce614397565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613e0157613e01614668565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610859565b6000915050610859565b6060611224848460008585600080866001600160a01b03168587604051613e6d919061467e565b60006040518083038185875af1925050503d8060008114613eaa576040519150601f19603f3d011682016040523d82523d6000602084013e613eaf565b606091505b5091509150613ec087838387613ecb565b979650505050505050565b60608315613f3a578251600003613f33576001600160a01b0385163b613f335760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611544565b5081611224565b6112248383815115613f4f5781518083602001fd5b8060405162461bcd60e51b81526004016115449190613f8d565b60005b83811015613f84578181015183820152602001613f6c565b50506000910152565b6020815260008251806020840152613fac816040850160208701613f69565b601f01601f19169190910160400192915050565b6001600160a01b038116811461108957600080fd5b60008060408385031215613fe857600080fd5b8235613ff381613fc0565b946020939093013593505050565b60006020828403121561401357600080fd5b5035919050565b60008060006060848603121561402f57600080fd5b833561403a81613fc0565b9250602084013561404a81613fc0565b929592945050506040919091013590565b6000806040838503121561406e57600080fd5b50508035926020909101359150565b60006020828403121561408f57600080fd5b8135610c2781613fc0565b6020808252825182820181905260009190848201906040850190845b818110156140db5783516001600160a01b0316835292840192918401916001016140b6565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261410e57600080fd5b813567ffffffffffffffff80821115614129576141296140e7565b604051601f8301601f19908116603f01168101908282118183101715614151576141516140e7565b8160405283815286602085880101111561416a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156141a257600080fd5b853567ffffffffffffffff808211156141ba57600080fd5b6141c689838a016140fd565b965060208801359150808211156141dc57600080fd5b506141e9888289016140fd565b94505060408601356141fa81613fc0565b9250606086013561420a81613fc0565b9150608086013561421a81613fc0565b809150509295509295909350565b602080825282518282018190526000919060409081850190868401855b8281101561427357815180516001600160a01b03168552860151868501529284019290850190600101614245565b5091979650505050505050565b6000806040838503121561429357600080fd5b823561429e81613fc0565b915060208301356142ae81613fc0565b809150509250929050565b600181811c908216806142cd57607f821691505b6020821081036142ed57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561430557600080fd5b8151610c2781613fc0565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111561085957610859614310565b60006020828403121561435157600080fd5b81518015158114610c2757600080fd5b60006020828403121561437357600080fd5b5051919050565b600060ff82168061438d5761438d614310565b6000190192915050565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff81036143c3576143c3614310565b60010192915050565b8082018082111561085957610859614310565b600181815b8085111561441a57816000190482111561440057614400614310565b8085161561440d57918102915b93841c93908002906143e4565b509250929050565b60008261443157506001610859565b8161443e57506000610859565b8160018114614454576002811461445e5761447a565b6001915050610859565b60ff84111561446f5761446f614310565b50506001821b610859565b5060208310610133831016604e8410600b841016171561449d575081810a610859565b6144a783836143df565b80600019048211156144bb576144bb614310565b029392505050565b6000610c2760ff841683614422565b6000602082840312156144e457600080fd5b815160ff81168114610c2757600080fd5b8181038181111561085957610859614310565b6000806040838503121561451b57600080fd5b825161452681613fc0565b6020939093015192949293505050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b601f8211156118e557600081815260208120601f850160051c810160208610156145895750805b601f850160051c820191505b818110156116ae57828155600101614595565b815167ffffffffffffffff8111156145c2576145c26140e7565b6145d6816145d084546142b9565b84614562565b602080601f83116001811461460b57600084156145f35750858301515b600019600386901b1c1916600185901b1785556116ae565b600085815260208120601f198616915b8281101561463a5788860151825594840194600190910190840161461b565b50858210156146585787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603160045260246000fd5b60008251614690818460208701613f69565b919091019291505056fe496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069a2646970667358221220117437feaf340e0dba3091f1ecdc2dc97a8597e7902ee832f48f151e08b9e97d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106103835760003560e01c8063729256eb116101de57806397b3fcaa1161010f578063d5abeb01116100ad578063eca05e961161007c578063eca05e961461076f578063ef98f88414610779578063f2fde38b1461078c578063fbfa77cf1461079f57600080fd5b8063d5abeb01146106f9578063db006a7514610703578063dd62ed3e14610723578063e7563f3f1461075c57600080fd5b8063a457c2d7116100e9578063a457c2d7146106a7578063a9059cbb146106ba578063aced1661146106cd578063b4abecc7146106e657600080fd5b806397b3fcaa14610684578063998065461461068c5780639db5dbe41461069457600080fd5b8063876853aa1161017c5780638fb69c4b116101565780638fb69c4b1461064e57806392a18b441461065657806395d89b4114610669578063977902171461067157600080fd5b8063876853aa1461062b5780638b539382146106355780638da5cb5b1461063d57600080fd5b806378f3ae74116101b857806378f3ae74146105e957806379cc6790146105fc578063825890381461060f5780638456cb591461062357600080fd5b8063729256eb146105ba57806376500c17146105ce57806377da7d8d146105d657600080fd5b806342966c68116102b85780636048d4911161025657806369f6f92c1161023057806369f6f92c1461056e5780636f307dc31461058157806370a0823114610589578063715018a6146105b257600080fd5b80636048d4911461054b578063614b4a431461055357806361902ffc1461055b57600080fd5b80634ce2f3ca116102925780634ce2f3ca146105105780635c975abb146105235780635dcc45b71461052e5780635ec572511461054157600080fd5b806342966c68146104d757806343cda19d146104ea57806347e7ef24146104fd57600080fd5b80632cff15ce11610325578063332d83d5116102ff578063332d83d51461049f578063364d22fc146104a757806339509351146104bc5780633f4ba83a146104cf57600080fd5b80632cff15ce146104515780632e5d55e114610464578063313ce5671461048557600080fd5b806318160ddd1161036157806318160ddd146103f45780631d8557d71461040657806323b872dd146104105780632bf8f1a51461042357600080fd5b806306fdde0314610388578063095ea7b3146103a6578063107c0418146103c9575b600080fd5b6103906107b3565b60405161039d9190613f8d565b60405180910390f35b6103b96103b4366004613fd5565b610845565b604051901515815260200161039d565b6103dc6103d7366004614001565b61085f565b6040516001600160a01b03909116815260200161039d565b6035545b60405190815260200161039d565b61040e61087a565b005b6103b961041e36600461401a565b610c08565b61043661043136600461401a565b610c2e565b6040805182518152602092830151928101929092520161039d565b61040e61045f36600461405b565b610d04565b6103f861047236600461407d565b6101386020526000908152604090205481565b61012d5460ff165b60405160ff909116815260200161039d565b6103dc610d3a565b6104af610d5f565b60405161039d919061409a565b6103b96104ca366004613fd5565b611007565b61040e611046565b61040e6104e5366004614001565b61107f565b6103f86104f836600461407d565b61108c565b6103f861050b366004613fd5565b611114565b61043661051e36600461401a565b6111d6565b60c95460ff166103b9565b6103b961053c36600461407d565b61122c565b6103f86101335481565b61048d600881565b6103f861123f565b6103f8610569366004613fd5565b61124e565b61040e61057c36600461407d565b611288565b6103dc61133b565b6103f861059736600461407d565b6001600160a01b031660009081526033602052604090205490565b61040e611347565b610131546103dc906001600160a01b031681565b61048d600b81565b6103f86105e436600461407d565b611359565b61040e6105f736600461418a565b61149c565b61040e61060a366004613fd5565b6116b6565b61012e546103dc906001600160a01b031681565b61040e6116cf565b6103f86101375481565b6103f8611708565b6097546001600160a01b03166103dc565b6103dc611728565b61040e61066436600461407d565b611743565b61039061180a565b61040e61067f36600461407d565b611819565b6103f8611861565b6103f8611873565b61040e6106a236600461401a565b611888565b6103b96106b5366004613fd5565b6118ea565b6103b96106c8366004613fd5565b611987565b61012d546103dc9061010090046001600160a01b031681565b61040e6106f436600461405b565b611995565b6103f86101365481565b610716610711366004614001565b6119d3565b60405161039d9190614228565b6103f8610731366004614280565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b61040e61076a36600461407d565b611af9565b6103f86101345481565b610716610787366004614001565b611b24565b61040e61079a36600461407d565b611b37565b61013d546103dc906001600160a01b031681565b6060603680546107c2906142b9565b80601f01602080910402602001604051908101604052809291908181526020018280546107ee906142b9565b801561083b5780601f106108105761010080835404028352916020019161083b565b820191906000526020600020905b81548152906001019060200180831161081e57829003601f168201915b5050505050905090565b600033610853818585611bad565b60019150505b92915050565b600061086961087a565b61087282611cd1565b90505b919050565b610882611cdf565b60c95460ff16610bfc57610131546040805163d5eb27a160e01b815290516000926001600160a01b03169163d5eb27a1916004808301926020929190829003018187875af11580156108d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108fc91906142f3565b610132549091506001600160a01b03808316911614801590610922575061092281611d38565b1561097a5761013280546001600160a01b0319166001600160a01b0383169081179091556040519081527f63e01b6b930f6bd3789aab43a62005627cb8a43517cd0569f997fd6b343b80239060200160405180910390a15b600061098761013a611fc5565b90506000610996600183614326565b90505b60ff811615610be55760006109b08260ff16611cd1565b90506000816001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1691906142f3565b90506000610a2c826001600160a01b0316611fcf565b1115610a39575050610bd3565b806001600160a01b031663ae4e7fdf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9b919061433f565b610af357806001600160a01b03166387b652076040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ada57600080fd5b505af1158015610aee573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b03808316916333d20e34918591908216906370a0823190602401602060405180830381865afa158015610b44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b689190614361565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610bae57600080fd5b505af1158015610bc2573d6000803e3d6000fd5b50505050610bcf8261204e565b5050505b80610bdd8161437a565b915050610999565b50610bf8610bf36000611cd1565b61204e565b5050505b610c06600160fb55565b565b600033610c168582856121b8565b610c2185858561224a565b60019150505b9392505050565b604080518082019091526000808252602082015261013d546001600160a01b03163314610c6e57604051637bf6a16f60e01b815260040160405180910390fd5b610c7661087a565b610c7e611cdf565b610c866123f5565b610c908484612448565b610cad57604051633c37540f60e21b815260040160405180910390fd5b6000610cba8585856124a4565b60208101519091501580610ccd57508051155b15610cd9579050610cfa565b610ce785826020015161292a565b50610cf684826000015161294a565b5090505b610c27600160fb55565b610d0c612960565b80821115610d2d57604051638d2e9ded60e01b815260040160405180910390fd5b6101339190915561013455565b6000610d4461087a565b61013254610d5a906001600160a01b03166129ba565b905090565b6060610d6961087a565b6000610d7661013a611fc5565b905060008160ff1667ffffffffffffffff811115610d9657610d966140e7565b604051908082528060200260200182016040528015610dbf578160200160208202803683370190505b509050600080610dcf6000611cd1565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3d9190614361565b1115610e7d578083600081518110610e5757610e57614397565b6001600160a01b039092166020928302919091019091015281610e79816143ad565b9250505b60015b8460ff168160ff161015610ef9576000610e9c8260ff16611cd1565b9050610ea781612a25565b15610ee85780858360ff1681518110610ec257610ec2614397565b6001600160a01b039092166020928302919091019091015283610ee4816143ad565b9450505b50610ef2816143ad565b9050610e80565b5060008260ff1667ffffffffffffffff811115610f1857610f186140e7565b604051908082528060200260200182016040528015610f41578160200160208202803683370190505b5090506000805b8660ff168160ff161015610ffb5760006001600160a01b0316868260ff1681518110610f7657610f76614397565b60200260200101516001600160a01b031614610feb57858160ff1681518110610fa157610fa1614397565b6020026020010151838380610fb5906143ad565b945060ff1681518110610fca57610fca614397565b60200260200101906001600160a01b031690816001600160a01b0316815250505b610ff4816143ad565b9050610f48565b50909550505050505090565b3360008181526034602090815260408083206001600160a01b038716845290915281205490919061085390829086906110419087906143cc565b611bad565b61012d5461010090046001600160a01b0316331461107757604051637bf6a16f60e01b815260040160405180910390fd5b610c06612aa6565b6110893382612af8565b50565b600061109661087a565b61109f82612c2c565b6110ab57506000919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a08231906024015b602060405180830381865afa1580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108729190614361565b600061111e61087a565b611126611cdf565b61112e6123f5565b61113783612c3a565b61115457604051632c88119960e11b815260040160405180910390fd5b60006111608484612c57565b905082158061116d575080155b1561117c5760009150506111cc565b611186848461292a565b506111913382612d7f565b6001600160a01b03841660009081526101386020526040812080548392906111ba9084906143cc565b909155506111c9905084612e40565b90505b610859600160fb55565b60408051808201909152600080825260208201526111f261087a565b6111fc8484612448565b61121957604051633c37540f60e21b815260040160405180910390fd5b6112248484846124a4565b949350505050565b600061123661087a565b61087282612c2c565b61124b6008600a6144c3565b81565b600061125861087a565b61126183612c3a565b61127e57604051632c88119960e11b815260040160405180910390fd5b610c278383612c57565b611290612960565b600860ff16816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f791906144d2565b60ff16146113185760405163c51d798560e01b815260040160405180910390fd5b61012e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610d5a6000611cd1565b61134f612960565b610c066000612eae565b600061136361087a565b61136c82612c2c565b61137857506000919050565b61138182612f00565b156113b2576040516370a0823160e01b81523060048201526001600160a01b038316906370a08231906024016110d3565b60008290506000816001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141b91906142f3565b9050611224828261142c6000611cd1565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a08231906024015b602060405180830381865afa158015611471573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114959190614361565b6001612f27565b600054610100900460ff16158080156114bc5750600054600160ff909116105b806114d65750303b1580156114d6575060005460ff166001145b61154d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015611570576000805461ff0019166101001790555b61157a8686613044565b6115826130a7565b61158a613100565b611592613161565b61159a6131c2565b836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc91906144d2565b61012d805460ff191660ff9290921691909117905561161d61013a85613223565b506116278461204e565b5061163d61067f6097546001600160a01b031690565b61164682611288565b61164f83611743565b61165c6001600019610d04565b61166860001980611995565b80156116ae576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6116c18233836121b8565b6116cb8282612af8565b5050565b61012d5461010090046001600160a01b0316331461170057604051637bf6a16f60e01b815260040160405180910390fd5b610c06613238565b600061171261087a565b61013254610d5a906001600160a01b0316613275565b600061173261087a565b50610132546001600160a01b031690565b61174b612960565b6117556000611cd1565b6001600160a01b0316816001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561179c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c091906142f3565b6001600160a01b0316146117e757604051632c88119960e11b815260040160405180910390fd5b61013180546001600160a01b0319166001600160a01b0392909216919091179055565b6060603780546107c2906142b9565b611821612960565b61012d80546001600160a01b03909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b600061186b61087a565b610d5a6132e0565b600061187d61087a565b610d5a61013a611fc5565b61189061087a565b611898611cdf565b6118a0612960565b6118a983612c2c565b156118c7576040516328071e2f60e11b815260040160405180910390fd5b6118db6001600160a01b0384168383613452565b6118e5600160fb55565b505050565b3360008181526034602090815260408083206001600160a01b03871684529091528120549091908381101561196f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401611544565b61197c8286868403611bad565b506001949350505050565b60003361085381858561224a565b61012d5461010090046001600160a01b031633146119c657604051637bf6a16f60e01b815260040160405180910390fd5b6101369190915561013755565b60606119dd61087a565b6119e5611cdf565b6119ed6123f5565b60008211611a3a576040805160008082526020820190925290611a32565b6040805180820190915260008082526020820152815260200190600190039081611a0b5790505b509050611aef565b6000611a45836134ca565b9050611a513384612af8565b805160005b8160ff168160ff161015611ae9576000838260ff1681518110611a7b57611a7b614397565b6020026020010151602001511115611ad957611ad7838260ff1681518110611aa557611aa5614397565b602002602001015160000151848360ff1681518110611ac657611ac6614397565b60200260200101516020015161294a565b505b611ae2816143ad565b9050611a56565b50909150505b610875600160fb55565b611b01612960565b61013d80546001600160a01b0319166001600160a01b0392909216919091179055565b6060611b2e61087a565b610872826134ca565b611b3f612960565b6001600160a01b038116611ba45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611544565b61108981612eae565b6001600160a01b038316611c0f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401611544565b6001600160a01b038216611c705760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401611544565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061087261013a83613750565b600260fb5403611d315760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611544565b600260fb55565b6000611d446000611cd1565b6001600160a01b0316826001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611daf91906142f3565b6001600160a01b0316148015611e265750816001600160a01b03166359eb82246040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e229190614361565b6002145b8015611e915750816001600160a01b03166324a9d8536040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8f9190614361565b155b8015611eb0575061013454611eae836001600160a01b0316611fcf565b105b8015611f3857506001600160a01b038216611ecc81600061375c565b6001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2d91906142f3565b6001600160a01b0316145b801561087257506001600160a01b038216611f5481600161375c565b6001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906142f3565b6001600160a01b03161492915050565b6000610872825490565b600080826001600160a01b031663d59624b46040518163ffffffff1660e01b8152600401602060405180830381865afa158015612010573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120349190614361565b9050428111612044576000610c27565b610c2742826144f5565b6040516370a0823160e01b815230600482015260009081906001600160a01b038416906370a0823190602401602060405180830381865afa158015612097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bb9190614361565b604080516001600160a01b0386168152602081018390529192507fd1fbbd81a5fd46d869b5cd6883d99108cd295072be1b09d36381bbc78b686939910160405180910390a161210983612f00565b156121145792915050565b600061211f84612c2c565b905060008211801561212f575080155b156121725761214061013a85613223565b50600b61214e61013a611fc5565b111561216d57604051630aadf0b960e41b815260040160405180910390fd5b6121aa565b8115801561217d5750805b156121aa5761218e61013a856137d1565b506001600160a01b038416600090815261013860205260408120555b5092915050565b600160fb55565b6001600160a01b03838116600090815260346020908152604080832093861683529290522054600019811461224457818110156122375760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401611544565b6122448484848403611bad565b50505050565b6001600160a01b0383166122ae5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401611544565b6001600160a01b0382166123105760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401611544565b6001600160a01b038316600090815260336020526040902054818110156123885760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401611544565b6001600160a01b0380851660008181526033602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906123e89086815260200190565b60405180910390a3612244565b60c95460ff1615610c065760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401611544565b600061245382612f00565b156124685761246183612c3a565b9050610859565b8161247284612c3a565b8015612482575061248281612c2c565b8015612494575061249281612c3a565b155b8015611224575061122481612a25565b604080518082019091526000808252602082015261012e5460408051606081019091526000916001600160a01b031690638b83535b9082906301356c8c90806124eb6132e0565b815261013d5460408051634bd9fe5560e11b815290516020938401936001600160a01b03909316926397b3fcaa92600480820193918290030181865afa158015612539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255d9190614361565b81526101325460209091019061257b906001600160a01b0316613275565b9052604080516001600160e01b031960e085901b16815282516004820152602083015160248201529101516044820152606401602060405180830381865afa1580156125cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ef9190614361565b6040518263ffffffff1660e01b815260040161260d91815260200190565b602060405180830381865afa15801561262a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264e9190614361565b9050600061265c6000611cd1565b61012d549091506000906126749060ff16600a6144c3565b610132549091506000906126959089906001600160a01b0316858585612f27565b9050816001600160a01b038881169085161461272357600088905061271f81826001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061271691906142f3565b87876001612f27565b9150505b6040516370a0823160e01b81523060048201526000906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561276a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278e9190614361565b905087158061279b575080155b806127a4575082155b806127ad575081155b156127d65760405180604001604052806000815260200160008152509650505050505050610c27565b60408051808201909152818152600090602081016127f784868860016137e6565b90529050600087131561284a576128406128136008600a6144c3565b61281c89613843565b6128286008600a6144c3565b61283291906144f5565b6020840151919060016137e6565b6020820152612887565b6000871215612887576128816128626008600a6144c3565b61286b89613899565b6128776008600a6144c3565b61283291906143cc565b60208201525b888160200151111561291c57602081018990526128a58985856138ac565b815260008713156128ee576128e76128bc88613899565b6128c86008600a6144c3565b6128d291906144f5565b6128de6008600a6144c3565b835191906138ac565b815261291c565b600087121561291c5761291961290388613899565b61290f6008600a6144c3565b6128d291906143cc565b81525b9a9950505050505050505050565b60006129416001600160a01b03841633308561399e565b610c278361204e565b60006129416001600160a01b0384163384613452565b6097546001600160a01b03163314610c065760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611544565b6040516313612cb160e11b8152600060048201819052906001600160a01b038316906326c25962906024016040805180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa9190614508565b600061013354612a9e836001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9091906142f3565b6001600160a01b0316611fcf565b111592915050565b612aae6139d6565b60c9805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216612b585760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401611544565b6001600160a01b03821660009081526033602052604090205481811015612bcc5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401611544565b6001600160a01b03831660008181526033602090815260408083208686039055603580548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b600061087261013a83613a28565b610132546000906001600160a01b0380841691611fb591166129ba565b610132546000908190612c809085906001600160a01b0316612c7884611cd1565b866000612f27565b61013d549091506000906001600160a01b03163314612d165761012e60009054906101000a90046001600160a01b03166001600160a01b0316630a98b70d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d119190614361565b612d19565b60005b90506000612d2660355490565b9050828115612d4657612d4382612d3b6132e0565b8391906138ac565b90505b8215612d7557612d7283612d5c6008600a6144c3565b612d6691906144f5565b612d3b6008600a6144c3565b90505b9695505050505050565b6001600160a01b038216612dd55760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401611544565b8060356000828254612de791906143cc565b90915550506001600160a01b0382166000818152603360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b610137546001600160a01b038216600090815261013860205260409020541115612e7d57604051630381ed1760e31b815260040160405180910390fd5b6000612e8860355490565b9050610136548111156116cb5760405163fb88d21560e01b815260040160405180910390fd5b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000612f0c6000611cd1565b6001600160a01b0316826001600160a01b0316149050919050565b6040516370a0823160e01b81526001600160a01b03858116600483015260009182918616906370a0823190602401602060405180830381865afa158015612f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f969190614361565b90506000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffc9190614361565b9050600061300a8284613a4a565b90506000821161301a5785613037565b61303786838761302b57600061302e565b60015b849291906137e6565b9998505050505050505050565b600054610100900460ff1661309d5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b6116cb8282613a60565b600054610100900460ff16610c065760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b600054610100900460ff166131595760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b610c06613ad2565b600054610100900460ff166131ba5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b610c06613b34565b600054610100900460ff1661321b5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b610c06613b99565b6000610c27836001600160a01b038416613bf2565b6132406123f5565b60c9805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612adb3390565b6040516313612cb160e11b8152600060048201819052906001600160a01b038316906326c25962906024016040805180830381865afa1580156132bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c279190614508565b6000806132ed6000611cd1565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613337573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061335b9190614361565b9050600061336a61013a611fc5565b905060015b8160ff168160ff16101561344957600061338b8260ff16611cd1565b90506000816001600160a01b03166364c9ec6f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f191906142f3565b6040516370a0823160e01b815230600482015290915061342a908390839089906001600160a01b038416906370a0823190602401611454565b61343490866143cc565b9450505080613442906143ad565b905061336f565b50909392505050565b6040516001600160a01b0383166024820152604481018290526118e590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152613c41565b606060006134d760355490565b61013d549091506000906001600160a01b0316331461356d5761012e60009054906101000a90046001600160a01b03166001600160a01b031663ca9cbcbe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613544573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135689190614361565b613570565b60005b9050600061357f61013a611fc5565b905060008160ff1667ffffffffffffffff81111561359f5761359f6140e7565b6040519080825280602002602001820160405280156135e457816020015b60408051808201909152600080825260208201528152602001906001900390816135bd5790505b50905060005b8260ff168160ff1610156137465760006136068260ff16611cd1565b6040805180820182526001600160a01b03831680825291516370a0823160e01b8152306004820152929350916020830191613690918c918b916370a0823190602401602060405180830381865afa158015613665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136899190614361565b91906138ac565b815250838360ff16815181106136a8576136a8614397565b602090810291909101015284156137355761370f856136c96008600a6144c3565b6136d391906144f5565b6136df6008600a6144c3565b858560ff16815181106136f4576136f4614397565b6020026020010151602001516138ac9092919063ffffffff16565b838360ff168151811061372457613724614397565b602002602001015160200181815250505b5061373f816143ad565b90506135ea565b5095945050505050565b6000610c278383613d29565b6040516313612cb160e11b815260ff821660048201526000906001600160a01b038416906326c25962906024016040805180830381865afa1580156137a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c99190614508565b509392505050565b6000610c27836001600160a01b038416613d53565b6000806137f48686866138ac565b9050600183600281111561380a5761380a614536565b1480156138275750600084806138225761382261454c565b868809115b1561383a576138376001826143cc565b90505b95945050505050565b6000808212156138955760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f7369746976656044820152606401611544565b5090565b6000808212156138955781600003610872565b60008080600019858709858702925082811083820303915050806000036138e6578382816138dc576138dc61454c565b0492505050610c27565b8084116139355760405162461bcd60e51b815260206004820152601560248201527f4d6174683a206d756c446976206f766572666c6f7700000000000000000000006044820152606401611544565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6040516001600160a01b03808516602483015283166044820152606481018290526122449085906323b872dd60e01b9060840161347e565b60c95460ff16610c065760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401611544565b6001600160a01b03811660009081526001830160205260408120541515610c27565b6000818310613a595781610c27565b5090919050565b600054610100900460ff16613ab95760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b6036613ac583826145a8565b5060376118e582826145a8565b600054610100900460ff16613b2b5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b610c0633612eae565b600054610100900460ff16613b8d5760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b60c9805460ff19169055565b600054610100900460ff166121b15760405162461bcd60e51b815260206004820152602b602482015260008051602061469b83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401611544565b6000818152600183016020526040812054613c3957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610859565b506000610859565b6000613c96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e469092919063ffffffff16565b9050805160001480613cb7575080806020019051810190613cb7919061433f565b6118e55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611544565b6000826000018281548110613d4057613d40614397565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613e3c576000613d776001836144f5565b8554909150600090613d8b906001906144f5565b9050818114613df0576000866000018281548110613dab57613dab614397565b9060005260206000200154905080876000018481548110613dce57613dce614397565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613e0157613e01614668565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610859565b6000915050610859565b6060611224848460008585600080866001600160a01b03168587604051613e6d919061467e565b60006040518083038185875af1925050503d8060008114613eaa576040519150601f19603f3d011682016040523d82523d6000602084013e613eaf565b606091505b5091509150613ec087838387613ecb565b979650505050505050565b60608315613f3a578251600003613f33576001600160a01b0385163b613f335760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611544565b5081611224565b6112248383815115613f4f5781518083602001fd5b8060405162461bcd60e51b81526004016115449190613f8d565b60005b83811015613f84578181015183820152602001613f6c565b50506000910152565b6020815260008251806020840152613fac816040850160208701613f69565b601f01601f19169190910160400192915050565b6001600160a01b038116811461108957600080fd5b60008060408385031215613fe857600080fd5b8235613ff381613fc0565b946020939093013593505050565b60006020828403121561401357600080fd5b5035919050565b60008060006060848603121561402f57600080fd5b833561403a81613fc0565b9250602084013561404a81613fc0565b929592945050506040919091013590565b6000806040838503121561406e57600080fd5b50508035926020909101359150565b60006020828403121561408f57600080fd5b8135610c2781613fc0565b6020808252825182820181905260009190848201906040850190845b818110156140db5783516001600160a01b0316835292840192918401916001016140b6565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261410e57600080fd5b813567ffffffffffffffff80821115614129576141296140e7565b604051601f8301601f19908116603f01168101908282118183101715614151576141516140e7565b8160405283815286602085880101111561416a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156141a257600080fd5b853567ffffffffffffffff808211156141ba57600080fd5b6141c689838a016140fd565b965060208801359150808211156141dc57600080fd5b506141e9888289016140fd565b94505060408601356141fa81613fc0565b9250606086013561420a81613fc0565b9150608086013561421a81613fc0565b809150509295509295909350565b602080825282518282018190526000919060409081850190868401855b8281101561427357815180516001600160a01b03168552860151868501529284019290850190600101614245565b5091979650505050505050565b6000806040838503121561429357600080fd5b823561429e81613fc0565b915060208301356142ae81613fc0565b809150509250929050565b600181811c908216806142cd57607f821691505b6020821081036142ed57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561430557600080fd5b8151610c2781613fc0565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111561085957610859614310565b60006020828403121561435157600080fd5b81518015158114610c2757600080fd5b60006020828403121561437357600080fd5b5051919050565b600060ff82168061438d5761438d614310565b6000190192915050565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff81036143c3576143c3614310565b60010192915050565b8082018082111561085957610859614310565b600181815b8085111561441a57816000190482111561440057614400614310565b8085161561440d57918102915b93841c93908002906143e4565b509250929050565b60008261443157506001610859565b8161443e57506000610859565b8160018114614454576002811461445e5761447a565b6001915050610859565b60ff84111561446f5761446f614310565b50506001821b610859565b5060208310610133831016604e8410600b841016171561449d575081810a610859565b6144a783836143df565b80600019048211156144bb576144bb614310565b029392505050565b6000610c2760ff841683614422565b6000602082840312156144e457600080fd5b815160ff81168114610c2757600080fd5b8181038181111561085957610859614310565b6000806040838503121561451b57600080fd5b825161452681613fc0565b6020939093015192949293505050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b601f8211156118e557600081815260208120601f850160051c810160208610156145895750805b601f850160051c820191505b818110156116ae57828155600101614595565b815167ffffffffffffffff8111156145c2576145c26140e7565b6145d6816145d084546142b9565b84614562565b602080601f83116001811461460b57600084156145f35750858301515b600019600386901b1c1916600185901b1785556116ae565b600085815260208120601f198616915b8281101561463a5788860151825594840194600190910190840161461b565b50858210156146585787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603160045260246000fd5b60008251614690818460208701613f69565b919091019291505056fe496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069a2646970667358221220117437feaf340e0dba3091f1ecdc2dc97a8597e7902ee832f48f151e08b9e97d64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/spot-subgraph/modified-artifacts/notes.txt b/spot-subgraph/modified-artifacts/notes.txt new file mode 100644 index 00000000..3004456d --- /dev/null +++ b/spot-subgraph/modified-artifacts/notes.txt @@ -0,0 +1 @@ +The "redeem()" function on perp has a modified ABI in v2; A return value was added. Using the v2 abi to parse transaction call handlers before the v2 implementation upgrade throws an error. The modified PerpetualTranche.json ABI uses the "redeem" function fragment from v1. \ No newline at end of file diff --git a/spot-subgraph/schema.graphql b/spot-subgraph/schema.graphql index ee9c3a76..624b640d 100644 --- a/spot-subgraph/schema.graphql +++ b/spot-subgraph/schema.graphql @@ -19,15 +19,6 @@ type BondController @entity { " bond issuer used to create the bond " issuer: BondIssuer - " address of the owner " - owner: String! - - " deposit limit of the bond " - depositLimit: BigInt! - - " fee percentage collected by bond owner " - feePerc: BigDecimal! - " reference to the collateral token " collateral: Token! @@ -85,6 +76,41 @@ type Tranche @entity { totalSupplyAtMaturity: BigDecimal } +type AccountTrancheValue @entity { + " Equals to: -" + id: ID! + + " if the tranche's parent bond has matured " + isBondMature: Boolean! + + " if the tranche has the most senior payout " + isSeniorTranche: Boolean! + + " total supply of tranche tokens " + trancheSupply: BigDecimal! + + " parent bond's collateral balance " + bondCollateralBalance: BigDecimal! + + " parent bond's total debt " + bondTotalDebt: BigDecimal! + + " collateral claimable by tranche " + trancheClaim: BigDecimal! + + " the tranche cdr " + trancheCDR: BigDecimal! + + " parent bond's cdr " + bondCDR: BigDecimal! + + " price of each tranche token " + tranchePrice: BigDecimal! + + " total value of account's tranche tokens" + trancheValue: BigDecimal! +} + type Token @entity { " token address " id: ID! @@ -136,82 +162,44 @@ type Account @entity { balances: [AccountBalance!]! @derivedFrom(field: "account") } - type BondIssuer @entity { " issuer address " id: ID! - " the minimum time between issues " - minIssueTimeIntervalSec: BigInt! - - " issue window offset time " - issueWindowOffsetSec: BigInt! - - " maximum bond duration " - maxMaturityDuration: BigInt! - " timestamp of last issue " lastIssueTimestamp: BigInt - " Block number of last issue " - lastIssueBlock: BigInt - " list of bonds issued by the issuer " issuedBonds: [BondController!] @derivedFrom(field: "issuer") } - type PerpetualTranche @entity { - " perp token address " + " perp token store reference " id: ID! " reference to the ERC20 token attributes " token: Token! " reference to the collateral " - collateral: Token! + underlying: Token! - " address of the owner " - owner: String! - - " address of the keeper " - keeper: String! - - " address of the bond issuer " - issuer: BondIssuer! - - " address of the fee strategy " - feeStrategy: String! - - " address of the pricing strategy " - pricingStrategy: String! - - " address of the discount strategy " - discountStrategy: String! - - " allowed time to maturity before tranche is moved to the holding pen " - minTrancheMaturitySec: BigInt! - - " allowed time from maturity after which tranche can be accepted " - maxTrancheMaturitySec: BigInt! - - " supply ceiling " - maxSupply: BigDecimal! - - " maximum mint allowed per tranche " - maxMintAmtPerTranche: BigDecimal! - - " percentage of reserve value allowed to be held in the holding pen " - matureValueTargetPerc: BigDecimal! - " reference to the current deposit bond " depositBond: BondController - " the virtual holding pen tranche balance " - matureTrancheBalance: BigDecimal! - " reference to assets held in the reserve " reserves: [PerpetualTrancheReserveAsset!]! @derivedFrom(field: "perp") + + " addresses of assets currently in the reserve " + activeReserves: [PerpetualTrancheReserveAsset!]! + + " the current tvl based on the active reserves " + tvl: BigDecimal! + + " the price of each perp token " + price: BigDecimal! + + " reference to the daily stats " + dailyStats: [PerpetualTrancheDailyStat!]! @derivedFrom(field: "perp") } type PerpetualTrancheReserveAsset @entity { @@ -224,13 +212,47 @@ type PerpetualTrancheReserveAsset @entity { " reference to the token " token: Token! - " reference to the underlying tranche " + " reference to the reserve tranche " tranche: Tranche + " Value of the reserve tranche " + value: AccountTrancheValue + " balance held by the reserve " balance: BigDecimal! } +type PerpetualTrancheDailyStat @entity { + " Equals to: -" + id: ID! + + " reference to the perpetual tranche token " + perp: PerpetualTranche! + + " the timestamp of the given day " + timestamp: BigInt! + + " the total perp tokens minted on the given day " + totalMints: BigDecimal! + + " the total perp tokens redeemed on the given day " + totalRedemptions: BigDecimal! + + " the total value of perp tokens minted on the given day " + totalMintValue: BigDecimal! + + " the total value of perp tokens redeemed on the given day " + totalRedemptionValue: BigDecimal! + + " the tvl on the given day " + tvl: BigDecimal! + + " the price on the given day " + price: BigDecimal! + + " the perp token supply on the given day " + totalSupply: BigDecimal! +} type RolloverVault @entity { " vault token address " @@ -245,20 +267,32 @@ type RolloverVault @entity { " reference to the perp on which rollovers are performed" perp: PerpetualTranche! - " address of the owner " - owner: String! - " reference to assets held in by the vault " assets: [RolloverVaultAsset!]! @derivedFrom(field: "vault") - " the total fixed mc share of underlying tokens in the system " - totalUnderlyingScaledHeld: BigDecimal! + " addresses of assets currently in the reserve " + activeReserves: [RolloverVaultAsset!]! + + " the total fixed mc share of underlying tokens deposited into the system " + totalScaledUnderlyingDeposited: BigDecimal! " the total fixed mc share of underlying tokens deposited by each user " - scaledUnderlyingBalances: [ScaledUnderlyingVaultBalance!]! @derivedFrom(field: "vault") + scaledUnderlyingBalances: [ScaledUnderlyingVaultDepositorBalance!]! @derivedFrom(field: "vault") + + " the current tvl based on the active reserves " + tvl: BigDecimal! + + " the current rebase multiplier " + rebaseMultiplier: BigDecimal! + + " the price of each token " + price: BigDecimal! + + " reference to the daily stats " + dailyStats: [RolloverVaultDailyStat!]! @derivedFrom(field: "vault") } -type ScaledUnderlyingVaultBalance @entity { +type ScaledUnderlyingVaultDepositorBalance @entity { id: ID! vault: RolloverVault! account: Bytes! @@ -280,4 +314,45 @@ type RolloverVaultAsset @entity { " balance held by the vault " balance: BigDecimal! + + " Value of the reserve tranche " + value: AccountTrancheValue +} + +type RolloverVaultDailyStat @entity { + " Equals to: -" + id: ID! + + " reference to the rollover vault " + vault: RolloverVault! + + " the timestamp of the given day " + timestamp: BigInt! + + " the total vault notes minted on the given day " + totalMints: BigDecimal! + + " the total vault notes redeemed on the given day " + totalRedemptions: BigDecimal! + + " the total value of vault notes minted on the given day " + totalMintValue: BigDecimal! + + " the total value of vault notes redeemed on the given day " + totalRedemptionValue: BigDecimal! + + " the tvl on the given day " + tvl: BigDecimal! + + " the rebase multiplier on the given day " + rebaseMultiplier: BigDecimal! + + " the price on the given day " + price: BigDecimal! + + " the vault note supply on the given day " + totalSupply: BigDecimal! + + " the total value of swaps on the given day " + totalSwapValue: BigDecimal! } \ No newline at end of file diff --git a/spot-subgraph/scripts/deploy.sh b/spot-subgraph/scripts/deploy.sh index 61b73a54..a6bcbc3f 100755 --- a/spot-subgraph/scripts/deploy.sh +++ b/spot-subgraph/scripts/deploy.sh @@ -3,12 +3,11 @@ set -e yarn mustache ../spot-contracts/deployments/$1.json subgraph.template.yaml > ./subgraph.yaml -yarn auth $GRAPH_AUTH - yarn codegen yarn build -yarn graph deploy \ - --product hosted-service \ - --access-token $GRAPH_AUTH $2 +yarn graph deploy $2 \ + --node https://subgraphs.alchemy.com/api/subgraphs/deploy \ + --deploy-key $GRAPH_AUTH \ + --ipfs https://ipfs.satsuma.xyz \ No newline at end of file diff --git a/spot-subgraph/src/data/bondIssuer.ts b/spot-subgraph/src/data/bondIssuer.ts index faccdd41..c6e52b17 100644 --- a/spot-subgraph/src/data/bondIssuer.ts +++ b/spot-subgraph/src/data/bondIssuer.ts @@ -11,10 +11,6 @@ export function fetchBondIssuer(address: Address): BondIssuer { let address = stringToAddress(id) let issuerContract = BondIssuerABI.bind(address) issuer = new BondIssuer(id) - - issuer.minIssueTimeIntervalSec = issuerContract.minIssueTimeIntervalSec() - issuer.issueWindowOffsetSec = issuerContract.issueWindowOffsetSec() - issuer.maxMaturityDuration = issuerContract.maxMaturityDuration() issuer.save() } return issuer as BondIssuer diff --git a/spot-subgraph/src/data/buttonTranche.ts b/spot-subgraph/src/data/buttonTranche.ts index df8a6897..a4d1d365 100644 --- a/spot-subgraph/src/data/buttonTranche.ts +++ b/spot-subgraph/src/data/buttonTranche.ts @@ -1,14 +1,10 @@ -import { - BigInt, - Address, - ethereum, - DataSourceContext, -} from '@graphprotocol/graph-ts' +import { BigInt, Address, ethereum, DataSourceContext } from '@graphprotocol/graph-ts' import { BondFactory, BondController, Tranche, Token, + AccountTrancheValue, } from '../../generated/schema' import { BondController as BondControllerABI } from '../../generated/BondFactory/BondController' import { ERC20 as ERC20ABI } from '../../generated/BondFactory/ERC20' @@ -16,13 +12,8 @@ import { BondController as BondControllerTemplate, RebasingToken as RebasingTokenTemplate, } from '../../generated/templates' -import { - BIGINT_ZERO, - BIGDECIMAL_ZERO, - stringToAddress, - formatBalance, -} from '../utils' -import { fetchToken } from './token' +import { BIGINT_ZERO, BIGDECIMAL_ZERO, stringToAddress, formatBalance } from '../utils' +import { fetchToken, refreshSupply } from './token' export function fetchBondFactory(address: Address): BondFactory { let id = address.toHexString() @@ -41,10 +32,7 @@ export function fetchBond(address: Address): BondController { if (bond == null) { let bondContract = BondControllerABI.bind(address) bond = new BondController(id) - bond.owner = bondContract.owner().toHexString() bond.collateral = fetchToken(bondContract.collateralToken()).id - bond.depositLimit = bondContract.depositLimit() - bond.feePerc = formatBalance(bondContract.feeBps(), BigInt.fromI32(2)) bond.creationDate = bondContract.creationDate() bond.maturityDate = bondContract.maturityDate() bond.isMature = bondContract.isMature() @@ -63,23 +51,15 @@ export function fetchBond(address: Address): BondController { let collateralContext = new DataSourceContext() collateralContext.setString('bond', id) - RebasingTokenTemplate.createWithContext( - stringToAddress(bond.collateral), - collateralContext, - ) + RebasingTokenTemplate.createWithContext(stringToAddress(bond.collateral), collateralContext) } return bond as BondController } -export function fetchTranche( - bond: BondController, - trancheIndex: number, -): Tranche { +export function fetchTranche(bond: BondController, trancheIndex: number): Tranche { let bondAddress = stringToAddress(bond.id) let bondContract = BondControllerABI.bind(bondAddress) - let trancheResult = bondContract.try_tranches( - BigInt.fromI32(trancheIndex as i32), - ) + let trancheResult = bondContract.try_tranches(BigInt.fromI32(trancheIndex as i32)) if (trancheResult.reverted) { throw new Error('Unable to fetch tranche') } @@ -104,16 +84,13 @@ export function refreshBond(bond: BondController): void { let collateralAddress = stringToAddress(bond.collateral) let collateralContract = ERC20ABI.bind(collateralAddress) let collateral = fetchToken(collateralAddress) + refreshSupply(collateral) bond.totalDebt = formatBalance(bondContract.totalDebt(), collateral.decimals) bond.totalCollateral = formatBalance( collateralContract.balanceOf(bondAddress), collateral.decimals, ) - collateral.totalSupply = formatBalance( - collateralContract.totalSupply(), - collateral.decimals, - ) let tranches = bond.tranches for (let i = 0; i < tranches.length; i++) { @@ -121,11 +98,8 @@ export function refreshBond(bond: BondController): void { let trancheAddress = stringToAddress(tranche.id) let trancheContract = ERC20ABI.bind(trancheAddress) let trancheToken = fetchToken(trancheAddress) + refreshSupply(trancheToken) - trancheToken.totalSupply = formatBalance( - trancheContract.totalSupply(), - collateral.decimals, - ) tranche.totalCollateral = formatBalance( collateralContract.balanceOf(trancheAddress), collateral.decimals, @@ -151,9 +125,7 @@ export function matureBond(bond: BondController, block: ethereum.Block): void { let trancheAddress = stringToAddress(tranche.id) let trancheToken = fetchToken(trancheAddress) - totalCollateralAtMaturity = totalCollateralAtMaturity.plus( - tranche.totalCollateral, - ) + totalCollateralAtMaturity = totalCollateralAtMaturity.plus(tranche.totalCollateral) tranche.totalSupplyAtMaturity = trancheToken.totalSupply tranche.totalCollateralAtMaturity = tranche.totalCollateral @@ -163,3 +135,28 @@ export function matureBond(bond: BondController, block: ethereum.Block): void { bond.totalCollateralAtMaturity = totalCollateralAtMaturity bond.save() } + +export function fetchAccountTrancheValue( + accountAddress: Address, + trancheAddress: Address, +): AccountTrancheValue { + let accountId = accountAddress.toHexString() + let trancheId = trancheAddress.toHexString() + let id = accountId.concat('-').concat(trancheId) + let trancheValueInfo = AccountTrancheValue.load(id) + if (trancheValueInfo === null) { + trancheValueInfo = new AccountTrancheValue(id) + trancheValueInfo.isBondMature = false + trancheValueInfo.isSeniorTranche = false + trancheValueInfo.trancheSupply = BIGDECIMAL_ZERO + trancheValueInfo.bondCollateralBalance = BIGDECIMAL_ZERO + trancheValueInfo.bondTotalDebt = BIGDECIMAL_ZERO + trancheValueInfo.trancheClaim = BIGDECIMAL_ZERO + trancheValueInfo.trancheCDR = BIGDECIMAL_ZERO + trancheValueInfo.bondCDR = BIGDECIMAL_ZERO + trancheValueInfo.tranchePrice = BIGDECIMAL_ZERO + trancheValueInfo.trancheValue = BIGDECIMAL_ZERO + trancheValueInfo.save() + } + return trancheValueInfo as AccountTrancheValue +} diff --git a/spot-subgraph/src/data/perpetualTranche.ts b/spot-subgraph/src/data/perpetualTranche.ts index 9cc1b866..dd0c5a28 100644 --- a/spot-subgraph/src/data/perpetualTranche.ts +++ b/spot-subgraph/src/data/perpetualTranche.ts @@ -1,9 +1,11 @@ -import { BigInt, Address, DataSourceContext } from '@graphprotocol/graph-ts' +import { BigInt, BigDecimal, Address, DataSourceContext } from '@graphprotocol/graph-ts' import { PerpetualTranche, PerpetualTrancheReserveAsset, + PerpetualTrancheDailyStat, } from '../../generated/schema' import { PerpetualTranche as PerpetualTrancheABI } from '../../generated/PerpetualTranche/PerpetualTranche' +import { PerpetualTrancheV1 as PerpetualTrancheABIV1 } from '../../generated/PerpetualTranche/PerpetualTrancheV1' import { ERC20 as ERC20ABI } from '../../generated/BondFactory/ERC20' import { RebasingToken as RebasingTokenTemplate } from '../../generated/templates' import { @@ -11,45 +13,103 @@ import { BIGDECIMAL_ZERO, stringToAddress, formatBalance, + getTrancheCDRInfo, } from '../utils' -import { fetchToken } from './token' +import { fetchToken, refreshSupply } from './token' +import { fetchAccountTrancheValue } from './buttonTranche' + +function getUnderlyingAddress(perpAddress: Address): Address { + let perpContract = PerpetualTrancheABI.bind(perpAddress) + let r = perpContract.try_underlying() + let underlyingAddress: Address + if (r.reverted) { + let perpContractV1 = PerpetualTrancheABIV1.bind(perpAddress) + underlyingAddress = perpContractV1.collateral() + } else { + underlyingAddress = r.value + } + return underlyingAddress +} export function refreshPerpetualTrancheStore(perp: PerpetualTranche): void { - let address = stringToAddress(perp.id) - let perpContract = PerpetualTrancheABI.bind(address) - let decimals = BigInt.fromI32(perpContract.decimals()) - let collateralAddress = perpContract.collateral() - let collateralContract = ERC20ABI.bind(collateralAddress) - let collateral = fetchToken(collateralAddress) - perp.collateral = collateral.id - perp.owner = perpContract.owner().toHexString() - perp.keeper = perpContract.keeper().toHexString() - perp.issuer = perpContract.bondIssuer().toHexString() - perp.feeStrategy = perpContract.feeStrategy().toHexString() - perp.pricingStrategy = perpContract.pricingStrategy().toHexString() - perp.discountStrategy = perpContract.discountStrategy().toHexString() - perp.minTrancheMaturitySec = perpContract.minTrancheMaturitySec() - perp.maxTrancheMaturitySec = perpContract.maxTrancheMaturitySec() - perp.maxSupply = formatBalance(perpContract.maxSupply(), decimals) - perp.maxMintAmtPerTranche = formatBalance( - perpContract.maxMintAmtPerTranche(), - decimals, - ) - perp.matureValueTargetPerc = formatBalance( - perpContract.matureValueTargetPerc(), - BigInt.fromI32(2), - ) + let perpAddress = stringToAddress(perp.id) + let perpToken = fetchToken(perpAddress) + refreshSupply(perpToken) + + let perpContract = PerpetualTrancheABI.bind(perpAddress) + let underlyingAddress = getUnderlyingAddress(perpAddress) + let underlyingERC20Contract = ERC20ABI.bind(underlyingAddress) + + let underlying = fetchToken(underlyingAddress) + underlying.save() + + perp.underlying = underlying.id perp.save() - let reserveCollateral = fetchPerpetualTrancheReserveAsset( - address, - collateralAddress, + let reserveUnderlying = fetchPerpetualTrancheReserveAsset(perpAddress, underlyingAddress) + reserveUnderlying.balance = formatBalance( + underlyingERC20Contract.balanceOf(perpAddress), + perpToken.decimals, ) - reserveCollateral.balance = formatBalance( - collateralContract.balanceOf(perpContract.reserve()), - decimals, + reserveUnderlying.save() +} + +export function refreshPerpetualTrancheTVL(perp: PerpetualTranche): void { + let perpAddress = stringToAddress(perp.id) + let perpToken = fetchToken(perpAddress) + refreshSupply(perpToken) + + let perpContract = PerpetualTrancheABI.bind(perpAddress) + let underlyingAddress = getUnderlyingAddress(perpAddress) + let underlyingERC20Contract = ERC20ABI.bind(underlyingAddress) + let underlyingBalance = formatBalance( + underlyingERC20Contract.balanceOf(perpAddress), + perpToken.decimals, ) - reserveCollateral.save() + + let activeReserves = perp.activeReserves + let tvl = BIGDECIMAL_ZERO + for (let i = 0; i < activeReserves.length; i++) { + let tokenAddress = stringToAddress(activeReserves[i].split('-')[1]) + let reserveAsset = fetchPerpetualTrancheReserveAsset(perpAddress, tokenAddress) + let tokenContract = ERC20ABI.bind(tokenAddress) + let tokenBalance = formatBalance(tokenContract.balanceOf(perpAddress), perpToken.decimals) + reserveAsset.balance = tokenBalance + if (tokenAddress == underlyingAddress) { + tvl = tvl.plus(tokenBalance) + } else { + let r = getTrancheCDRInfo(tokenAddress, underlyingAddress, tokenBalance) + let reserveTrancheValue = fetchAccountTrancheValue(perpAddress, tokenAddress) + reserveTrancheValue.isBondMature = r.isBondMature + reserveTrancheValue.isSeniorTranche = r.isSeniorTranche + reserveTrancheValue.trancheSupply = r.trancheSupply + reserveTrancheValue.bondCollateralBalance = r.bondCollateralBalance + reserveTrancheValue.bondTotalDebt = r.bondTotalDebt + reserveTrancheValue.trancheClaim = r.trancheClaim + reserveTrancheValue.trancheCDR = r.trancheCDR + reserveTrancheValue.bondCDR = r.bondCDR + reserveTrancheValue.tranchePrice = r.tranchePrice + reserveTrancheValue.trancheValue = r.trancheValue + reserveTrancheValue.save() + tvl = tvl.plus(r.trancheValue) + } + reserveAsset.save() + } + perp.tvl = tvl + if (perpToken.totalSupply.gt(BIGDECIMAL_ZERO)) { + perp.price = perp.tvl.div(perpToken.totalSupply) + } + perp.save() +} + +export function refreshPerpetualTrancheDailyStat(dailyStat: PerpetualTrancheDailyStat): void { + let perp = PerpetualTranche.load(dailyStat.perp) + let perpToken = fetchToken(stringToAddress(dailyStat.perp)) + refreshSupply(perpToken) + dailyStat.tvl = perp.tvl + dailyStat.price = perp.price + dailyStat.totalSupply = perpToken.totalSupply + dailyStat.save() } export function fetchPerpetualTranche(address: Address): PerpetualTranche { @@ -57,21 +117,21 @@ export function fetchPerpetualTranche(address: Address): PerpetualTranche { let perp = PerpetualTranche.load(id) if (perp == null) { let perpToken = fetchToken(address) + perpToken.save() + perp = new PerpetualTranche(id) perp.token = perpToken.id perp.depositBond = null - perp.matureTrancheBalance = BIGDECIMAL_ZERO + perp.activeReserves = [] + perp.tvl = BIGDECIMAL_ZERO + perp.price = BIGDECIMAL_ZERO refreshPerpetualTrancheStore(perp as PerpetualTranche) let collateralContext = new DataSourceContext() collateralContext.setString('perp', id) - RebasingTokenTemplate.createWithContext( - stringToAddress(perp.collateral), - collateralContext, - ) + RebasingTokenTemplate.createWithContext(stringToAddress(perp.underlying), collateralContext) perp.save() } - return perp as PerpetualTranche } @@ -85,16 +145,40 @@ export function fetchPerpetualTrancheReserveAsset( let reserveToken = PerpetualTrancheReserveAsset.load(id) if (reserveToken === null) { let perpContract = PerpetualTrancheABI.bind(perpAddress) - let collateralAddress = perpContract.collateral() + let underlyingAddress = getUnderlyingAddress(perpAddress) reserveToken = new PerpetualTrancheReserveAsset(id) reserveToken.perp = perpId reserveToken.token = tokenId reserveToken.balance = BIGDECIMAL_ZERO // if the reserve asset isn't the underlying collateral, we infer its a tranche - if (tokenAddress != collateralAddress) { + if (tokenAddress != underlyingAddress) { reserveToken.tranche = tokenId + let reserveTrancheValue = fetchAccountTrancheValue(perpAddress, tokenAddress) + reserveTrancheValue.save() + reserveToken.value = reserveTrancheValue.id } reserveToken.save() } return reserveToken as PerpetualTrancheReserveAsset } + +export function fetchPerpetualTrancheDailyStat( + perp: PerpetualTranche, + timestamp: BigInt, +): PerpetualTrancheDailyStat { + let id = perp.id.concat('-').concat(timestamp.toString()) + let dailyStat = PerpetualTrancheDailyStat.load(id) + if (dailyStat === null) { + dailyStat = new PerpetualTrancheDailyStat(id) + dailyStat.perp = perp.id + dailyStat.timestamp = timestamp + dailyStat.totalMints = BIGDECIMAL_ZERO + dailyStat.totalRedemptions = BIGDECIMAL_ZERO + dailyStat.totalMintValue = BIGDECIMAL_ZERO + dailyStat.totalRedemptionValue = BIGDECIMAL_ZERO + dailyStat.tvl = BIGDECIMAL_ZERO + dailyStat.price = BIGDECIMAL_ZERO + dailyStat.totalSupply = BIGDECIMAL_ZERO + } + return dailyStat as PerpetualTrancheDailyStat +} diff --git a/spot-subgraph/src/data/rolloverVault.ts b/spot-subgraph/src/data/rolloverVault.ts index 0834b3f2..77f7919c 100644 --- a/spot-subgraph/src/data/rolloverVault.ts +++ b/spot-subgraph/src/data/rolloverVault.ts @@ -1,62 +1,183 @@ -import { BigInt, Address, DataSourceContext } from '@graphprotocol/graph-ts' +import { BigDecimal, BigInt, Address, DataSourceContext } from '@graphprotocol/graph-ts' import { RolloverVault, RolloverVaultAsset, - ScaledUnderlyingVaultBalance, + ScaledUnderlyingVaultDepositorBalance, + RolloverVaultDailyStat, + Tranche } from '../../generated/schema' import { RolloverVault as RolloverVaultABI } from '../../generated/RolloverVault/RolloverVault' import { ERC20 as ERC20ABI } from '../../generated/BondFactory/ERC20' import { RebasingToken as RebasingTokenTemplate } from '../../generated/templates' import { ADDRESS_ZERO, + BIGINT_ZERO, BIGDECIMAL_ZERO, + BIGDECIMAL_ONE, stringToAddress, formatBalance, + getTrancheCDRInfo, } from '../utils' import { fetchPerpetualTranche } from './perpetualTranche' -import { fetchToken } from './token' +import { fetchAccountTrancheValue } from './buttonTranche' +import { fetchToken, refreshSupply } from './token' export function refreshRolloverVaultStore(vault: RolloverVault): void { - let address = stringToAddress(vault.id) - let vaultContract = RolloverVaultABI.bind(address) - let decimals = BigInt.fromI32(vaultContract.decimals()) + let vaultAddress = stringToAddress(vault.id) + let vaultToken = fetchToken(vaultAddress) + refreshSupply(vaultToken) + let vaultContract = RolloverVaultABI.bind(vaultAddress) let underlyingAddress = vaultContract.underlying() let underlying = fetchToken(underlyingAddress) - vault.underlying = underlying.id let perpAddress = vaultContract.perp() let perp = fetchPerpetualTranche(perpAddress) - vault.perp = perp.id - vault.owner = vaultContract.owner().toHexString() + vault.underlying = underlying.id + vault.perp = perp.id vault.save() let underlyingContract = ERC20ABI.bind(underlyingAddress) - let underlyingAsset = fetchRolloverVaultAsset(address, underlyingAddress) + let underlyingAsset = fetchRolloverVaultAsset(vaultAddress, underlyingAddress) underlyingAsset.balance = formatBalance( - underlyingContract.balanceOf(address), - decimals, + underlyingContract.balanceOf(vaultAddress), + vaultToken.decimals, ) underlyingAsset.save() } +export function refreshRolloverVaultTVL(vault: RolloverVault): void { + let vaultAddress = stringToAddress(vault.id) + let vaultContract = RolloverVaultABI.bind(vaultAddress) + + let vaultToken = fetchToken(vaultAddress) + refreshSupply(vaultToken) + + let underlyingAddress = vaultContract.underlying() + let perpAddress = vaultContract.perp() + let underlyingToken = fetchToken(underlyingAddress) + + let activeReserves = vault.activeReserves + let tvl = BIGDECIMAL_ZERO + for (let i = 0; i < activeReserves.length; i++) { + let tokenAddress = stringToAddress(activeReserves[i].split('-')[1]) + let reserveAsset = fetchRolloverVaultAsset(vaultAddress, tokenAddress) + let tokenContract = ERC20ABI.bind(tokenAddress) + let tokenBalance = formatBalance( + tokenContract.balanceOf(vaultAddress), + underlyingToken.decimals, + ) + reserveAsset.balance = tokenBalance + if (tokenAddress == underlyingAddress) { + tvl = tvl.plus(tokenBalance) + } else if (tokenAddress == perpAddress) { + // do nothing + } else { + reserveAsset.balance = tokenBalance + let r = getTrancheCDRInfo(tokenAddress, underlyingAddress, tokenBalance) + let reserveTrancheValue = fetchAccountTrancheValue(vaultAddress, tokenAddress) + reserveTrancheValue.isBondMature = r.isBondMature + reserveTrancheValue.isSeniorTranche = r.isSeniorTranche + reserveTrancheValue.trancheSupply = r.trancheSupply + reserveTrancheValue.bondCollateralBalance = r.bondCollateralBalance + reserveTrancheValue.bondTotalDebt = r.bondTotalDebt + reserveTrancheValue.trancheClaim = r.trancheClaim + reserveTrancheValue.trancheCDR = r.trancheCDR + reserveTrancheValue.bondCDR = r.bondCDR + reserveTrancheValue.tranchePrice = r.tranchePrice + reserveTrancheValue.trancheValue = r.trancheValue + reserveTrancheValue.save() + tvl = tvl.plus(r.trancheValue) + } + reserveAsset.save() + } + vault.tvl = tvl + if (vaultToken.totalSupply.gt(BIGDECIMAL_ZERO)) { + vault.price = vault.tvl.div(vaultToken.totalSupply) + } + vault.save() +} + +export function refreshRolloverVaultRebaseMultiplier(vault: RolloverVault): void { + let vaultAddress = stringToAddress(vault.id) + let underlyingAddress = stringToAddress(vault.underlying) + let perpAddress = stringToAddress(vault.perp) + let underlyingToken = fetchToken(underlyingAddress) + + let sumAs: BigDecimal = BIGDECIMAL_ZERO + let sumZs: BigDecimal = BIGDECIMAL_ZERO + let vaultUnderlyingBalance: BigDecimal = BIGDECIMAL_ZERO + let vaultPerpBalance: BigDecimal = BIGDECIMAL_ZERO + let vaultZBalance = BIGDECIMAL_ZERO + let ONE_THOUSAND = BigDecimal.fromString('1000') + + let activeReserves = vault.activeReserves + for (let i = 0; i < activeReserves.length; i++) { + let tokenAddress = stringToAddress(activeReserves[i].split('-')[1]) + let tokenContract = ERC20ABI.bind(tokenAddress) + let tokenBalance = formatBalance( + tokenContract.balanceOf(vaultAddress), + underlyingToken.decimals, + ) + if (tokenAddress == underlyingAddress) { + vaultUnderlyingBalance = tokenBalance + } else if (tokenAddress == perpAddress) { + vaultPerpBalance = tokenBalance + } else { + let tranche = Tranche.load(tokenAddress.toHexString()) + // junior tranche + if (tranche.index.gt(BIGINT_ZERO)) { + let zRatio = BigDecimal.fromString(tranche.ratio.toString()).div(ONE_THOUSAND) + sumZs = sumZs.plus(tokenBalance.div(zRatio)) + vaultZBalance = vaultZBalance.plus(tokenBalance) + } + // senior tranche + else { + sumAs = sumAs.plus(tokenBalance) + } + } + } + + let numerator = sumZs.plus(vaultUnderlyingBalance) + let denominator = sumAs + .plus(vaultPerpBalance) + .plus(vaultZBalance) + .plus(vaultUnderlyingBalance) + if(denominator.gt(BIGDECIMAL_ZERO)){ + vault.rebaseMultiplier = numerator.div(denominator) + } + vault.save() +} + +export function refreshRolloverVaultDailyStat(dailyStat: RolloverVaultDailyStat): void { + let vault = RolloverVault.load(dailyStat.vault) + let vaultToken = fetchToken(stringToAddress(dailyStat.vault)) + dailyStat.tvl = vault.tvl + dailyStat.rebaseMultiplier = vault.rebaseMultiplier + dailyStat.price = vault.price + dailyStat.totalSupply = vaultToken.totalSupply + dailyStat.save() +} + export function fetchRolloverVault(address: Address): RolloverVault { let id = address.toHexString() let vault = RolloverVault.load(id) if (vault == null) { let vaultToken = fetchToken(address) + vaultToken.save() vault = new RolloverVault(id) vault.token = vaultToken.id - vault.totalUnderlyingScaledHeld = BIGDECIMAL_ZERO + vault.totalScaledUnderlyingDeposited = BIGDECIMAL_ZERO + vault.activeReserves = [] + vault.tvl = BIGDECIMAL_ZERO + vault.rebaseMultiplier = BIGDECIMAL_ONE + vault.price = BIGDECIMAL_ZERO refreshRolloverVaultStore(vault as RolloverVault) let underlyingContext = new DataSourceContext() underlyingContext.setString('vault', id) - RebasingTokenTemplate.createWithContext( - stringToAddress(vault.underlying), - underlyingContext, - ) + RebasingTokenTemplate.createWithContext(stringToAddress(vault.underlying), underlyingContext) vault.save() } @@ -82,23 +203,49 @@ export function fetchRolloverVaultAsset( // if the vault asset isn't perp or the underlying, we infer its a tranche if (tokenAddress != underlyingAddress && tokenAddress != perpAddress) { assetToken.tranche = tokenId + let reserveTrancheValue = fetchAccountTrancheValue(vaultAddress, tokenAddress) + reserveTrancheValue.save() + assetToken.value = reserveTrancheValue.id } assetToken.save() } return assetToken as RolloverVaultAsset } -export function fetchScaledUnderlyingVaultBalance( +export function fetchScaledUnderlyingVaultDepositorBalance( vault: RolloverVault, account: Address, -): ScaledUnderlyingVaultBalance { - let id = vault.id.concat('|').concat(account.toHexString()) - let balance = ScaledUnderlyingVaultBalance.load(id) +): ScaledUnderlyingVaultDepositorBalance { + let id = vault.id.concat('-').concat(account.toHexString()) + let balance = ScaledUnderlyingVaultDepositorBalance.load(id) if (balance == null) { - balance = new ScaledUnderlyingVaultBalance(id) + balance = new ScaledUnderlyingVaultDepositorBalance(id) balance.vault = vault.id balance.account = account balance.value = BIGDECIMAL_ZERO } - return balance as ScaledUnderlyingVaultBalance + return balance as ScaledUnderlyingVaultDepositorBalance +} + +export function fetchRolloverVaultDailyStat( + vault: RolloverVault, + timestamp: BigInt, +): RolloverVaultDailyStat { + let id = vault.id.concat('-').concat(timestamp.toString()) + let dailyStat = RolloverVaultDailyStat.load(id) + if (dailyStat === null) { + dailyStat = new RolloverVaultDailyStat(id) + dailyStat.vault = vault.id + dailyStat.timestamp = timestamp + dailyStat.totalMints = BIGDECIMAL_ZERO + dailyStat.totalRedemptions = BIGDECIMAL_ZERO + dailyStat.totalMintValue = BIGDECIMAL_ZERO + dailyStat.totalRedemptionValue = BIGDECIMAL_ZERO + dailyStat.tvl = BIGDECIMAL_ZERO + dailyStat.rebaseMultiplier = BIGDECIMAL_ONE + dailyStat.price = BIGDECIMAL_ZERO + dailyStat.totalSupply = BIGDECIMAL_ZERO + dailyStat.totalSwapValue = BIGDECIMAL_ZERO + } + return dailyStat as RolloverVaultDailyStat } diff --git a/spot-subgraph/src/mappings/bondController.ts b/spot-subgraph/src/mappings/bondController.ts index a908405b..31b110a0 100644 --- a/spot-subgraph/src/mappings/bondController.ts +++ b/spot-subgraph/src/mappings/bondController.ts @@ -8,30 +8,11 @@ import { Redeem, RedeemMature, } from '../../generated/templates/BondController/BondController' -import { - fetchTranche, - fetchBond, - refreshBond, - matureBond, -} from '../data/buttonTranche' +import { fetchTranche, fetchBond, refreshBond, matureBond } from '../data/buttonTranche' import { fetchToken } from '../data/token' import { BIGDECIMAL_ZERO, stringToAddress, formatBalance } from '../utils' -export function handleOwnershipTransferred(event: OwnershipTransferred): void { - log.debug('triggered handleOwnershipTransferred', []) - let bond = fetchBond(event.address) - bond.owner = event.params.newOwner.toHexString() - bond.save() -} - -export function handleFeeUpdate(event: FeeUpdate): void { - log.debug('triggered handleFeeUpdate', []) - let bond = fetchBond(event.address) - bond.feePerc = formatBalance(event.params.newFee, BigInt.fromI32(2)) - bond.save() -} - export function handleDeposit(event: Deposit): void { log.debug('triggered handleDeposit', []) refreshBond(fetchBond(event.address)) diff --git a/spot-subgraph/src/mappings/bondIssuer.ts b/spot-subgraph/src/mappings/bondIssuer.ts index 295160ed..91044611 100644 --- a/spot-subgraph/src/mappings/bondIssuer.ts +++ b/spot-subgraph/src/mappings/bondIssuer.ts @@ -8,7 +8,6 @@ export function handleBondIssued(event: BondIssued): void { let issuer = fetchBondIssuer(event.address) issuer.lastIssueTimestamp = event.block.timestamp - issuer.lastIssueBlock = event.block.number issuer.save() let bond = fetchBond(event.params.bond) diff --git a/spot-subgraph/src/mappings/perpetualTranche.ts b/spot-subgraph/src/mappings/perpetualTranche.ts index 4c30fba7..a0e01020 100644 --- a/spot-subgraph/src/mappings/perpetualTranche.ts +++ b/spot-subgraph/src/mappings/perpetualTranche.ts @@ -1,65 +1,92 @@ -import { log, ethereum } from '@graphprotocol/graph-ts' +import { log, ethereum, BigInt } from '@graphprotocol/graph-ts' import { ReserveSynced, UpdatedDepositBond, - UpdatedMatureTrancheBalance, + Transfer, + RedeemCall, } from '../../generated/PerpetualTranche/PerpetualTranche' import { fetchPerpetualTranche, - refreshPerpetualTrancheStore, + refreshPerpetualTrancheTVL, + refreshPerpetualTrancheDailyStat, fetchPerpetualTrancheReserveAsset, + fetchPerpetualTrancheDailyStat, } from '../data/perpetualTranche' import { fetchBond } from '../data/buttonTranche' -import { fetchToken } from '../data/token' -import { formatBalance } from '../utils' - -export function handleGenericStorageUpdateViaEvent( - event: ethereum.Event, -): void { - log.debug('triggered handleGenericStorageUpdate', []) - refreshPerpetualTrancheStore(fetchPerpetualTranche(event.address)) -} - -export function handleGenericStorageUpdateViaCall(call: ethereum.Call): void { - log.debug('triggered handleGenericStorageUpdate', []) - refreshPerpetualTrancheStore(fetchPerpetualTranche(call.to)) -} +import { fetchToken, refreshSupply } from '../data/token' +import { + formatBalance, + addToSet, + removeFromSet, + BIGDECIMAL_ZERO, + ADDRESS_ZERO, + dayTimestamp, +} from '../utils' export function handleReserveSynced(event: ReserveSynced): void { log.debug('triggered handleReserveSynced', []) let perp = fetchPerpetualTranche(event.address) + let reserveToken = fetchToken(event.params.token) - let reserveAsset = fetchPerpetualTrancheReserveAsset( - event.address, - event.params.token, - ) - reserveAsset.balance = formatBalance( - event.params.balance, - reserveToken.decimals, - ) + let reserveAsset = fetchPerpetualTrancheReserveAsset(event.address, event.params.token) + reserveAsset.balance = formatBalance(event.params.balance, reserveToken.decimals) reserveAsset.save() + + let perpAddress = event.address.toHexString() + let reserveAssetAddress = event.params.token.toHexString() + let activeReserveId = perpAddress.concat('-').concat(reserveAssetAddress) + + if (reserveAsset.balance > BIGDECIMAL_ZERO) { + perp.activeReserves = addToSet(perp.activeReserves, activeReserveId) + } else { + perp.activeReserves = removeFromSet(perp.activeReserves, activeReserveId) + } + refreshPerpetualTrancheTVL(perp) + + let dailyStat = fetchPerpetualTrancheDailyStat(perp, dayTimestamp(event.block.timestamp)) + refreshPerpetualTrancheDailyStat(dailyStat) } export function handleUpdatedDepositBond(event: UpdatedDepositBond): void { log.debug('triggered handleUpdatedDepositBond', []) - let perp = fetchPerpetualTranche(event.address) let bond = fetchBond(event.params.bond) perp.depositBond = bond.id perp.save() } -export function handleUpdatedMatureTrancheBalance( - event: UpdatedMatureTrancheBalance, -): void { - log.debug('triggered handleUpdatedMatureTrancheBalance', []) +export function handleMint(event: Transfer): void { + let from = event.params.from + if (from == ADDRESS_ZERO) { + log.debug('triggered mint', []) + let perpToken = fetchToken(event.address) + refreshSupply(perpToken) - let perp = fetchPerpetualTranche(event.address) - let perpToken = fetchToken(event.address) - perp.matureTrancheBalance = formatBalance( - event.params.matureTrancheBalance, - perpToken.decimals, + let perp = fetchPerpetualTranche(event.address) + refreshPerpetualTrancheTVL(perp) + + let perpAmtMinted = formatBalance(event.params.value, perpToken.decimals) + let dailyStat = fetchPerpetualTrancheDailyStat(perp, dayTimestamp(event.block.timestamp)) + dailyStat.totalMints = dailyStat.totalMints.plus(perpAmtMinted) + dailyStat.totalMintValue = dailyStat.totalMintValue.plus(perpAmtMinted.times(perp.price)) + dailyStat.save() + } +} + +export function handleRedeem(call: RedeemCall): void { + log.debug('triggered redeem', []) + let perpToken = fetchToken(call.to) + refreshSupply(perpToken) + + let perp = fetchPerpetualTranche(call.to) + refreshPerpetualTrancheTVL(perp) + + let perpAmtBurnt = formatBalance(call.inputs.perpAmtBurnt, perpToken.decimals) + let dailyStat = fetchPerpetualTrancheDailyStat(perp, dayTimestamp(call.block.timestamp)) + dailyStat.totalRedemptions = dailyStat.totalRedemptions.plus(perpAmtBurnt) + dailyStat.totalRedemptionValue = dailyStat.totalRedemptionValue.plus( + perpAmtBurnt.times(perp.price), ) - perp.save() + dailyStat.save() } diff --git a/spot-subgraph/src/mappings/rebasingToken.ts b/spot-subgraph/src/mappings/rebasingToken.ts index f55772cf..852ae45d 100644 --- a/spot-subgraph/src/mappings/rebasingToken.ts +++ b/spot-subgraph/src/mappings/rebasingToken.ts @@ -1,21 +1,23 @@ -import { log, dataSource, Address } from '@graphprotocol/graph-ts' -import { - LogRebase, - Rebase, -} from '../../generated/templates/RebasingToken/RebasingERC20' +import { log, dataSource, Address, BigInt } from '@graphprotocol/graph-ts' +import { LogRebase, Rebase } from '../../generated/templates/RebasingToken/RebasingERC20' import { fetchToken, refreshSupply } from '../data/token' import { fetchBond, refreshBond } from '../data/buttonTranche' import { fetchPerpetualTranche, - refreshPerpetualTrancheStore, + refreshPerpetualTrancheTVL, + refreshPerpetualTrancheDailyStat, + fetchPerpetualTrancheDailyStat, } from '../data/perpetualTranche' import { fetchRolloverVault, - refreshRolloverVaultStore, + refreshRolloverVaultTVL, + refreshRolloverVaultRebaseMultiplier, + refreshRolloverVaultDailyStat, + fetchRolloverVaultDailyStat, } from '../data/rolloverVault' -import { stringToAddress } from '../utils' +import { stringToAddress, dayTimestamp } from '../utils' -function _handleRebase(address: Address): void { +function _handleRebase(address: Address, timestamp: BigInt): void { let token = fetchToken(address) refreshSupply(token) @@ -31,23 +33,30 @@ function _handleRebase(address: Address): void { let perpId = context.getString('perp') log.debug('perpRefresh: {}', [perpId]) let perp = fetchPerpetualTranche(stringToAddress(perpId)) - refreshPerpetualTrancheStore(perp) + refreshPerpetualTrancheTVL(perp) + + let dailyStat = fetchPerpetualTrancheDailyStat(perp, dayTimestamp(timestamp)) + refreshPerpetualTrancheDailyStat(dailyStat) } if (context.get('vault') != null) { let vaultId = context.getString('vault') log.debug('vaultRefresh: {}', [vaultId]) let vault = fetchRolloverVault(stringToAddress(vaultId)) - refreshRolloverVaultStore(vault) + refreshRolloverVaultTVL(vault) + refreshRolloverVaultRebaseMultiplier(vault) + + let dailyStat = fetchRolloverVaultDailyStat(vault, dayTimestamp(timestamp)) + refreshRolloverVaultDailyStat(dailyStat) } } export function handleRebase(event: Rebase): void { log.debug('triggered handleRebase', []) - _handleRebase(event.address) + _handleRebase(event.address, event.block.timestamp) } export function handleLogRebase(event: LogRebase): void { log.debug('triggered handleLogRebase', []) - _handleRebase(event.address) + _handleRebase(event.address, event.block.timestamp) } diff --git a/spot-subgraph/src/mappings/rolloverVault.ts b/spot-subgraph/src/mappings/rolloverVault.ts index 3d6f6b95..d29317c7 100644 --- a/spot-subgraph/src/mappings/rolloverVault.ts +++ b/spot-subgraph/src/mappings/rolloverVault.ts @@ -3,78 +3,155 @@ import { DepositCall, RedeemCall, AssetSynced, + SwapPerpsForUnderlyingCall, + SwapUnderlyingForPerpsCall, } from '../../generated/RolloverVault/RolloverVault' import { RebasingERC20 as RebasingERC20ABI } from '../../generated/templates/RebasingToken/RebasingERC20' +import { fetchPerpetualTranche, refreshPerpetualTrancheTVL } from '../data/perpetualTranche' import { fetchRolloverVault, - fetchScaledUnderlyingVaultBalance, - refreshRolloverVaultStore, + fetchScaledUnderlyingVaultDepositorBalance, + refreshRolloverVaultTVL, + refreshRolloverVaultRebaseMultiplier, + refreshRolloverVaultDailyStat, fetchRolloverVaultAsset, + fetchRolloverVaultDailyStat, } from '../data/rolloverVault' -import { fetchToken } from '../data/token' -import { formatBalance, stringToAddress } from '../utils' - -export function handleGenericStorageUpdateViaEvent( - event: ethereum.Event, -): void { - log.debug('triggered handleGenericStorageUpdate', []) - refreshRolloverVaultStore(fetchRolloverVault(event.address)) -} - -export function handleGenericStorageUpdateViaCall(call: ethereum.Call): void { - log.debug('triggered handleGenericStorageUpdate', []) - refreshRolloverVaultStore(fetchRolloverVault(call.to)) -} +import { fetchToken, refreshSupply } from '../data/token' +import { + formatBalance, + stringToAddress, + addToSet, + removeFromSet, + BIGDECIMAL_ZERO, + dayTimestamp, +} from '../utils' export function handleDeposit(call: DepositCall): void { log.debug('triggered deposit', []) let vault = fetchRolloverVault(call.to) + let vaultToken = fetchToken(stringToAddress(vault.token)) + refreshSupply(vaultToken) + refreshRolloverVaultTVL(vault) + refreshRolloverVaultRebaseMultiplier(vault) + let underlyingToken = fetchToken(stringToAddress(vault.underlying)) - let tokenContract = RebasingERC20ABI.bind(stringToAddress(vault.underlying)) - let amountIn = formatBalance(call.inputs.amount, underlyingToken.decimals) - let totalSupply = formatBalance( - tokenContract.totalSupply(), - underlyingToken.decimals, - ) - let scaledTotalSupply = tokenContract.scaledTotalSupply().toBigDecimal() - let scaledAmountIn = amountIn.times(scaledTotalSupply).div(totalSupply) - vault.totalUnderlyingScaledHeld = vault.totalUnderlyingScaledHeld.plus( - scaledAmountIn, + refreshSupply(underlyingToken) + let underlyingTokenSupply = underlyingToken.totalSupply + + let underlyingTokenContract = RebasingERC20ABI.bind(stringToAddress(vault.underlying)) + let scaledUnderlyingSupply = underlyingTokenContract.scaledTotalSupply().toBigDecimal() + + let underlyingAmtIn = formatBalance(call.inputs.underlyingAmtIn, underlyingToken.decimals) + let scaledUnderlyingAmountIn = underlyingAmtIn + .times(scaledUnderlyingSupply) + .div(underlyingTokenSupply) + vault.totalScaledUnderlyingDeposited = vault.totalScaledUnderlyingDeposited.plus( + scaledUnderlyingAmountIn, ) vault.save() - let userBalance = fetchScaledUnderlyingVaultBalance(vault, call.from) - userBalance.value = userBalance.value.plus(scaledAmountIn) - userBalance.save() + let scaledUnderlyingDepositorBalance = fetchScaledUnderlyingVaultDepositorBalance( + vault, + call.from, + ) + scaledUnderlyingDepositorBalance.value = scaledUnderlyingDepositorBalance.value.plus( + scaledUnderlyingAmountIn, + ) + scaledUnderlyingDepositorBalance.save() + + let dailyStat = fetchRolloverVaultDailyStat(vault, dayTimestamp(call.block.timestamp)) + dailyStat.totalMints = dailyStat.totalMints.plus(underlyingAmtIn.div(vault.price)) + dailyStat.totalMintValue = dailyStat.totalMintValue.plus(underlyingAmtIn) + dailyStat.save() } export function handleRedeem(call: RedeemCall): void { log.debug('triggered redeem', []) let vault = fetchRolloverVault(call.to) let vaultToken = fetchToken(stringToAddress(vault.token)) - let tokenContract = RebasingERC20ABI.bind(stringToAddress(vault.underlying)) + refreshSupply(vaultToken) + refreshRolloverVaultTVL(vault) + refreshRolloverVaultRebaseMultiplier(vault) + let notesOut = formatBalance(call.inputs.notes, vaultToken.decimals) - let scaledAmountOut = vault.totalUnderlyingScaledHeld + let scaledAmountOut = vault.totalScaledUnderlyingDeposited .times(notesOut) .div(vaultToken.totalSupply) - vault.totalUnderlyingScaledHeld = vault.totalUnderlyingScaledHeld.minus( + vault.totalScaledUnderlyingDeposited = vault.totalScaledUnderlyingDeposited.minus( scaledAmountOut, ) vault.save() - let userBalance = fetchScaledUnderlyingVaultBalance(vault, call.from) - userBalance.value = userBalance.value.minus(scaledAmountOut) - userBalance.save() + let scaledUnderlyingDepositorBalance = fetchScaledUnderlyingVaultDepositorBalance( + vault, + call.from, + ) + scaledUnderlyingDepositorBalance.value = scaledUnderlyingDepositorBalance.value.minus( + scaledAmountOut, + ) + scaledUnderlyingDepositorBalance.save() + + let dailyStat = fetchRolloverVaultDailyStat(vault, dayTimestamp(call.block.timestamp)) + dailyStat.totalRedemptions = dailyStat.totalRedemptions.plus(notesOut) + dailyStat.totalRedemptionValue = dailyStat.totalRedemptionValue.plus(notesOut.times(vault.price)) + dailyStat.save() } export function handleAssetSynced(event: AssetSynced): void { log.debug('triggered AssetSynced', []) let vault = fetchRolloverVault(event.address) + let assetToken = fetchToken(event.params.token) let reserveAsset = fetchRolloverVaultAsset(event.address, event.params.token) - reserveAsset.balance = formatBalance( - event.params.balance, - assetToken.decimals, - ) + reserveAsset.balance = formatBalance(event.params.balance, assetToken.decimals) reserveAsset.save() + + let vaultAddress = event.address.toHexString() + let reserveAssetAddress = event.params.token.toHexString() + let activeReserveId = vaultAddress.concat('-').concat(reserveAssetAddress) + + if (reserveAsset.balance > BIGDECIMAL_ZERO) { + vault.activeReserves = addToSet(vault.activeReserves, activeReserveId) + } else { + vault.activeReserves = removeFromSet(vault.activeReserves, activeReserveId) + } + refreshRolloverVaultTVL(vault) + refreshRolloverVaultRebaseMultiplier(vault) + + let dailyStat = fetchRolloverVaultDailyStat(vault, dayTimestamp(event.block.timestamp)) + refreshRolloverVaultDailyStat(dailyStat) +} + +export function handleUnderlyingToPerpSwap(call: SwapUnderlyingForPerpsCall): void { + log.debug('triggered UnderlyingToPerpSwap', []) + + let vault = fetchRolloverVault(call.to) + refreshRolloverVaultTVL(vault) + refreshRolloverVaultRebaseMultiplier(vault) + + let underlyingToken = fetchToken(stringToAddress(vault.underlying)) + let underlyingAmtIn = formatBalance(call.inputs.underlyingAmtIn, underlyingToken.decimals) + + let dailyStat = fetchRolloverVaultDailyStat(vault, dayTimestamp(call.block.timestamp)) + dailyStat.totalSwapValue = dailyStat.totalSwapValue.plus(underlyingAmtIn) + dailyStat.save() +} + +export function handlePerpToUnderlyingSwap(call: SwapPerpsForUnderlyingCall): void { + log.debug('triggered PerpToUnderlyingSwap', []) + + let vault = fetchRolloverVault(call.to) + refreshRolloverVaultTVL(vault) + refreshRolloverVaultRebaseMultiplier(vault) + + let perp = fetchPerpetualTranche(stringToAddress(vault.perp)) + refreshPerpetualTrancheTVL(perp) + + let underlyingToken = fetchToken(stringToAddress(vault.underlying)) + let perpAmtIn = formatBalance(call.inputs.perpAmtIn, underlyingToken.decimals) + + let dailyStat = fetchRolloverVaultDailyStat(vault, dayTimestamp(call.block.timestamp)) + dailyStat.totalSwapValue = dailyStat.totalSwapValue.plus(perpAmtIn.times(perp.price)) + dailyStat.save() } diff --git a/spot-subgraph/src/utils.ts b/spot-subgraph/src/utils.ts index a7287004..f44a0e57 100644 --- a/spot-subgraph/src/utils.ts +++ b/spot-subgraph/src/utils.ts @@ -1,12 +1,13 @@ import { BigDecimal, BigInt, Address } from '@graphprotocol/graph-ts' +import { ERC20 as ERC20ABI } from '../generated/BondFactory/ERC20' +import { Tranche as TrancheABI } from '../generated/BondFactory/Tranche' +import { BondController as BondControllerABI } from '../generated/BondFactory/BondController' export let BIGINT_ZERO = BigInt.fromI32(0) export let BIGINT_ONE = BigInt.fromI32(1) export let BIGDECIMAL_ZERO = new BigDecimal(BIGINT_ZERO) export let BIGDECIMAL_ONE = new BigDecimal(BIGINT_ONE) -export let ADDRESS_ZERO = Address.fromString( - '0x0000000000000000000000000000000000000000', -) +export let ADDRESS_ZERO = Address.fromString('0x0000000000000000000000000000000000000000') export const formatBalance = (wei: BigInt, decimals: BigInt): BigDecimal => { return wei.toBigDecimal().div( @@ -19,3 +20,93 @@ export const formatBalance = (wei: BigInt, decimals: BigInt): BigDecimal => { export const stringToAddress = (id: string): Address => { return Address.fromString(id) } + +export const dayTimestamp = (timestamp: BigInt): BigInt => { + return timestamp.minus(timestamp % BigInt.fromI32(24 * 3600)) +} + +export function addToSet(set: string[], e: string): string[] { + let isPresent = false + for (let i = 0; i < set.length; i++) { + if (set[i] == e) { + isPresent = true + break + } + } + if (!isPresent) { + set.push(e) + } + return set +} + +export function removeFromSet(set: string[], e: string): string[] { + let isPresent = false + let set_: string[] = [] + for (let i = 0; i < set.length; i++) { + if (set[i] != e) { + set_.push(set[i]) + } + } + return set_ +} + +export class CDRInfo { + isBondMature: boolean + isSeniorTranche: boolean + trancheSupply: BigDecimal + bondCollateralBalance: BigDecimal + bondTotalDebt: BigDecimal + trancheClaim: BigDecimal + trancheCDR: BigDecimal + bondCDR: BigDecimal + tranchePrice: BigDecimal + trancheValue: BigDecimal +} + +export function getTrancheCDRInfo( + trancheAddress: Address, + underlyingAddress: Address, + trancheBalance: BigDecimal, +): CDRInfo { + let underlyingERC20Contract = ERC20ABI.bind(underlyingAddress) + let decimals = BigInt.fromI32(underlyingERC20Contract.decimals()) + let trancheContract = TrancheABI.bind(trancheAddress) + let bondAddress = trancheContract.bond() + let bondContract = BondControllerABI.bind(bondAddress) + let bondSeniorTrancheData = bondContract.tranches(BIGINT_ZERO) + + let r = new CDRInfo() + r.isBondMature = bondContract.isMature() == 1 + r.isSeniorTranche = bondSeniorTrancheData.value0 == trancheAddress + r.trancheSupply = formatBalance(trancheContract.totalSupply(), decimals) + r.bondCollateralBalance = formatBalance(underlyingERC20Contract.balanceOf(bondAddress), decimals) + r.bondTotalDebt = formatBalance(bondContract.totalDebt(), decimals) + + if (r.trancheSupply.equals(BIGDECIMAL_ZERO)) { + return r + } + + if (!r.isBondMature) { + if (!r.isSeniorTranche) { + let seniorTrancheContract = ERC20ABI.bind(bondSeniorTrancheData.value0) + let seniorSupply = formatBalance(seniorTrancheContract.totalSupply(), decimals) + r.trancheClaim = r.bondCollateralBalance.gt(seniorSupply) + ? r.bondCollateralBalance.minus(seniorSupply) + : BIGDECIMAL_ZERO + r.trancheCDR = r.trancheClaim.div(r.trancheSupply) + } else { + r.trancheClaim = r.bondCollateralBalance.gt(r.trancheSupply) + ? r.trancheSupply + : r.bondCollateralBalance + r.trancheCDR = r.bondCollateralBalance.div(r.trancheSupply) + } + r.bondCDR = r.bondCollateralBalance.div(r.bondTotalDebt) + } else { + r.trancheClaim = formatBalance(underlyingERC20Contract.balanceOf(trancheAddress), decimals) + r.trancheCDR = r.trancheClaim.div(r.trancheSupply) + r.bondCDR = r.trancheCDR + } + r.tranchePrice = r.trancheClaim.div(r.trancheSupply) + r.trancheValue = trancheBalance.times(r.tranchePrice) + return r +} diff --git a/spot-subgraph/subgraph.template.yaml b/spot-subgraph/subgraph.template.yaml index 0f6a76a2..33e8c8d4 100644 --- a/spot-subgraph/subgraph.template.yaml +++ b/spot-subgraph/subgraph.template.yaml @@ -10,6 +10,7 @@ dataSources: network: {{ network }} source: abi: BondFactory + address: "{{ bondFactory }}" startBlock: {{ startBlock }} mapping: kind: ethereum/events @@ -22,6 +23,8 @@ dataSources: file: ../spot-contracts/external-artifacts/BondFactory.json - name: BondController file: ../spot-contracts/external-artifacts/BondController.json + - name: Tranche + file: ../spot-contracts/external-artifacts/Tranche.json - name: ERC20 file: ../spot-contracts/external-artifacts/ERC20ABI.json eventHandlers: @@ -29,11 +32,67 @@ dataSources: handler: handleBondCreated file: ./src/mappings/bondFactory.ts + {{#previousBondFactories}} + - kind: ethereum/contract + name: BondFactoryPrev{{0}} + network: {{ network }} + source: + abi: BondFactory + address: "{{1}}" + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.4 + language: wasm/assemblyscript + entities: + - BondCreated + abis: + - name: BondFactory + file: ../spot-contracts/external-artifacts/BondFactory.json + - name: BondController + file: ../spot-contracts/external-artifacts/BondController.json + - name: Tranche + file: ../spot-contracts/external-artifacts/Tranche.json + - name: ERC20 + file: ../spot-contracts/external-artifacts/ERC20ABI.json + eventHandlers: + - event: BondCreated(address,address) + handler: handleBondCreated + file: ./src/mappings/bondFactory.ts + {{/previousBondFactories}} + - kind: ethereum/contract name: BondIssuer network: {{ network }} source: abi: BondIssuer + address: "{{ bondIssuer }}" + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.4 + language: wasm/assemblyscript + entities: + - BondIssued + abis: + - name: BondIssuer + file: ../spot-contracts/exported-artifacts/BondIssuer.json + - name: BondController + file: ../spot-contracts/external-artifacts/BondController.json + - name: Tranche + file: ../spot-contracts/external-artifacts/Tranche.json + eventHandlers: + - event: BondIssued(address) + handler: handleBondIssued + file: ./src/mappings/bondIssuer.ts + + {{#previousIssuers}} + - kind: ethereum/contract + name: BondIssuerPrev{{0}} + network: {{ network }} + source: + abi: BondIssuer + address: "{{1}}" startBlock: {{ startBlock }} mapping: kind: ethereum/events @@ -46,69 +105,51 @@ dataSources: file: ../spot-contracts/exported-artifacts/BondIssuer.json - name: BondController file: ../spot-contracts/external-artifacts/BondController.json + - name: Tranche + file: ../spot-contracts/external-artifacts/Tranche.json eventHandlers: - event: BondIssued(address) handler: handleBondIssued file: ./src/mappings/bondIssuer.ts + {{/previousIssuers}} - kind: ethereum/contract name: PerpetualTranche network: {{ network }} source: abi: PerpetualTranche - address: "{{ spot }}" + address: "{{ perpetualTranche }}" startBlock: {{ startBlock }} mapping: kind: ethereum/events apiVersion: 0.0.4 language: wasm/assemblyscript entities: - - UpdatedKeeper - - UpdatedBondIssuer - - UpdatedFeeStrategy - - UpdatedPricingStrategy - - UpdatedDiscountStrategy - - UpdatedTolerableTrancheMaturity - - UpdatedMintingLimits - - UpdatedMatureValueTargetPerc - UpdatedDepositBond - - UpdatedMatureTrancheBalance - ReserveSynced abis: - name: PerpetualTranche - file: ../spot-contracts/exported-artifacts/PerpetualTranche.json + file: ./modified-artifacts/PerpetualTranche.json + - name: PerpetualTrancheV1 + file: ../spot-contracts/exported-artifacts/PerpetualTrancheV1.json - name: BondController file: ../spot-contracts/external-artifacts/BondController.json + - name: Tranche + file: ../spot-contracts/external-artifacts/Tranche.json - name: ERC20 file: ../spot-contracts/external-artifacts/ERC20ABI.json - name: RebasingERC20 file: ../spot-contracts/external-artifacts/RebasingERC20ABI.json eventHandlers: - - event: UpdatedKeeper(address,address) - handler: handleGenericStorageUpdateViaEvent - - event: UpdatedBondIssuer(address) - handler: handleGenericStorageUpdateViaEvent - - event: UpdatedFeeStrategy(address) - handler: handleGenericStorageUpdateViaEvent - - event: UpdatedPricingStrategy(address) - handler: handleGenericStorageUpdateViaEvent - - event: UpdatedDiscountStrategy(address) - handler: handleGenericStorageUpdateViaEvent - - event: UpdatedTolerableTrancheMaturity(uint256,uint256) - handler: handleGenericStorageUpdateViaEvent - - event: UpdatedMintingLimits(uint256,uint256) - handler: handleGenericStorageUpdateViaEvent - - event: UpdatedMatureValueTargetPerc(uint256) - handler: handleGenericStorageUpdateViaEvent - event: ReserveSynced(address,uint256) handler: handleReserveSynced - event: UpdatedDepositBond(address) handler: handleUpdatedDepositBond - - event: UpdatedMatureTrancheBalance(uint256) - handler: handleUpdatedMatureTrancheBalance + - event: Transfer(indexed address,indexed address,uint256) + handler: handleMint callHandlers: - - function: init(string,string,address,address,address,address,address) - handler: handleGenericStorageUpdateViaCall + - function: redeem(uint256) + handler: handleRedeem file: ./src/mappings/perpetualTranche.ts - kind: ethereum/contract @@ -127,22 +168,28 @@ dataSources: abis: - name: RolloverVault file: ../spot-contracts/exported-artifacts/RolloverVault.json + - name: PerpetualTranche + file: ../spot-contracts/exported-artifacts/PerpetualTranche.json + - name: BondController + file: ../spot-contracts/external-artifacts/BondController.json + - name: Tranche + file: ../spot-contracts/external-artifacts/Tranche.json - name: ERC20 file: ../spot-contracts/external-artifacts/ERC20ABI.json - name: RebasingERC20 file: ../spot-contracts/external-artifacts/RebasingERC20ABI.json eventHandlers: - - event: OwnershipTransferred(indexed address,indexed address) - handler: handleGenericStorageUpdateViaEvent - event: AssetSynced(address,uint256) handler: handleAssetSynced callHandlers: - - function: init(string,string,address) - handler: handleGenericStorageUpdateViaCall - function: deposit(uint256) handler: handleDeposit - function: redeem(uint256) handler: handleRedeem + - function: swapUnderlyingForPerps(uint256) + handler: handleUnderlyingToPerpSwap + - function: swapPerpsForUnderlying(uint256) + handler: handlePerpToUnderlyingSwap file: ./src/mappings/rolloverVault.ts templates: - kind: ethereum/contract @@ -155,8 +202,6 @@ templates: apiVersion: 0.0.4 language: wasm/assemblyscript entities: - - OwnershipTransferred - - FeeUpdate - Deposit - Mature - Redeem @@ -164,13 +209,11 @@ templates: abis: - name: BondController file: ../spot-contracts/external-artifacts/BondController.json + - name: Tranche + file: ../spot-contracts/external-artifacts/Tranche.json - name: ERC20 file: ../spot-contracts/external-artifacts/ERC20ABI.json eventHandlers: - - event: OwnershipTransferred(indexed address,indexed address) - handler: handleOwnershipTransferred - - event: FeeUpdate(uint256) - handler: handleFeeUpdate - event: Deposit(address,uint256,uint256) handler: handleDeposit - event: Mature(address) @@ -215,10 +258,14 @@ templates: abis: - name: PerpetualTranche file: ../spot-contracts/exported-artifacts/PerpetualTranche.json + - name: PerpetualTrancheV1 + file: ../spot-contracts/exported-artifacts/PerpetualTrancheV1.json - name: RolloverVault file: ../spot-contracts/exported-artifacts/RolloverVault.json - name: BondController file: ../spot-contracts/external-artifacts/BondController.json + - name: Tranche + file: ../spot-contracts/external-artifacts/Tranche.json - name: ERC20 file: ../spot-contracts/external-artifacts/ERC20ABI.json - name: RebasingERC20 diff --git a/spot-vaults/.eslintignore b/spot-vaults/.eslintignore new file mode 100644 index 00000000..85f5562a --- /dev/null +++ b/spot-vaults/.eslintignore @@ -0,0 +1,4 @@ +node_modules +artifacts +cache +coverage diff --git a/spot-vaults/.eslintrc.js b/spot-vaults/.eslintrc.js new file mode 100644 index 00000000..a785c8ed --- /dev/null +++ b/spot-vaults/.eslintrc.js @@ -0,0 +1,46 @@ +module.exports = { + env: { + browser: false, + es2021: true, + mocha: true, + node: true, + }, + plugins: ["@typescript-eslint", "no-only-tests", "unused-imports"], + extends: ["standard", "plugin:prettier/recommended", "plugin:node/recommended"], + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: 12, + warnOnUnsupportedTypeScriptVersion: false, + }, + rules: { + "node/no-unsupported-features/es-syntax": ["error", { ignores: ["modules"] }], + "node/no-missing-import": [ + "error", + { + tryExtensions: [".ts", ".js", ".json"], + }, + ], + "node/no-unpublished-import": [ + "error", + { + allowModules: [ + "hardhat", + "ethers", + "@openzeppelin/upgrades-core", + "chai", + "@nomicfoundation/hardhat-ethers", + "@nomicfoundation/hardhat-chai-matchers", + "@nomicfoundation/hardhat-verify", + "@nomicfoundation/hardhat-toolbox", + "@openzeppelin/hardhat-upgrades", + "solidity-coverage", + "hardhat-gas-reporter", + "dotenv", + ], + }, + ], + "no-only-tests/no-only-tests": "error", + "unused-imports/no-unused-imports": "error", + "unused-imports/no-unused-vars": ["warn", { vars: "all" }], + }, +}; diff --git a/spot-vaults/.eslintrc.yaml b/spot-vaults/.eslintrc.yaml new file mode 100644 index 00000000..e69de29b diff --git a/spot-vaults/.gitignore b/spot-vaults/.gitignore new file mode 100644 index 00000000..9722dbfa --- /dev/null +++ b/spot-vaults/.gitignore @@ -0,0 +1,14 @@ +node_modules +.env + +# Hardhat files +/cache +/artifacts + +# TypeChain files +/typechain +/typechain-types + +# solidity-coverage files +/coverage +/coverage.json diff --git a/spot-vaults/.openzeppelin/mainnet.json b/spot-vaults/.openzeppelin/mainnet.json new file mode 100644 index 00000000..bcc7efee --- /dev/null +++ b/spot-vaults/.openzeppelin/mainnet.json @@ -0,0 +1,331 @@ +{ + "manifestVersion": "3.2", + "proxies": [ + { + "address": "0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB", + "txHash": "0x7b991de0ac1a42dc8b2d2ba290f0c36ed40d9433d06af0a726e36f723a561fe2", + "kind": "transparent" + } + ], + "impls": { + "60be4f02bfbd611d46825ab48407a5f15d43902b07a1ada4ab950b5808bc2c8c": { + "address": "0x6ca2E2B0F2e1964BBCceDE5b2Dd37AE25966662F", + "txHash": "0xf118c67360b55f0de6c74a07b6d3fffdbf007fc8aef4d762705bf589147828cb", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_balances", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:37" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:39" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "53", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "54", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:43" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "55", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "__gap", + "offset": 0, + "slot": "56", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:394" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC20BurnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol:51" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "201", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "_status", + "offset": 0, + "slot": "251", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:74" + }, + { + "label": "perp", + "offset": 0, + "slot": "301", + "type": "t_contract(IPerpetualTranche)2802", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:86" + }, + { + "label": "usd", + "offset": 0, + "slot": "302", + "type": "t_contract(IERC20Upgradeable)4792", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:89" + }, + { + "label": "usdUnitAmt", + "offset": 0, + "slot": "303", + "type": "t_uint256", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:92" + }, + { + "label": "perpUnitAmt", + "offset": 0, + "slot": "304", + "type": "t_uint256", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:95" + }, + { + "label": "keeper", + "offset": 0, + "slot": "305", + "type": "t_address", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:100" + }, + { + "label": "pricingStrategy", + "offset": 0, + "slot": "306", + "type": "t_contract(IBillBrokerPricingStrategy)11393", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:103" + }, + { + "label": "fees", + "offset": 0, + "slot": "307", + "type": "t_struct(BillBrokerFees)11353_storage", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:106" + }, + { + "label": "arHardBound", + "offset": 0, + "slot": "314", + "type": "t_struct(Range)11334_storage", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:109" + }, + { + "label": "arSoftBound", + "offset": 0, + "slot": "316", + "type": "t_struct(Range)11334_storage", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:113" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IBillBrokerPricingStrategy)11393": { + "label": "contract IBillBrokerPricingStrategy", + "numberOfBytes": "20" + }, + "t_contract(IERC20Upgradeable)4792": { + "label": "contract IERC20Upgradeable", + "numberOfBytes": "20" + }, + "t_contract(IPerpetualTranche)2802": { + "label": "contract IPerpetualTranche", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(BillBrokerFees)11353_storage": { + "label": "struct BillBrokerFees", + "members": [ + { + "label": "mintFeePerc", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "burnFeePerc", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "perpToUSDSwapFeePercs", + "type": "t_struct(Range)11334_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "usdToPerpSwapFeePercs", + "type": "t_struct(Range)11334_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "protocolSwapSharePerc", + "type": "t_uint256", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_struct(Range)11334_storage": { + "label": "struct Range", + "members": [ + { + "label": "lower", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "upper", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + } + } +} diff --git a/spot-vaults/.openzeppelin/sepolia.json b/spot-vaults/.openzeppelin/sepolia.json new file mode 100644 index 00000000..6087f3cb --- /dev/null +++ b/spot-vaults/.openzeppelin/sepolia.json @@ -0,0 +1,331 @@ +{ + "manifestVersion": "3.2", + "proxies": [ + { + "address": "0xc3f6D1F1d253EdC8B34D78Bc6cDD2b3eEFAd76BD", + "txHash": "0xe08468aac2fe4f178e7dbddd07de8bb8d4e8066358082aa0a17c1be74400ad7c", + "kind": "transparent" + } + ], + "impls": { + "60be4f02bfbd611d46825ab48407a5f15d43902b07a1ada4ab950b5808bc2c8c": { + "address": "0x62640188ac7E8d562DcAF47F47470844DAeC7463", + "txHash": "0xa11f678fb1afac3317e76a2415de5da5836026b354d561e27e06cee1edaaa118", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_balances", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:37" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:39" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "53", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "54", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:43" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "55", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "__gap", + "offset": 0, + "slot": "56", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:394" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC20BurnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol:51" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "201", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "_status", + "offset": 0, + "slot": "251", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:74" + }, + { + "label": "perp", + "offset": 0, + "slot": "301", + "type": "t_contract(IPerpetualTranche)2802", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:86" + }, + { + "label": "usd", + "offset": 0, + "slot": "302", + "type": "t_contract(IERC20Upgradeable)4792", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:89" + }, + { + "label": "usdUnitAmt", + "offset": 0, + "slot": "303", + "type": "t_uint256", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:92" + }, + { + "label": "perpUnitAmt", + "offset": 0, + "slot": "304", + "type": "t_uint256", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:95" + }, + { + "label": "keeper", + "offset": 0, + "slot": "305", + "type": "t_address", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:100" + }, + { + "label": "pricingStrategy", + "offset": 0, + "slot": "306", + "type": "t_contract(IBillBrokerPricingStrategy)12579", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:103" + }, + { + "label": "fees", + "offset": 0, + "slot": "307", + "type": "t_struct(BillBrokerFees)12539_storage", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:106" + }, + { + "label": "arHardBound", + "offset": 0, + "slot": "314", + "type": "t_struct(Range)12520_storage", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:109" + }, + { + "label": "arSoftBound", + "offset": 0, + "slot": "316", + "type": "t_struct(Range)12520_storage", + "contract": "BillBroker", + "src": "contracts/BillBroker.sol:113" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IBillBrokerPricingStrategy)12579": { + "label": "contract IBillBrokerPricingStrategy", + "numberOfBytes": "20" + }, + "t_contract(IERC20Upgradeable)4792": { + "label": "contract IERC20Upgradeable", + "numberOfBytes": "20" + }, + "t_contract(IPerpetualTranche)2802": { + "label": "contract IPerpetualTranche", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(BillBrokerFees)12539_storage": { + "label": "struct BillBrokerFees", + "members": [ + { + "label": "mintFeePerc", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "burnFeePerc", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "perpToUSDSwapFeePercs", + "type": "t_struct(Range)12520_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "usdToPerpSwapFeePercs", + "type": "t_struct(Range)12520_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "protocolSwapSharePerc", + "type": "t_uint256", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_struct(Range)12520_storage": { + "label": "struct Range", + "members": [ + { + "label": "lower", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "upper", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + } + } +} diff --git a/spot-vaults/.prettierignore b/spot-vaults/.prettierignore new file mode 100644 index 00000000..ad450725 --- /dev/null +++ b/spot-vaults/.prettierignore @@ -0,0 +1,12 @@ +# folders +artifacts/ +build/ +cache/ +coverage/ +dist/ +lib/ +node_modules/ +typechain/ + +# files +coverage.json diff --git a/spot-vaults/.prettierrc b/spot-vaults/.prettierrc new file mode 100644 index 00000000..46a7cb19 --- /dev/null +++ b/spot-vaults/.prettierrc @@ -0,0 +1,17 @@ +{ + "arrowParens": "avoid", + "bracketSpacing": true, + "endOfLine":"auto", + "printWidth": 90, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "all", + "overrides": [ + { + "files": "*.sol", + "options": { + "tabWidth": 4 + } + } + ] +} diff --git a/spot-vaults/.solcover.js b/spot-vaults/.solcover.js new file mode 100644 index 00000000..081573c5 --- /dev/null +++ b/spot-vaults/.solcover.js @@ -0,0 +1,3 @@ +module.exports = { + skipFiles: ["_test", "_interfaces", "_external"], +}; diff --git a/spot-vaults/.solhint.json b/spot-vaults/.solhint.json new file mode 100644 index 00000000..95267e66 --- /dev/null +++ b/spot-vaults/.solhint.json @@ -0,0 +1,10 @@ +{ + "extends": "solhint:recommended", + "rules": { + "compiler-version": ["error", "^0.8.0"], + "func-visibility": ["warn", { "ignoreConstructors": true }], + "reason-string": ["warn", { "maxLength": 64 }], + "not-rely-on-time": "off", + "max-states-count": ["warn", 17] + } +} diff --git a/spot-vaults/.solhintignore b/spot-vaults/.solhintignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/spot-vaults/.solhintignore @@ -0,0 +1 @@ +node_modules diff --git a/spot-vaults/README.md b/spot-vaults/README.md new file mode 100644 index 00000000..64e7ea07 --- /dev/null +++ b/spot-vaults/README.md @@ -0,0 +1,44 @@ +# spot-vaults + +This repository is a collection of vault strategies leveraging the SPOT system. + +The official mainnet addresses are: + +- Bill Broker (SPOT-USDC): [0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB](https://etherscan.io/address/0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB) +- SpotAppraiser: [0x965FBFebDA76d9AA11642C1d0074CdF02e546F3c](https://etherscan.io/address/0x965FBFebDA76d9AA11642C1d0074CdF02e546F3c) + +The official testnet addresses are: + +- Bill Broker (SPOT-USDC): [0xc3f6D1F1d253EdC8B34D78Bc6cDD2b3eEFAd76BD](https://sepolia.etherscan.io/address/0xc3f6D1F1d253EdC8B34D78Bc6cDD2b3eEFAd76BD) +- SpotAppraiser: [0x08c5b39F000705ebeC8427C1d64D6262392944EE](https://sepolia.etherscan.io/address/0x08c5b39F000705ebeC8427C1d64D6262392944EE) + +## Install + +```bash +# Install project dependencies +yarn +``` + +## Testing + +```bash +# Run all unit tests (compatible with node v12+) +yarn test +``` + +## Contribute + +To report bugs within this package, create an issue in this repository. +For security issues, please contact dev-support@ampleforth.org. +When submitting code ensure that it is free of lint errors and has 100% test coverage. + +```bash +# Lint code +yarn lint:fix + +# Run solidity coverage report (compatible with node v12) +yarn coverage + +# Run solidity gas usage report +yarn profile +``` diff --git a/spot-vaults/contracts/BillBroker.sol b/spot-vaults/contracts/BillBroker.sol new file mode 100644 index 00000000..fc05f7da --- /dev/null +++ b/spot-vaults/contracts/BillBroker.sol @@ -0,0 +1,791 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; +import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; +import { MathUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; +import { SignedMathUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol"; +import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; +import { ERC20BurnableUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; +import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import { IERC20MetadataUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; + +import { IPerpetualTranche } from "@ampleforthorg/spot-contracts/contracts/_interfaces/IPerpetualTranche.sol"; +import { IBillBrokerPricingStrategy } from "./_interfaces/IBillBrokerPricingStrategy.sol"; +import { ReserveState, Range, Line, BillBrokerFees } from "./_interfaces/BillBrokerTypes.sol"; +import { UnacceptableSwap, UnreliablePrice, UnexpectedDecimals, InvalidPerc, InvalidARBound, SlippageTooHigh, UnauthorizedCall, UnexpectedARDelta } from "./_interfaces/BillBrokerErrors.sol"; + +/** + * @title BillBroker + * + * @notice The `BillBroker` contract (inspired by bill brokers in LombardSt) acts as an intermediary between + * parties who want to borrow and lend. + * + * `BillBroker` LPs deposit perps and dollars as available liquidity into the contract. + * Any user can now sell/buy perps (swap) from the bill broker for dollars, + * at a "fair" exchange rate determined by the contract. + * + * The contract charges a fee for swap operations. + * The fee is a function of available liquidity held in the contract, and goes to the LPs. + * + * The ratio of value of dollar tokens vs perp tokens held by the contract is defined as it's `assetRatio`. + * => `assetRatio` = reserveValue(usd) / reserveValue(perp) + * + * The owner can define hard limits on the system's assetRatio outside which swapping is disabled. + * + * The contract relies on external data sources to price assets. + * If the data is unreliable, swaps are simply halted. + * + * Intermediating borrowing: + * Borrowers who want to borrower dollars against their collateral, + * tranche their collateral, mint perps and sell it for dollars to the bill broker. + * When they want to close out their position they can buy back perps from the bill broker + * using dollars, and redeem their tranches for the original collateral. + * The spread is the "interest rate" paid for the loan, which goes to the bill broker LPs + * who take on the risk of holding perps through the duration of the loan. + * + * Intermediating lending: + * Lenders can buy perps from the bill broker contract when it's under-priced, + * hold the perp tokens until the market price recovers and sell it back to the bill broker contract. + * + * + */ +contract BillBroker is + ERC20BurnableUpgradeable, + OwnableUpgradeable, + PausableUpgradeable, + ReentrancyGuardUpgradeable +{ + //------------------------------------------------------------------------- + // Libraries + + // ERC20 operations + using SafeERC20Upgradeable for IERC20Upgradeable; + using SafeERC20Upgradeable for IPerpetualTranche; + + // Math + using MathUpgradeable for uint256; + using SafeCastUpgradeable for uint256; + using SafeCastUpgradeable for int256; + using SignedMathUpgradeable for int256; + + //------------------------------------------------------------------------- + // Constants & Immutables + + uint256 public constant DECIMALS = 18; + uint256 public constant ONE = (10 ** DECIMALS); + uint256 private constant INITIAL_RATE = 1000000; + uint256 public constant MINIMUM_LIQUIDITY = 10 ** 22; + + //------------------------------------------------------------------------- + // Storage + + /// @notice The perpetual senior tranche token. + IPerpetualTranche public perp; + + /// @notice The USD token. + IERC20Upgradeable public usd; + + /// @notice The fixed-point amount of usd tokens equivalent to 1.0 usd. + uint256 public usdUnitAmt; + + /// @notice The fixed-point amount of perp tokens equivalent to 1.0 perp. + uint256 public perpUnitAmt; + + /// @notice Reference to the address that has the ability to pause/unpause operations. + /// @dev The keeper is meant for time-sensitive operations, and may be different from the owner address. + /// @return The address of the keeper. + address public keeper; + + /// @notice The pricing strategy. + IBillBrokerPricingStrategy public pricingStrategy; + + /// @notice All of the system fees. + BillBrokerFees public fees; + + /// @notice The asset ratio bounds outside which swapping is disabled. + Range public arHardBound; + + /// @notice The asset ratio bounds outside which swapping is still functional but, + /// the swap fees transition from a flat percentage fee to a linear function. + Range public arSoftBound; + + //-------------------------------------------------------------------------- + // Modifiers + + /// @dev Throws if called by any account other than the keeper. + modifier onlyKeeper() { + if (msg.sender != keeper) { + revert UnauthorizedCall(); + } + _; + } + + //----------------------------------------------------------------------------- + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /// @notice Contract initializer. + /// @param name ERC-20 Name of the Bill broker LP token. + /// @param symbol ERC-20 Symbol of the Bill broker LP token. + /// @param usd_ Address of the usd token. + /// @param perp_ Address of the perp token. + /// @param pricingStrategy_ Address of the pricing strategy contract. + function init( + string memory name, + string memory symbol, + IERC20Upgradeable usd_, + IPerpetualTranche perp_, + IBillBrokerPricingStrategy pricingStrategy_ + ) public initializer { + // initialize dependencies + __ERC20_init(name, symbol); + __ERC20Burnable_init(); + __Ownable_init(); + __Pausable_init(); + __ReentrancyGuard_init(); + + usd = usd_; + perp = perp_; + + usdUnitAmt = 10 ** IERC20MetadataUpgradeable(address(usd_)).decimals(); + perpUnitAmt = 10 ** IERC20MetadataUpgradeable(address(perp_)).decimals(); + + updateKeeper(owner()); + updatePricingStrategy(pricingStrategy_); + updateFees( + BillBrokerFees({ + mintFeePerc: 0, + burnFeePerc: 0, + perpToUSDSwapFeePercs: Range({ lower: ONE, upper: ONE }), + usdToPerpSwapFeePercs: Range({ lower: ONE, upper: ONE }), + protocolSwapSharePerc: 0 + }) + ); + + updateARBounds( + // Soft bound + Range({ lower: 0, upper: type(uint256).max }), + // Hard bound + Range({ lower: 0, upper: type(uint256).max }) + ); + } + + //-------------------------------------------------------------------------- + // Owner only methods + + /// @notice Updates the reference to the keeper. + /// @param keeper_ The address of the new keeper. + function updateKeeper(address keeper_) public onlyOwner { + keeper = keeper_; + } + + /// @notice Updates the reference to the pricing strategy. + /// @param pricingStrategy_ The address of the new pricing strategy. + function updatePricingStrategy( + IBillBrokerPricingStrategy pricingStrategy_ + ) public onlyOwner { + if (pricingStrategy_.decimals() != DECIMALS) { + revert UnexpectedDecimals(); + } + pricingStrategy = pricingStrategy_; + } + + /// @notice Updates the system fees. + /// @param fees_ The new system fees. + function updateFees(BillBrokerFees memory fees_) public onlyOwner { + if ( + fees_.mintFeePerc > ONE || + fees_.burnFeePerc > ONE || + fees_.perpToUSDSwapFeePercs.lower > fees_.perpToUSDSwapFeePercs.upper || + fees_.usdToPerpSwapFeePercs.lower > fees_.usdToPerpSwapFeePercs.upper || + fees_.protocolSwapSharePerc > ONE + ) { + revert InvalidPerc(); + } + + fees = fees_; + } + + /// @notice Updates the hard asset ratio bound. + /// @dev Swaps are made expensive when the system is outside the defined soft bounds, + /// and swaps are disabled when the system is outside the defined hard bounds. + /// @param arSoftBound_ The updated soft bounds. + /// @param arHardBound_ The updated hard bounds. + function updateARBounds( + Range memory arSoftBound_, + Range memory arHardBound_ + ) public onlyOwner { + bool validBounds = (arHardBound_.lower <= arSoftBound_.lower && + arSoftBound_.lower <= arSoftBound_.upper && + arSoftBound_.upper <= arHardBound_.upper); + if (!validBounds) { + revert InvalidARBound(); + } + arSoftBound = arSoftBound_; + arHardBound = arHardBound_; + } + + //-------------------------------------------------------------------------- + // Keeper only methods + + /// @notice Pauses deposits, withdrawals and swaps. + /// @dev ERC-20 functions, like transfers will always remain operational. + function pause() external onlyKeeper { + _pause(); + } + + /// @notice Unpauses deposits, withdrawals and rollovers. + /// @dev ERC-20 functions, like transfers will always remain operational. + function unpause() external onlyKeeper { + _unpause(); + } + + //-------------------------------------------------------------------------- + // External & Public write methods + + /// @notice Deposits usd tokens and perp tokens and mint LP tokens. + /// @param usdAmtMax The amount of usd tokens maximum available to be deposited. + /// @param perpAmtMax The amount of perp tokens maximum available to be deposited. + /// @param usdAmtMin The minimum amount of usd tokens that are expected to be deposited. + /// @param perpAmtMin The minimum amount of perp tokens that are expected to be deposited. + /// @return mintAmt The amount of LP tokens minted. + function deposit( + uint256 usdAmtMax, + uint256 perpAmtMax, + uint256 usdAmtMin, + uint256 perpAmtMin + ) external nonReentrant whenNotPaused returns (uint256 mintAmt) { + uint256 usdAmtIn; + uint256 perpAmtIn; + bool isFirstMint; + (mintAmt, usdAmtIn, perpAmtIn, isFirstMint) = computeMintAmt( + usdAmtMax, + perpAmtMax + ); + if (mintAmt <= 0) { + return 0; + } + if (usdAmtIn < usdAmtMin || perpAmtIn < perpAmtMin) { + revert SlippageTooHigh(); + } + + // Transfer perp and usd tokens from the user + usd.safeTransferFrom(msg.sender, address(this), usdAmtIn); + perp.safeTransferFrom(msg.sender, address(this), perpAmtIn); + + // Permanently lock the MINIMUM_LIQUIDITY tokens on first mint + if (isFirstMint) { + _mint(address(this), MINIMUM_LIQUIDITY); + mintAmt -= MINIMUM_LIQUIDITY; + } + + // mint LP tokens to the user + _mint(msg.sender, mintAmt); + } + + /// @notice Burns LP tokens and redeems usd and perp tokens. + /// @param burnAmt The LP tokens to be burnt. + /// @return usdAmtOut The amount usd tokens returned. + /// @return perpAmtOut The amount perp tokens returned. + function redeem( + uint256 burnAmt + ) + external + nonReentrant + whenNotPaused + returns (uint256 usdAmtOut, uint256 perpAmtOut) + { + (usdAmtOut, perpAmtOut) = computeRedemptionAmts(burnAmt); + if (usdAmtOut == 0 && perpAmtOut == 0) { + return (0, 0); + } + + // burn LP tokens + _burn(msg.sender, burnAmt); + + // return funds + usd.safeTransfer(msg.sender, usdAmtOut); + perp.safeTransfer(msg.sender, perpAmtOut); + } + + /// @notice Swaps usd tokens from the user for perp tokens from the reserve. + /// @param usdAmtIn The amount of usd tokens swapped in. + /// @param perpAmtMin The minimum amount of perp tokens that are expected out. + /// @return perpAmtOut The amount perp tokens swapped out. + function swapUSDForPerps( + uint256 usdAmtIn, + uint256 perpAmtMin + ) external nonReentrant whenNotPaused returns (uint256 perpAmtOut) { + // compute perp amount out + uint256 protocolFeePerpAmt; + (perpAmtOut, , protocolFeePerpAmt) = computeUSDToPerpSwapAmt( + usdAmtIn, + reserveState() + ); + if (usdAmtIn <= 0 || perpAmtOut <= 0) { + revert UnacceptableSwap(); + } + if (perpAmtOut < perpAmtMin) { + revert SlippageTooHigh(); + } + + // Transfer usd tokens from user + usd.safeTransferFrom(msg.sender, address(this), usdAmtIn); + + // settle fees + if (protocolFeePerpAmt > 0) { + perp.safeTransfer(protocolFeeCollector(), protocolFeePerpAmt); + } + + // transfer perps out to the user + perp.safeTransfer(msg.sender, perpAmtOut); + } + + /// @notice Swaps perp tokens from the user for usd tokens from the reserve. + /// @param perpAmtIn The amount of perp tokens swapped in. + /// @param usdAmtMin The minimum amount of usd tokens that are expected out. + /// @return usdAmtOut The amount usd tokens swapped out. + function swapPerpsForUSD( + uint256 perpAmtIn, + uint256 usdAmtMin + ) external nonReentrant whenNotPaused returns (uint256 usdAmtOut) { + // Compute swap amount + uint256 protocolFeeUsdAmt; + (usdAmtOut, , protocolFeeUsdAmt) = computePerpToUSDSwapAmt( + perpAmtIn, + reserveState() + ); + if (perpAmtIn <= 0 || usdAmtOut <= 0) { + revert UnacceptableSwap(); + } + if (usdAmtOut < usdAmtMin) { + revert SlippageTooHigh(); + } + + // Transfer perp tokens from user + perp.safeTransferFrom(msg.sender, address(this), perpAmtIn); + + // settle fees + if (protocolFeeUsdAmt > 0) { + usd.safeTransfer(protocolFeeCollector(), protocolFeeUsdAmt); + } + + // transfer usd out to the user + usd.safeTransfer(msg.sender, usdAmtOut); + } + + //----------------------------------------------------------------------------- + // Public methods + + /// @notice Computes the amount of usd tokens swapped out, + /// when the given number of perp tokens are sent in. + /// @param perpAmtIn The amount of perp tokens swapped in. + /// @return usdAmtOut The amount usd tokens swapped out. + function computePerpToUSDSwapAmt( + uint256 perpAmtIn + ) public returns (uint256 usdAmtOut) { + (usdAmtOut, , ) = computePerpToUSDSwapAmt(perpAmtIn, reserveState()); + } + + /// @notice Computes the amount of perp tokens swapped out, + /// when the given number of usd tokens are sent in. + /// @param usdAmtIn The number of usd tokens sent in. + /// @return perpAmtOut The amount of perp tokens swapped out. + function computeUSDToPerpSwapAmt( + uint256 usdAmtIn + ) public returns (uint256 perpAmtOut) { + (perpAmtOut, , ) = computeUSDToPerpSwapAmt(usdAmtIn, reserveState()); + } + + /// @return s The reserve usd and perp token balances and prices. + function reserveState() public returns (ReserveState memory s) { + return + ReserveState({ + usdBalance: usd.balanceOf(address(this)), + perpBalance: perp.balanceOf(address(this)), + usdPrice: usdPrice(), + perpPrice: perpPrice() + }); + } + + /// @dev Reverts if the pricing strategy returns an invalid price. + /// @return The price of usd tokens from the pricing strategy. + function usdPrice() public returns (uint256) { + (uint256 p, bool v) = pricingStrategy.usdPrice(); + if (!v) { + revert UnreliablePrice(); + } + return p; + } + + /// @dev Reverts if the pricing strategy returns an invalid price. + /// @return The price of perp tokens from the pricing strategy. + function perpPrice() public returns (uint256) { + (uint256 p, bool v) = pricingStrategy.perpPrice(); + if (!v) { + revert UnreliablePrice(); + } + return p; + } + + //----------------------------------------------------------------------------- + // External view methods + + /// @return The balance of usd tokens in the reserve. + function usdBalance() external view returns (uint256) { + return usd.balanceOf(address(this)); + } + + /// @return The balance of perp tokens in the reserve. + function perpBalance() external view returns (uint256) { + return perp.balanceOf(address(this)); + } + + //----------------------------------------------------------------------------- + // Public view methods + + /// @notice Computes the amount of LP tokens minted, + /// when the given number of usd and perp tokens are deposited. + /// @param usdAmtMax The maximum available usd tokens. + /// @param perpAmtMax The maximum available perp tokens. + /// @return mintAmt The amount of LP tokens minted. + /// @return usdAmtIn The usd tokens to be deposited. + /// @return perpAmtIn The perp tokens to be deposited. + /// @return isFirstMint If the pool currently has no deposits. + function computeMintAmt( + uint256 usdAmtMax, + uint256 perpAmtMax + ) + public + view + returns (uint256 mintAmt, uint256 usdAmtIn, uint256 perpAmtIn, bool isFirstMint) + { + uint256 totalSupply_ = totalSupply(); + isFirstMint = (totalSupply_ <= 0); + + if (usdAmtMax <= 0 && perpAmtMax <= 0) { + return (0, 0, 0, isFirstMint); + } + + // During the initial deposit we deposit the entire available amounts. + // The onus is on the depositor to ensure that the value of USD tokens and + // perp tokens on first deposit are equivalent. + if (isFirstMint) { + usdAmtIn = usdAmtMax; + perpAmtIn = perpAmtMax; + mintAmt = (ONE.mulDiv(usdAmtIn, usdUnitAmt) + + ONE.mulDiv(perpAmtIn, perpUnitAmt)); + mintAmt = mintAmt * INITIAL_RATE; + } else { + // Users can deposit assets proportional to the reserve. + uint256 usdBalance_ = usd.balanceOf(address(this)); + uint256 perpBalance_ = perp.balanceOf(address(this)); + if (usdBalance_ == 0) { + usdAmtIn = 0; + perpAmtIn = perpAmtMax; + mintAmt = totalSupply_.mulDiv(perpAmtIn, perpBalance_); + } else if (perpBalance_ == 0) { + perpAmtIn = 0; + usdAmtIn = usdAmtMax; + mintAmt = totalSupply_.mulDiv(usdAmtIn, usdBalance_); + } else { + usdAmtIn = usdAmtMax; + perpAmtIn = perpBalance_.mulDiv(usdAmtIn, usdBalance_); + if (perpAmtIn > perpAmtMax) { + perpAmtIn = perpAmtMax; + usdAmtIn = usdBalance_.mulDiv(perpAmtIn, perpBalance_); + } + mintAmt = totalSupply_.mulDiv(usdAmtIn, usdBalance_); + } + } + + mintAmt = mintAmt.mulDiv(ONE - fees.mintFeePerc, ONE); + } + + /// @notice Computes the amount of usd and perp tokens redeemed, + /// when the given number of LP tokens are burnt. + /// @param burnAmt The amount of LP tokens to be burnt. + /// @return usdAmtOut The amount of usd tokens redeemed. + /// @return perpAmtOut The amount of perp tokens redeemed. + function computeRedemptionAmts( + uint256 burnAmt + ) public view returns (uint256 usdAmtOut, uint256 perpAmtOut) { + if (burnAmt <= 0) { + return (0, 0); + } + + uint256 totalSupply_ = totalSupply(); + usdAmtOut = usd.balanceOf(address(this)).mulDiv(burnAmt, totalSupply_).mulDiv( + ONE - fees.burnFeePerc, + ONE + ); + perpAmtOut = perp.balanceOf(address(this)).mulDiv(burnAmt, totalSupply_).mulDiv( + ONE - fees.burnFeePerc, + ONE + ); + } + + /// @notice Computes the amount of usd tokens swapped out, + /// when the given number of perp tokens are sent in. + /// @param perpAmtIn The number of perp tokens sent in. + /// @param s The current reserve state. + /// @dev Quoted usd token amount out includes the fees withheld. + /// @return usdAmtOut The amount of usd tokens swapped out. + /// @return lpFeeUsdAmt The amount of usd tokens charged as swap fees by LPs. + /// @return protocolFeeUsdAmt The amount of usd tokens charged as protocol fees. + function computePerpToUSDSwapAmt( + uint256 perpAmtIn, + ReserveState memory s + ) + public + view + returns (uint256 usdAmtOut, uint256 lpFeeUsdAmt, uint256 protocolFeeUsdAmt) + { + // We compute equal value of usd tokens out given perp tokens in. + usdAmtOut = perpAmtIn.mulDiv(s.perpPrice, s.usdPrice).mulDiv( + usdUnitAmt, + perpUnitAmt + ); + + // We compute the total fee percentage, lp fees and protocol fees + uint256 totalFeePerc = computePerpToUSDSwapFeePerc( + assetRatio(s), + assetRatio( + ReserveState({ + usdBalance: s.usdBalance - usdAmtOut, + perpBalance: s.perpBalance + perpAmtIn, + usdPrice: s.usdPrice, + perpPrice: s.perpPrice + }) + ) + ); + if (totalFeePerc >= ONE) { + return (0, 0, 0); + } + uint256 totalFeeUsdAmt = usdAmtOut.mulDiv(totalFeePerc, ONE); + usdAmtOut -= totalFeeUsdAmt; + protocolFeeUsdAmt = totalFeeUsdAmt.mulDiv(fees.protocolSwapSharePerc, ONE); + lpFeeUsdAmt = totalFeeUsdAmt - protocolFeeUsdAmt; + } + + /// @notice Computes the amount of perp tokens swapped out, + /// when the given number of usd tokens are sent in. + /// @param usdAmtIn The number of usd tokens sent in. + /// @param s The current reserve state. + /// @dev Quoted perp token amount out includes the fees withheld. + /// @return perpAmtOut The amount of perp tokens swapped out. + /// @return lpFeePerpAmt The amount of perp tokens charged as swap fees by LPs. + /// @return protocolFeePerpAmt The amount of perp tokens charged as protocol fees. + function computeUSDToPerpSwapAmt( + uint256 usdAmtIn, + ReserveState memory s + ) + public + view + returns (uint256 perpAmtOut, uint256 lpFeePerpAmt, uint256 protocolFeePerpAmt) + { + // We compute equal value of perp tokens out given usd tokens in. + perpAmtOut = usdAmtIn.mulDiv(s.usdPrice, s.perpPrice).mulDiv( + perpUnitAmt, + usdUnitAmt + ); + // We compute the total fee percentage, lp fees and protocol fees + uint256 totalFeePerc = computeUSDToPerpSwapFeePerc( + assetRatio(s), + assetRatio( + ReserveState({ + usdBalance: s.usdBalance + usdAmtIn, + perpBalance: s.perpBalance - perpAmtOut, + usdPrice: s.usdPrice, + perpPrice: s.perpPrice + }) + ) + ); + if (totalFeePerc >= ONE) { + return (0, 0, 0); + } + uint256 totalFeePerpAmt = perpAmtOut.mulDiv(totalFeePerc, ONE); + perpAmtOut -= totalFeePerpAmt; + protocolFeePerpAmt = totalFeePerpAmt.mulDiv(fees.protocolSwapSharePerc, ONE); + lpFeePerpAmt = totalFeePerpAmt - protocolFeePerpAmt; + } + + /// @notice Computes the swap fee percentage when swapping from perp to usd tokens. + /// @dev Swapping from perp to usd tokens, leaves the system with more perp and fewer usd tokens + /// thereby decreasing the system's `assetRatio`. Thus arPost < arPre. + /// @param arPre The asset ratio of the system before swapping. + /// @param arPost The asset ratio of the system after swapping. + /// @return The fee percentage. + function computePerpToUSDSwapFeePerc( + uint256 arPre, + uint256 arPost + ) public view returns (uint256) { + if (arPost > arPre) { + revert UnexpectedARDelta(); + } + + // When the ar decreases below the lower bound, + // swaps are effectively halted by setting fees to 100%. + if (arPost < arHardBound.lower) { + return ONE; + } + // When the ar is between the soft and hard bound, a linear function is applied. + // When the ar is above the soft bound, a flat percentage fee is applied. + // + // fee + // ^ + // | + // fh | \ | + // | \ | + // | \ | + // | \ | + // | \ | + // | \ | + // fl | \__________ + // | | + // | | + // | | + // +---------------------------> ar + // arHL arSL 1.0 + // + Range memory swapFeePercs = fees.perpToUSDSwapFeePercs; + return + _computeFeePerc( + Line({ + x1: arHardBound.lower, + y1: swapFeePercs.upper, + x2: arSoftBound.lower, + y2: swapFeePercs.lower + }), + Line({ x1: 0, y1: swapFeePercs.lower, x2: ONE, y2: swapFeePercs.lower }), + arPost, + arPre, + arSoftBound.lower + ); + } + + /// @notice Computes the swap fee percentage when swapping from usd to perp tokens. + /// @dev Swapping from usd to perp tokens, leaves the system with more usd and fewer perp tokens + /// thereby increasing the system's `assetRatio`. Thus arPost > arPre. + /// @param arPre The asset ratio of the system before swapping. + /// @param arPost The asset ratio of the system after swapping. + /// @return The fee percentage. + function computeUSDToPerpSwapFeePerc( + uint256 arPre, + uint256 arPost + ) public view returns (uint256) { + if (arPost < arPre) { + revert UnexpectedARDelta(); + } + + // When the ar increases above the hard bound, + // swaps are effectively halted by setting fees to 100%. + if (arPost > arHardBound.upper) { + return ONE; + } + + // When the ar is between the soft and hard bound, a linear function is applied. + // When the ar is below the soft bound, a flat percentage fee is applied. + // + // fee + // ^ + // | + // fh | | / + // | | / + // | | / + // | | / + // | | / + // | | / + // fl | __________/ + // | | + // | | + // | | + // +---------------------------> ar + // 1.0 arSU arHU + // + Range memory swapFeePercs = fees.usdToPerpSwapFeePercs; + return + _computeFeePerc( + Line({ x1: 0, y1: swapFeePercs.lower, x2: ONE, y2: swapFeePercs.lower }), + Line({ + x1: arSoftBound.upper, + y1: swapFeePercs.lower, + x2: arHardBound.upper, + y2: swapFeePercs.upper + }), + arPre, + arPost, + arSoftBound.upper + ); + } + + /// @param s The system reserve state. + /// @return The computed asset ratio of the system. + function assetRatio(ReserveState memory s) public view returns (uint256) { + return + s.perpBalance > 0 + ? ( + s.usdBalance.mulDiv(s.usdPrice, usdUnitAmt).mulDiv( + ONE, + s.perpBalance.mulDiv(s.perpPrice, perpUnitAmt) + ) + ) + : type(uint256).max; + } + + /// @notice The address which holds any revenue extracted by protocol. + /// @return Address of the fee collector. + function protocolFeeCollector() public view returns (address) { + return owner(); + } + + //----------------------------------------------------------------------------- + // Private methods + + /// @dev The function assumes the fee curve is defined as a pair-wise linear function which merge at the cutoff point. + /// The swap fee is computed as avg height of the fee curve between {arL,arU}. + function _computeFeePerc( + Line memory fn1, + Line memory fn2, + uint256 arL, + uint256 arU, + uint256 cutoff + ) private pure returns (uint256 feePerc) { + if (arU <= cutoff) { + feePerc = _avgY(fn1, arL, arU); + } else if (arL >= cutoff) { + feePerc = _avgY(fn2, arL, arU); + } else { + feePerc = (_avgY(fn1, arL, cutoff).mulDiv(cutoff - arL, arU - arL) + + _avgY(fn2, cutoff, arU).mulDiv(arU - cutoff, arU - arL)); + } + feePerc = MathUpgradeable.min(feePerc, ONE); + } + + /// @dev We compute the average height of the line between {xL,xU}. + function _avgY( + Line memory fn, + uint256 xL, + uint256 xU + ) private pure returns (uint256) { + // if the line has a zero slope, return any y + if (fn.y1 == fn.y2) { + return fn.y2; + } + + // m = dlY/dlX + // c = y2 - m . x2 + // Avg height => (yL + yU) / 2 + // => m . ( xL + xU ) / 2 + c + int256 dlY = fn.y2.toInt256() - fn.y1.toInt256(); + int256 dlX = fn.x2.toInt256() - fn.x1.toInt256(); + int256 c = fn.y2.toInt256() - ((fn.x2.toInt256() * dlY) / dlX); + return ((((xL + xU).toInt256() * dlY) / (2 * dlX)) + c).abs(); + } +} diff --git a/spot-vaults/contracts/_interfaces/BillBrokerErrors.sol b/spot-vaults/contracts/_interfaces/BillBrokerErrors.sol new file mode 100644 index 00000000..babbae79 --- /dev/null +++ b/spot-vaults/contracts/_interfaces/BillBrokerErrors.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +/// @notice Expected contract call to be triggered by authorized caller. +error UnauthorizedCall(); + +/// @notice Expected interface contract to return a fixed point with a different number of decimals. +error UnexpectedDecimals(); + +/// @notice Expected perc value to be at most (1 * 10**DECIMALS), i.e) 1.0 or 100%. +error InvalidPerc(); + +/// @notice Expected Senior CDR bound to be more than 1.0 or 100%. +error InvalidSeniorCDRBound(); + +/// @notice Expect AR lower bound to be under the upper bound. +error InvalidARBound(); + +/// @notice Expected pre and post swap AR delta to be non-increasing or non-decreasing. +error UnexpectedARDelta(); + +/// @notice Slippage higher than tolerance requested by user. +error SlippageTooHigh(); + +/// @notice Expected non-zero swap amounts; +error UnacceptableSwap(); + +/// @notice Expected usable external price. +error UnreliablePrice(); diff --git a/spot-vaults/contracts/_interfaces/BillBrokerTypes.sol b/spot-vaults/contracts/_interfaces/BillBrokerTypes.sol new file mode 100644 index 00000000..d24601ad --- /dev/null +++ b/spot-vaults/contracts/_interfaces/BillBrokerTypes.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +/// @notice A data structure to define a geometric Line with two points. +struct Line { + /// @notice x-coordinate of the first point. + uint256 x1; + /// @notice y-coordinate of the first point. + uint256 y1; + /// @notice x-coordinate of the second point. + uint256 x2; + /// @notice y-coordinate of the second point. + uint256 y2; +} + +/// @notice A data structure to define a numeric Range. +struct Range { + /// @notice Lower bound of the range. + uint256 lower; + /// @notice Upper bound of the range. + uint256 upper; +} + +/// @notice A data structure to store various fees associated with BillBroker operations. +struct BillBrokerFees { + /// @notice The percentage fee charged for minting BillBroker LP tokens. + uint256 mintFeePerc; + /// @notice The percentage fee charged for burning BillBroker LP tokens. + uint256 burnFeePerc; + /// @notice Range of fee percentages for swapping from perp tokens to USD. + Range perpToUSDSwapFeePercs; + /// @notice Range of fee percentages for swapping from USD to perp tokens. + Range usdToPerpSwapFeePercs; + /// @notice The percentage of the swap fees that goes to the protocol. + uint256 protocolSwapSharePerc; +} + +/// @notice A data structure to represent the BillBroker's reserve state. +struct ReserveState { + /// @notice The reserve USD token balance. + uint256 usdBalance; + /// @notice The reserve perp token balance. + uint256 perpBalance; + /// @notice The price of USD tokens in dollars (or some common denomination). + uint256 usdPrice; + /// @notice The price of perp tokens in dollars (or some common denomination). + uint256 perpPrice; +} diff --git a/spot-vaults/contracts/_interfaces/IBillBrokerPricingStrategy.sol b/spot-vaults/contracts/_interfaces/IBillBrokerPricingStrategy.sol new file mode 100644 index 00000000..0787c298 --- /dev/null +++ b/spot-vaults/contracts/_interfaces/IBillBrokerPricingStrategy.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +/** + * @title IBillBrokerPricingStrategy + * + * @notice Pricing strategy adapter for a BillBroker vault + * which accepts Perp and USDC tokens. + * + */ +interface IBillBrokerPricingStrategy { + /// @return Number of decimals representing the prices returned. + function decimals() external pure returns (uint8); + + /// @return price The price of USD tokens. + /// @return isValid True if the returned price is valid. + function usdPrice() external returns (uint256 price, bool isValid); + + /// @return price The price of perp tokens. + /// @return isValid True if the returned price is valid. + function perpPrice() external returns (uint256 price, bool isValid); +} diff --git a/spot-vaults/contracts/_interfaces/external/IAMPL.sol b/spot-vaults/contracts/_interfaces/external/IAMPL.sol new file mode 100644 index 00000000..c29afada --- /dev/null +++ b/spot-vaults/contracts/_interfaces/external/IAMPL.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; +import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import { IAmpleforth } from "./IAmpleforth.sol"; + +interface IAMPL is IERC20Upgradeable { + function monetaryPolicy() external view returns (IAmpleforth); +} diff --git a/spot-vaults/contracts/_interfaces/external/IAmpleforth.sol b/spot-vaults/contracts/_interfaces/external/IAmpleforth.sol new file mode 100644 index 00000000..d16f307e --- /dev/null +++ b/spot-vaults/contracts/_interfaces/external/IAmpleforth.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; +import { IAmpleforthOracle } from "./IAmpleforthOracle.sol"; + +interface IAmpleforth { + function cpiOracle() external view returns (IAmpleforthOracle); +} diff --git a/spot-vaults/contracts/_interfaces/external/IAmpleforthOracle.sol b/spot-vaults/contracts/_interfaces/external/IAmpleforthOracle.sol new file mode 100644 index 00000000..0e78a96d --- /dev/null +++ b/spot-vaults/contracts/_interfaces/external/IAmpleforthOracle.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +interface IAmpleforthOracle { + // solhint-disable-next-line func-name-mixedcase + function DECIMALS() external returns (uint8); + function getData() external returns (uint256, bool); +} diff --git a/spot-vaults/contracts/_interfaces/external/IChainlinkOracle.sol b/spot-vaults/contracts/_interfaces/external/IChainlinkOracle.sol new file mode 100644 index 00000000..07ee0999 --- /dev/null +++ b/spot-vaults/contracts/_interfaces/external/IChainlinkOracle.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +interface IChainlinkOracle { + function decimals() external view returns (uint8); + + function latestRoundData() + external + view + returns ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ); +} diff --git a/spot-vaults/contracts/_strategies/SpotAppraiser.sol b/spot-vaults/contracts/_strategies/SpotAppraiser.sol new file mode 100644 index 00000000..380804f3 --- /dev/null +++ b/spot-vaults/contracts/_strategies/SpotAppraiser.sol @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { ITranche } from "@ampleforthorg/spot-contracts/contracts/_interfaces/buttonwood/ITranche.sol"; +import { IBondController } from "@ampleforthorg/spot-contracts/contracts/_interfaces/buttonwood/IBondController.sol"; +import { IPerpetualTranche } from "@ampleforthorg/spot-contracts/contracts/_interfaces/IPerpetualTranche.sol"; +import { IChainlinkOracle } from "../_interfaces/external/IChainlinkOracle.sol"; +import { IAmpleforthOracle } from "../_interfaces/external/IAmpleforthOracle.sol"; +import { IBillBrokerPricingStrategy } from "../_interfaces/IBillBrokerPricingStrategy.sol"; +import { InvalidSeniorCDRBound } from "../_interfaces/BillBrokerErrors.sol"; + +/** + * @title SpotAppraiser + * + * @notice Pricing strategy adapter for a BillBroker vault which accepts + * SPOT (as the perp token) and dollar tokens like USDC. + * + * AMPL is the underlying token for SPOT. + * The market price of AMPL is mean reverting and eventually converges to its target. + * However, it can significantly deviate from the target in the near term. + * + * SPOT is a perpetual claim on AMPL senior tranches. Insofar as SPOT is fully backed by + * healthy senior tranches, we can price spot reliably using the following strategy: + * + * SPOT_PRICE = MULTIPLIER * AMPL_TARGET + * MULTIPLIER = spot.getTVL() / spot.totalSupply(), which is it's enrichment/debasement factor. + * To know more, read the spot documentation. + * + * We get the AMPL target price from Ampleforth's CPI oracle, + * which is also used by the protocol to adjust AMPL supply through rebasing. + * + * And the MULTIPLIER is directly queried from the SPOT contract. + * + */ +contract SpotAppraiser is Ownable, IBillBrokerPricingStrategy { + //------------------------------------------------------------------------- + // Libraries + using Math for uint256; + + //------------------------------------------------------------------------- + // Constants & Immutables + + uint256 private constant DECIMALS = 18; + uint256 private constant ONE = (10 ** DECIMALS); + uint256 private constant SPOT_DR_DECIMALS = 8; + uint256 private constant SPOT_DR_ONE = (10 ** SPOT_DR_DECIMALS); + uint256 public constant CL_ORACLE_DECIMALS = 8; + uint256 public constant CL_ORACLE_STALENESS_THRESHOLD_SEC = 3600 * 48; // 2 days + uint256 public constant USD_LOWER_BOUND = (99 * ONE) / 100; // 0.99$ + uint256 public constant AMPL_DUST_AMT = 25000 * (10 ** 9); // 25000 AMPL + + /// @notice Address of the SPOT (perpetual tranche) ERC-20 token contract. + IPerpetualTranche public immutable SPOT; + + /// @notice Address of the AMPL ERC-20 token contract. + IERC20 public immutable AMPL; + + /// @notice Address of the USD token market price oracle. + IChainlinkOracle public immutable USD_ORACLE; + + /// @notice Number of decimals representing the prices returned by the chainlink oracle. + uint256 public immutable USD_ORACLE_DECIMALS; + + /// @notice Address of the Ampleforth CPI oracle. (provides the inflation-adjusted target price for AMPL). + IAmpleforthOracle public immutable AMPL_CPI_ORACLE; + + /// @notice Number of decimals representing the prices returned by the ampleforth oracle. + uint256 public immutable AMPL_CPI_ORACLE_DECIMALS; + + //------------------------------------------------------------------------- + // Storage + + /// @notice The minimum "deviation ratio" of the SPOT outside which it's considered unhealthy. + uint256 public minSPOTDR; + + /// @notice The minimum CDR of senior tranches backing SPOT outside which it's considered unhealthy. + uint256 public minSeniorCDR; + + //----------------------------------------------------------------------------- + // Constructor + + /// @notice Contract constructor. + /// @param spot Address of the SPOT token. + /// @param usdOracle Address of the USD token market price oracle token. + /// @param cpiOracle Address of the Ampleforth CPI oracle. + constructor( + IPerpetualTranche spot, + IChainlinkOracle usdOracle, + IAmpleforthOracle cpiOracle + ) Ownable() { + SPOT = spot; + AMPL = IERC20(address(spot.underlying())); + + USD_ORACLE = usdOracle; + USD_ORACLE_DECIMALS = usdOracle.decimals(); + + AMPL_CPI_ORACLE = cpiOracle; + AMPL_CPI_ORACLE_DECIMALS = cpiOracle.DECIMALS(); + + minSPOTDR = (ONE * 8) / 10; // 0.8 + minSeniorCDR = (ONE * 11) / 10; // 110% + } + + //-------------------------------------------------------------------------- + // Owner only methods + + /// @notice Controls the minimum `deviationRatio` ratio of SPOT below which SPOT is considered unhealthy. + /// @param minSPOTDR_ The minimum SPOT `deviationRatio`. + function updateMinSPOTDR(uint256 minSPOTDR_) external onlyOwner { + minSPOTDR = minSPOTDR_; + } + + /// @notice Controls the minimum CDR of SPOT's senior tranche below which SPOT is considered unhealthy. + /// @param minSeniorCDR_ The minimum senior tranche CDR. + function updateMinPerpCollateralCDR(uint256 minSeniorCDR_) external onlyOwner { + if (minSeniorCDR_ < ONE) { + revert InvalidSeniorCDRBound(); + } + minSeniorCDR = minSeniorCDR_; + } + + //-------------------------------------------------------------------------- + // External methods + + /// @return p The price of the usd token in dollars. + /// @return v True if the price is valid and can be used by downstream consumers. + function usdPrice() external view override returns (uint256, bool) { + (uint256 p, bool v) = _getCLOracleData(USD_ORACLE, USD_ORACLE_DECIMALS); + // If the market price of the USD coin fallen too much below 1$, + // it's an indication of some systemic issue with the USD token + // and thus its price should be considered unreliable. + return (ONE, (v && p > USD_LOWER_BOUND)); + } + + /// @return p The price of the spot token in dollar coins. + /// @return v True if the price is valid and can be used by downstream consumers. + function perpPrice() external override returns (uint256, bool) { + (uint256 targetPrice, bool targetPriceValid) = AMPL_CPI_ORACLE.getData(); + uint256 p = targetPrice.mulDiv(SPOT.getTVL(), SPOT.totalSupply()); + bool v = (targetPriceValid && isSPOTHealthy()); + return (p, v); + } + + /// @return Number of decimals representing a price of 1.0 USD. + function decimals() external pure override returns (uint8) { + return uint8(DECIMALS); + } + + //----------------------------------------------------------------------------- + // Public methods + + /// @return If the spot token is healthy. + function isSPOTHealthy() public returns (bool) { + // If the SPOT's `deviationRatio` is lower than the defined bound + // i.e) it doesn't have enough capital to cover future rollovers, + // we consider it unhealthy. + uint256 spotDR = SPOT.deviationRatio().mulDiv(ONE, SPOT_DR_ONE); + if (spotDR < minSPOTDR) { + return false; + } + + // We compute the CDR of all the senior tranches backing perp. + // If any one of the seniors is mature or has a CDR below below the defined minimum, + // we consider it unhealthy. + // NOTE: Any CDR below 100%, means that the tranche is impaired + // and is roughly equivalent to holding AMPL. + uint8 reserveCount = uint8(SPOT.getReserveCount()); + for (uint8 i = 1; i < reserveCount; i++) { + ITranche tranche = ITranche(address(SPOT.getReserveAt(i))); + IBondController bond = IBondController(tranche.bond()); + if (bond.isMature()) { + return false; + } + uint256 seniorCDR = AMPL.balanceOf(address(bond)).mulDiv( + ONE, + tranche.totalSupply() + ); + if (seniorCDR < minSeniorCDR) { + return false; + } + } + + // If SPOT has ANY raw AMPL as collateral, we consider it unhealthy. + // NOTE: In practice some dust might exist or someone could grief this check + // by transferring some dust AMPL into the spot contract. + // We consider SPOT unhealthy if it has more than `AMPL_DUST_AMT` AMPL. + if (AMPL.balanceOf(address(SPOT)) > AMPL_DUST_AMT) { + return false; + } + + return true; + } + + //----------------------------------------------------------------------------- + // Private methods + + /// @dev Fetches most recent report from the given chain link oracle contract. + /// The data is considered invalid if the latest report is stale. + function _getCLOracleData( + IChainlinkOracle oracle, + uint256 oracleDecimals + ) private view returns (uint256, bool) { + (, int256 p, , uint256 updatedAt, ) = oracle.latestRoundData(); + uint256 price = uint256(p).mulDiv(ONE, 10 ** oracleDecimals); + return ( + price, + (block.timestamp - updatedAt) <= CL_ORACLE_STALENESS_THRESHOLD_SEC + ); + } +} diff --git a/spot-vaults/contracts/_test/DMock.sol b/spot-vaults/contracts/_test/DMock.sol new file mode 100644 index 00000000..caa62f00 --- /dev/null +++ b/spot-vaults/contracts/_test/DMock.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +contract DMock { + struct MockCall { + bytes data; + bytes returnValue; + } + + // Maps a method signature to its mock call definition + mapping(bytes32 => MockCall) public mockCalls; + + // Fallback function to handle all calls + // solhint-disable-next-line + fallback(bytes calldata) external returns (bytes memory) { + // Check if mock has been defined based on {sig,param} pair + MockCall storage mockCall_ = mockCalls[keccak256(msg.data)]; + + // else check if generic mock has been defined based on sig + if (mockCall_.data.length <= 0) { + mockCall_ = mockCalls[keccak256(abi.encodePacked(bytes4(msg.data)))]; + } + + // solhint-disable-next-line custom-errors + require(mockCall_.data.length > 0, "DMock: method not mocked"); + + // Return the mocked return value + return mockCall_.returnValue; + } + + // Function to set up a mock call, given method sig and parameters + function mockCall(bytes memory data, bytes memory returnValue) public { + mockCalls[keccak256(data)] = MockCall(data, returnValue); + } + + // Function to set up a mock call, given just method sig + function mockMethod(bytes4 sig, bytes memory returnValue) public { + bytes memory data = abi.encodePacked(sig); + mockCalls[keccak256(data)] = MockCall(data, returnValue); + } + + // Function to clear mocked call + function clearMockCall(bytes memory data) public { + delete mockCalls[keccak256(data)]; + } + + // Function to clear mocked method call + function clearMockMethodSig(bytes4 sig) public { + bytes memory data = abi.encodePacked(sig); + delete mockCalls[keccak256(data)]; + } +} diff --git a/spot-vaults/contracts/_test/MockCLOracle.sol b/spot-vaults/contracts/_test/MockCLOracle.sol new file mode 100644 index 00000000..617a134b --- /dev/null +++ b/spot-vaults/contracts/_test/MockCLOracle.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import { IChainlinkOracle } from "../_interfaces/external/IChainlinkOracle.sol"; + +contract MockCLOracle is IChainlinkOracle { + int256 private _answer; + uint256 private _reportTime; + + function mockLastRoundData(int256 answer, uint256 reportTime) external { + _answer = answer; + _reportTime = reportTime; + } + + function latestRoundData() + external + view + returns (uint80, int256, uint256, uint256, uint80) + { + return (uint80(0), _answer, 0, _reportTime, uint80(0)); + } + + function decimals() public pure override returns (uint8) { + return 8; + } +} diff --git a/spot-vaults/contracts/_test/MockCPIOracle.sol b/spot-vaults/contracts/_test/MockCPIOracle.sol new file mode 100644 index 00000000..97beef62 --- /dev/null +++ b/spot-vaults/contracts/_test/MockCPIOracle.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +contract MockCPIOracle { + uint256 private _report; + bool private _valid; + + function mockData(uint256 report, bool valid) external { + _report = report; + _valid = valid; + } + + function getData() external view returns (uint256, bool) { + return (_report, _valid); + } + + // solhint-disable-next-line func-name-mixedcase + function DECIMALS() public pure returns (uint8) { + return 18; + } +} diff --git a/spot-vaults/contracts/_test/MockERC20.sol b/spot-vaults/contracts/_test/MockERC20.sol new file mode 100644 index 00000000..04f23811 --- /dev/null +++ b/spot-vaults/contracts/_test/MockERC20.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; + +contract MockERC20 is ERC20Upgradeable { + uint8 private _decimals; + function init( + string memory name_, + string memory symbol_, + uint8 decimals_ + ) external initializer { + __ERC20_init(name_, symbol_); + _decimals = decimals_; + } + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function decimals() public view override returns (uint8) { + return _decimals; + } +} diff --git a/spot-vaults/contracts/_test/PerpTestArtifacts.sol b/spot-vaults/contracts/_test/PerpTestArtifacts.sol new file mode 100644 index 00000000..88f6d5e9 --- /dev/null +++ b/spot-vaults/contracts/_test/PerpTestArtifacts.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +// solhint-disable-next-line no-unused-import +import { PerpetualTranche } from "@ampleforthorg/spot-contracts/contracts/PerpetualTranche.sol"; diff --git a/spot-vaults/contracts/_test/TrancheTestArtifacts.sol b/spot-vaults/contracts/_test/TrancheTestArtifacts.sol new file mode 100644 index 00000000..bfbb2cab --- /dev/null +++ b/spot-vaults/contracts/_test/TrancheTestArtifacts.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.3; + +// solhint-disable-next-line no-unused-import +import { BondController } from "tranche/contracts/BondController.sol"; + +// solhint-disable-next-line no-unused-import +import { Tranche } from "tranche/contracts/Tranche.sol"; diff --git a/spot-vaults/contracts/_test/UFragmentsTestArtifacts.sol b/spot-vaults/contracts/_test/UFragmentsTestArtifacts.sol new file mode 100644 index 00000000..b4849d4f --- /dev/null +++ b/spot-vaults/contracts/_test/UFragmentsTestArtifacts.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.4; + +// solhint-disable-next-line no-unused-import +import { UFragments } from "ampleforth-contracts/contracts/UFragments.sol"; + +// solhint-disable-next-line no-unused-import +import { UFragmentsPolicy } from "ampleforth-contracts/contracts/UFragmentsPolicy.sol"; + +// solhint-disable-next-line no-unused-import +import { MedianOracle } from "ampleforth-contracts/contracts/MedianOracle.sol"; diff --git a/spot-vaults/hardhat.config.ts b/spot-vaults/hardhat.config.ts new file mode 100644 index 00000000..22d4cfde --- /dev/null +++ b/spot-vaults/hardhat.config.ts @@ -0,0 +1,80 @@ +import { HardhatUserConfig } from "hardhat/config"; +import { Wallet } from "ethers"; + +import "@nomicfoundation/hardhat-ethers"; +import "@nomicfoundation/hardhat-chai-matchers"; +import "@nomicfoundation/hardhat-verify"; +import "@openzeppelin/hardhat-upgrades"; +import "solidity-coverage"; +import "hardhat-gas-reporter"; + +// Loads custom tasks +import "./tasks/deploy"; +import "./tasks/ops"; +import "./tasks/info"; +import "./tasks/tools"; + +// Loads env variables from .env file +import * as dotenv from "dotenv"; +dotenv.config(); + +export default { + networks: { + hardhat: { + initialBaseFeePerGas: 0, + accounts: { + mnemonic: Wallet.createRandom().mnemonic.phrase, + }, + }, + ganache: { + url: "http://127.0.0.1:8545", + chainId: 1337, + }, + sepolia: { + url: `https://eth-sepolia.g.alchemy.com/v2/${process.env.ALCHEMY_SECRET}`, + accounts: { + mnemonic: process.env.PROD_MNEMONIC || Wallet.createRandom().mnemonic.phrase, + }, + gasMultiplier: 1.01, + }, + mainnet: { + url: `https://eth-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_SECRET}`, + accounts: { + mnemonic: process.env.PROD_MNEMONIC || Wallet.createRandom().mnemonic.phrase, + }, + gasMultiplier: 1.005, + }, + }, + solidity: { + compilers: [ + { + version: "0.8.3", + }, + { + version: "0.8.4", + }, + { + version: "0.8.24", + settings: { + optimizer: { + enabled: true, + runs: 750, + }, + }, + }, + ], + }, + gasReporter: { + currency: "USD", + enabled: !!process.env.REPORT_GAS, + excludeContracts: ["_test/"], + coinmarketcap: process.env.COINMARKETCAP_API_KEY, + }, + etherscan: { + apiKey: process.env.ETHERSCAN_API_KEY, + }, + mocha: { + bail: false, + timeout: 100000000, + }, +} as HardhatUserConfig; diff --git a/spot-vaults/package.json b/spot-vaults/package.json new file mode 100644 index 00000000..785c6649 --- /dev/null +++ b/spot-vaults/package.json @@ -0,0 +1,78 @@ +{ + "name": "@ampleforthorg/spot-vaults", + "packageManager": "yarn@3.2.1", + "scripts": { + "compile": "yarn hardhat compile", + "coverage": "yarn hardhat coverage --testfiles 'test/*.ts test/**/*.ts'", + "lint": "yarn run lint:sol && yarn run lint:ts && yarn run prettier:list-different", + "lint:fix": "yarn run prettier && yarn run lint:sol:fix && yarn run lint:ts:fix", + "lint:sol": "solhint --config ./.solhint.json --max-warnings 0 \"contracts/**/*.sol\"", + "lint:sol:fix": "solhint --config ./.solhint.json --fix --max-warnings 1 \"contracts/**/*.sol\"", + "lint:ts": "eslint --config ./.eslintrc.yaml --ignore-path ./.eslintignore --ext .js,.ts .", + "lint:ts:fix": "eslint --config ./.eslintrc.yaml --fix --ignore-path ./.eslintignore --ext .js,.ts .", + "prettier": "prettier --config .prettierrc --write \"**/*.{js,json,md,sol,ts}\"", + "prettier:list-different": "prettier --config .prettierrc --list-different \"**/*.{js,json,md,sol,ts}\"", + "profile": "REPORT_GAS=true yarn hardhat test test/*.ts test/**/*.ts", + "test": "yarn hardhat test test/*.ts test/**/*.ts" + }, + "dependencies": { + "@ampleforthorg/spot-contracts": "workspaces:*", + "@openzeppelin/contracts": "4.9.6", + "@openzeppelin/contracts-upgradeable": "4.7.3", + "ampleforth-contracts": "https://github.com/ampleforth/ampleforth-contracts#master", + "tranche": "https://github.com/buttonwood-protocol/tranche.git#main" + }, + "devDependencies": { + "@ethersproject/abi": "^5.6.4", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/providers": "^5.6.8", + "@nomicfoundation/hardhat-chai-matchers": "latest", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-toolbox": "latest", + "@nomicfoundation/hardhat-verify": "latest", + "@nomiclabs/hardhat-waffle": "^2.0.6", + "@openzeppelin/hardhat-upgrades": "^3.0.4", + "@openzeppelin/upgrades-core": "latest", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^6.1.2", + "@types/chai": "^4.3.1", + "@types/mocha": "^9.1.1", + "@types/node": "^18.6.1", + "@types/sinon-chai": "^3.2.12", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "chai": "^4.3.6", + "dotenv": "^16.0.1", + "eslint": "^8.20.0", + "eslint-config-prettier": "^8.5.0", + "eslint-config-standard": "^17.0.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-n": "^15.2.4", + "eslint-plugin-no-only-tests": "^3.1.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-promise": "^6.0.0", + "eslint-plugin-unused-imports": "^3.0.0", + "ethereum-waffle": "latest", + "ethers": "^6.6.0", + "ethers-v5": "npm:ethers@^5.7.0", + "ganache-cli": "latest", + "hardhat": "^2.22.1", + "hardhat-gas-reporter": "latest", + "lodash": "^4.17.21", + "prettier": "^2.7.1", + "prettier-plugin-solidity": "^1.0.0-dev.23", + "solhint": "^3.3.7", + "solidity-coverage": "^0.8.5", + "ts-node": "^10.9.1", + "typechain": "^8.1.0", + "typescript": "^4.7.4" + }, + "engines": { + "node": ">=20" + } +} diff --git a/spot-vaults/tasks/deploy.ts b/spot-vaults/tasks/deploy.ts new file mode 100644 index 00000000..e07833ee --- /dev/null +++ b/spot-vaults/tasks/deploy.ts @@ -0,0 +1,93 @@ +import { task, types } from "hardhat/config"; +import { TaskArguments } from "hardhat/types"; +import { sleep } from "./tools"; + +task("deploy:mocks").setAction(async function (args: TaskArguments, hre) { + const deployer = (await hre.ethers.getSigners())[0]; + console.log("Signer", await deployer.getAddress()); + + const MockUSDOracle = await hre.ethers.getContractFactory("MockCLOracle"); + const usdOracle = await MockUSDOracle.deploy(); + console.log("usdOracle", usdOracle.target); + await usdOracle.mockLastRoundData("100000000", parseInt(Date.now() / 1000)); + + const MockCPIOracle = await hre.ethers.getContractFactory("MockCPIOracle"); + const cpiOracle = await MockCPIOracle.deploy(); + console.log("cpiOracle", cpiOracle.target); + await cpiOracle.mockData("1200000000000000000", true); +}); + +task("deploy:SpotAppraiser") + .addParam("perp", "the address of the perp token", undefined, types.string, false) + .addParam("usdOracle", "the address of the usd oracle", undefined, types.string, false) + .addParam("cpiOracle", "the address of the usd oracle", undefined, types.string, false) + .addParam("verify", "flag to set false for local deployments", true, types.boolean) + .setAction(async function (args: TaskArguments, hre) { + const deployer = (await hre.ethers.getSigners())[0]; + console.log("Signer", await deployer.getAddress()); + + const { perp, usdOracle, cpiOracle } = args; + + const SpotAppraiser = await hre.ethers.getContractFactory("SpotAppraiser"); + const spotAppraiser = await SpotAppraiser.deploy(perp, usdOracle, cpiOracle); + console.log("spotAppraiser", spotAppraiser.target); + + if (args.verify) { + await sleep(30); + await hre.run("verify:contract", { + address: spotAppraiser.target, + }); + } else { + console.log("Skipping verification"); + } + }); + +task("deploy:BillBroker") + .addParam( + "name", + "the ERC20 name of the bill broker LP token", + undefined, + types.string, + false, + ) + .addParam( + "symbol", + "the ERC20 symbol of the bill broker LP token", + undefined, + types.string, + false, + ) + .addParam("usd", "the address of the usd token", undefined, types.string, false) + .addParam("perp", "the address of the perp token", undefined, types.string, false) + .addParam( + "pricingStrategy", + "the address of the pricing strategy", + undefined, + types.string, + false, + ) + .addParam("verify", "flag to set false for local deployments", true, types.boolean) + .setAction(async function (args: TaskArguments, hre) { + const deployer = (await hre.ethers.getSigners())[0]; + console.log("Signer", await deployer.getAddress()); + + const { name, symbol, usd, perp, pricingStrategy } = args; + const BillBroker = await hre.ethers.getContractFactory("BillBroker"); + const billBroker = await hre.upgrades.deployProxy( + BillBroker.connect(deployer), + [name, symbol, usd, perp, pricingStrategy], + { + initializer: "init(string,string,address,address,address)", + }, + ); + console.log("billBroker", billBroker.target); + + if (args.verify) { + await sleep(30); + await hre.run("verify:contract", { + address: billBroker.target, + }); + } else { + console.log("Skipping verification"); + } + }); diff --git a/spot-vaults/tasks/info.ts b/spot-vaults/tasks/info.ts new file mode 100644 index 00000000..f6357102 --- /dev/null +++ b/spot-vaults/tasks/info.ts @@ -0,0 +1,125 @@ +import { getAdminAddress, getImplementationAddress } from "@openzeppelin/upgrades-core"; +import { task, types } from "hardhat/config"; +import { TaskArguments } from "hardhat/types"; +import { ethers } from "ethers"; + +function pp(val, decimals) { + return parseFloat(ethers.formatUnits(val, decimals)); +} + +task("info:BillBroker") + .addPositionalParam( + "address", + "the address of the bill broker contract", + undefined, + types.string, + false, + ) + .setAction(async function (args: TaskArguments, hre) { + const { address } = args; + + const billBroker = await hre.ethers.getContractAt("BillBroker", address); + const billBrokerDecimals = await billBroker.decimals(); + const proxyAdminAddress = await getAdminAddress(hre.ethers.provider, address); + const implAddress = await getImplementationAddress(hre.ethers.provider, address); + + const usd = await hre.ethers.getContractAt("ERC20", await billBroker.usd()); + const usdDecimals = await usd.decimals(); + const perp = await hre.ethers.getContractAt("ERC20", await billBroker.perp()); + const perpDecimals = await perp.decimals(); + + const unitUsd = await billBroker.usdUnitAmt(); + const unitPerp = await billBroker.perpUnitAmt(); + + const spotAppraiser = await hre.ethers.getContractAt( + "SpotAppraiser", + await billBroker.pricingStrategy.staticCall(), + ); + const appraiserDecimals = await spotAppraiser.decimals(); + console.log("---------------------------------------------------------------"); + console.log("SpotAppraiser:", spotAppraiser.target); + console.log("owner:", await spotAppraiser.owner()); + const usdPriceCall = await spotAppraiser.usdPrice.staticCall(); + console.log("usdPrice:", pp(usdPriceCall[0], appraiserDecimals)); + console.log("usdPriceValid:", usdPriceCall[1]); + const perpPriceCall = await spotAppraiser.perpPrice.staticCall(); + console.log("perpPrice:", pp(perpPriceCall[0], appraiserDecimals)); + console.log("perpPriceValid:", perpPriceCall[1]); + console.log("isSpotHealthy:", await spotAppraiser.isSPOTHealthy.staticCall()); + console.log("---------------------------------------------------------------"); + console.log("BillBroker:", billBroker.target); + console.log("owner:", await billBroker.owner()); + console.log("keeper:", await billBroker.keeper()); + console.log("proxyAdmin:", proxyAdminAddress); + console.log("implementation:", implAddress); + console.log("paused:", await billBroker.paused()); + const fees = await billBroker.fees.staticCall(); + console.log("Fees:"); + console.table([ + ["mintFeePerc", pp(fees[0], billBrokerDecimals)], + ["burnFeePerc", pp(fees[1], billBrokerDecimals)], + ["perpToUsdSwapFeeLowerPerc", pp(fees[2][0], billBrokerDecimals)], + ["perpToUsdSwapFeeUpperPerc", pp(fees[2][1], billBrokerDecimals)], + ["usdToPerpSwapFeeLowerPerc", pp(fees[3][0], billBrokerDecimals)], + ["usdToPerpSwapFeeUpperPerc", pp(fees[3][1], billBrokerDecimals)], + ["protocolSwapSharePerc", pp(fees[4], billBrokerDecimals)], + ]); + + console.log("ARBounds:"); + const arSoft = await billBroker.arSoftBound.staticCall(); + const arHard = await billBroker.arHardBound.staticCall(); + console.table([ + ["softLower", pp(arSoft[0], billBrokerDecimals)], + ["softUpper", pp(arSoft[1], billBrokerDecimals)], + ["hardLower", pp(arHard[0], billBrokerDecimals)], + ["hardUpper", pp(arHard[1], billBrokerDecimals)], + ]); + + try { + console.log("ReserveState:"); + const r = await billBroker.reserveState.staticCall(); + console.table([ + ["usdBalance", pp(r[0], usdDecimals)], + ["perpBalance", pp(r[1], perpDecimals)], + ["usdPrice", pp(r[2], billBrokerDecimals)], + ["perpPrice", pp(r[3], billBrokerDecimals)], + ]); + const assetRatio = await billBroker.assetRatio({ + usdBalance: r[0], + perpBalance: r[1], + usdPrice: r[2], + perpPrice: r[3], + }); + console.log("assetRatio", pp(assetRatio, billBrokerDecimals)); + + const tvl = + pp(r[0], usdDecimals) * pp(r[2], billBrokerDecimals) + + pp(r[1], perpDecimals) * pp(r[3], billBrokerDecimals); + console.log("tvl", tvl); + + const swapAmt = 1n; + console.log( + `Buy price for ${swapAmt} perp: `, + pp( + await billBroker["computePerpToUSDSwapAmt(uint256)"].staticCall( + unitPerp * swapAmt, + ), + usdDecimals, + ), + ); + console.log( + `Sell price for ${swapAmt} perp: `, + 1 / + pp( + await billBroker["computeUSDToPerpSwapAmt(uint256)"].staticCall( + unitUsd * swapAmt, + ), + perpDecimals, + ), + ); + } catch (e) { + console.log(e); + console.log("ReserveState: NA"); + } + console.log("---------------------------------------------------------------"); + }); diff --git a/spot-vaults/tasks/ops.ts b/spot-vaults/tasks/ops.ts new file mode 100644 index 00000000..2533f01d --- /dev/null +++ b/spot-vaults/tasks/ops.ts @@ -0,0 +1,300 @@ +import { task, types } from "hardhat/config"; +import { TaskArguments } from "hardhat/types"; +import { ethers } from "ethers"; + +task("mock:usdPrice", "Mocks usd price") + .addPositionalParam( + "oracleAddress", + "the address of the usd oracle", + undefined, + types.string, + false, + ) + .setAction(async function (args: TaskArguments, hre) { + const deployer = (await hre.ethers.getSigners())[0]; + console.log("Signer", await deployer.getAddress()); + + const { oracleAddress } = args; + const oracle = await hre.ethers.getContractAt("MockCLOracle", oracleAddress); + const tx = await oracle.mockLastRoundData("100000000", parseInt(Date.now() / 1000)); + await tx.wait(); + console.log("tx", tx.hash); + }); + +task("ops:deposit", "Deposits perp and usd tokens to mint bb lp tokens") + .addParam( + "address", + "the address of the bill broker contract", + undefined, + types.string, + false, + ) + .addParam( + "usdAmount", + "the total amount of usd tokens (in float) to deposit", + undefined, + types.string, + false, + ) + .addParam( + "perpAmount", + "the total amount of usd tokens (in float) to deposit", + undefined, + types.string, + false, + ) + .setAction(async function (args: TaskArguments, hre) { + const signer = (await hre.ethers.getSigners())[0]; + const signerAddress = await signer.getAddress(); + console.log("Signer", signerAddress); + + const { address, usdAmount, perpAmount } = args; + const billBroker = await hre.ethers.getContractAt("BillBroker", address); + const usd = await hre.ethers.getContractAt("ERC20", await billBroker.usd()); + const perp = await hre.ethers.getContractAt("ERC20", await billBroker.perp()); + const usdFixedPtAmount = ethers.parseUnits(usdAmount, await usd.decimals()); + const perpFixedPtAmount = ethers.parseUnits(perpAmount, await perp.decimals()); + + console.log( + "Signer perp balance", + ethers.formatUnits(await perp.balanceOf(signerAddress), await perp.decimals()), + ); + console.log( + "Signer usd balance", + ethers.formatUnits(await usd.balanceOf(signerAddress), await usd.decimals()), + ); + + console.log("---------------------------------------------------------------"); + console.log("Execution:"); + console.log("Approving router to spend tokens:"); + if ((await usd.allowance(signerAddress, billBroker.target)) < usdFixedPtAmount) { + const tx1 = await usd.connect(signer).approve(billBroker.target, usdFixedPtAmount); + await tx1.wait(); + console.log("Tx", tx1.hash); + } + if ((await perp.allowance(signerAddress, billBroker.target)) < perpFixedPtAmount) { + const tx2 = await perp + .connect(signer) + .approve(billBroker.target, perpFixedPtAmount); + await tx2.wait(); + console.log("Tx", tx2.hash); + } + + console.log("Deposit:"); + const expectedDepositAmts = await billBroker.computeMintAmt.staticCall( + usdFixedPtAmount, + perpFixedPtAmount, + ); + const tx3 = await billBroker + .connect(signer) + .deposit( + usdFixedPtAmount, + perpFixedPtAmount, + expectedDepositAmts[1], + expectedDepositAmts[2], + ); + await tx3.wait(); + console.log("Tx", tx3.hash); + + console.log( + "Signer lp balance", + ethers.formatUnits( + await billBroker.balanceOf(signerAddress), + await billBroker.decimals(), + ), + ); + console.log( + "Signer perp balance", + ethers.formatUnits(await perp.balanceOf(signerAddress), await perp.decimals()), + ); + console.log( + "Signer usd balance", + ethers.formatUnits(await usd.balanceOf(signerAddress), await usd.decimals()), + ); + }); + +task("ops:redeem") + .addParam( + "address", + "the address of the billBroker contract", + undefined, + types.string, + false, + ) + .addParam( + "amount", + "the total amount of bill broker LP tokens (in float) to redeem", + undefined, + types.string, + false, + ) + .setAction(async function (args: TaskArguments, hre) { + const signer = (await hre.ethers.getSigners())[0]; + const signerAddress = await signer.getAddress(); + console.log("Signer", signerAddress); + + const { address, amount } = args; + + const billBroker = await hre.ethers.getContractAt("BillBroker", address); + const usd = await hre.ethers.getContractAt("ERC20", await billBroker.usd()); + const usdDecimals = await usd.decimals(); + const perp = await hre.ethers.getContractAt("ERC20", await billBroker.perp()); + const perpDecimals = await perp.decimals(); + + const fixedPtAmount = ethers.parseUnits(amount, await billBroker.decimals()); + console.log( + "Signer LP balance", + ethers.formatUnits( + await billBroker.balanceOf(signerAddress), + await billBroker.decimals(), + ), + ); + + console.log("---------------------------------------------------------------"); + console.log("Preview redeem:", amount); + const redemptions = await billBroker.redeem.staticCall(fixedPtAmount); + + const redemptionData = []; + redemptionData.push({ + asset: "usd", + amount: ethers.formatUnits(redemptions[0], usdDecimals), + }); + redemptionData.push({ + asset: "perp", + amount: ethers.formatUnits(redemptions[1], perpDecimals), + }); + console.table(redemptionData); + + console.log("---------------------------------------------------------------"); + console.log("Execution:"); + console.log("Redeem:"); + const tx = await billBroker.connect(signer).redeem(fixedPtAmount); + await tx.wait(); + console.log("Tx", tx.hash); + console.log( + "Signer LP balance", + ethers.formatUnits( + await billBroker.balanceOf(signerAddress), + await billBroker.decimals(), + ), + ); + }); + +task("ops:swapUSDForPerps") + .addParam( + "address", + "the address of the bill broker contract", + undefined, + types.string, + false, + ) + .addParam( + "usdAmount", + "the total amount of usd tokens (in float) to deposit", + undefined, + types.string, + false, + ) + .setAction(async function (args: TaskArguments, hre) { + const signer = (await hre.ethers.getSigners())[0]; + const signerAddress = await signer.getAddress(); + console.log("Signer", signerAddress); + + const { address, usdAmount } = args; + + const billBroker = await hre.ethers.getContractAt("BillBroker", address); + const usd = await hre.ethers.getContractAt("ERC20", await billBroker.usd()); + const perp = await hre.ethers.getContractAt("ERC20", await billBroker.perp()); + const fixedPtAmount = ethers.parseUnits(usdAmount, await usd.decimals()); + + console.log( + "Signer perp balance", + ethers.formatUnits(await perp.balanceOf(signerAddress), await perp.decimals()), + ); + console.log( + "Signer usd balance", + ethers.formatUnits(await usd.balanceOf(signerAddress), await usd.decimals()), + ); + + console.log("---------------------------------------------------------------"); + console.log("Execution:"); + console.log("Approving billBroker to spend tokens:"); + if ((await usd.allowance(signerAddress, billBroker.target)) < fixedPtAmount) { + const tx1 = await usd.connect(signer).approve(billBroker.target, fixedPtAmount); + await tx1.wait(); + console.log("Tx", tx1.hash); + } + + console.log("Swap:"); + const tx2 = await billBroker.connect(signer).swapUSDForPerps(fixedPtAmount, "0"); + await tx2.wait(); + console.log("Tx", tx2.hash); + + console.log( + "Signer perp balance", + ethers.formatUnits(await perp.balanceOf(signerAddress), await perp.decimals()), + ); + console.log( + "Signer usd balance", + ethers.formatUnits(await usd.balanceOf(signerAddress), await usd.decimals()), + ); + }); + +task("ops:swapPerpsForUSD") + .addParam( + "address", + "the address of the billBroker contract", + undefined, + types.string, + false, + ) + .addParam( + "perpAmount", + "the total amount of perp tokens (in float) to deposit", + undefined, + types.string, + false, + ) + .setAction(async function (args: TaskArguments, hre) { + const signer = (await hre.ethers.getSigners())[0]; + const signerAddress = await signer.getAddress(); + console.log("Signer", signerAddress); + + const { address, perpAmount } = args; + const billBroker = await hre.ethers.getContractAt("BillBroker", address); + const perp = await hre.ethers.getContractAt("ERC20", await billBroker.perp()); + const usd = await hre.ethers.getContractAt("ERC20", await billBroker.usd()); + const fixedPtAmount = ethers.parseUnits(perpAmount, await perp.decimals()); + + console.log( + "Signer usd balance", + ethers.formatUnits(await usd.balanceOf(signerAddress), await usd.decimals()), + ); + console.log( + "Signer perp balance", + ethers.formatUnits(await perp.balanceOf(signerAddress), await perp.decimals()), + ); + + console.log("---------------------------------------------------------------"); + console.log("Execution:"); + console.log("Approving router to spend tokens:"); + if ((await perp.allowance(signerAddress, billBroker.target)) < fixedPtAmount) { + const tx1 = await perp.connect(signer).approve(billBroker.target, fixedPtAmount); + await tx1.wait(); + console.log("Tx", tx1.hash); + } + + console.log("Swap:"); + const tx2 = await billBroker.connect(signer).swapPerpsForUSD(fixedPtAmount, "0"); + await tx2.wait(); + console.log("Tx", tx2.hash); + + console.log( + "Signer usd balance", + ethers.formatUnits(await usd.balanceOf(signerAddress), await usd.decimals()), + ); + console.log( + "Signer perp balance", + ethers.formatUnits(await perp.balanceOf(signerAddress), await perp.decimals()), + ); + }); diff --git a/spot-vaults/tasks/scripts/mainnet.sh b/spot-vaults/tasks/scripts/mainnet.sh new file mode 100644 index 00000000..c37b2f9c --- /dev/null +++ b/spot-vaults/tasks/scripts/mainnet.sh @@ -0,0 +1,48 @@ +######################################################################## +## DEPLOYMENT + +yarn hardhat --network mainnet deploy:SpotAppraiser \ + --perp "0xC1f33e0cf7e40a67375007104B929E49a581bafE" \ + --usd-oracle "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6" \ + --cpi-oracle "0x2A18bfb505b49AED12F19F271cC1183F98ff4f71" + +yarn hardhat --network mainnet deploy:BillBroker \ + --name "Bill Broker USDC-SPOT LP" \ + --symbol "BB-USDC-SPOT" \ + --usd "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" \ + --perp "0xC1f33e0cf7e40a67375007104B929E49a581bafE" \ + --pricing-strategy "0x965FBFebDA76d9AA11642C1d0074CdF02e546F3c" + +yarn hardhat --network mainnet transferOwnership "0x965FBFebDA76d9AA11642C1d0074CdF02e546F3c" \ + --new-owner-address "0x57981B1EaFe4b18EC97f8B10859B40207b364662" + +yarn hardhat --network mainnet transferOwnership "0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB" \ + --new-owner-address "0x57981B1EaFe4b18EC97f8B10859B40207b364662" + +yarn hardhat --network mainnet transferOwnership "0xF6E42F7a83fCfB1Bd28aC209fD4a849f54bD1044" \ + --new-owner-address "0x57981B1EaFe4b18EC97f8B10859B40207b364662" + +######################################################################## +## INFO + +yarn hardhat --network mainnet info:BillBroker "0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB" + +######################################################################## +## OPS + +yarn hardhat --network mainnet ops:deposit \ + --address "0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB" \ + --perp-amount 1000 \ + --usd-amount 1000 + +yarn hardhat --network mainnet ops:swapUSDForPerps \ + --address "0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB" \ + --usd-amount 10 + +yarn hardhat --network mainnet ops:swapPerpsForUSD \ + --address "0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB" \ + --perp-amount 10 + +yarn hardhat --network mainnet ops:redeem \ + --address "0xA088Aef966CAD7fE0B38e28c2E07590127Ab4ccB" \ + --amount 1000 \ No newline at end of file diff --git a/spot-vaults/tasks/scripts/sepolia.sh b/spot-vaults/tasks/scripts/sepolia.sh new file mode 100644 index 00000000..c2079221 --- /dev/null +++ b/spot-vaults/tasks/scripts/sepolia.sh @@ -0,0 +1,41 @@ +######################################################################## +## DEPLOYMENT + +yarn hardhat --network sepolia deploy:mocks + +yarn hardhat --network sepolia deploy:SpotAppraiser \ + --perp "0xdcCef9065876fD654bAddeBAa778FDA43E0bfC1F" \ + --usd-oracle "0xA2F78ab2355fe2f984D808B5CeE7FD0A93D5270E" \ + --cpi-oracle "0xbB65d97f9222109Fea38923705B4Fe3dE43DA546" + +yarn hardhat --network sepolia deploy:BillBroker \ + --name "Bill Broker USDC-SPOT LP" \ + --symbol "BB-USDC-SPOT" \ + --usd "0x94a9d9ac8a22534e3faca9f4e7f2e2cf85d5e4c8" \ + --perp "0xdcCef9065876fD654bAddeBAa778FDA43E0bfC1F" \ + --pricing-strategy "0x08c5b39F000705ebeC8427C1d64D6262392944EE" + +######################################################################## +## INFO + +yarn hardhat --network sepolia info:BillBroker "0xc3f6D1F1d253EdC8B34D78Bc6cDD2b3eEFAd76BD" + +######################################################################## +## OPS + +yarn hardhat --network sepolia ops:deposit \ + --address "0xc3f6D1F1d253EdC8B34D78Bc6cDD2b3eEFAd76BD" \ + --perp-amount 1000 \ + --usd-amount 1000 + +yarn hardhat --network sepolia ops:swapUSDForPerps \ + --address "0xc3f6D1F1d253EdC8B34D78Bc6cDD2b3eEFAd76BD" \ + --usd-amount 10 + +yarn hardhat --network sepolia ops:swapPerpsForUSD \ + --address "0xc3f6D1F1d253EdC8B34D78Bc6cDD2b3eEFAd76BD" \ + --perp-amount 10 + +yarn hardhat --network sepolia ops:redeem \ + --address "0xc3f6D1F1d253EdC8B34D78Bc6cDD2b3eEFAd76BD" \ + --amount 1000 \ No newline at end of file diff --git a/spot-vaults/tasks/tools.ts b/spot-vaults/tasks/tools.ts new file mode 100644 index 00000000..e9faa5d9 --- /dev/null +++ b/spot-vaults/tasks/tools.ts @@ -0,0 +1,63 @@ +import { task, types } from "hardhat/config"; +import { TaskArguments } from "hardhat/types"; + +export async function sleep(sleepSec: number) { + await new Promise(resolve => setTimeout(resolve, sleepSec)); +} + +task("accounts", "Prints the list of accounts", async (_taskArgs, hre) => { + const accounts = await hre.ethers.getSigners(); + for (const account of accounts) { + console.log(await account.getAddress()); + } +}); + +task("verify:contract", "Verifies on etherscan") + .addParam("address", "the contract address", undefined, types.string, false) + .addParam( + "constructorArguments", + "the list of constructor arguments", + [], + types.json, + true, + ) + .addParam("sleepSec", "sleep time before verification", 15, types.int, true) + .setAction(async function (args: TaskArguments, hre) { + try { + await sleep(args.sleepSec); + await hre.run("verify:verify", { + address: args.address, + constructorArguments: args.constructorArguments, + }); + } catch (e) { + console.log("Unable to verify on etherscan"); + console.warn(e); + console.log( + `yarn hardhat verify:contract --network ${hre.network.name} --address ${ + args.address + } --constructor-arguments "${JSON.stringify(args.constructorArguments).replace( + /"/g, + '\\"', + )}"`, + ); + } + }); + +task("transferOwnership", "Transfers ownership of contract to new owner") + .addPositionalParam("address", "the contract address", undefined, types.string, false) + .addParam("newOwnerAddress", "the new owner address", undefined, types.string, false) + .addParam("fromIdx", "the index of sender", 0, types.int) + .setAction(async function (args: TaskArguments, hre) { + const { address, newOwnerAddress } = args; + const contract = await hre.ethers.getContractAt("OwnableUpgradeable", address); + + const signer = (await hre.ethers.getSigners())[args.fromIdx]; + const signerAddress = await signer.getAddress(); + console.log("Signer", signerAddress); + + console.log(`Transferring ownership of ${address} to ${newOwnerAddress}`); + await sleep(10); + const tx = await contract.transferOwnership(newOwnerAddress); + console.log(tx.hash); + await tx.wait(); + }); diff --git a/spot-vaults/test/BillBroker.ts b/spot-vaults/test/BillBroker.ts new file mode 100644 index 00000000..230b794e --- /dev/null +++ b/spot-vaults/test/BillBroker.ts @@ -0,0 +1,637 @@ +import { ethers, upgrades } from "hardhat"; +import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers"; +import { expect } from "chai"; +import { DMock, usdFP, perpFP, percentageFP, priceFP } from "./helpers"; + +describe("BillBroker", function () { + async function setupContracts() { + const accounts = await ethers.getSigners(); + const deployer = accounts[0]; + + const Token = await ethers.getContractFactory("MockERC20"); + const usd = await Token.deploy(); + await usd.init("USD token", "usd", 6); + const perp = await Token.deploy(); + await perp.init("Perp token", "perp", 9); + const pricingStrategy = new DMock("SpotAppraiser"); + await pricingStrategy.deploy(); + await pricingStrategy.mockMethod("decimals()", [18]); + await pricingStrategy.mockMethod("perpPrice()", [0, false]); + await pricingStrategy.mockMethod("usdPrice()", [0, false]); + + const BillBroker = await ethers.getContractFactory("BillBroker"); + const billBroker = await upgrades.deployProxy( + BillBroker.connect(deployer), + ["BillBroker LP", "LP token", usd.target, perp.target, pricingStrategy.target], + { + initializer: "init(string,string,address,address,address)", + }, + ); + return { deployer, usd, perp, pricingStrategy, billBroker }; + } + + describe("init", function () { + it("should set initial values", async function () { + const { deployer, billBroker, usd, pricingStrategy } = await loadFixture( + setupContracts, + ); + expect(await billBroker.usd()).to.eq(usd.target); + expect(await billBroker.pricingStrategy()).to.eq(pricingStrategy.target); + expect(await billBroker.usdUnitAmt()).to.eq(usdFP("1")); + expect(await billBroker.perpUnitAmt()).to.eq(perpFP("1")); + + expect(await billBroker.owner()).to.eq(await deployer.getAddress()); + expect(await billBroker.keeper()).to.eq(await deployer.getAddress()); + + const arHardBound = await billBroker.arHardBound(); + expect(arHardBound.upper).to.eq(ethers.MaxUint256); + expect(arHardBound.lower).to.eq(0n); + + const arSoftBound = await billBroker.arSoftBound(); + expect(arSoftBound.upper).to.eq(ethers.MaxUint256); + expect(arSoftBound.lower).to.eq(0n); + + const fees = await billBroker.fees(); + expect(fees.mintFeePerc).to.eq(0); + expect(fees.burnFeePerc).to.eq(0); + expect(fees.perpToUSDSwapFeePercs.lower).to.eq(percentageFP("1")); + expect(fees.perpToUSDSwapFeePercs.upper).to.eq(percentageFP("1")); + expect(fees.usdToPerpSwapFeePercs.lower).to.eq(percentageFP("1")); + expect(fees.usdToPerpSwapFeePercs.upper).to.eq(percentageFP("1")); + expect(fees.protocolSwapSharePerc).to.eq(0); + + expect(await billBroker.usdBalance()).to.eq(0n); + expect(await billBroker.perpBalance()).to.eq(0n); + }); + }); + + describe("#updateKeeper", function () { + describe("when triggered by non-owner", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.renounceOwnership(); + await expect(billBroker.updateKeeper(ethers.ZeroAddress)).to.be.revertedWith( + "Ownable: caller is not the owner", + ); + }); + }); + + describe("when set address is valid", function () { + it("should update reference", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateKeeper(billBroker.target); + expect(await billBroker.keeper()).to.eq(billBroker.target); + }); + }); + }); + + describe("#updatePricingStrategy", function () { + describe("when triggered by non-owner", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.renounceOwnership(); + await expect( + billBroker.updatePricingStrategy(ethers.ZeroAddress), + ).to.be.revertedWith("Ownable: caller is not the owner"); + }); + }); + + describe("when pricing strategy is not valid", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + const pricingStrategy = new DMock("SpotAppraiser"); + await pricingStrategy.deploy(); + await pricingStrategy.mockMethod("decimals()", [17]); + await expect( + billBroker.updatePricingStrategy(pricingStrategy.target), + ).to.be.revertedWithCustomError(billBroker, "UnexpectedDecimals"); + }); + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + const pricingStrategy = new DMock("SpotAppraiser"); + await pricingStrategy.deploy(); + await pricingStrategy.mockMethod("decimals()", [18]); + + await billBroker.updatePricingStrategy(pricingStrategy.target); + expect(await billBroker.pricingStrategy()).to.eq(pricingStrategy.target); + }); + }); + }); + + describe("#updateFees", function () { + let fees: any; + beforeEach(async function () { + fees = { + mintFeePerc: percentageFP("0.005"), + burnFeePerc: percentageFP("0.025"), + perpToUSDSwapFeePercs: { + lower: percentageFP("0.01"), + upper: percentageFP("0.1"), + }, + usdToPerpSwapFeePercs: { + lower: percentageFP("0.02"), + upper: percentageFP("0.2"), + }, + protocolSwapSharePerc: percentageFP("0.05"), + }; + }); + + describe("when triggered by non-owner", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.renounceOwnership(); + await expect(billBroker.updateFees(fees)).to.be.revertedWith( + "Ownable: caller is not the owner", + ); + }); + }); + + describe("when parameters are invalid", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + fees.mintFeePerc = percentageFP("1.01"); + await expect(billBroker.updateFees(fees)).to.be.revertedWithCustomError( + billBroker, + "InvalidPerc", + ); + }); + }); + + describe("when parameters are invalid", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + fees.burnFeePerc = percentageFP("1.01"); + await expect(billBroker.updateFees(fees)).to.be.revertedWithCustomError( + billBroker, + "InvalidPerc", + ); + }); + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + fees.perpToUSDSwapFeePercs.lower = percentageFP("0.2"); + fees.perpToUSDSwapFeePercs.upper = percentageFP("0.1"); + await expect(billBroker.updateFees(fees)).to.be.revertedWithCustomError( + billBroker, + "InvalidPerc", + ); + }); + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + fees.usdToPerpSwapFeePercs.lower = percentageFP("0.2"); + fees.usdToPerpSwapFeePercs.upper = percentageFP("0.1"); + await expect(billBroker.updateFees(fees)).to.be.revertedWithCustomError( + billBroker, + "InvalidPerc", + ); + }); + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + fees.protocolSwapSharePerc = percentageFP("1.01"); + await expect(billBroker.updateFees(fees)).to.be.revertedWithCustomError( + billBroker, + "InvalidPerc", + ); + }); + }); + + describe("when parameters are valid", function () { + it("should update fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateFees(fees); + const f = await billBroker.fees(); + expect(f.mintFeePerc).to.eq(fees.mintFeePerc); + expect(f.burnFeePerc).to.eq(fees.burnFeePerc); + expect(f.perpToUSDSwapFeePercs.lower).to.eq(fees.perpToUSDSwapFeePercs.lower); + expect(f.perpToUSDSwapFeePercs.upper).to.eq(fees.perpToUSDSwapFeePercs.upper); + expect(f.usdToPerpSwapFeePercs.lower).to.eq(fees.usdToPerpSwapFeePercs.lower); + expect(f.usdToPerpSwapFeePercs.upper).to.eq(fees.usdToPerpSwapFeePercs.upper); + expect(f.protocolSwapSharePerc).to.eq(fees.protocolSwapSharePerc); + }); + }); + }); + + describe("#updateARBounds", function () { + describe("when triggered by non-owner", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.renounceOwnership(); + await expect( + billBroker.updateARBounds( + [percentageFP("0.9"), percentageFP("1.1")], + [percentageFP("0.8"), percentageFP("1.2")], + ), + ).to.be.revertedWith("Ownable: caller is not the owner"); + }); + }); + + describe("when parameters are not valid", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect( + billBroker.updateARBounds( + [percentageFP("1.1"), percentageFP("1.0")], + [percentageFP("0.8"), percentageFP("1.2")], + ), + ).to.be.revertedWithCustomError(billBroker, "InvalidARBound"); + }); + + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect( + billBroker.updateARBounds( + [percentageFP("0.9"), percentageFP("1.1")], + [percentageFP("1.2"), percentageFP("0.8")], + ), + ).to.be.revertedWithCustomError(billBroker, "InvalidARBound"); + }); + + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect( + billBroker.updateARBounds( + [percentageFP("0.9"), percentageFP("0.8")], + [percentageFP("1.1"), percentageFP("1.2")], + ), + ).to.be.revertedWithCustomError(billBroker, "InvalidARBound"); + }); + + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect( + billBroker.updateARBounds( + [percentageFP("0.8"), percentageFP("1.2")], + [percentageFP("0.9"), percentageFP("1.1")], + ), + ).to.be.revertedWithCustomError(billBroker, "InvalidARBound"); + }); + }); + + describe("when parameters are valid", function () { + it("should update bound", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateARBounds( + [percentageFP("0.9"), percentageFP("1.1")], + [percentageFP("0.8"), percentageFP("1.2")], + ); + const b1 = await billBroker.arSoftBound(); + expect(b1.lower).to.eq(percentageFP("0.9")); + expect(b1.upper).to.eq(percentageFP("1.1")); + + const b2 = await billBroker.arHardBound(); + expect(b2.lower).to.eq(percentageFP("0.8")); + expect(b2.upper).to.eq(percentageFP("1.2")); + }); + }); + }); + + describe("#pause", function () { + describe("when triggered by non-keeper", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateKeeper(ethers.ZeroAddress); + await expect(billBroker.pause()).to.be.revertedWithCustomError( + billBroker, + "UnauthorizedCall", + ); + }); + }); + + describe("when already paused", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.pause(); + await expect(billBroker.pause()).to.be.revertedWith("Pausable: paused"); + }); + }); + + describe("when valid", function () { + it("should pause", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.pause(); + expect(await billBroker.paused()).to.eq(true); + }); + }); + }); + + describe("#unpause", function () { + describe("when triggered by non-keeper", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.pause(); + await billBroker.updateKeeper(ethers.ZeroAddress); + await expect(billBroker.unpause()).to.be.revertedWithCustomError( + billBroker, + "UnauthorizedCall", + ); + }); + }); + + describe("when not paused", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect(billBroker.unpause()).to.be.revertedWith("Pausable: not paused"); + }); + }); + + describe("when valid", function () { + it("should unpause", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.pause(); + await billBroker.unpause(); + expect(await billBroker.paused()).to.eq(false); + }); + }); + }); + + describe("#usdPrice", function () { + describe("when the price is invalid", function () { + it("should revert", async function () { + const { billBroker, pricingStrategy } = await loadFixture(setupContracts); + await pricingStrategy.mockMethod("usdPrice()", [priceFP("1"), false]); + await expect(billBroker.usdPrice()).to.be.revertedWithCustomError( + billBroker, + "UnreliablePrice", + ); + }); + }); + + describe("when the price is valid", function () { + it("should return strategy price", async function () { + const { billBroker, pricingStrategy } = await loadFixture(setupContracts); + await pricingStrategy.mockMethod("usdPrice()", [priceFP("1.001"), true]); + expect(await billBroker.usdPrice.staticCall()).to.eq(priceFP("1.001")); + }); + }); + }); + + describe("#perpPrice", function () { + describe("when the price is invalid", function () { + it("should revert", async function () { + const { billBroker, pricingStrategy } = await loadFixture(setupContracts); + await pricingStrategy.mockMethod("perpPrice()", [priceFP("1.17"), false]); + await expect(billBroker.perpPrice()).to.be.revertedWithCustomError( + billBroker, + "UnreliablePrice", + ); + }); + }); + + describe("when the price is valid", function () { + it("should return strategy price", async function () { + const { billBroker, pricingStrategy } = await loadFixture(setupContracts); + await pricingStrategy.mockMethod("perpPrice()", [priceFP("1.17"), true]); + expect(await billBroker.perpPrice.staticCall()).to.eq(priceFP("1.17")); + }); + }); + }); + + describe("#usdBalance", function () { + it("should return the reserve balance", async function () { + const { billBroker, usd } = await loadFixture(setupContracts); + await usd.mint(billBroker.target, usdFP("1246")); + expect(await billBroker.usdBalance()).to.eq(usdFP("1246")); + }); + }); + + describe("#perpBalance", function () { + it("should return the reserve balance", async function () { + const { billBroker, perp } = await loadFixture(setupContracts); + await perp.mint(billBroker.target, perpFP("999")); + expect(await billBroker.perpBalance()).to.eq(perpFP("999")); + }); + }); + + describe("#reserveState", function () { + it("should return the reserve state", async function () { + const { billBroker, perp, usd, pricingStrategy } = await loadFixture( + setupContracts, + ); + await usd.mint(billBroker.target, usdFP("115")); + await perp.mint(billBroker.target, perpFP("100")); + await pricingStrategy.mockMethod("usdPrice()", [priceFP("1"), true]); + await pricingStrategy.mockMethod("perpPrice()", [priceFP("1.3"), true]); + const r = { + usdBalance: await billBroker.usdBalance(), + perpBalance: await billBroker.perpBalance(), + usdPrice: await billBroker.usdPrice.staticCall(), + perpPrice: await billBroker.perpPrice.staticCall(), + }; + expect(r.usdBalance).to.eq(usdFP("115")); + expect(r.perpBalance).to.eq(perpFP("100")); + expect(r.usdPrice).to.eq(priceFP("1")); + expect(r.perpPrice).to.eq(priceFP("1.3")); + }); + }); + + describe("#computeUSDToPerpSwapFeePerc", function () { + it("should compute the right fee perc", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateARBounds( + [percentageFP("0.75"), percentageFP("1.25")], + [percentageFP("0.5"), percentageFP("1.5")], + ); + + await billBroker.updateFees({ + mintFeePerc: 0n, + burnFeePerc: 0n, + perpToUSDSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("1.5"), + }, + protocolSwapSharePerc: 0n, + }); + + await expect( + billBroker.computeUSDToPerpSwapFeePerc(percentageFP("1.5"), percentageFP("0.5")), + ).to.be.revertedWithCustomError(billBroker, "UnexpectedARDelta"); + await expect( + billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("1.25"), + percentageFP("1.249"), + ), + ).to.be.revertedWithCustomError(billBroker, "UnexpectedARDelta"); + + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("0.25"), + percentageFP("1.2"), + ), + ).to.eq(percentageFP("0.05")); + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("0.25"), + percentageFP("1.25"), + ), + ).to.eq(percentageFP("0.05")); + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("1.2"), + percentageFP("1.3"), + ), + ).to.eq(percentageFP("0.1225")); + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("1.3"), + percentageFP("1.45"), + ), + ).to.eq(percentageFP("0.775")); + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("1.3"), + percentageFP("1.5"), + ), + ).to.eq(percentageFP("0.92")); + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("0.5"), + percentageFP("1.5"), + ), + ).to.eq(percentageFP("0.23125")); + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("1.3"), + percentageFP("1.501"), + ), + ).to.eq(percentageFP("1")); + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("1.3"), + percentageFP("2"), + ), + ).to.eq(percentageFP("1")); + }); + + it("should compute the right fee perc when outside bounds", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateARBounds( + [percentageFP("0.75"), percentageFP("1.25")], + [percentageFP("0"), percentageFP("10")], + ); + + await billBroker.updateFees({ + mintFeePerc: 0n, + burnFeePerc: 0n, + perpToUSDSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + usdToPerpSwapFeePercs: { + lower: percentageFP("1.01"), + upper: percentageFP("2"), + }, + protocolSwapSharePerc: 0n, + }); + + expect( + await billBroker.computeUSDToPerpSwapFeePerc( + percentageFP("1"), + percentageFP("1.25"), + ), + ).to.eq(percentageFP("1")); + }); + }); + + describe("#computePerpToUSDSwapFeePerc", function () { + it("should compute the right fee perc", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateARBounds( + [percentageFP("0.75"), percentageFP("1.25")], + [percentageFP("0.5"), percentageFP("1.5")], + ); + + await billBroker.updateFees({ + mintFeePerc: 0n, + burnFeePerc: 0n, + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + usdToPerpSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + protocolSwapSharePerc: 0n, + }); + + await expect( + billBroker.computePerpToUSDSwapFeePerc(percentageFP("0.5"), percentageFP("1.5")), + ).to.be.revertedWithCustomError(billBroker, "UnexpectedARDelta"); + await expect( + billBroker.computePerpToUSDSwapFeePerc( + percentageFP("1.25"), + percentageFP("1.251"), + ), + ).to.be.revertedWithCustomError(billBroker, "UnexpectedARDelta"); + + expect( + await billBroker.computePerpToUSDSwapFeePerc( + percentageFP("2"), + percentageFP("0.8"), + ), + ).to.eq(percentageFP("0.1")); + expect( + await billBroker.computePerpToUSDSwapFeePerc( + percentageFP("1.45"), + percentageFP("0.8"), + ), + ).to.eq(percentageFP("0.1")); + expect( + await billBroker.computePerpToUSDSwapFeePerc( + percentageFP("0.8"), + percentageFP("0.7"), + ), + ).to.eq(percentageFP("0.12")); + expect( + await billBroker.computePerpToUSDSwapFeePerc( + percentageFP("0.8"), + percentageFP("0.5"), + ), + ).to.eq(percentageFP("0.266666666666666666")); + expect( + await billBroker.computePerpToUSDSwapFeePerc( + percentageFP("1.5"), + percentageFP("0.5"), + ), + ).to.eq(percentageFP("0.15")); + expect( + await billBroker.computePerpToUSDSwapFeePerc( + percentageFP("1.0"), + percentageFP("0.49"), + ), + ).to.eq(percentageFP("1")); + }); + + it("should compute the right fee perc when outside bounds", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateARBounds( + [percentageFP("0.75"), percentageFP("1.25")], + [percentageFP("0"), percentageFP("10")], + ); + + await billBroker.updateFees({ + mintFeePerc: 0n, + burnFeePerc: 0n, + perpToUSDSwapFeePercs: { + lower: percentageFP("1.01"), + upper: percentageFP("2"), + }, + usdToPerpSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + protocolSwapSharePerc: 0n, + }); + + expect( + await billBroker.computePerpToUSDSwapFeePerc( + percentageFP("1.25"), + percentageFP("1.11"), + ), + ).to.eq(percentageFP("1")); + }); + }); +}); diff --git a/spot-vaults/test/BillBroker_deposit_redeem.ts b/spot-vaults/test/BillBroker_deposit_redeem.ts new file mode 100644 index 00000000..2c460873 --- /dev/null +++ b/spot-vaults/test/BillBroker_deposit_redeem.ts @@ -0,0 +1,903 @@ +import { ethers, upgrades } from "hardhat"; +import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers"; +import { expect } from "chai"; +import { DMock, usdFP, perpFP, lpAmtFP, percentageFP, priceFP } from "./helpers"; + +describe("BillBroker", function () { + async function setupContracts() { + const accounts = await ethers.getSigners(); + const deployer = accounts[0]; + const otherUser = accounts[1]; + + const Token = await ethers.getContractFactory("MockERC20"); + const usd = await Token.deploy(); + await usd.init("USD token", "usd", 6); + const perp = await Token.deploy(); + await perp.init("Perp token", "perp", 9); + const pricingStrategy = new DMock("SpotAppraiser"); + await pricingStrategy.deploy(); + await pricingStrategy.mockMethod("decimals()", [18]); + await pricingStrategy.mockMethod("perpPrice()", [priceFP("1.15"), true]); + await pricingStrategy.mockMethod("usdPrice()", [priceFP("1"), true]); + + const BillBroker = await ethers.getContractFactory("BillBroker"); + const billBroker = await upgrades.deployProxy( + BillBroker.connect(deployer), + ["BillBroker LP", "LP token", usd.target, perp.target, pricingStrategy.target], + { + initializer: "init(string,string,address,address,address)", + }, + ); + await billBroker.updateFees({ + mintFeePerc: 0n, + burnFeePerc: 0n, + perpToUSDSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + usdToPerpSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + protocolSwapSharePerc: 0n, + }); + await usd.mint(await deployer.getAddress(), usdFP("2000")); + await perp.mint(await deployer.getAddress(), perpFP("2000")); + await usd.mint(await otherUser.getAddress(), usdFP("2000")); + await perp.mint(await otherUser.getAddress(), perpFP("2000")); + return { deployer, otherUser, usd, perp, pricingStrategy, billBroker }; + } + + describe("#computeMintAmt", function () { + describe("when amounts available are zero", function () { + it("should return zero", async function () { + const { billBroker } = await loadFixture(setupContracts); + const r = await billBroker.computeMintAmt.staticCall(0n, 0n); + expect(r[0]).to.eq(0n); + expect(r[1]).to.eq(0n); + expect(r[2]).to.eq(0n); + }); + }); + + describe("first mint", function () { + it("should compute mint amount", async function () { + const { billBroker } = await loadFixture(setupContracts); + const r = await billBroker.computeMintAmt.staticCall(usdFP("115"), perpFP("100")); + expect(r[0]).to.eq(lpAmtFP("215")); + expect(r[1]).to.eq(usdFP("115")); + expect(r[2]).to.eq(perpFP("100")); + }); + }); + + describe("when supply > 0 and minting in the right ratio", function () { + it("should compute mint amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + const r = await billBroker.computeMintAmt.staticCall(usdFP("230"), perpFP("200")); + expect(r[0]).to.eq(lpAmtFP("430")); + expect(r[1]).to.eq(usdFP("230")); + expect(r[2]).to.eq(perpFP("200")); + }); + }); + + describe("when supply > 0 and minting ratio is different", function () { + it("should compute mint amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + const r = await billBroker.computeMintAmt.staticCall(usdFP("230"), perpFP("100")); + expect(r[0]).to.eq(lpAmtFP("215")); + expect(r[1]).to.eq(usdFP("115")); + expect(r[2]).to.eq(perpFP("100")); + }); + }); + + describe("when supply > 0 and minting ratio is different", function () { + it("should compute mint amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + const r = await billBroker.computeMintAmt.staticCall(usdFP("50"), perpFP("100")); + expect(r[0]).to.eq(lpAmtFP("93.478260869565217391304347")); + expect(r[1]).to.eq(usdFP("50")); + expect(r[2]).to.eq(perpFP("43.478260869")); + }); + }); + + describe("when fee > 0", async function () { + it("should compute mint amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await billBroker.updateFees({ + mintFeePerc: percentageFP("0.1"), + burnFeePerc: 0n, + perpToUSDSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + usdToPerpSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + protocolSwapSharePerc: 0n, + }); + const r = await billBroker.computeMintAmt.staticCall(usdFP("115"), perpFP("100")); + expect(r[0]).to.eq(lpAmtFP("193.5")); + expect(r[1]).to.eq(usdFP("115")); + expect(r[2]).to.eq(perpFP("100")); + }); + }); + + describe("when the pool has only usd", function () { + it("should compute mint amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + + await usd.approve(billBroker.target, usdFP("115")); + await billBroker.swapUSDForPerps(usdFP("115"), 0n); + expect(await perp.balanceOf(billBroker.target)).to.eq(0n); + + const s = await billBroker.reserveState.staticCall(); + expect( + await billBroker.assetRatio({ + usdBalance: s[0], + perpBalance: s[1], + usdPrice: s[2], + perpPrice: s[3], + }), + ).to.eq(ethers.MaxUint256); + + const r = await billBroker.computeMintAmt.staticCall(usdFP("100"), 0n); + expect(r[0]).to.eq(lpAmtFP("93.478260869565217391304347")); + expect(r[1]).to.eq(usdFP("100")); + expect(r[2]).to.eq(0n); + }); + }); + + describe("when the pool has only perps", function () { + it("should compute mint amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.swapPerpsForUSD(perpFP("100"), 0n); + expect(await usd.balanceOf(billBroker.target)).to.eq(0n); + + const s = await billBroker.reserveState.staticCall(); + expect( + await billBroker.assetRatio({ + usdBalance: s[0], + perpBalance: s[1], + usdPrice: s[2], + perpPrice: s[3], + }), + ).to.eq(0); + + const r = await billBroker.computeMintAmt.staticCall(0n, perpFP("100")); + expect(r[0]).to.eq(lpAmtFP("107.5")); + expect(r[1]).to.eq(0n); + expect(r[2]).to.eq(perpFP("100")); + }); + }); + }); + + describe("#deposit", function () { + describe("when paused", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.pause(); + await expect( + billBroker.deposit(usdFP("115"), perpFP("100"), usdFP("115"), perpFP("100")), + ).to.be.reverted; + }); + }); + + describe("when amounts available are zero", function () { + it("should return zero", async function () { + const { billBroker } = await loadFixture(setupContracts); + const r = await billBroker.deposit.staticCall(0n, 0n, 0n, 0n); + expect(r).to.eq(0n); + }); + }); + + describe("when slippage is too high", function () { + it("should revert", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await expect( + billBroker.deposit(usdFP("100"), perpFP("100"), usdFP("120"), perpFP("100")), + ).to.be.revertedWithCustomError(billBroker, "SlippageTooHigh"); + }); + + it("should revert", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("100")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("100"), + perpFP("100"), + usdFP("100"), + perpFP("100"), + ); + await expect( + billBroker.deposit(usdFP("100"), perpFP("115"), usdFP("100"), perpFP("115")), + ).to.be.revertedWithCustomError(billBroker, "SlippageTooHigh"); + }); + }); + + describe("first deposit", function () { + it("should transfer usd from user", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker.deposit(usdFP("115"), perpFP("100"), usdFP("115"), perpFP("100")), + ).to.changeTokenBalance(usd, deployer, usdFP("-115")); + }); + + it("should transfer perps from user", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker.deposit(usdFP("115"), perpFP("100"), usdFP("115"), perpFP("100")), + ).to.changeTokenBalance(perp, deployer, perpFP("-100")); + }); + + it("should mint lp tokens", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker.deposit(usdFP("115"), perpFP("100"), usdFP("115"), perpFP("100")), + ).to.changeTokenBalance(billBroker, deployer, lpAmtFP("214.99")); + expect(await billBroker.totalSupply()).to.eq(lpAmtFP("215")); + }); + + it("should return mint amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + const r = await billBroker.deposit.staticCall( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + expect(r).to.eq(lpAmtFP("214.99")); + }); + }); + + describe("subsequent deposits", function () { + it("should transfer usd from user", async function () { + const { billBroker, usd, perp, otherUser } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await usd.connect(otherUser).approve(billBroker.target, usdFP("100")); + await perp.connect(otherUser).approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker + .connect(otherUser) + .deposit(usdFP("23"), perpFP("100"), usdFP("20"), perpFP("20")), + ).to.changeTokenBalance(usd, otherUser, usdFP("-23")); + }); + + it("should transfer perps from user", async function () { + const { billBroker, usd, perp, otherUser } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await usd.connect(otherUser).approve(billBroker.target, usdFP("100")); + await perp.connect(otherUser).approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker + .connect(otherUser) + .deposit(usdFP("23"), perpFP("100"), usdFP("20"), perpFP("20")), + ).to.changeTokenBalance(perp, otherUser, perpFP("-20")); + }); + + it("should mint lp tokens", async function () { + const { billBroker, usd, perp, otherUser } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await usd.connect(otherUser).approve(billBroker.target, usdFP("100")); + await perp.connect(otherUser).approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker + .connect(otherUser) + .deposit(usdFP("23"), perpFP("100"), usdFP("20"), perpFP("20")), + ).to.changeTokenBalance(billBroker, otherUser, lpAmtFP("43")); + expect(await billBroker.totalSupply()).to.eq(lpAmtFP("258")); + }); + + it("should return mint amount", async function () { + const { billBroker, usd, perp, otherUser } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await usd.connect(otherUser).approve(billBroker.target, usdFP("100")); + await perp.connect(otherUser).approve(billBroker.target, perpFP("100")); + const r = await billBroker + .connect(otherUser) + .deposit.staticCall(usdFP("23"), perpFP("100"), usdFP("20"), perpFP("20")); + expect(r).to.eq(lpAmtFP("43")); + }); + }); + + describe("when fee > 0", function () { + it("should withhold fees and mint lp tokens", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await billBroker.updateFees({ + mintFeePerc: percentageFP("0.1"), + burnFeePerc: 0n, + perpToUSDSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + usdToPerpSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + protocolSwapSharePerc: 0n, + }); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker.deposit(usdFP("115"), perpFP("100"), usdFP("115"), perpFP("100")), + ).to.changeTokenBalance(billBroker, deployer, lpAmtFP("193.49")); + }); + }); + + describe("when the pool has only usd", function () { + it("should mint lp tokens", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + + await usd.approve(billBroker.target, usdFP("115")); + await billBroker.swapUSDForPerps(usdFP("115"), 0n); + expect(await perp.balanceOf(billBroker.target)).to.eq(0n); + + const s = await billBroker.reserveState.staticCall(); + expect( + await billBroker.assetRatio({ + usdBalance: s[0], + perpBalance: s[1], + usdPrice: s[2], + perpPrice: s[3], + }), + ).to.eq(ethers.MaxUint256); + + await usd.approve(billBroker.target, usdFP("115")); + await expect(() => + billBroker.deposit(usdFP("100"), 0n, usdFP("100"), 0n), + ).to.changeTokenBalance( + billBroker, + deployer, + lpAmtFP("93.478260869565217391304347"), + ); + }); + }); + + describe("when the pool has only perps", function () { + it("should mint lp tokens", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.swapPerpsForUSD(perpFP("100"), 0n); + expect(await usd.balanceOf(billBroker.target)).to.eq(0n); + + const s = await billBroker.reserveState.staticCall(); + expect( + await billBroker.assetRatio({ + usdBalance: s[0], + perpBalance: s[1], + usdPrice: s[2], + perpPrice: s[3], + }), + ).to.eq(0); + + await perp.approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker.deposit(usdFP("100"), perpFP("100"), 0n, perpFP("100")), + ).to.changeTokenBalance(billBroker, deployer, lpAmtFP("107.5")); + }); + }); + }); + + describe("#computeRedemptionAmts", function () { + describe("when burn amount is zero", function () { + it("should return zero", async function () { + const { billBroker } = await loadFixture(setupContracts); + const r = await billBroker.computeRedemptionAmts.staticCall(0n); + expect(r[0]).to.eq(0n); + expect(r[1]).to.eq(0n); + }); + }); + + describe("when supply is zero", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect(billBroker.computeRedemptionAmts.staticCall(lpAmtFP("100"))).to.be + .reverted; + }); + }); + + describe("when redeeming partial supply", function () { + it("should return redemption amounts", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + const r = await billBroker.computeRedemptionAmts.staticCall(lpAmtFP("100")); + expect(r[0]).to.eq(usdFP("53.488372")); + expect(r[1]).to.eq(perpFP("46.511627906")); + }); + }); + + describe("when redeeming entire supply", function () { + it("should return redemption amounts", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + const r = await billBroker.computeRedemptionAmts.staticCall(lpAmtFP("215")); + expect(r[0]).to.eq(usdFP("115")); + expect(r[1]).to.eq(perpFP("100")); + }); + }); + + describe("when fee is zero", function () { + it("should withhold and return redemption amounts", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await billBroker.updateFees({ + mintFeePerc: 0n, + burnFeePerc: percentageFP("0.1"), + perpToUSDSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + usdToPerpSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + protocolSwapSharePerc: 0n, + }); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + const r = await billBroker.computeRedemptionAmts.staticCall(lpAmtFP("215")); + expect(r[0]).to.eq(usdFP("103.5")); + expect(r[1]).to.eq(perpFP("90")); + }); + }); + + describe("when the pool has only usd", function () { + it("should return redemption amounts", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + + await usd.approve(billBroker.target, usdFP("115")); + await billBroker.swapUSDForPerps(usdFP("115"), 0n); + expect(await perp.balanceOf(billBroker.target)).to.eq(0n); + + const s = await billBroker.reserveState.staticCall(); + expect( + await billBroker.assetRatio({ + usdBalance: s[0], + perpBalance: s[1], + usdPrice: s[2], + perpPrice: s[3], + }), + ).to.eq(ethers.MaxUint256); + + const r = await billBroker.computeRedemptionAmts.staticCall(lpAmtFP("100")); + expect(r[0]).to.eq(usdFP("106.976744")); + expect(r[1]).to.eq(0n); + }); + }); + + describe("when the pool has only perps", function () { + it("should return redemption amounts", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.swapPerpsForUSD(perpFP("100"), 0n); + expect(await usd.balanceOf(billBroker.target)).to.eq(0n); + + const s = await billBroker.reserveState.staticCall(); + expect( + await billBroker.assetRatio({ + usdBalance: s[0], + perpBalance: s[1], + usdPrice: s[2], + perpPrice: s[3], + }), + ).to.eq(0); + + const r = await billBroker.computeRedemptionAmts.staticCall(lpAmtFP("100")); + expect(r[0]).to.eq(0n); + expect(r[1]).to.eq(perpFP("93.023255813")); + }); + }); + }); + + describe("#redeem", function () { + describe("when paused", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.pause(); + await expect(billBroker.redeem.staticCall(0n)).to.be.reverted; + }); + }); + + describe("when burn amount is zero", function () { + it("should return zero", async function () { + const { billBroker } = await loadFixture(setupContracts); + const r = await billBroker.redeem.staticCall(0n); + expect(r[0]).to.eq(0n); + expect(r[1]).to.eq(0n); + }); + }); + + describe("when burning more than balance", function () { + it("should return zero", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await expect(billBroker.redeem.staticCall(lpAmtFP("1000"))).to.be.reverted; + }); + }); + + describe("on partial redemption", function () { + it("should burn lp tokens", async function () { + const { billBroker, usd, perp, otherUser } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await billBroker.transfer(await otherUser.getAddress(), lpAmtFP("101")); + await expect(() => + billBroker.connect(otherUser).redeem(lpAmtFP("100")), + ).to.changeTokenBalance(billBroker, otherUser, lpAmtFP("-100")); + expect(await billBroker.balanceOf(await otherUser.getAddress())).to.eq( + lpAmtFP("1"), + ); + expect(await billBroker.totalSupply()).to.eq(lpAmtFP("115")); + }); + + it("should not change other balances", async function () { + const { billBroker, usd, perp, deployer, otherUser } = await loadFixture( + setupContracts, + ); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await billBroker.transfer(await otherUser.getAddress(), lpAmtFP("101")); + await expect(() => + billBroker.connect(otherUser).redeem(lpAmtFP("100")), + ).to.changeTokenBalance(billBroker, deployer, 0n); + }); + + it("should return returned amounts", async function () { + const { billBroker, usd, perp, otherUser } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await billBroker.transfer(await otherUser.getAddress(), lpAmtFP("101")); + const r = await billBroker.connect(otherUser).redeem.staticCall(lpAmtFP("100")); + expect(r[0]).to.eq(usdFP("53.488372")); + expect(r[1]).to.eq(perpFP("46.511627906")); + }); + + it("should transfer usd to user", async function () { + const { billBroker, usd, perp, otherUser } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await billBroker.transfer(await otherUser.getAddress(), lpAmtFP("101")); + await expect(() => + billBroker.connect(otherUser).redeem(lpAmtFP("100")), + ).to.changeTokenBalance(usd, otherUser, usdFP("53.488372")); + }); + + it("should transfer perps to user", async function () { + const { billBroker, usd, perp, otherUser } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await billBroker.transfer(await otherUser.getAddress(), lpAmtFP("101")); + await expect(() => + billBroker.connect(otherUser).redeem(lpAmtFP("100")), + ).to.changeTokenBalance(perp, otherUser, perpFP("46.511627906")); + }); + }); + + describe("on complete redemption", function () { + it("should burn lp tokens", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await expect(() => billBroker.redeem(lpAmtFP("214.99"))).to.changeTokenBalance( + billBroker, + deployer, + lpAmtFP("-214.99"), + ); + expect(await billBroker.balanceOf(await deployer.getAddress())).to.eq(0n); + expect(await billBroker.totalSupply()).to.eq(lpAmtFP("0.01")); + }); + + it("should return returned amounts", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + const r = await billBroker.redeem.staticCall(lpAmtFP("214.99")); + expect(r[0]).to.eq(usdFP("114.994651")); + expect(r[1]).to.eq(perpFP("99.995348837")); + }); + + it("should transfer usd to user", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await expect(() => billBroker.redeem(lpAmtFP("214.99"))).to.changeTokenBalance( + usd, + deployer, + usdFP("114.994651"), + ); + }); + + it("should transfer perps to user", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + await expect(() => billBroker.redeem(lpAmtFP("214.99"))).to.changeTokenBalance( + perp, + deployer, + perpFP("99.995348837"), + ); + }); + }); + + describe("when the pool has only usd", function () { + it("should burn lp tokens", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + + await usd.approve(billBroker.target, usdFP("115")); + await billBroker.swapUSDForPerps(usdFP("115"), 0n); + expect(await perp.balanceOf(billBroker.target)).to.eq(0n); + + const s = await billBroker.reserveState.staticCall(); + expect( + await billBroker.assetRatio({ + usdBalance: s[0], + perpBalance: s[1], + usdPrice: s[2], + perpPrice: s[3], + }), + ).to.eq(ethers.MaxUint256); + + const perpBal = await perp.balanceOf(await deployer.getAddress()); + await expect(() => billBroker.redeem(lpAmtFP("100"))).to.changeTokenBalance( + usd, + deployer, + usdFP("106.976744"), + ); + const perpBal_ = await perp.balanceOf(await deployer.getAddress()); + expect(perpBal_ - perpBal).to.eq(0n); + }); + }); + + describe("when the pool has only perps", function () { + it("should burn lp tokens", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await usd.approve(billBroker.target, usdFP("115")); + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.deposit( + usdFP("115"), + perpFP("100"), + usdFP("115"), + perpFP("100"), + ); + + await perp.approve(billBroker.target, perpFP("100")); + await billBroker.swapPerpsForUSD(perpFP("100"), 0n); + expect(await usd.balanceOf(billBroker.target)).to.eq(0n); + + const s = await billBroker.reserveState.staticCall(); + expect( + await billBroker.assetRatio({ + usdBalance: s[0], + perpBalance: s[1], + usdPrice: s[2], + perpPrice: s[3], + }), + ).to.eq(0); + + const usdBal = await usd.balanceOf(await deployer.getAddress()); + await expect(() => billBroker.redeem(lpAmtFP("100"))).to.changeTokenBalance( + perp, + deployer, + perpFP("93.023255813"), + ); + const usdBal_ = await usd.balanceOf(await deployer.getAddress()); + expect(usdBal_ - usdBal).to.eq(0n); + }); + }); + }); +}); diff --git a/spot-vaults/test/BillBroker_swap.ts b/spot-vaults/test/BillBroker_swap.ts new file mode 100644 index 00000000..c58faab5 --- /dev/null +++ b/spot-vaults/test/BillBroker_swap.ts @@ -0,0 +1,1103 @@ +import { ethers, upgrades } from "hardhat"; +import { Contract } from "ethers"; +import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers"; +import { expect } from "chai"; +import { DMock, usdFP, perpFP, priceFP, percentageFP } from "./helpers"; + +async function updateFees(billBroker: Contract, fees: any) { + const currentFees = await billBroker.fees(); + await billBroker.updateFees({ + ...{ + mintFeePerc: currentFees[0], + burnFeePerc: currentFees[1], + perpToUSDSwapFeePercs: { + lower: currentFees[2][0], + upper: currentFees[2][1], + }, + usdToPerpSwapFeePercs: { + lower: currentFees[3][0], + upper: currentFees[3][1], + }, + protocolSwapSharePerc: currentFees[4], + }, + ...fees, + }); +} + +async function checkUSDToPerpSwapAmt( + billBroker: Contract, + usdAmtIn: BigInt, + reserveState: any, + amoutsOut: any, +) { + const r = await billBroker[ + "computeUSDToPerpSwapAmt(uint256,(uint256,uint256,uint256,uint256))" + ](usdAmtIn, reserveState); + expect(r[0]).to.eq(amoutsOut[0]); + expect(r[1]).to.eq(amoutsOut[1]); + expect(r[2]).to.eq(amoutsOut[2]); +} + +async function checkPerpTpUSDSwapAmt( + billBroker: Contract, + perpAmtIn: BigInt, + reserveState: any, + amoutsOut: any, +) { + const r = await billBroker[ + "computePerpToUSDSwapAmt(uint256,(uint256,uint256,uint256,uint256))" + ](perpAmtIn, reserveState); + expect(r[0]).to.eq(amoutsOut[0]); + expect(r[1]).to.eq(amoutsOut[1]); + expect(r[2]).to.eq(amoutsOut[2]); +} + +async function reserveState(billBroker: Contract) { + const r = await billBroker.reserveState.staticCall(); + return { + usdBalance: r[0], + perpBalance: r[1], + usdPrice: r[2], + perpPrice: r[3], + }; +} + +async function assetRatio(billBroker: Contract) { + return billBroker.assetRatio(await reserveState(billBroker)); +} + +describe("BillBroker", function () { + async function setupContracts() { + const accounts = await ethers.getSigners(); + const deployer = accounts[0]; + const feeCollector = accounts[1]; + + const Token = await ethers.getContractFactory("MockERC20"); + const usd = await Token.deploy(); + await usd.init("USD token", "usd", 6); + const perp = await Token.deploy(); + await perp.init("Perp token", "perp", 9); + const pricingStrategy = new DMock("SpotAppraiser"); + await pricingStrategy.deploy(); + await pricingStrategy.mockMethod("decimals()", [18]); + await pricingStrategy.mockMethod("perpPrice()", [priceFP("1.15"), true]); + await pricingStrategy.mockMethod("usdPrice()", [priceFP("1"), true]); + + const BillBroker = await ethers.getContractFactory("BillBroker"); + const billBroker = await upgrades.deployProxy( + BillBroker.connect(deployer), + ["BillBroker LP", "LP token", usd.target, perp.target, pricingStrategy.target], + { + initializer: "init(string,string,address,address,address)", + }, + ); + await updateFees(billBroker, { + mintFeePerc: 0n, + burnFeePerc: 0n, + perpToUSDSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + usdToPerpSwapFeePercs: { + lower: 0n, + upper: 0n, + }, + protocolSwapSharePerc: 0n, + }); + await billBroker.updateARBounds( + [percentageFP("0.9"), percentageFP("1.1")], + [percentageFP("0.75"), percentageFP("1.25")], + ); + + await usd.mint(billBroker.target, usdFP("115000")); + await perp.mint(billBroker.target, perpFP("100000")); + await usd.mint(await deployer.getAddress(), usdFP("250000")); + await perp.mint(await deployer.getAddress(), perpFP("250000")); + await usd.approve(billBroker.target, usdFP("25000")); + await perp.approve(billBroker.target, perpFP("25000")); + + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("115000")); + expect(r.perpBalance).to.eq(perpFP("100000")); + expect(r.usdPrice).to.eq(priceFP("1")); + expect(r.perpPrice).to.eq(priceFP("1.15")); + + return { deployer, feeCollector, usd, perp, pricingStrategy, billBroker }; + } + + describe("#computeUSDToPerpSwapAmt", function () { + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("115"), + [usdFP("115000"), perpFP("100000"), priceFP("1"), priceFP("1.15")], + [perpFP("100"), 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("100"), + [usdFP("110000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [perpFP("100"), 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("11111"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [perpFP("11111"), 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("11112"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [0n, 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("100"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("0.9")], + [perpFP("111.111111"), 0n, 0n], + ); + }); + + describe("when fees are set", async function () { + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("115"), + [usdFP("115000"), perpFP("100000"), priceFP("1"), priceFP("1.15")], + [perpFP("95"), perpFP("5"), 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("100"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [perpFP("95"), perpFP("5"), 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("100"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("0.9")], + [perpFP("101.460470381"), perpFP("9.650640619"), 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("10000"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [perpFP("8491.666666667"), perpFP("1508.333333333"), 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("20000"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [0n, 0n, 0n], + ); + }); + }); + + describe("when protocol fees are set", async function () { + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("115"), + [usdFP("115000"), perpFP("100000"), priceFP("1"), priceFP("1.15")], + [perpFP("95"), perpFP("4.5"), perpFP("0.5")], + ); + }); + }); + + describe("when the pool has only usd", function () { + it("should revert", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + + await billBroker.updateARBounds([0n, ethers.MaxUint256], [0n, ethers.MaxUint256]); + await usd.approve(billBroker.target, usdFP("115000")); + await billBroker.swapUSDForPerps(usdFP("115000"), 0n); + expect(await perp.balanceOf(billBroker.target)).to.eq(0n); + + await expect( + billBroker[ + "computeUSDToPerpSwapAmt(uint256,(uint256,uint256,uint256,uint256))" + ](usdFP("100"), [usdFP("100000"), 0n, priceFP("1"), priceFP("1")]), + ).to.be.reverted; + }); + }); + + describe("when the pool has only perps", function () { + it("should return the swap amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + + await billBroker.updateARBounds([0n, ethers.MaxUint256], [0n, ethers.MaxUint256]); + await perp.approve(billBroker.target, perpFP("100000")); + await billBroker.swapPerpsForUSD(perpFP("100000"), 0n); + expect(await usd.balanceOf(billBroker.target)).to.eq(0n); + + await checkUSDToPerpSwapAmt( + billBroker, + usdFP("100"), + [0n, perpFP("100000"), priceFP("1"), priceFP("1")], + [perpFP("100"), 0n, 0n], + ); + }); + }); + }); + + describe("#computePerpToUSDSwapAmt", function () { + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("100"), + [usdFP("115000"), perpFP("100000"), priceFP("1"), priceFP("1.15")], + [usdFP("115"), 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("100"), + [usdFP("110000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [usdFP("100"), 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("14285"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [usdFP("14285"), 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("14286"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [0n, 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("100"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("0.9")], + [usdFP("90"), 0n, 0n], + ); + }); + + describe("when fees are set", async function () { + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("100"), + [usdFP("115000"), perpFP("100000"), priceFP("1"), priceFP("1.15")], + [usdFP("103.5"), usdFP("11.5"), 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("100"), + [usdFP("110000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [usdFP("90"), usdFP("10"), 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("14285"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [usdFP("11142.474991"), usdFP("3142.525009"), 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("14286"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [0n, 0n, 0n], + ); + }); + + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("100"), + [usdFP("100000"), perpFP("100000"), priceFP("1"), priceFP("0.9")], + [usdFP("81"), usdFP("9"), 0n], + ); + }); + }); + + describe("when protocol fees are set", async function () { + it("should return the perp amount and fees", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("100"), + [usdFP("110000"), perpFP("100000"), priceFP("1"), priceFP("1")], + [usdFP("90"), usdFP("9"), usdFP("1")], + ); + }); + }); + + describe("when the pool has only usd", function () { + it("should return the swap amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await billBroker.updateARBounds([0n, ethers.MaxUint256], [0n, ethers.MaxUint256]); + await usd.approve(billBroker.target, usdFP("115000")); + await billBroker.swapUSDForPerps(usdFP("115000"), 0n); + expect(await perp.balanceOf(billBroker.target)).to.eq(0n); + + await checkPerpTpUSDSwapAmt( + billBroker, + perpFP("100"), + [usdFP("100000"), 0n, priceFP("1"), priceFP("1")], + [usdFP("100"), 0n, 0n], + ); + }); + }); + + describe("when the pool has only perps", function () { + it("should return the swap amount", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await billBroker.updateARBounds([0n, ethers.MaxUint256], [0n, ethers.MaxUint256]); + await perp.approve(billBroker.target, perpFP("100000")); + await billBroker.swapPerpsForUSD(perpFP("100000"), 0n); + expect(await usd.balanceOf(billBroker.target)).to.eq(0n); + + await expect( + billBroker[ + "computePerpToUSDSwapAmt(uint256,(uint256,uint256,uint256,uint256))" + ](perpFP("100"), [0n, perpFP("100000"), priceFP("1"), priceFP("1")]), + ).to.be.reverted; + }); + }); + }); + + describe("#swapUSDForPerps", function () { + describe("when paused", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.pause(); + await expect(billBroker.swapUSDForPerps(usdFP("115"), perpFP("90"))).to.be + .reverted; + }); + }); + describe("when swap amount is zero", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect(billBroker.swapUSDForPerps(0n, 0n)).to.be.revertedWithCustomError( + billBroker, + "UnacceptableSwap", + ); + }); + }); + + describe("when slippage is too high", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect( + billBroker.swapUSDForPerps(usdFP("115"), perpFP("100.01")), + ).to.be.revertedWithCustomError(billBroker, "SlippageTooHigh"); + }); + }); + + describe("when oracle price is unreliable", function () { + it("should revert", async function () { + const { billBroker, pricingStrategy } = await loadFixture(setupContracts); + await pricingStrategy.mockMethod("perpPrice()", [0n, false]); + await expect( + billBroker.swapUSDForPerps(usdFP("115"), perpFP("100")), + ).to.be.revertedWithCustomError(billBroker, "UnreliablePrice"); + }); + it("should revert", async function () { + const { billBroker, pricingStrategy } = await loadFixture(setupContracts); + await pricingStrategy.mockMethod("usdPrice()", [0n, false]); + await expect( + billBroker.swapUSDForPerps(usdFP("115"), perpFP("100")), + ).to.be.revertedWithCustomError(billBroker, "UnreliablePrice"); + }); + }); + + describe("stable swap", function () { + it("should transfer usd from the user", async function () { + const { billBroker, deployer, usd } = await loadFixture(setupContracts); + await expect(() => + billBroker.swapUSDForPerps(usdFP("115"), perpFP("100")), + ).to.changeTokenBalance(usd, deployer, usdFP("-115")); + }); + it("should transfer perps to the user", async function () { + const { billBroker, deployer, perp } = await loadFixture(setupContracts); + await expect(() => + billBroker.swapUSDForPerps(usdFP("115"), perpFP("100")), + ).to.changeTokenBalance(perp, deployer, perpFP("100")); + }); + it("should increase the reserve ar", async function () { + const { billBroker } = await loadFixture(setupContracts); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1")); + await billBroker.swapUSDForPerps(usdFP("115"), perpFP("100")); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1.002002002002002002")); + }); + it("should update the reserve", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.swapUSDForPerps(usdFP("115"), perpFP("100")); + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("115115")); + expect(r.perpBalance).to.eq(perpFP("99900")); + }); + }); + + describe("stable swap with fees", function () { + it("should transfer usd from the user", async function () { + const { billBroker, deployer, usd } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await expect(() => + billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")), + ).to.changeTokenBalance(usd, deployer, usdFP("-115")); + }); + it("should transfer perps to the user", async function () { + const { billBroker, deployer, perp } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await expect(() => + billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")), + ).to.changeTokenBalance(perp, deployer, perpFP("95")); + }); + it("should increase the reserve ar", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1")); + await billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1.001951854261548471")); + }); + it("should update the reserve", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")); + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("115115")); + expect(r.perpBalance).to.eq(perpFP("99905")); + }); + }); + + describe("stable swap with protocol fees", function () { + it("should transfer usd from the user", async function () { + const { billBroker, deployer, usd } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await expect(() => + billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")), + ).to.changeTokenBalance(usd, deployer, usdFP("-115")); + }); + it("should transfer perps to the user", async function () { + const { billBroker, deployer, feeCollector, perp } = await loadFixture( + setupContracts, + ); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await billBroker + .connect(deployer) + .transferOwnership(await feeCollector.getAddress()); + await expect(() => + billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")), + ).to.changeTokenBalance(perp, deployer, perpFP("95")); + }); + it("should transfer protocol fee to the owner", async function () { + const { billBroker, perp, feeCollector } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await billBroker.transferOwnership(await feeCollector.getAddress()); + await expect(() => + billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")), + ).to.changeTokenBalance(perp, feeCollector, perpFP("0.5")); + }); + it("should increase the reserve ar", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1")); + await billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1.001956868809713276")); + }); + it("should update the reserve", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await billBroker.swapUSDForPerps(usdFP("115"), perpFP("95")); + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("115115")); + expect(r.perpBalance).to.eq(perpFP("99904.5")); + }); + }); + + describe("when swap amount pushes system outside soft bound", async function () { + it("should transfer usd from the user", async function () { + const { billBroker, deployer, usd } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await expect(() => + billBroker.swapUSDForPerps(usdFP("3795"), perpFP("3130")), + ).to.changeTokenBalance(usd, deployer, usdFP("-3795")); + }); + it("should transfer perps to the user", async function () { + const { billBroker, deployer, perp } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await expect(() => + billBroker.swapUSDForPerps(usdFP("3795"), perpFP("3130")), + ).to.changeTokenBalance(perp, deployer, perpFP("3135")); + }); + + it("should increase the reserve ar", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1")); + await billBroker.swapUSDForPerps(usdFP("3795"), perpFP("3130")); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1.066432664016930779")); + }); + it("should update the reserve", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await billBroker.swapUSDForPerps(usdFP("3795"), perpFP("3130")); + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("118795")); + expect(r.perpBalance).to.eq(perpFP("96865")); + }); + }); + + describe("when swap amount pushes system outside hard bound", async function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateARBounds( + [percentageFP("0.8"), percentageFP("1")], + [percentageFP("0.75"), percentageFP("1.05")], + ); + await updateFees(billBroker, { + usdToPerpSwapFeePercs: { + lower: percentageFP("0.05"), + upper: percentageFP("0.5"), + }, + }); + await expect( + billBroker.swapUSDForPerps(usdFP("5000"), perpFP("4000")), + ).to.be.revertedWithCustomError(billBroker, "UnacceptableSwap"); + }); + }); + + describe("when the pool has only usd", function () { + it("should revert", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await billBroker.updateARBounds([0n, ethers.MaxUint256], [0n, ethers.MaxUint256]); + await usd.approve(billBroker.target, usdFP("115000")); + await billBroker.swapUSDForPerps(usdFP("115000"), 0n); + expect(await perp.balanceOf(billBroker.target)).to.eq(0n); + + await usd.approve(billBroker.target, usdFP("115")); + await expect(billBroker.swapUSDForPerps(usdFP("115"), perpFP("0"))).to.be + .reverted; + }); + }); + + describe("when the pool has only perps", function () { + it("should execute swap", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await billBroker.updateARBounds([0n, ethers.MaxUint256], [0n, ethers.MaxUint256]); + await perp.approve(billBroker.target, perpFP("100000")); + await billBroker.swapPerpsForUSD(perpFP("100000"), 0n); + expect(await usd.balanceOf(billBroker.target)).to.eq(0n); + + await usd.approve(billBroker.target, usdFP("115")); + await expect(() => + billBroker.swapUSDForPerps(usdFP("115"), perpFP("0")), + ).to.changeTokenBalance(perp, deployer, perpFP("100")); + }); + }); + }); + + describe("#swapPerpsForUSD", function () { + describe("when paused", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.pause(); + await expect(billBroker.swapPerpsForUSD(perpFP("100"), usdFP("100"))).to.be + .reverted; + }); + }); + describe("when swap amount is zero", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect(billBroker.swapPerpsForUSD(0n, 0n)).to.be.revertedWithCustomError( + billBroker, + "UnacceptableSwap", + ); + }); + }); + + describe("when slippage is too high", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await expect( + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("116")), + ).to.be.revertedWithCustomError(billBroker, "SlippageTooHigh"); + }); + }); + + describe("when oracle price is unreliable", function () { + it("should revert", async function () { + const { billBroker, pricingStrategy } = await loadFixture(setupContracts); + await pricingStrategy.mockMethod("perpPrice()", [0n, false]); + await expect( + billBroker.swapPerpsForUSD(perpFP("115"), usdFP("100")), + ).to.be.revertedWithCustomError(billBroker, "UnreliablePrice"); + }); + it("should revert", async function () { + const { billBroker, pricingStrategy } = await loadFixture(setupContracts); + await pricingStrategy.mockMethod("usdPrice()", [0n, false]); + await expect( + billBroker.swapPerpsForUSD(perpFP("115"), usdFP("100")), + ).to.be.revertedWithCustomError(billBroker, "UnreliablePrice"); + }); + }); + + describe("stable swap", function () { + it("should transfer perps from the user", async function () { + const { billBroker, deployer, perp } = await loadFixture(setupContracts); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("115")), + ).to.changeTokenBalance(perp, deployer, perpFP("-100")); + }); + it("should transfer usd to the user", async function () { + const { billBroker, deployer, usd } = await loadFixture(setupContracts); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("115")), + ).to.changeTokenBalance(usd, deployer, usdFP("115")); + }); + + it("should decrease the reserve ar", async function () { + const { billBroker } = await loadFixture(setupContracts); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1")); + await billBroker.swapPerpsForUSD(perpFP("100"), usdFP("115")); + expect(await assetRatio(billBroker)).to.eq(percentageFP("0.998001998001998001")); + }); + it("should update the reserve", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.swapPerpsForUSD(perpFP("100"), usdFP("115")); + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("114885")); + expect(r.perpBalance).to.eq(perpFP("100100")); + }); + }); + + describe("stable swap with fees", function () { + it("should transfer perps from the user", async function () { + const { billBroker, deployer, perp } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")), + ).to.changeTokenBalance(perp, deployer, perpFP("-100")); + }); + it("should transfer usd to the user", async function () { + const { billBroker, deployer, usd } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")), + ).to.changeTokenBalance(usd, deployer, usdFP("103.5")); + }); + it("should increase the reserve ar", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1")); + await billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")); + expect(await assetRatio(billBroker)).to.eq(percentageFP("0.998101898101898101")); + }); + it("should update the reserve", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")); + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("114896.5")); + expect(r.perpBalance).to.eq(perpFP("100100")); + }); + }); + + describe("stable swap with protocol fees", function () { + it("should transfer perps from the user", async function () { + const { billBroker, deployer, perp } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")), + ).to.changeTokenBalance(perp, deployer, perpFP("-100")); + }); + it("should transfer usd to the user", async function () { + const { billBroker, deployer, usd, feeCollector } = await loadFixture( + setupContracts, + ); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await billBroker.transferOwnership(await feeCollector.getAddress()); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")), + ).to.changeTokenBalance(usd, deployer, usdFP("103.5")); + }); + it("should transfer protocol fee to the owner", async function () { + const { billBroker, usd, feeCollector } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await billBroker.transferOwnership(await feeCollector.getAddress()); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")), + ).to.changeTokenBalance(usd, feeCollector, usdFP("1.15")); + }); + it("should increase the reserve ar", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1")); + await billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")); + expect(await assetRatio(billBroker)).to.eq(percentageFP("0.998091908091908091")); + }); + it("should update the reserve", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + protocolSwapSharePerc: percentageFP("0.1"), + }); + await billBroker.swapPerpsForUSD(perpFP("100"), usdFP("103")); + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("114895.35")); + expect(r.perpBalance).to.eq(perpFP("100100")); + }); + }); + + describe("when swap pushes system outside soft bound", function () { + it("should transfer perps from the user", async function () { + const { billBroker, deployer, perp } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("3600"), usdFP("3700")), + ).to.changeTokenBalance(perp, deployer, perpFP("-3600")); + }); + it("should transfer usd to the user", async function () { + const { billBroker, deployer, usd } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("3600"), usdFP("3000")), + ).to.changeTokenBalance(usd, deployer, usdFP("3726")); + }); + it("should decrease the reserve ar", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + expect(await assetRatio(billBroker)).to.eq(percentageFP("1")); + await billBroker.swapPerpsForUSD(perpFP("3600"), usdFP("3700")); + expect(await assetRatio(billBroker)).to.eq(percentageFP("0.933976833976833976")); + }); + it("should update the reserve", async function () { + const { billBroker } = await loadFixture(setupContracts); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await billBroker.swapPerpsForUSD(perpFP("3600"), usdFP("3700")); + const r = await reserveState(billBroker); + expect(r.usdBalance).to.eq(usdFP("111274")); + expect(r.perpBalance).to.eq(perpFP("103600")); + }); + }); + + describe("when swap pushes system outside hard bound", function () { + it("should revert", async function () { + const { billBroker } = await loadFixture(setupContracts); + await billBroker.updateARBounds( + [percentageFP("1"), percentageFP("1.1")], + [percentageFP("0.95"), percentageFP("1.25")], + ); + await updateFees(billBroker, { + perpToUSDSwapFeePercs: { + lower: percentageFP("0.1"), + upper: percentageFP("0.5"), + }, + }); + await expect( + billBroker.swapPerpsForUSD(perpFP("5000"), usdFP("4000")), + ).to.be.revertedWithCustomError(billBroker, "UnacceptableSwap"); + }); + }); + + describe("when the pool has only usd", function () { + it("should execute swap", async function () { + const { billBroker, usd, perp, deployer } = await loadFixture(setupContracts); + await billBroker.updateARBounds([0n, ethers.MaxUint256], [0n, ethers.MaxUint256]); + await usd.approve(billBroker.target, usdFP("115000")); + await billBroker.swapUSDForPerps(usdFP("115000"), 0n); + expect(await perp.balanceOf(billBroker.target)).to.eq(0n); + + await perp.approve(billBroker.target, perpFP("100")); + await expect(() => + billBroker.swapPerpsForUSD(perpFP("100"), usdFP("0")), + ).to.changeTokenBalance(usd, deployer, usdFP("115")); + }); + }); + + describe("when the pool has only perps", function () { + it("should revert", async function () { + const { billBroker, usd, perp } = await loadFixture(setupContracts); + await billBroker.updateARBounds([0n, ethers.MaxUint256], [0n, ethers.MaxUint256]); + await perp.approve(billBroker.target, perpFP("100000")); + await billBroker.swapPerpsForUSD(perpFP("100000"), 0n); + expect(await usd.balanceOf(billBroker.target)).to.eq(0n); + + await perp.approve(billBroker.target, perpFP("100")); + await expect(billBroker.swapPerpsForUSD(perpFP("100"), usdFP("0"))).to.be + .reverted; + }); + }); + }); +}); diff --git a/spot-vaults/test/SpotAppraiser.ts b/spot-vaults/test/SpotAppraiser.ts new file mode 100644 index 00000000..ab281b7f --- /dev/null +++ b/spot-vaults/test/SpotAppraiser.ts @@ -0,0 +1,242 @@ +import { ethers } from "hardhat"; +import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers"; +import { expect } from "chai"; +import { oracleAnsFP, perpFP, percentageFP, priceFP, DMock } from "./helpers"; + +const nowTS = () => parseInt(Date.now() / 1000); + +describe("SpotAppraiser", function () { + async function setupContracts() { + const accounts = await ethers.getSigners(); + const deployer = accounts[0]; + + const amplTargetOracle = new DMock("MedianOracle"); + await amplTargetOracle.deploy(); + await amplTargetOracle.mockMethod("getData()", [priceFP("1.15"), true]); + await amplTargetOracle.mockMethod("DECIMALS()", [18]); + + const policy = new DMock("UFragmentsPolicy"); + await policy.deploy(); + await policy.mockMethod("cpiOracle()", [amplTargetOracle.target]); + + const ampl = new DMock("UFragments"); + await ampl.deploy(); + await ampl.mockMethod("decimals()", [9]); + await ampl.mockMethod("monetaryPolicy()", [policy.target]); + + const bond = new DMock("BondController"); + await bond.deploy(); + await bond.mockMethod("isMature()", [false]); + await bond.mockMethod("trancheCount()", [2]); + await bond.mockMethod("totalDebt()", [perpFP("500000")]); + await ampl.mockCall("balanceOf(address)", [bond.target], [perpFP("500000")]); + + const tranche = new DMock("Tranche"); + await tranche.deploy(); + await tranche.mockMethod("bond()", [bond.target]); + await tranche.mockMethod("totalSupply()", [perpFP("100000")]); + await bond.mockCall("tranches(uint256)", [0], [tranche.target, 200]); + await bond.mockCall("tranches(uint256)", [1], [ethers.ZeroAddress, 800]); + + const spot = new DMock("PerpetualTranche"); + await spot.deploy(); + await spot.mockMethod("underlying()", [ampl.target]); + await spot.mockMethod("getTVL()", [perpFP("1000000")]); + await spot.mockMethod("totalSupply()", [perpFP("1000000")]); + await spot.mockMethod("deviationRatio()", [oracleAnsFP("1.5")]); + await spot.mockMethod("getReserveCount()", [2]); + await spot.mockCall("getReserveAt(uint256)", [0], [ampl.target]); + await spot.mockCall("getReserveAt(uint256)", [1], [tranche.target]); + await ampl.mockCall("balanceOf(address)", [spot.target], [perpFP("1000")]); + + const PriceOracle = await ethers.getContractFactory("MockCLOracle"); + const usdPriceOrcle = await PriceOracle.deploy(); + await usdPriceOrcle.mockLastRoundData(oracleAnsFP("1"), nowTS()); + + const SpotAppraiser = await ethers.getContractFactory("SpotAppraiser"); + const strategy = await SpotAppraiser.deploy( + spot.target, + usdPriceOrcle.target, + amplTargetOracle.target, + ); + return { + deployer, + ampl, + spot, + usdPriceOrcle, + amplTargetOracle, + bond, + tranche, + strategy, + }; + } + + describe("init", function () { + it("should initial params", async function () { + const { deployer, strategy, ampl, spot, usdPriceOrcle, amplTargetOracle } = + await loadFixture(setupContracts); + expect(await strategy.AMPL()).to.eq(ampl.target); + expect(await strategy.SPOT()).to.eq(spot.target); + expect(await strategy.USD_ORACLE()).to.eq(usdPriceOrcle.target); + expect(await strategy.AMPL_CPI_ORACLE()).to.eq(amplTargetOracle.target); + expect(await strategy.AMPL_DUST_AMT()).to.eq(perpFP("25000")); + expect(await strategy.minSPOTDR()).to.eq(percentageFP("0.8")); + expect(await strategy.minSeniorCDR()).to.eq(percentageFP("1.1")); + expect(await strategy.owner()).to.eq(await deployer.getAddress()); + expect(await strategy.decimals()).to.eq(18); + }); + }); + + describe("#updateMinSPOTDR", function () { + describe("when triggered by non-owner", function () { + it("should revert", async function () { + const { strategy } = await loadFixture(setupContracts); + await strategy.renounceOwnership(); + await expect(strategy.updateMinSPOTDR(percentageFP("1.15"))).to.be.revertedWith( + "Ownable: caller is not the owner", + ); + }); + }); + + describe("when triggered by owner", function () { + it("should update value", async function () { + const { strategy } = await loadFixture(setupContracts); + await strategy.updateMinSPOTDR(percentageFP("1.15")); + expect(await strategy.minSPOTDR()).to.eq(percentageFP("1.15")); + }); + }); + }); + + describe("#updateMinPerpCollateralCDR", function () { + describe("when triggered by non-owner", function () { + it("should revert", async function () { + const { strategy } = await loadFixture(setupContracts); + await strategy.renounceOwnership(); + await expect( + strategy.updateMinPerpCollateralCDR(percentageFP("1.25")), + ).to.be.revertedWith("Ownable: caller is not the owner"); + }); + }); + + describe("when cdr is invalid", function () { + it("should revert", async function () { + const { strategy } = await loadFixture(setupContracts); + await expect( + strategy.updateMinPerpCollateralCDR(percentageFP("0.9")), + ).to.be.revertedWithCustomError(strategy, "InvalidSeniorCDRBound"); + }); + }); + + describe("when triggered by owner", function () { + it("should update value", async function () { + const { strategy } = await loadFixture(setupContracts); + await strategy.updateMinPerpCollateralCDR(percentageFP("1.25")); + expect(await strategy.minSeniorCDR()).to.eq(percentageFP("1.25")); + }); + }); + }); + + describe("#usdPrice", function () { + describe("when data is stale", function () { + it("should return invalid", async function () { + const { strategy, usdPriceOrcle } = await loadFixture(setupContracts); + await usdPriceOrcle.mockLastRoundData(oracleAnsFP("1"), nowTS() - 50 * 3600); + const p = await strategy.usdPrice(); + expect(p[0]).to.eq(priceFP("1")); + expect(p[1]).to.eq(false); + }); + }); + + describe("when oracle price is below thresh", function () { + it("should return invalid", async function () { + const { strategy, usdPriceOrcle } = await loadFixture(setupContracts); + await usdPriceOrcle.mockLastRoundData(oracleAnsFP("0.98"), nowTS()); + const p = await strategy.usdPrice(); + expect(p[0]).to.eq(priceFP("1")); + expect(p[1]).to.eq(false); + }); + }); + + it("should return price", async function () { + const { strategy } = await loadFixture(setupContracts); + const p = await strategy.usdPrice(); + expect(p[0]).to.eq(priceFP("1")); + expect(p[1]).to.eq(true); + }); + }); + + describe("#perpPrice", function () { + describe("when AMPL target data is invalid", function () { + it("should return invalid", async function () { + const { strategy, amplTargetOracle } = await loadFixture(setupContracts); + await amplTargetOracle.mockMethod("getData()", [priceFP("1.2"), false]); + const p = await strategy.perpPrice.staticCall(); + expect(p[0]).to.eq(priceFP("1.2")); + expect(p[1]).to.eq(false); + }); + }); + + describe("when balancer DR is too low", function () { + it("should return invalid", async function () { + const { strategy, spot } = await loadFixture(setupContracts); + await spot.mockMethod("deviationRatio()", [oracleAnsFP("0.79999")]); + const p = await strategy.perpPrice.staticCall(); + expect(p[0]).to.eq(priceFP("1.15")); + expect(p[1]).to.eq(false); + }); + }); + + describe("when spot senior cdr is too low", function () { + it("should return invalid", async function () { + const { strategy, ampl, bond } = await loadFixture(setupContracts); + await ampl.mockCall("balanceOf(address)", [bond.target], [perpFP("109999")]); + const p = await strategy.perpPrice.staticCall(); + expect(p[0]).to.eq(priceFP("1.15")); + expect(p[1]).to.eq(false); + }); + it("should return invalid", async function () { + const { strategy, bond } = await loadFixture(setupContracts); + await bond.mockMethod("isMature()", [true]); + const p = await strategy.perpPrice.staticCall(); + expect(p[0]).to.eq(priceFP("1.15")); + expect(p[1]).to.eq(false); + }); + }); + + describe("when spot has mature AMPL", function () { + it("should return invalid", async function () { + const { strategy, ampl, spot } = await loadFixture(setupContracts); + await ampl.mockCall("balanceOf(address)", [spot.target], [perpFP("25001")]); + const p = await strategy.perpPrice.staticCall(); + expect(p[0]).to.eq(priceFP("1.15")); + expect(p[1]).to.eq(false); + }); + }); + + it("should return price", async function () { + const { strategy } = await loadFixture(setupContracts); + const p = await strategy.perpPrice.staticCall(); + expect(p[0]).to.eq(priceFP("1.15")); + expect(p[1]).to.eq(true); + }); + + describe("when debasement/enrichment multiplier is not 1", function () { + it("should return price", async function () { + const { strategy, spot } = await loadFixture(setupContracts); + await spot.mockMethod("getTVL()", [perpFP("1500000")]); + await spot.mockMethod("totalSupply()", [perpFP("1000000")]); + const p = await strategy.perpPrice.staticCall(); + expect(p[0]).to.eq(priceFP("1.725")); + expect(p[1]).to.eq(true); + }); + it("should return price", async function () { + const { strategy, spot } = await loadFixture(setupContracts); + await spot.mockMethod("getTVL()", [perpFP("900000")]); + await spot.mockMethod("totalSupply()", [perpFP("1000000")]); + const p = await strategy.perpPrice.staticCall(); + expect(p[0]).to.eq(priceFP("1.035")); + expect(p[1]).to.eq(true); + }); + }); + }); +}); diff --git a/spot-vaults/test/helpers.ts b/spot-vaults/test/helpers.ts new file mode 100644 index 00000000..2319d254 --- /dev/null +++ b/spot-vaults/test/helpers.ts @@ -0,0 +1,79 @@ +import { ethers } from "hardhat"; +import { Contract, ContractFactory } from "ethers"; + +const sciParseFloat = (a: string): BigInt => + a.includes("e") ? parseFloat(a).toFixed(18) : a; +export const usdFP = (a: string): BigInt => ethers.parseUnits(sciParseFloat(a), 6); +export const perpFP = (a: string): BigInt => ethers.parseUnits(sciParseFloat(a), 9); +export const percentageFP = (a: string): BigInt => + ethers.parseUnits(sciParseFloat(a), 18); +export const priceFP = (a: string): BigInt => ethers.parseUnits(sciParseFloat(a), 18); +export const lpAmtFP = (a: string): BigInt => ethers.parseUnits(sciParseFloat(a), 24); +export const oracleAnsFP = (a: string): BigInt => ethers.parseUnits(sciParseFloat(a), 8); + +export class DMock { + private refArtifact: string; + private refFactory: ContractFactory; + private contract: Contract | null = null; + private target: string | null = null; + + constructor(refArtifact: string) { + this.refArtifact = refArtifact; + } + + public async deploy(): Promise { + this.refFactory = await ethers.getContractFactory(this.refArtifact); + this.contract = await (await ethers.getContractFactory("DMock")).deploy(); + this.target = this.contract.target; + } + + public async mockMethod(methodFragment: string, returnValue: any = []): Promise { + if (!this.contract) { + await this.deploy(); + } + const methodFragmentObj = this.refFactory.interface.fragments.filter( + f => f.type === "function" && f.format("sighash") === methodFragment, + )[0]; + if (!methodFragmentObj) { + throw Error( + `Unkown function fragment ${methodFragment}, not part of the contract abi`, + ); + } + const encodedReturnValue = ethers.AbiCoder.defaultAbiCoder().encode( + methodFragmentObj.outputs, + returnValue, + ); + await this.contract.mockMethod(methodFragmentObj.selector, encodedReturnValue); + } + + public async mockCall( + methodFragment: string, + parameters: any, + returnValue: any = [], + ): Promise { + if (!this.contract) { + await this.deploy(); + } + const methodFragmentObj = this.refFactory.interface.fragments.filter( + f => f.type === "function" && f.format("sighash") === methodFragment, + )[0]; + if (!methodFragmentObj) { + throw Error( + `Unkown function fragment ${methodFragment}, not part of the contract abi`, + ); + } + const encodedData = this.refFactory.interface.encodeFunctionData( + methodFragmentObj, + parameters, + ); + await this.contract.mockCall( + encodedData, + ethers.AbiCoder.defaultAbiCoder().encode(methodFragmentObj.outputs, returnValue), + ); + } + + public async staticCall(methodFragment: string, parameters: any = []): Promise { + const mock = this.refFactory.attach(this.contract.target); + return mock[methodFragment].staticCall(...parameters); + } +} diff --git a/spot-vaults/tsconfig.json b/spot-vaults/tsconfig.json new file mode 100644 index 00000000..574e785c --- /dev/null +++ b/spot-vaults/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + } +} diff --git a/yarn.lock b/yarn.lock index b576ca51..ed55e4b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,14 +5,21 @@ __metadata: version: 6 cacheKey: 8 -"@aashutoshrathi/word-wrap@npm:^1.2.3": - version: 1.2.6 - resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" - checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd +"@adraffy/ens-normalize@npm:1.10.0": + version: 1.10.0 + resolution: "@adraffy/ens-normalize@npm:1.10.0" + checksum: af0540f963a2632da2bbc37e36ea6593dcfc607b937857133791781e246d47f870d5e3d21fa70d5cfe94e772c284588c81ea3f5b7f4ea8fbb824369444e4dbcb + languageName: node + linkType: hard + +"@adraffy/ens-normalize@npm:1.10.1": + version: 1.10.1 + resolution: "@adraffy/ens-normalize@npm:1.10.1" + checksum: 0836f394ea256972ec19a0b5e78cb7f5bcdfd48d8a32c7478afc94dd53ae44c04d1aa2303d7f3077b4f3ac2323b1f557ab9188e8059978748fdcd83e04a80dcc languageName: node linkType: hard -"@ampleforthorg/spot-contracts@workspace:spot-contracts": +"@ampleforthorg/spot-contracts@workspace:spot-contracts, @ampleforthorg/spot-contracts@workspaces:*": version: 0.0.0-use.local resolution: "@ampleforthorg/spot-contracts@workspace:spot-contracts" dependencies: @@ -71,6 +78,22 @@ __metadata: languageName: unknown linkType: soft +"@ampleforthorg/spot-staking-subgraph@workspace:spot-staking-subgraph": + version: 0.0.0-use.local + resolution: "@ampleforthorg/spot-staking-subgraph@workspace:spot-staking-subgraph" + dependencies: + "@graphprotocol/graph-cli": ^0.21.1 + "@graphprotocol/graph-ts": ^0.20.0 + "@typescript-eslint/eslint-plugin": ^2.0.0 + "@typescript-eslint/parser": ^2.0.0 + eslint: ^6.2.2 + eslint-config-prettier: ^6.1.0 + mustache: ^4.2.0 + prettier: ^1.18.2 + typescript: ^3.5.2 + languageName: unknown + linkType: soft + "@ampleforthorg/spot-subgraph@workspace:spot-subgraph": version: 0.0.0-use.local resolution: "@ampleforthorg/spot-subgraph@workspace:spot-subgraph" @@ -87,6 +110,66 @@ __metadata: languageName: unknown linkType: soft +"@ampleforthorg/spot-vaults@workspace:spot-vaults": + version: 0.0.0-use.local + resolution: "@ampleforthorg/spot-vaults@workspace:spot-vaults" + dependencies: + "@ampleforthorg/spot-contracts": "workspaces:*" + "@ethersproject/abi": ^5.6.4 + "@ethersproject/abstract-provider": ^5.7.0 + "@ethersproject/abstract-signer": ^5.7.0 + "@ethersproject/bytes": ^5.6.1 + "@ethersproject/providers": ^5.6.8 + "@nomicfoundation/hardhat-chai-matchers": latest + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@nomicfoundation/hardhat-ignition-ethers": ^0.15.0 + "@nomicfoundation/hardhat-network-helpers": ^1.0.0 + "@nomicfoundation/hardhat-toolbox": latest + "@nomicfoundation/hardhat-verify": latest + "@nomiclabs/hardhat-waffle": ^2.0.6 + "@openzeppelin/contracts": 4.9.6 + "@openzeppelin/contracts-upgradeable": 4.7.3 + "@openzeppelin/hardhat-upgrades": ^3.0.4 + "@openzeppelin/upgrades-core": latest + "@typechain/ethers-v6": ^0.5.1 + "@typechain/hardhat": ^6.1.2 + "@types/chai": ^4.3.1 + "@types/mocha": ^9.1.1 + "@types/node": ^18.6.1 + "@types/sinon-chai": ^3.2.12 + "@typescript-eslint/eslint-plugin": ^5.0.0 + "@typescript-eslint/parser": ^5.0.0 + ampleforth-contracts: "https://github.com/ampleforth/ampleforth-contracts#master" + chai: ^4.3.6 + dotenv: ^16.0.1 + eslint: ^8.20.0 + eslint-config-prettier: ^8.5.0 + eslint-config-standard: ^17.0.0 + eslint-plugin-import: ^2.26.0 + eslint-plugin-n: ^15.2.4 + eslint-plugin-no-only-tests: ^3.1.0 + eslint-plugin-node: ^11.1.0 + eslint-plugin-prettier: ^4.2.1 + eslint-plugin-promise: ^6.0.0 + eslint-plugin-unused-imports: ^3.0.0 + ethereum-waffle: latest + ethers: ^6.6.0 + ethers-v5: "npm:ethers@^5.7.0" + ganache-cli: latest + hardhat: ^2.22.1 + hardhat-gas-reporter: latest + lodash: ^4.17.21 + prettier: ^2.7.1 + prettier-plugin-solidity: ^1.0.0-dev.23 + solhint: ^3.3.7 + solidity-coverage: ^0.8.5 + tranche: "https://github.com/buttonwood-protocol/tranche.git#main" + ts-node: ^10.9.1 + typechain: ^8.1.0 + typescript: ^4.7.4 + languageName: unknown + linkType: soft + "@aws-crypto/sha256-js@npm:1.2.2": version: 1.2.2 resolution: "@aws-crypto/sha256-js@npm:1.2.2" @@ -110,12 +193,12 @@ __metadata: linkType: hard "@aws-sdk/types@npm:^3.1.0": - version: 3.502.0 - resolution: "@aws-sdk/types@npm:3.502.0" + version: 3.598.0 + resolution: "@aws-sdk/types@npm:3.598.0" dependencies: - "@smithy/types": ^2.9.1 - tslib: ^2.5.0 - checksum: 11dddc2c1fb7b601adba1df6339b68367a3c77fcdd298c7ceb42541c813ba777ffc9ddfbb68633f9fd9082c883edf1b2fe3139acdf822d7d423c0b5f76ce78dd + "@smithy/types": ^3.1.0 + tslib: ^2.6.2 + checksum: 9b2bd50d6935422dd1046e6eaa48c4c774d06aa1374bf4600a3af2c7a52432b5e25ec111cf49976b07b03d7cb5f4fa6fd44b7ce8a67dd0b3a4cee4abaf9e6fa5 languageName: node linkType: hard @@ -129,76 +212,38 @@ __metadata: linkType: hard "@babel/code-frame@npm:^7.0.0": - version: 7.23.5 - resolution: "@babel/code-frame@npm:7.23.5" + version: 7.24.7 + resolution: "@babel/code-frame@npm:7.24.7" dependencies: - "@babel/highlight": ^7.23.4 - chalk: ^2.4.2 - checksum: d90981fdf56a2824a9b14d19a4c0e8db93633fd488c772624b4e83e0ceac6039a27cd298a247c3214faa952bf803ba23696172ae7e7235f3b97f43ba278c569a + "@babel/highlight": ^7.24.7 + picocolors: ^1.0.0 + checksum: 830e62cd38775fdf84d612544251ce773d544a8e63df667728cc9e0126eeef14c6ebda79be0f0bc307e8318316b7f58c27ce86702e0a1f5c321d842eb38ffda4 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-validator-identifier@npm:7.22.20" - checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc +"@babel/helper-validator-identifier@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-identifier@npm:7.24.7" + checksum: 6799ab117cefc0ecd35cd0b40ead320c621a298ecac88686a14cffceaac89d80cdb3c178f969861bf5fa5e4f766648f9161ea0752ecfe080d8e89e3147270257 languageName: node linkType: hard -"@babel/highlight@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/highlight@npm:7.23.4" +"@babel/highlight@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/highlight@npm:7.24.7" dependencies: - "@babel/helper-validator-identifier": ^7.22.20 + "@babel/helper-validator-identifier": ^7.24.7 chalk: ^2.4.2 js-tokens: ^4.0.0 - checksum: 643acecdc235f87d925979a979b539a5d7d1f31ae7db8d89047269082694122d11aa85351304c9c978ceeb6d250591ccadb06c366f358ccee08bb9c122476b89 + picocolors: ^1.0.0 + checksum: 5cd3a89f143671c4ac129960024ba678b669e6fc673ce078030f5175002d1d3d52bc10b22c5b916a6faf644b5028e9a4bd2bb264d053d9b05b6a98690f1d46f1 languageName: node linkType: hard -"@chainsafe/as-sha256@npm:^0.3.1": - version: 0.3.1 - resolution: "@chainsafe/as-sha256@npm:0.3.1" - checksum: 58ea733be1657b0e31dbf48b0dba862da0833df34a81c1460c7352f04ce90874f70003cbf34d0afb9e5e53a33ee2d63a261a8b12462be85b2ba0a6f7f13d6150 - languageName: node - linkType: hard - -"@chainsafe/persistent-merkle-tree@npm:^0.4.2": - version: 0.4.2 - resolution: "@chainsafe/persistent-merkle-tree@npm:0.4.2" - dependencies: - "@chainsafe/as-sha256": ^0.3.1 - checksum: f9cfcb2132a243992709715dbd28186ab48c7c0c696f29d30857693cca5526bf753974a505ef68ffd5623bbdbcaa10f9083f4dd40bf99eb6408e451cc26a1a9e - languageName: node - linkType: hard - -"@chainsafe/persistent-merkle-tree@npm:^0.5.0": - version: 0.5.0 - resolution: "@chainsafe/persistent-merkle-tree@npm:0.5.0" - dependencies: - "@chainsafe/as-sha256": ^0.3.1 - checksum: 2c67203da776c79cd3a6132e2d672fe132393b2e63dc71604e3134acc8c0ec25cc5e431051545939ea0f7c5ff2066fb806b9e5cab974ca085d046226a1671f7d - languageName: node - linkType: hard - -"@chainsafe/ssz@npm:^0.10.0": - version: 0.10.2 - resolution: "@chainsafe/ssz@npm:0.10.2" - dependencies: - "@chainsafe/as-sha256": ^0.3.1 - "@chainsafe/persistent-merkle-tree": ^0.5.0 - checksum: 6bb70cf741d0a19dd0b28b3f6f067b96fa39f556e2eefa6ac745b21db9c3b3a8393dc3cca8ff4a6ce065ed71ddc3fb1b2b390a92004b9d01067c26e2558e5503 - languageName: node - linkType: hard - -"@chainsafe/ssz@npm:^0.9.2": - version: 0.9.4 - resolution: "@chainsafe/ssz@npm:0.9.4" - dependencies: - "@chainsafe/as-sha256": ^0.3.1 - "@chainsafe/persistent-merkle-tree": ^0.4.2 - case: ^1.6.3 - checksum: c6eaedeae9e5618b3c666ff4507a27647f665a8dcf17d5ca86da4ed4788c5a93868f256d0005467d184fdf35ec03f323517ec2e55ec42492d769540a2ec396bc +"@colors/colors@npm:1.5.0": + version: 1.5.0 + resolution: "@colors/colors@npm:1.5.0" + checksum: d64d5260bed1d5012ae3fc617d38d1afc0329fec05342f4e6b838f46998855ba56e0a73833f4a80fa8378c84810da254f76a8a19c39d038260dc06dc4e007425 languageName: node linkType: hard @@ -212,12 +257,10 @@ __metadata: linkType: hard "@defi-wonderland/smock@npm:^2.3.4": - version: 2.3.5 - resolution: "@defi-wonderland/smock@npm:2.3.5" + version: 2.4.0 + resolution: "@defi-wonderland/smock@npm:2.4.0" dependencies: - "@nomicfoundation/ethereumjs-evm": ^1.0.0-rc.3 - "@nomicfoundation/ethereumjs-util": ^8.0.0-rc.3 - "@nomicfoundation/ethereumjs-vm": ^6.0.0-rc.3 + "@nomicfoundation/ethereumjs-util": ^9.0.4 diff: ^5.0.0 lodash.isequal: ^4.5.0 lodash.isequalwith: ^4.4.0 @@ -229,8 +272,8 @@ __metadata: "@ethersproject/abstract-signer": ^5 "@nomiclabs/hardhat-ethers": ^2 ethers: ^5 - hardhat: ^2 - checksum: b3c408fb43cd7b02bf6f3b3a392758944ee4d4ad9d92a5bcb595b2bdf7ebe702d052b8631afba0b408e80185b1db22d655dc63feba82365f5f1f6786eb98d859 + hardhat: ^2.21.0 + checksum: 421f97cfa9a8f7bbdafc6521723f5ed0c3b7cd0462dc7d1a143a2de9cbdac46dd6acd7db619aa03a09d62695c5337fb17699259db2d5e4ddb530f5f55ef4ef30 languageName: node linkType: hard @@ -266,9 +309,9 @@ __metadata: linkType: hard "@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.6.1": - version: 4.10.0 - resolution: "@eslint-community/regexpp@npm:4.10.0" - checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b + version: 4.10.1 + resolution: "@eslint-community/regexpp@npm:4.10.1" + checksum: 1e04bc366fb8152c9266258cd25e3fded102f1d212a9476928e3cb98c48be645df6d676728d1c596053992fb9134879fe0de23c9460035b342cceb22d3af1776 languageName: node linkType: hard @@ -289,10 +332,23 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.56.0": - version: 8.56.0 - resolution: "@eslint/js@npm:8.56.0" - checksum: 5804130574ef810207bdf321c265437814e7a26f4e6fac9b496de3206afd52f533e09ec002a3be06cd9adcc9da63e727f1883938e663c4e4751c007d5b58e539 +"@eslint/js@npm:8.57.0": + version: 8.57.0 + resolution: "@eslint/js@npm:8.57.0" + checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb + languageName: node + linkType: hard + +"@ethereum-waffle/chai@npm:4.0.10": + version: 4.0.10 + resolution: "@ethereum-waffle/chai@npm:4.0.10" + dependencies: + "@ethereum-waffle/provider": 4.0.5 + debug: ^4.3.4 + json-bigint: ^1.0.0 + peerDependencies: + ethers: "*" + checksum: 11a2fa51224e98ee4cbf346a731be68b17b3c172e68391b25fc0027545d7477dbeca916bbd10be0fa9de612eaed6115a0578f9d3e312e9fe95af2b7791fd0981 languageName: node linkType: hard @@ -306,6 +362,25 @@ __metadata: languageName: node linkType: hard +"@ethereum-waffle/compiler@npm:4.0.3": + version: 4.0.3 + resolution: "@ethereum-waffle/compiler@npm:4.0.3" + dependencies: + "@resolver-engine/imports": ^0.3.3 + "@resolver-engine/imports-fs": ^0.3.3 + "@typechain/ethers-v5": ^10.0.0 + "@types/mkdirp": ^0.5.2 + "@types/node-fetch": ^2.6.1 + mkdirp: ^0.5.1 + node-fetch: ^2.6.7 + peerDependencies: + ethers: "*" + solc: "*" + typechain: ^8.0.0 + checksum: ec7839b0f79a40a77fa05bb6941e00b2b3b1e0aa5514a617400c988b302bbbc5e9373b25ba52c7319bb00b83923dce42011384883c7a234c52f8c44eb5b571fc + languageName: node + linkType: hard + "@ethereum-waffle/compiler@npm:^3.4.4": version: 3.4.4 resolution: "@ethereum-waffle/compiler@npm:3.4.4" @@ -325,6 +400,17 @@ __metadata: languageName: node linkType: hard +"@ethereum-waffle/ens@npm:4.0.3": + version: 4.0.3 + resolution: "@ethereum-waffle/ens@npm:4.0.3" + peerDependencies: + "@ensdomains/ens": ^0.4.4 + "@ensdomains/resolver": ^0.2.4 + ethers: "*" + checksum: 84435c3dda78c416b332c481cfa9322f5bf06168d5887607d320cb30f20283ccde52eabd18adb5791485125d44d99ff7b5f84bd7bbdb1fde86465abb40a81966 + languageName: node + linkType: hard + "@ethereum-waffle/ens@npm:^3.4.4": version: 3.4.4 resolution: "@ethereum-waffle/ens@npm:3.4.4" @@ -336,6 +422,15 @@ __metadata: languageName: node linkType: hard +"@ethereum-waffle/mock-contract@npm:4.0.4": + version: 4.0.4 + resolution: "@ethereum-waffle/mock-contract@npm:4.0.4" + peerDependencies: + ethers: "*" + checksum: 45bea2ba4615a0bb81692c3d647ad39c2c37fcf250b577aeb6c5aad03fd4d0912d8d9ef5de638ab276ece1eb9ca1d09d23ed297d96da683fe34e0b01ba631da9 + languageName: node + linkType: hard + "@ethereum-waffle/mock-contract@npm:^3.4.4": version: 3.4.4 resolution: "@ethereum-waffle/mock-contract@npm:3.4.4" @@ -346,6 +441,20 @@ __metadata: languageName: node linkType: hard +"@ethereum-waffle/provider@npm:4.0.5": + version: 4.0.5 + resolution: "@ethereum-waffle/provider@npm:4.0.5" + dependencies: + "@ethereum-waffle/ens": 4.0.3 + "@ganache/ethereum-options": 0.1.4 + debug: ^4.3.4 + ganache: 7.4.3 + peerDependencies: + ethers: "*" + checksum: b1282ea28cbfba05343cc101bceab3f72fdd9ed391f7c7e0f252aead81aec46b6a0ab7d7ca8504e080e306d6554c21e5420765965d92ed5b303a12543dc85cf4 + languageName: node + linkType: hard + "@ethereum-waffle/provider@npm:^3.4.4": version: 3.4.4 resolution: "@ethereum-waffle/provider@npm:3.4.4" @@ -359,6 +468,67 @@ __metadata: languageName: node linkType: hard +"@ethereumjs/block@npm:^3.5.0, @ethereumjs/block@npm:^3.6.0, @ethereumjs/block@npm:^3.6.2": + version: 3.6.3 + resolution: "@ethereumjs/block@npm:3.6.3" + dependencies: + "@ethereumjs/common": ^2.6.5 + "@ethereumjs/tx": ^3.5.2 + ethereumjs-util: ^7.1.5 + merkle-patricia-tree: ^4.2.4 + checksum: d08c78134d15bc09c08b9a355ab736faa0f6b04ab87d2962e60df9c8bf977ebc68fe10aec6ca50bc2486532f489d7968fb5046defcd839b3b5ce28ca9dbce40f + languageName: node + linkType: hard + +"@ethereumjs/blockchain@npm:^5.5.0": + version: 5.5.3 + resolution: "@ethereumjs/blockchain@npm:5.5.3" + dependencies: + "@ethereumjs/block": ^3.6.2 + "@ethereumjs/common": ^2.6.4 + "@ethereumjs/ethash": ^1.1.0 + debug: ^4.3.3 + ethereumjs-util: ^7.1.5 + level-mem: ^5.0.1 + lru-cache: ^5.1.1 + semaphore-async-await: ^1.5.1 + checksum: eeefb4735ac06e6fe5ec5457eb9ac7aa26ced8651093d05067aee264f23704d79eacb1b2742e0651b73d2528aa8a9a40f3cc9e479f1837253c2dbb784a7a8e59 + languageName: node + linkType: hard + +"@ethereumjs/common@npm:2.6.0": + version: 2.6.0 + resolution: "@ethereumjs/common@npm:2.6.0" + dependencies: + crc-32: ^1.2.0 + ethereumjs-util: ^7.1.3 + checksum: f1e775f0d3963011f84cd6f6de985b342064331c8fd41bc81a6497abe959078704bf4febd8c59a3fc51c3527b1261441436d55d032f85f0453ff1af4a8dbccb3 + languageName: node + linkType: hard + +"@ethereumjs/common@npm:^2.6.0, @ethereumjs/common@npm:^2.6.4, @ethereumjs/common@npm:^2.6.5": + version: 2.6.5 + resolution: "@ethereumjs/common@npm:2.6.5" + dependencies: + crc-32: ^1.2.0 + ethereumjs-util: ^7.1.5 + checksum: 0143386f267ef01b7a8bb1847596f964ad58643c084e5fd8e3a0271a7bf8428605dbf38cbb92c84f6622080ad095abeb765f178c02d86ec52abf9e8a4c0e4ecf + languageName: node + linkType: hard + +"@ethereumjs/ethash@npm:^1.1.0": + version: 1.1.0 + resolution: "@ethereumjs/ethash@npm:1.1.0" + dependencies: + "@ethereumjs/block": ^3.5.0 + "@types/levelup": ^4.3.0 + buffer-xor: ^2.0.1 + ethereumjs-util: ^7.1.1 + miller-rabin: ^4.0.0 + checksum: 152bc0850eeb0f2507383ca005418697b0a6a4487b120d7b3fadae4cb3b4781403c96c01f0c47149031431e518fb174c284ff38806b457f86f00c500eb213df3 + languageName: node + linkType: hard + "@ethereumjs/rlp@npm:^4.0.1": version: 4.0.1 resolution: "@ethereumjs/rlp@npm:4.0.1" @@ -368,6 +538,26 @@ __metadata: languageName: node linkType: hard +"@ethereumjs/tx@npm:3.4.0": + version: 3.4.0 + resolution: "@ethereumjs/tx@npm:3.4.0" + dependencies: + "@ethereumjs/common": ^2.6.0 + ethereumjs-util: ^7.1.3 + checksum: 381cbb872edb0ae83a56bf5d5657ac4f594f43ca0956b6577fb762840033081252345d67151d4feafde3f97caaab9a9826348780553c05d5a8ca2984259ad555 + languageName: node + linkType: hard + +"@ethereumjs/tx@npm:^3.4.0, @ethereumjs/tx@npm:^3.5.2": + version: 3.5.2 + resolution: "@ethereumjs/tx@npm:3.5.2" + dependencies: + "@ethereumjs/common": ^2.6.4 + ethereumjs-util: ^7.1.5 + checksum: a34a7228a623b40300484d15875b9f31f0a612cfeab64a845f6866cf0bfe439519e9455ac6396149f29bc527cf0ee277ace082ae013a1075dcbf7193220a0146 + languageName: node + linkType: hard + "@ethereumjs/util@npm:^8.1.0": version: 8.1.0 resolution: "@ethereumjs/util@npm:8.1.0" @@ -379,6 +569,26 @@ __metadata: languageName: node linkType: hard +"@ethereumjs/vm@npm:5.6.0": + version: 5.6.0 + resolution: "@ethereumjs/vm@npm:5.6.0" + dependencies: + "@ethereumjs/block": ^3.6.0 + "@ethereumjs/blockchain": ^5.5.0 + "@ethereumjs/common": ^2.6.0 + "@ethereumjs/tx": ^3.4.0 + async-eventemitter: ^0.2.4 + core-js-pure: ^3.0.1 + debug: ^2.2.0 + ethereumjs-util: ^7.1.3 + functional-red-black-tree: ^1.0.1 + mcl-wasm: ^0.7.1 + merkle-patricia-tree: ^4.2.2 + rustbn.js: ~0.2.0 + checksum: 67f803f7dc851aeed9996cdab6751dc3f7565146ff8a24982526d33a07c173e84dd449b2fbb9202a479c7446b628105af41465b75c1f9143e1e68cf573fed4c3 + languageName: node + linkType: hard + "@ethersproject/abi@npm:5.0.0-beta.153": version: 5.0.0-beta.153 resolution: "@ethersproject/abi@npm:5.0.0-beta.153" @@ -623,7 +833,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.6.8, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": +"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.6.8": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" dependencies: @@ -738,7 +948,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/units@npm:5.7.0": +"@ethersproject/units@npm:5.7.0, @ethersproject/units@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/units@npm:5.7.0" dependencies: @@ -799,9 +1009,85 @@ __metadata: linkType: hard "@fastify/busboy@npm:^2.0.0": - version: 2.1.0 - resolution: "@fastify/busboy@npm:2.1.0" - checksum: 3233abd10f73e50668cb4bb278a79b7b3fadd30215ac6458299b0e5a09a29c3586ec07597aae6bd93f5cbedfcef43a8aeea51829cd28fc13850cdbcd324c28d5 + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 42c32ef75e906c9a4809c1e1930a5ca6d4ddc8d138e1a8c8ba5ea07f997db32210617d23b2e4a85fe376316a41a1a0439fc6ff2dedf5126d96f45a9d80754fb2 + languageName: node + linkType: hard + +"@ganache/ethereum-address@npm:0.1.4": + version: 0.1.4 + resolution: "@ganache/ethereum-address@npm:0.1.4" + dependencies: + "@ganache/utils": 0.1.4 + checksum: 0e07102c67aa2c25233e30f8ca359cbd012ad0e0b9580b8e6aff6f87dd46daee89bbc60d9518f2204f36f943e7bd5d20e571646c85e6a68a98784c3ede2ccec0 + languageName: node + linkType: hard + +"@ganache/ethereum-options@npm:0.1.4": + version: 0.1.4 + resolution: "@ganache/ethereum-options@npm:0.1.4" + dependencies: + "@ganache/ethereum-address": 0.1.4 + "@ganache/ethereum-utils": 0.1.4 + "@ganache/options": 0.1.4 + "@ganache/utils": 0.1.4 + bip39: 3.0.4 + seedrandom: 3.0.5 + checksum: 597b32502654ce9f3fec02fdf308f1e6b2c657b5e25c6d4219d71ecbea94e45faa4135c6d4e25cacf1faac1509f2b7546f3d8bbdba1e9121975d820999d3aa76 + languageName: node + linkType: hard + +"@ganache/ethereum-utils@npm:0.1.4": + version: 0.1.4 + resolution: "@ganache/ethereum-utils@npm:0.1.4" + dependencies: + "@ethereumjs/common": 2.6.0 + "@ethereumjs/tx": 3.4.0 + "@ethereumjs/vm": 5.6.0 + "@ganache/ethereum-address": 0.1.4 + "@ganache/rlp": 0.1.4 + "@ganache/utils": 0.1.4 + emittery: 0.10.0 + ethereumjs-abi: 0.6.8 + ethereumjs-util: 7.1.3 + checksum: 74bc7b7fb62e9dc2f114f6f428c465d9365c0bb84c85144d34935d24a2893c5471c8cae263ae4bea51f1335803b6b1771f57c25a276e9c0539a08a90c3289bca + languageName: node + linkType: hard + +"@ganache/options@npm:0.1.4": + version: 0.1.4 + resolution: "@ganache/options@npm:0.1.4" + dependencies: + "@ganache/utils": 0.1.4 + bip39: 3.0.4 + seedrandom: 3.0.5 + checksum: 4f1cda646f5599b18a0eeaf27286499c78c3e2e0eb2541db756c27f2ca16e58539c9db99aab8441e593f9fe586269940d800900f63312fcb10231ab95ebdc3dc + languageName: node + linkType: hard + +"@ganache/rlp@npm:0.1.4": + version: 0.1.4 + resolution: "@ganache/rlp@npm:0.1.4" + dependencies: + "@ganache/utils": 0.1.4 + rlp: 2.2.6 + checksum: 425c5d4a0a36b834cfac005d05679b3df970a6d8d953f385a5f9bd003a326ba23c1bce06095729879136699b70389d7f2627f939f712ed8897c96e542766771f + languageName: node + linkType: hard + +"@ganache/utils@npm:0.1.4": + version: 0.1.4 + resolution: "@ganache/utils@npm:0.1.4" + dependencies: + "@trufflesuite/bigint-buffer": 1.1.9 + emittery: 0.10.0 + keccak: 3.0.1 + seedrandom: 3.0.5 + dependenciesMeta: + "@trufflesuite/bigint-buffer": + optional: true + checksum: c81b7380d56292a44e9cdb0e581d815b9510fb1be87661fe135e2d3611b495f1cd01aa4b91e287bfc28d08d1b4b4210f7b54e32ea28e054faa006cf232fb3dcc languageName: node linkType: hard @@ -844,7 +1130,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13": +"@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: @@ -863,9 +1149,9 @@ __metadata: linkType: hard "@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.2 - resolution: "@humanwhocodes/object-schema@npm:2.0.2" - checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: d3b78f6c5831888c6ecc899df0d03bcc25d46f3ad26a11d7ea52944dc36a35ef543fad965322174238d677a43d5c694434f6607532cff7077062513ad7022631 languageName: node linkType: hard @@ -913,9 +1199,9 @@ __metadata: linkType: hard "@jridgewell/resolve-uri@npm:^3.0.3": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 83b85f72c59d1c080b4cbec0fef84528963a1b5db34e4370fa4bd1e3ff64a0d80e0cee7369d11d73c704e0286fb2865b530acac7a871088fbe92b5edf1000870 languageName: node linkType: hard @@ -946,11 +1232,11 @@ __metadata: linkType: hard "@ljharb/through@npm:^2.3.9, @ljharb/through@npm:~2.3.9": - version: 2.3.12 - resolution: "@ljharb/through@npm:2.3.12" + version: 2.3.13 + resolution: "@ljharb/through@npm:2.3.13" dependencies: - call-bind: ^1.0.5 - checksum: d5a78568cd3025c03264a9f9c61b30511d27cb9611fae7575cb1339a1baa1a263b6af03e28505b821324f3c6285086ee5add612b8b0155d1f253ed5159cd3f56 + call-bind: ^1.0.7 + checksum: 0255464a0ec7901b08cff3e99370b87e66663f46249505959c0cb4f6121095d533bbb7c7cda338063d3e134cbdd721e2705bc18eac7611b4f9ead6e7935d13ba languageName: node linkType: hard @@ -967,12 +1253,21 @@ __metadata: languageName: node linkType: hard -"@noble/curves@npm:1.3.0, @noble/curves@npm:~1.3.0": - version: 1.3.0 - resolution: "@noble/curves@npm:1.3.0" +"@noble/curves@npm:1.2.0, @noble/curves@npm:~1.2.0": + version: 1.2.0 + resolution: "@noble/curves@npm:1.2.0" dependencies: - "@noble/hashes": 1.3.3 - checksum: b65342ee66c4a440eee2978524412eabba9a9efdd16d6370e15218c6a7d80bddf35e66bb57ed52c0dfd32cb9a717b439ab3a72db618f1a0066dfebe3fd12a421 + "@noble/hashes": 1.3.2 + checksum: bb798d7a66d8e43789e93bc3c2ddff91a1e19fdb79a99b86cd98f1e5eff0ee2024a2672902c2576ef3577b6f282f3b5c778bebd55761ddbb30e36bf275e83dd0 + languageName: node + linkType: hard + +"@noble/curves@npm:1.4.0, @noble/curves@npm:~1.4.0": + version: 1.4.0 + resolution: "@noble/curves@npm:1.4.0" + dependencies: + "@noble/hashes": 1.4.0 + checksum: 0014ff561d16e98da4a57e2310a4015e4bdab3b1e1eafcd18d3f9b955c29c3501452ca5d702fddf8ca92d570bbeadfbe53fe16ebbd81a319c414f739154bb26b languageName: node linkType: hard @@ -983,7 +1278,21 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.3.3, @noble/hashes@npm:~1.3.2": +"@noble/hashes@npm:1.3.2": + version: 1.3.2 + resolution: "@noble/hashes@npm:1.3.2" + checksum: fe23536b436539d13f90e4b9be843cc63b1b17666a07634a2b1259dded6f490be3d050249e6af98076ea8f2ea0d56f578773c2197f2aa0eeaa5fba5bc18ba474 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.4.0, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:~1.4.0": + version: 1.4.0 + resolution: "@noble/hashes@npm:1.4.0" + checksum: 8ba816ae26c90764b8c42493eea383716396096c5f7ba6bea559993194f49d80a73c081f315f4c367e51bd2d5891700bcdfa816b421d24ab45b41cb03e4f3342 + languageName: node + linkType: hard + +"@noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.2": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" checksum: 8a6496d1c0c64797339bc694ad06cdfaa0f9e56cd0c3f68ae3666cfb153a791a55deb0af9c653c7ed2db64d537aa3e3054629740d2f2338bb1dcb7ab60cd205b @@ -1024,335 +1333,215 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-block@npm:4.2.2": - version: 4.2.2 - resolution: "@nomicfoundation/ethereumjs-block@npm:4.2.2" - dependencies: - "@nomicfoundation/ethereumjs-common": 3.1.2 - "@nomicfoundation/ethereumjs-rlp": 4.0.3 - "@nomicfoundation/ethereumjs-trie": 5.0.5 - "@nomicfoundation/ethereumjs-tx": 4.1.2 - "@nomicfoundation/ethereumjs-util": 8.0.6 - ethereum-cryptography: 0.1.3 - checksum: 174a251d9c4e0bb9c1a7a6e77c52f1b2b4708d8135dba55c1025776248258ce905e4383a79da0ce7ac4e67e03b6c56351ca634a771b5eae976ed97498fc163f9 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-block@npm:5.0.2": - version: 5.0.2 - resolution: "@nomicfoundation/ethereumjs-block@npm:5.0.2" - dependencies: - "@nomicfoundation/ethereumjs-common": 4.0.2 - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - "@nomicfoundation/ethereumjs-trie": 6.0.2 - "@nomicfoundation/ethereumjs-tx": 5.0.2 - "@nomicfoundation/ethereumjs-util": 9.0.2 - ethereum-cryptography: 0.1.3 - ethers: ^5.7.1 - checksum: 7ff744f44a01f1c059ca7812a1cfc8089f87aa506af6cb39c78331dca71b32993cbd6fa05ad03f8c4f4fab73bb998a927af69e0d8ff01ae192ee5931606e09f5 +"@nomicfoundation/edr-darwin-arm64@npm:0.4.0": + version: 0.4.0 + resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.4.0" + checksum: 61458dc5c9a6429c8225c3a5cffa6e634df86ae7d0a4e27392e99c5ddd0d9bc355de07ba74f9527b3d40a0d819a04485ade107c8ecc3ec86381411ef86b430ce languageName: node linkType: hard -"@nomicfoundation/ethereumjs-blockchain@npm:6.2.2": - version: 6.2.2 - resolution: "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2" - dependencies: - "@nomicfoundation/ethereumjs-block": 4.2.2 - "@nomicfoundation/ethereumjs-common": 3.1.2 - "@nomicfoundation/ethereumjs-ethash": 2.0.5 - "@nomicfoundation/ethereumjs-rlp": 4.0.3 - "@nomicfoundation/ethereumjs-trie": 5.0.5 - "@nomicfoundation/ethereumjs-util": 8.0.6 - abstract-level: ^1.0.3 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - level: ^8.0.0 - lru-cache: ^5.1.1 - memory-level: ^1.0.0 - checksum: 5933600bf005ec3e33f6fdd0b3582b80ed7eac8fa776fc86f21de8a6ac3614e3262c48ad3737015c19558165aecd7b13a8056e96afd61511d0605411e0264871 +"@nomicfoundation/edr-darwin-x64@npm:0.4.0": + version: 0.4.0 + resolution: "@nomicfoundation/edr-darwin-x64@npm:0.4.0" + checksum: 95bbb5371028e66caabce6d819d54f1726f3497855ec5395989b48e7313343e4f6f04f2d70a036ab518acaff1db309f2f50af19054eb2eb5d582122cff0c3b7c languageName: node linkType: hard -"@nomicfoundation/ethereumjs-blockchain@npm:7.0.2": - version: 7.0.2 - resolution: "@nomicfoundation/ethereumjs-blockchain@npm:7.0.2" - dependencies: - "@nomicfoundation/ethereumjs-block": 5.0.2 - "@nomicfoundation/ethereumjs-common": 4.0.2 - "@nomicfoundation/ethereumjs-ethash": 3.0.2 - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - "@nomicfoundation/ethereumjs-trie": 6.0.2 - "@nomicfoundation/ethereumjs-tx": 5.0.2 - "@nomicfoundation/ethereumjs-util": 9.0.2 - abstract-level: ^1.0.3 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - level: ^8.0.0 - lru-cache: ^5.1.1 - memory-level: ^1.0.0 - checksum: b7e440dcd73e32aa72d13bfd28cb472773c9c60ea808a884131bf7eb3f42286ad594a0864215f599332d800f3fe1f772fff4b138d2dcaa8f41e4d8389bff33e7 +"@nomicfoundation/edr-linux-arm64-gnu@npm:0.4.0": + version: 0.4.0 + resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.4.0" + checksum: 7a0d39bc6402d0694e550d21a78bc49ab5b8a45a4853d619f4e42022bc1d4c06d380e31dfcade43f732dd3f799a725e7d2efdb942f34ca64e34c58cb92dc9afd languageName: node linkType: hard -"@nomicfoundation/ethereumjs-common@npm:3.1.2": - version: 3.1.2 - resolution: "@nomicfoundation/ethereumjs-common@npm:3.1.2" - dependencies: - "@nomicfoundation/ethereumjs-util": 8.0.6 - crc-32: ^1.2.0 - checksum: b886e47bb4da26b42bf9e905c5f073db62d2ad1b740d50898012580b501868839fcf08430debe3fca927b4d73e01628c1b0b2e84401feb551245dacfac045404 +"@nomicfoundation/edr-linux-arm64-musl@npm:0.4.0": + version: 0.4.0 + resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.4.0" + checksum: 1f2623fad98bcb9118b17ff004b4ea40ce0afea85292e633ebea972ec678815a218774840c15eabd5f1cf3b6359cae26a7e20912c741b14577dc823def40a3bf languageName: node linkType: hard -"@nomicfoundation/ethereumjs-common@npm:4.0.2": - version: 4.0.2 - resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.2" - dependencies: - "@nomicfoundation/ethereumjs-util": 9.0.2 - crc-32: ^1.2.0 - checksum: f0d84704d6254d374299c19884312bd5666974b4b6f342d3f10bc76e549de78d20e45a53d25fbdc146268a52335497127e4f069126da7c60ac933a158e704887 +"@nomicfoundation/edr-linux-x64-gnu@npm:0.4.0": + version: 0.4.0 + resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.4.0" + checksum: 6164a41c9310e755168b78ae7654d5cad1b6b2c3586d694d0e7e70fc3a9eb12312b5e2e5be893abe4cec2b402553cb32428c0553d31d655643bc2db200fbf040 languageName: node linkType: hard -"@nomicfoundation/ethereumjs-ethash@npm:2.0.5": - version: 2.0.5 - resolution: "@nomicfoundation/ethereumjs-ethash@npm:2.0.5" - dependencies: - "@nomicfoundation/ethereumjs-block": 4.2.2 - "@nomicfoundation/ethereumjs-rlp": 4.0.3 - "@nomicfoundation/ethereumjs-util": 8.0.6 - abstract-level: ^1.0.3 - bigint-crypto-utils: ^3.0.23 - ethereum-cryptography: 0.1.3 - checksum: 0b03c8771602cfa64c9d35e5686326d0bfecb7dc0874cd9ff737cae0ec401396187d8499c103b8858fed5b9bd930e132b8fd09d19b3f0649df36d7d0fdf4d27c +"@nomicfoundation/edr-linux-x64-musl@npm:0.4.0": + version: 0.4.0 + resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.4.0" + checksum: ad067b489bd2ea00dc68614fd87ed82c1261b3b31013322a259065b35d13a1aa3f4210e5f0bc84119e674abdc464723d3ce70a6fdff1810ea84ef14b0cf4ea68 languageName: node linkType: hard -"@nomicfoundation/ethereumjs-ethash@npm:3.0.2": - version: 3.0.2 - resolution: "@nomicfoundation/ethereumjs-ethash@npm:3.0.2" - dependencies: - "@nomicfoundation/ethereumjs-block": 5.0.2 - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - "@nomicfoundation/ethereumjs-util": 9.0.2 - abstract-level: ^1.0.3 - bigint-crypto-utils: ^3.0.23 - ethereum-cryptography: 0.1.3 - checksum: e4011e4019dd9b92f7eeebfc1e6c9a9685c52d8fd0ee4f28f03e50048a23b600c714490827f59fdce497b3afb503b3fd2ebf6815ff307e9949c3efeff1403278 +"@nomicfoundation/edr-win32-x64-msvc@npm:0.4.0": + version: 0.4.0 + resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.4.0" + checksum: 3f36760dbb80b0d0dde6685d4eddadc2aa8e4cc002bae291c89378a90402b95815066b50b4226e691f3fceea732f535dbeedc4c51525bd8f5d9f574de846d369 languageName: node linkType: hard -"@nomicfoundation/ethereumjs-evm@npm:1.3.2, @nomicfoundation/ethereumjs-evm@npm:^1.0.0-rc.3": - version: 1.3.2 - resolution: "@nomicfoundation/ethereumjs-evm@npm:1.3.2" +"@nomicfoundation/edr@npm:^0.4.0": + version: 0.4.0 + resolution: "@nomicfoundation/edr@npm:0.4.0" dependencies: - "@nomicfoundation/ethereumjs-common": 3.1.2 - "@nomicfoundation/ethereumjs-util": 8.0.6 - "@types/async-eventemitter": ^0.2.1 - async-eventemitter: ^0.2.4 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - mcl-wasm: ^0.7.1 - rustbn.js: ~0.2.0 - checksum: 4a051f36968574ffbee5d3c401ebf1c81899b69a0692c372fced67691fe18f26741f26d1781e79dfa52136af888e561d80de4fd7dd59000d640c51bd8b130023 + "@nomicfoundation/edr-darwin-arm64": 0.4.0 + "@nomicfoundation/edr-darwin-x64": 0.4.0 + "@nomicfoundation/edr-linux-arm64-gnu": 0.4.0 + "@nomicfoundation/edr-linux-arm64-musl": 0.4.0 + "@nomicfoundation/edr-linux-x64-gnu": 0.4.0 + "@nomicfoundation/edr-linux-x64-musl": 0.4.0 + "@nomicfoundation/edr-win32-x64-msvc": 0.4.0 + checksum: 1baaa3f666bb9ea15cf04ba9e3ca8a1d654c722d37d61d93299933113a4305aa9e5cbf667df035ff7161c79a7e461af48986467129c700f4aa843be6fd9d4e7f languageName: node linkType: hard -"@nomicfoundation/ethereumjs-evm@npm:2.0.2": - version: 2.0.2 - resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.2" +"@nomicfoundation/ethereumjs-common@npm:4.0.4": + version: 4.0.4 + resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.4" dependencies: - "@ethersproject/providers": ^5.7.1 - "@nomicfoundation/ethereumjs-common": 4.0.2 - "@nomicfoundation/ethereumjs-tx": 5.0.2 - "@nomicfoundation/ethereumjs-util": 9.0.2 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - mcl-wasm: ^0.7.1 - rustbn.js: ~0.2.0 - checksum: a23cf570836ddc147606b02df568069de946108e640f902358fef67e589f6b371d856056ee44299d9b4e3497f8ae25faa45e6b18fefd90e9b222dc6a761d85f0 + "@nomicfoundation/ethereumjs-util": 9.0.4 + checksum: ce3f6e4ae15b976efdb7ccda27e19aadb62b5ffee209f9503e68b4fd8633715d4d697c0cc10ccd35f5e4e977edd05100d0f214e28880ec64fff77341dc34fcdf languageName: node linkType: hard -"@nomicfoundation/ethereumjs-rlp@npm:4.0.3": - version: 4.0.3 - resolution: "@nomicfoundation/ethereumjs-rlp@npm:4.0.3" - bin: - rlp: bin/rlp - checksum: 14fc83701dd52323fae705786549ab07482ace315de69a586bb948b6f21ec529794cef8248af0b5c7e8f8b05fbadfbe222754b305841fa2189bfbc8f1eb064a2 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-rlp@npm:5.0.2": - version: 5.0.2 - resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.2" +"@nomicfoundation/ethereumjs-rlp@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.4" bin: - rlp: bin/rlp - checksum: a74434cadefca9aa8754607cc1ad7bb4bbea4ee61c6214918e60a5bbee83206850346eb64e39fd1fe97f854c7ec0163e01148c0c881dda23881938f0645a0ef2 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-statemanager@npm:1.0.5": - version: 1.0.5 - resolution: "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5" - dependencies: - "@nomicfoundation/ethereumjs-common": 3.1.2 - "@nomicfoundation/ethereumjs-rlp": 4.0.3 - "@nomicfoundation/ethereumjs-trie": 5.0.5 - "@nomicfoundation/ethereumjs-util": 8.0.6 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - functional-red-black-tree: ^1.0.1 - checksum: 0f88743900b2211deb5d2393bf111ef63411ce533387a6d06c48cc9ac1f4fc38f968cdecc4712ebdafdebc3c4c2ce6bd1abd82989f4f4f515d3f571981d38f9f - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-statemanager@npm:2.0.2": - version: 2.0.2 - resolution: "@nomicfoundation/ethereumjs-statemanager@npm:2.0.2" - dependencies: - "@nomicfoundation/ethereumjs-common": 4.0.2 - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - ethers: ^5.7.1 - js-sdsl: ^4.1.4 - checksum: 3ab6578e252e53609afd98d8ba42a99f182dcf80252f23ed9a5e0471023ffb2502130f85fc47fa7c94cd149f9be799ed9a0942ca52a143405be9267f4ad94e64 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-trie@npm:5.0.5": - version: 5.0.5 - resolution: "@nomicfoundation/ethereumjs-trie@npm:5.0.5" - dependencies: - "@nomicfoundation/ethereumjs-rlp": 4.0.3 - "@nomicfoundation/ethereumjs-util": 8.0.6 - ethereum-cryptography: 0.1.3 - readable-stream: ^3.6.0 - checksum: bed56b55093275166c40d0aa097b32d348b3795cbfdc3797d48d136a578161431e70f30bcf453b74b52f77b897d79b61a3fb9d1abd10187c0cb7f25e40dea9c5 + rlp: bin/rlp.cjs + checksum: ee2c2e5776c73801dc5ed636f4988b599b4563c2d0037da542ea57eb237c69dd1ac555f6bcb5e06f70515b6459779ba0d68252a6e105132b4659ab4bf62919b0 languageName: node linkType: hard -"@nomicfoundation/ethereumjs-trie@npm:6.0.2": - version: 6.0.2 - resolution: "@nomicfoundation/ethereumjs-trie@npm:6.0.2" +"@nomicfoundation/ethereumjs-tx@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.4" dependencies: - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - "@nomicfoundation/ethereumjs-util": 9.0.2 - "@types/readable-stream": ^2.3.13 + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 ethereum-cryptography: 0.1.3 - readable-stream: ^3.6.0 - checksum: d4da918d333851b9f2cce7dbd25ab5753e0accd43d562d98fd991b168b6a08d1794528f0ade40fe5617c84900378376fe6256cdbe52c8d66bf4c53293bbc7c40 + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 0f1c87716682ccbcf4d92ffc6cf8ab557e658b90319d82be3219a091a736859f8803c73c98e4863682e3e86d264751c472d33ff6d3c3daf4e75b5f01d0af8fa3 languageName: node linkType: hard -"@nomicfoundation/ethereumjs-tx@npm:4.1.2": - version: 4.1.2 - resolution: "@nomicfoundation/ethereumjs-tx@npm:4.1.2" +"@nomicfoundation/ethereumjs-util@npm:9.0.4, @nomicfoundation/ethereumjs-util@npm:^9.0.4": + version: 9.0.4 + resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.4" dependencies: - "@nomicfoundation/ethereumjs-common": 3.1.2 - "@nomicfoundation/ethereumjs-rlp": 4.0.3 - "@nomicfoundation/ethereumjs-util": 8.0.6 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 ethereum-cryptography: 0.1.3 - checksum: 209622bdc56e5f1267e5d2de69ed18388b141edc568f739f0ed865aecfe96e07c381aab779ed0adacefeae4da5be64fa1110a02e481e9a7c343bf0d53f4fd1b9 + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 754439f72b11cad2d8986707ad020077dcc763c4055f73e2668a0b4cadb22aa4407faa9b3c587d9eb5b97ac337afbe037eb642bc1d5a16197284f83db3462cbe languageName: node linkType: hard -"@nomicfoundation/ethereumjs-tx@npm:5.0.2": - version: 5.0.2 - resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.2" +"@nomicfoundation/hardhat-chai-matchers@npm:^1.0.6": + version: 1.0.6 + resolution: "@nomicfoundation/hardhat-chai-matchers@npm:1.0.6" dependencies: - "@chainsafe/ssz": ^0.9.2 - "@ethersproject/providers": ^5.7.2 - "@nomicfoundation/ethereumjs-common": 4.0.2 - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - "@nomicfoundation/ethereumjs-util": 9.0.2 - ethereum-cryptography: 0.1.3 - checksum: 0bbcea75786b2ccb559afe2ecc9866fb4566a9f157b6ffba4f50960d14f4b3da2e86e273f6fadda9b860e67cfcabf589970fb951b328cb5f900a585cd21842a2 + "@ethersproject/abi": ^5.1.2 + "@types/chai-as-promised": ^7.1.3 + chai-as-promised: ^7.1.1 + deep-eql: ^4.0.1 + ordinal: ^1.0.3 + peerDependencies: + "@nomiclabs/hardhat-ethers": ^2.0.0 + chai: ^4.2.0 + ethers: ^5.0.0 + hardhat: ^2.9.4 + checksum: c388e5ed9068f2ba7c227737ab7312dd03405d5fab195247b061f2fa52e700fbd0fb65359c2d4f2086f2905bfca642c19a9122d034533edd936f89aea65ac7f2 languageName: node linkType: hard -"@nomicfoundation/ethereumjs-util@npm:8.0.6, @nomicfoundation/ethereumjs-util@npm:^8.0.0-rc.3": - version: 8.0.6 - resolution: "@nomicfoundation/ethereumjs-util@npm:8.0.6" +"@nomicfoundation/hardhat-chai-matchers@npm:latest": + version: 2.0.7 + resolution: "@nomicfoundation/hardhat-chai-matchers@npm:2.0.7" dependencies: - "@nomicfoundation/ethereumjs-rlp": 4.0.3 - ethereum-cryptography: 0.1.3 - checksum: 7a51c2069702750d94bf6bc5afd4a26c50321fe42504339d5275b60974941451eb41232f8a08c307797bcd498f20a3b27074351a76abdfc36a5e74473a7eda01 + "@types/chai-as-promised": ^7.1.3 + chai-as-promised: ^7.1.1 + deep-eql: ^4.0.1 + ordinal: ^1.0.3 + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.0 + chai: ^4.2.0 + ethers: ^6.1.0 + hardhat: ^2.9.4 + checksum: 7162187522d441cd06643d926fa06b36bdea9029cbd7b9d735a2642dd343e6f9d93ea7a01d3d2efe06d9696c0035911d299574014a27d2c8521ab2387cfc83f8 languageName: node linkType: hard -"@nomicfoundation/ethereumjs-util@npm:9.0.2": - version: 9.0.2 - resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.2" +"@nomicfoundation/hardhat-ethers@npm:^3.0.0": + version: 3.0.6 + resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.6" dependencies: - "@chainsafe/ssz": ^0.10.0 - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - ethereum-cryptography: 0.1.3 - checksum: 3a08f7b88079ef9f53b43da9bdcb8195498fd3d3911c2feee2571f4d1204656053f058b2f650471c86f7d2d0ba2f814768c7cfb0f266eede41c848356afc4900 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-vm@npm:7.0.2": - version: 7.0.2 - resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.2" - dependencies: - "@nomicfoundation/ethereumjs-block": 5.0.2 - "@nomicfoundation/ethereumjs-blockchain": 7.0.2 - "@nomicfoundation/ethereumjs-common": 4.0.2 - "@nomicfoundation/ethereumjs-evm": 2.0.2 - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - "@nomicfoundation/ethereumjs-statemanager": 2.0.2 - "@nomicfoundation/ethereumjs-trie": 6.0.2 - "@nomicfoundation/ethereumjs-tx": 5.0.2 - "@nomicfoundation/ethereumjs-util": 9.0.2 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - mcl-wasm: ^0.7.1 - rustbn.js: ~0.2.0 - checksum: 1c25ba4d0644cadb8a2b0241a4bb02e578bfd7f70e3492b855c2ab5c120cb159cb8f7486f84dc1597884bd1697feedbfb5feb66e91352afb51f3694fd8e4a043 + debug: ^4.1.1 + lodash.isequal: ^4.5.0 + peerDependencies: + ethers: ^6.1.0 + hardhat: ^2.0.0 + checksum: 31a9b5aeb7b42cf3d8bcd1f11e680ce7018874a4c63b16b01a928fb34d2bd3e0f046fc4c7180e01bcd8b8b398874fc370317165284b3f543c4f3d1fbdcfbf05d languageName: node linkType: hard -"@nomicfoundation/ethereumjs-vm@npm:^6.0.0-rc.3": - version: 6.4.2 - resolution: "@nomicfoundation/ethereumjs-vm@npm:6.4.2" - dependencies: - "@nomicfoundation/ethereumjs-block": 4.2.2 - "@nomicfoundation/ethereumjs-blockchain": 6.2.2 - "@nomicfoundation/ethereumjs-common": 3.1.2 - "@nomicfoundation/ethereumjs-evm": 1.3.2 - "@nomicfoundation/ethereumjs-rlp": 4.0.3 - "@nomicfoundation/ethereumjs-statemanager": 1.0.5 - "@nomicfoundation/ethereumjs-trie": 5.0.5 - "@nomicfoundation/ethereumjs-tx": 4.1.2 - "@nomicfoundation/ethereumjs-util": 8.0.6 - "@types/async-eventemitter": ^0.2.1 - async-eventemitter: ^0.2.4 - debug: ^4.3.3 - ethereum-cryptography: 0.1.3 - functional-red-black-tree: ^1.0.1 - mcl-wasm: ^0.7.1 - rustbn.js: ~0.2.0 - checksum: 9138b8cce872a51fe2e378942c52fc6c54d8126ff094ba6bb78cbb630cafa20d7fbaa2b08bdcf7cad6de78e19ce68493ddbcc2e02acb7c803b866dc121274ea7 +"@nomicfoundation/hardhat-ignition-ethers@npm:^0.15.0": + version: 0.15.5 + resolution: "@nomicfoundation/hardhat-ignition-ethers@npm:0.15.5" + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.4 + "@nomicfoundation/hardhat-ignition": ^0.15.5 + "@nomicfoundation/ignition-core": ^0.15.5 + ethers: ^6.7.0 + hardhat: ^2.18.0 + checksum: 4fb0b7a88f907d51b6f28b3fb5f8c245659d49490f7976e421bf18fba331723be0292b35ac59f350f32fa75aef92d15e0926a3c811a3e15fd04942e22379d6d4 languageName: node linkType: hard -"@nomicfoundation/hardhat-chai-matchers@npm:^1.0.6": - version: 1.0.6 - resolution: "@nomicfoundation/hardhat-chai-matchers@npm:1.0.6" +"@nomicfoundation/hardhat-network-helpers@npm:^1.0.0": + version: 1.0.11 + resolution: "@nomicfoundation/hardhat-network-helpers@npm:1.0.11" dependencies: - "@ethersproject/abi": ^5.1.2 - "@types/chai-as-promised": ^7.1.3 - chai-as-promised: ^7.1.1 - deep-eql: ^4.0.1 - ordinal: ^1.0.3 + ethereumjs-util: ^7.1.4 peerDependencies: - "@nomiclabs/hardhat-ethers": ^2.0.0 + hardhat: ^2.9.5 + checksum: b1566de2b0ff6de0fa825b13befd9a3318538e45c2d7e54b52dbf724b9ea5019365f1cf6962f4b89313747da847b575692783cfe03b60dbff3a2e419e135c3fb + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-toolbox@npm:latest": + version: 5.0.0 + resolution: "@nomicfoundation/hardhat-toolbox@npm:5.0.0" + peerDependencies: + "@nomicfoundation/hardhat-chai-matchers": ^2.0.0 + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@nomicfoundation/hardhat-ignition-ethers": ^0.15.0 + "@nomicfoundation/hardhat-network-helpers": ^1.0.0 + "@nomicfoundation/hardhat-verify": ^2.0.0 + "@typechain/ethers-v6": ^0.5.0 + "@typechain/hardhat": ^9.0.0 + "@types/chai": ^4.2.0 + "@types/mocha": ">=9.1.0" + "@types/node": ">=18.0.0" chai: ^4.2.0 - ethers: ^5.0.0 - hardhat: ^2.9.4 - checksum: c388e5ed9068f2ba7c227737ab7312dd03405d5fab195247b061f2fa52e700fbd0fb65359c2d4f2086f2905bfca642c19a9122d034533edd936f89aea65ac7f2 + ethers: ^6.4.0 + hardhat: ^2.11.0 + hardhat-gas-reporter: ^1.0.8 + solidity-coverage: ^0.8.1 + ts-node: ">=8.0.0" + typechain: ^8.3.0 + typescript: ">=4.5.0" + checksum: 18890eaf1cc130afb7dc83ea48cb6ef23c499eb5d28c3fbb36e706082383a320118ee6d4491ede64acf684d2f1ffa117cf84ad80d8ebde9fa52a443f8780a898 languageName: node linkType: hard @@ -1375,97 +1564,90 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@nomicfoundation/solidity-analyzer-freebsd-x64@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-freebsd-x64@npm:0.1.1" - conditions: os=freebsd & cpu=x64 +"@nomicfoundation/hardhat-verify@npm:latest": + version: 2.0.8 + resolution: "@nomicfoundation/hardhat-verify@npm:2.0.8" + dependencies: + "@ethersproject/abi": ^5.1.2 + "@ethersproject/address": ^5.0.2 + cbor: ^8.1.0 + chalk: ^2.4.2 + debug: ^4.1.1 + lodash.clonedeep: ^4.5.0 + semver: ^6.3.0 + table: ^6.8.0 + undici: ^5.14.0 + peerDependencies: + hardhat: ^2.0.4 + checksum: 2c6d239a08e7aca26625ab8c3637e5e7c1e7c8a88f62fb80c6a008fd56352431856aaf79b7a24b1755a6ee48d1423995e02d85a58ea53ceb5552b30c03073c97 languageName: node linkType: hard -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.1" - conditions: os=linux & cpu=arm64 & libc=glibc +"@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2" + checksum: 5bf3cf3f88e39d7b684f0ca75621b794b62e2676eb63c6977e847acc9c827bdc132143cc84e46be2797b93edc522f2c6f85bf5501fd7b8c85b346fb27e4dd488 languageName: node linkType: hard -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.1" - conditions: os=linux & cpu=arm64 & libc=musl +"@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.2" + checksum: 8061dc7749d97409ccde4a2e529316c29f83f2d07c78ffea87803777229e2a7d967bbb8bda564903ab5e9e89ad3b46cbcb060621209d1c6e4212c4b1b096c076 languageName: node linkType: hard -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.1" - conditions: os=linux & cpu=x64 & libc=glibc +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.2" + checksum: 46111d18446ea5d157628c202d1ee1fc3444b32a0e3aa24337bbb407653606a79a3b199bf1e5fe5f74c5c78833cf243e492f20ab6a1503137e89f2236b3ecfe7 languageName: node linkType: hard -"@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.1" - conditions: os=linux & cpu=x64 & libc=musl +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.2" + checksum: 588e81e7b36cbe80b9d2c502dc2db4bf8706732bcea6906b79bac202eb441fa2f4b9f703c30d82a17ed2a4402eaf038057fb14fc1c16eac5ade103ff9b085cdc languageName: node linkType: hard -"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-win32-arm64-msvc@npm:0.1.1" - conditions: os=win32 & cpu=arm64 +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.2" + checksum: 26f8307bde4a2c7609d297f2af6a50cad87aa46e914326b09d5cb424b4f45f0f75e982f9fcb9ee3361a2f9b141fcc9c10a665ddbc9686e01b017c639fbfb500b languageName: node linkType: hard -"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-win32-ia32-msvc@npm:0.1.1" - conditions: os=win32 & cpu=ia32 +"@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.2" + checksum: d3628bae4f04bcdb2f1dec1d6790cdf97812e7e5c0a426f4227acc97883fa3165017a800375237e36bc588f0fb4971b0936a372869a801a97f42336ee4e42feb languageName: node linkType: hard -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.1": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.1" - conditions: os=win32 & cpu=x64 +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.2" + checksum: 4a7d34d8419608cc343b6c028e07bd9ec72fd4ab82ccd36807ccf0fc8ad708b8d5baae9121532073ef08b2deb24d9c3a6f7b627c26f91f2a7de0cdb7024238f1 languageName: node linkType: hard "@nomicfoundation/solidity-analyzer@npm:^0.1.0": - version: 0.1.1 - resolution: "@nomicfoundation/solidity-analyzer@npm:0.1.1" - dependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64": 0.1.1 - "@nomicfoundation/solidity-analyzer-darwin-x64": 0.1.1 - "@nomicfoundation/solidity-analyzer-freebsd-x64": 0.1.1 - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": 0.1.1 - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": 0.1.1 - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": 0.1.1 - "@nomicfoundation/solidity-analyzer-linux-x64-musl": 0.1.1 - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": 0.1.1 - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": 0.1.1 - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": 0.1.1 + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer@npm:0.1.2" + dependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64": 0.1.2 + "@nomicfoundation/solidity-analyzer-darwin-x64": 0.1.2 + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": 0.1.2 + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": 0.1.2 + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": 0.1.2 + "@nomicfoundation/solidity-analyzer-linux-x64-musl": 0.1.2 + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": 0.1.2 dependenciesMeta: "@nomicfoundation/solidity-analyzer-darwin-arm64": optional: true "@nomicfoundation/solidity-analyzer-darwin-x64": optional: true - "@nomicfoundation/solidity-analyzer-freebsd-x64": - optional: true "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": optional: true "@nomicfoundation/solidity-analyzer-linux-arm64-musl": @@ -1474,13 +1656,9 @@ __metadata: optional: true "@nomicfoundation/solidity-analyzer-linux-x64-musl": optional: true - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": - optional: true - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": - optional: true "@nomicfoundation/solidity-analyzer-win32-x64-msvc": optional: true - checksum: 038cffafd5769e25256b5b8bef88d95cc1c021274a65c020cf84aceb3237752a3b51645fdb0687f5516a2bdfebf166fcf50b08ab64857925100213e0654b266b + checksum: 0de3a317658345b9012285665bb4c810a98b3668bcf32a118912fda00e5760fa2c77d0a92bce6b687dcc7b4bb34b0a83f8e6748bfa68660a2303d781ca728aef languageName: node linkType: hard @@ -1494,7 +1672,7 @@ __metadata: languageName: node linkType: hard -"@nomiclabs/hardhat-waffle@npm:^2.0.3": +"@nomiclabs/hardhat-waffle@npm:^2.0.3, @nomiclabs/hardhat-waffle@npm:^2.0.6": version: 2.0.6 resolution: "@nomiclabs/hardhat-waffle@npm:2.0.6" peerDependencies: @@ -1508,44 +1686,110 @@ __metadata: linkType: hard "@npmcli/agent@npm:^2.0.0": - version: 2.2.0 - resolution: "@npmcli/agent@npm:2.2.0" + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" dependencies: agent-base: ^7.1.0 http-proxy-agent: ^7.0.0 https-proxy-agent: ^7.0.1 lru-cache: ^10.0.1 - socks-proxy-agent: ^8.0.1 - checksum: 3b25312edbdfaa4089af28e2d423b6f19838b945e47765b0c8174c1395c79d43c3ad6d23cb364b43f59fd3acb02c93e3b493f72ddbe3dfea04c86843a7311fc4 + socks-proxy-agent: ^8.0.3 + checksum: 67de7b88cc627a79743c88bab35e023e23daf13831a8aa4e15f998b92f5507b644d8ffc3788afc8e64423c612e0785a6a92b74782ce368f49a6746084b50d874 languageName: node linkType: hard "@npmcli/fs@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/fs@npm:3.1.0" + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" dependencies: semver: ^7.3.5 - checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e + checksum: d960cab4b93adcb31ce223bfb75c5714edbd55747342efb67dcc2f25e023d930a7af6ece3e75f2f459b6f38fc14d031c766f116cd124fdc937fd33112579e820 languageName: node linkType: hard -"@openzeppelin/contracts-upgradeable@npm:^4.7.3": - version: 4.9.5 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.5" - checksum: d5d9bad93fe2a88a8336060901d45f185ebfe1fed9844b1fe50e8641d946588c6e69a5a8f1694f0bd073c913b4b9a5c34316acfc17d8f75228adecbcb635ea62 +"@openzeppelin/contracts-upgradeable@npm:4.7.3": + version: 4.7.3 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.7.3" + checksum: c9ffb40cb847a975d440204fc6a811f43af960050242f707332b984d29bd16dc242ffa0935de61867aeb9e0357fadedb16b09b276deda5e9775582face831021 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:^4.1.0, @openzeppelin/contracts-upgradeable@npm:^4.7.3": + version: 4.9.6 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.6" + checksum: 481075e7222cab025ae55304263fca69a2d04305521957bc16d2aece9fa2b86b6914711724822493e3d04df7e793469cd0bcb1e09f0ddd10cb4e360ac7eed12a + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:3.4.2-solc-0.7": + version: 3.4.2-solc-0.7 + resolution: "@openzeppelin/contracts@npm:3.4.2-solc-0.7" + checksum: 1a6048f31ed560c34429a05e534102c51124ecaf113aca7ebeb7897cfaaf61007cdd7952374c282adaeb79b04ee86ee80b16eed28b62fc6d60e3ffcd7a696895 + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.9.6": + version: 4.9.6 + resolution: "@openzeppelin/contracts@npm:4.9.6" + checksum: 274b6e968268294f12d5ca4f0278f6e6357792c8bb4d76664f83dbdc325f780541538a127e6a6e97e4f018088b42f65952014dec9c745c0fa25081f43ef9c4bf + languageName: node + linkType: hard + +"@openzeppelin/defender-admin-client@npm:^1.52.0": + version: 1.54.6 + resolution: "@openzeppelin/defender-admin-client@npm:1.54.6" + dependencies: + "@openzeppelin/defender-base-client": 1.54.6 + axios: ^1.4.0 + ethers: ^5.7.2 + lodash: ^4.17.19 + node-fetch: ^2.6.0 + checksum: 212e4dd496b7c41dacbdbc2d27aca5bb34e39f5d9a52cb641c86fc9af0cd1bfb0cdb4cfa0b6ed8ba01de689ed1c3c6104f9b21e4c50db969b79880e39fc3d379 languageName: node linkType: hard -"@openzeppelin/defender-base-client@npm:^1.46.0": - version: 1.54.1 - resolution: "@openzeppelin/defender-base-client@npm:1.54.1" +"@openzeppelin/defender-base-client@npm:1.54.6, @openzeppelin/defender-base-client@npm:^1.46.0, @openzeppelin/defender-base-client@npm:^1.52.0": + version: 1.54.6 + resolution: "@openzeppelin/defender-base-client@npm:1.54.6" dependencies: amazon-cognito-identity-js: ^6.0.1 async-retry: ^1.3.3 axios: ^1.4.0 lodash: ^4.17.19 node-fetch: ^2.6.0 - checksum: bb44d305b3a7b20ce765bef4c8385c1187f9eca8f2647a99ad55111034da471709e946472ca5f641eb4bd26e1c7ebd19fb9832c29919c36d353a355c009ae98c + checksum: 75b260a545fd734b7678d5591b29847f5211466bad25caca95fc24490c36d49b419b1ef06e6abc9dc6c9b4be97ae2957e033f3050a8675ddd246da817eaedd83 + languageName: node + linkType: hard + +"@openzeppelin/defender-sdk-base-client@npm:^1.10.0, @openzeppelin/defender-sdk-base-client@npm:^1.13.4": + version: 1.13.4 + resolution: "@openzeppelin/defender-sdk-base-client@npm:1.13.4" + dependencies: + amazon-cognito-identity-js: ^6.3.6 + async-retry: ^1.3.3 + checksum: 41d9ddbb19a1611c1c6f2f3da666c2732d32f396cf337dfbba214567daa1c52469f2a39baa88fce717353e5a9f8526aafd6af6dd15064c2aae372e24600fdfa3 + languageName: node + linkType: hard + +"@openzeppelin/defender-sdk-deploy-client@npm:^1.10.0": + version: 1.13.4 + resolution: "@openzeppelin/defender-sdk-deploy-client@npm:1.13.4" + dependencies: + "@openzeppelin/defender-sdk-base-client": ^1.13.4 + axios: ^1.6.8 + lodash: ^4.17.21 + checksum: 8c76a6a23cb95a923185140299fa7655e19d742fb570c252a3c5ea1d4ddb5b20909aeb6de79149825463c1c6d0ccaa153f4322417b66a2fb1bca6234a0890e3c + languageName: node + linkType: hard + +"@openzeppelin/defender-sdk-network-client@npm:^1.10.0": + version: 1.13.4 + resolution: "@openzeppelin/defender-sdk-network-client@npm:1.13.4" + dependencies: + "@openzeppelin/defender-sdk-base-client": ^1.13.4 + axios: ^1.6.8 + lodash: ^4.17.21 + checksum: 1e00c1cb5be3130e043e83a946bdad0cb5490a63386785a0c459654337d3352f64670004c5102c43045ab29ae8da49c0c63f2f14480d0c4622dcdef3490a6526 languageName: node linkType: hard @@ -1573,6 +1817,35 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/hardhat-upgrades@npm:^3.0.4": + version: 3.1.1 + resolution: "@openzeppelin/hardhat-upgrades@npm:3.1.1" + dependencies: + "@openzeppelin/defender-admin-client": ^1.52.0 + "@openzeppelin/defender-base-client": ^1.52.0 + "@openzeppelin/defender-sdk-base-client": ^1.10.0 + "@openzeppelin/defender-sdk-deploy-client": ^1.10.0 + "@openzeppelin/defender-sdk-network-client": ^1.10.0 + "@openzeppelin/upgrades-core": ^1.32.0 + chalk: ^4.1.0 + debug: ^4.1.1 + ethereumjs-util: ^7.1.5 + proper-lockfile: ^4.1.1 + undici: ^6.11.1 + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@nomicfoundation/hardhat-verify": ^2.0.0 + ethers: ^6.6.0 + hardhat: ^2.0.2 + peerDependenciesMeta: + "@nomicfoundation/hardhat-verify": + optional: true + bin: + migrate-oz-cli-project: dist/scripts/migrate-oz-cli-project.js + checksum: dfb0e602c591735ee34552ff542dfe5fbff9fb46d2fe91bbddecc9818e305b59320cf2e0ad9fc1a2393d4b7f4b381ce1eb06b6f879f6a74db95c4ca296a4daff + languageName: node + linkType: hard + "@openzeppelin/platform-deploy-client@npm:^0.8.0": version: 0.8.0 resolution: "@openzeppelin/platform-deploy-client@npm:0.8.0" @@ -1586,9 +1859,9 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/upgrades-core@npm:^1.27.0, @openzeppelin/upgrades-core@npm:latest": - version: 1.32.4 - resolution: "@openzeppelin/upgrades-core@npm:1.32.4" +"@openzeppelin/upgrades-core@npm:^1.27.0, @openzeppelin/upgrades-core@npm:^1.32.0, @openzeppelin/upgrades-core@npm:latest": + version: 1.34.1 + resolution: "@openzeppelin/upgrades-core@npm:1.34.1" dependencies: cbor: ^9.0.0 chalk: ^4.1.0 @@ -1600,7 +1873,7 @@ __metadata: solidity-ast: ^0.4.51 bin: openzeppelin-upgrades-core: dist/cli/cli.js - checksum: 3efb07adbc8b1c92ca64817f2c48a7312f6c9338d0e79f7a640756aad472be023b201962d79704eb8e1f470a2c50a6c920f0cb860dd2a04c8bc6ea09a0b451c0 + checksum: a35024d1861c83531cc434f8d2bda346dc2133e97b6d40128c229658cf680935cf36b4eaee742ec2d7c662d3371d0ee14d6dd6dafb5e0278f661adf0066f2f0b languageName: node linkType: hard @@ -1684,6 +1957,13 @@ __metadata: languageName: node linkType: hard +"@rari-capital/solmate@npm:^6.4.0": + version: 6.4.0 + resolution: "@rari-capital/solmate@npm:6.4.0" + checksum: 27c656f72ce9b51ab6ec25165ae5426f74af934352eca062eb8419c4cf7fc4c6debf45487afd6bee7860e38b7c33d3a6d353a0d4c176c961c9c8125d30cf52a4 + languageName: node + linkType: hard + "@resolver-engine/core@npm:^0.3.3": version: 0.3.3 resolution: "@resolver-engine/core@npm:0.3.3" @@ -1729,10 +2009,10 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.4": - version: 1.1.5 - resolution: "@scure/base@npm:1.1.5" - checksum: 9e9ee6088cb3aa0fb91f5a48497d26682c7829df3019b1251d088d166d7a8c0f941c68aaa8e7b96bbad20c71eb210397cb1099062cde3e29d4bad6b975c18519 +"@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2, @scure/base@npm:~1.1.6": + version: 1.1.7 + resolution: "@scure/base@npm:1.1.7" + checksum: d9084be9a2f27971df1684af9e40bb750e86f549345e1bb3227fb61673c0c83569c92c1cb0a4ddccb32650b39d3cd3c145603b926ba751c9bc60c27317549b20 languageName: node linkType: hard @@ -1747,14 +2027,25 @@ __metadata: languageName: node linkType: hard -"@scure/bip32@npm:1.3.3": - version: 1.3.3 - resolution: "@scure/bip32@npm:1.3.3" +"@scure/bip32@npm:1.3.2": + version: 1.3.2 + resolution: "@scure/bip32@npm:1.3.2" dependencies: - "@noble/curves": ~1.3.0 + "@noble/curves": ~1.2.0 "@noble/hashes": ~1.3.2 - "@scure/base": ~1.1.4 - checksum: f939ca733972622fcc1e61d4fdf170a0ad294b24ddb7ed7cdd4c467e1ef283b970154cb101cf5f1a7b64cf5337e917ad31135911dfc36b1d76625320167df2fa + "@scure/base": ~1.1.2 + checksum: c5ae84fae43490853693b481531132b89e056d45c945fc8b92b9d032577f753dfd79c5a7bbcbf0a7f035951006ff0311b6cf7a389e26c9ec6335e42b20c53157 + languageName: node + linkType: hard + +"@scure/bip32@npm:1.4.0": + version: 1.4.0 + resolution: "@scure/bip32@npm:1.4.0" + dependencies: + "@noble/curves": ~1.4.0 + "@noble/hashes": ~1.4.0 + "@scure/base": ~1.1.6 + checksum: eff491651cbf2bea8784936de75af5fc020fc1bbb9bcb26b2cfeefbd1fb2440ebfaf30c0733ca11c0ae1e272a2ef4c3c34ba5c9fb3e1091c3285a4272045b0c6 languageName: node linkType: hard @@ -1768,13 +2059,23 @@ __metadata: languageName: node linkType: hard -"@scure/bip39@npm:1.2.2": - version: 1.2.2 - resolution: "@scure/bip39@npm:1.2.2" +"@scure/bip39@npm:1.2.1": + version: 1.2.1 + resolution: "@scure/bip39@npm:1.2.1" dependencies: - "@noble/hashes": ~1.3.2 - "@scure/base": ~1.1.4 - checksum: cb99505e6d2deef8e55e81df8c563ce8dbfdf1595596dc912bceadcf366c91b05a98130e928ecb090df74efdb20150b64acc4be55bc42768cab4d39a2833d234 + "@noble/hashes": ~1.3.0 + "@scure/base": ~1.1.0 + checksum: c5bd6f1328fdbeae2dcdd891825b1610225310e5e62a4942714db51066866e4f7bef242c7b06a1b9dcc8043a4a13412cf5c5df76d3b10aa9e36b82e9b6e3eeaa + languageName: node + linkType: hard + +"@scure/bip39@npm:1.3.0": + version: 1.3.0 + resolution: "@scure/bip39@npm:1.3.0" + dependencies: + "@noble/hashes": ~1.4.0 + "@scure/base": ~1.1.6 + checksum: dbb0b27df753eb6c6380010b25cc9a9ea31f9cb08864fc51e69e5880ff7e2b8f85b72caea1f1f28af165e83b72c48dd38617e43fc632779d025b50ba32ea759e languageName: node linkType: hard @@ -1874,12 +2175,12 @@ __metadata: languageName: node linkType: hard -"@smithy/types@npm:^2.9.1": - version: 2.9.1 - resolution: "@smithy/types@npm:2.9.1" +"@smithy/types@npm:^3.1.0": + version: 3.2.0 + resolution: "@smithy/types@npm:3.2.0" dependencies: - tslib: ^2.5.0 - checksum: 8570affb4abb5d0ead57293977fc915d44be481120defcabb87a3fb1c7b5d2501b117835eca357b5d54ea4bbee08032f9dc3d909ecbf0abb0cec2ca9678ae7bd + tslib: ^2.6.2 + checksum: f07caa63cd2f1ed9a14612a9493fcc9c0aca974593e16c1328daecc7f36af2ece5e5e79c24212966180f88a183abf078bfbcd98cf362a8d8f95f3f8642d41389 languageName: node linkType: hard @@ -1933,10 +2234,30 @@ __metadata: languageName: node linkType: hard +"@trufflesuite/bigint-buffer@npm:1.1.10": + version: 1.1.10 + resolution: "@trufflesuite/bigint-buffer@npm:1.1.10" + dependencies: + node-gyp: latest + node-gyp-build: 4.4.0 + checksum: e1dc5e4fbf348a55e660c0055267021eb04cbbdb7f6b0ee983ad32cd4aae1200be448a2ca3963c7d19c7c936d42f66c1ff8b5e4e2332cb1a9e3f870ff818dce4 + languageName: node + linkType: hard + +"@trufflesuite/bigint-buffer@npm:1.1.9": + version: 1.1.9 + resolution: "@trufflesuite/bigint-buffer@npm:1.1.9" + dependencies: + node-gyp: latest + node-gyp-build: 4.3.0 + checksum: 627dcff2cae7afe31432646232518363869e89b300f90f88ca68d903d0bdc79119975a5bc338223c03c1a4484cfac6d9cf4413ef20933a69eee48dd925519165 + languageName: node + linkType: hard + "@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df + version: 1.0.11 + resolution: "@tsconfig/node10@npm:1.0.11" + checksum: 51fe47d55fe1b80ec35e6e5ed30a13665fd3a531945350aa74a14a1e82875fb60b350c2f2a5e72a64831b1b6bc02acb6760c30b3738b54954ec2dea82db7a267 languageName: node linkType: hard @@ -1961,7 +2282,7 @@ __metadata: languageName: node linkType: hard -"@typechain/ethers-v5@npm:^10.1.0": +"@typechain/ethers-v5@npm:^10.0.0, @typechain/ethers-v5@npm:^10.1.0": version: 10.2.1 resolution: "@typechain/ethers-v5@npm:10.2.1" dependencies: @@ -1989,6 +2310,20 @@ __metadata: languageName: node linkType: hard +"@typechain/ethers-v6@npm:^0.5.1": + version: 0.5.1 + resolution: "@typechain/ethers-v6@npm:0.5.1" + dependencies: + lodash: ^4.17.15 + ts-essentials: ^7.0.1 + peerDependencies: + ethers: 6.x + typechain: ^8.3.2 + typescript: ">=4.7.0" + checksum: 44e7970ce95eeb1a02019f8a53bbe30dcb87664e1df15fe436ae48eea1bf91ca72b5b230eac1bdf9cbe9b55bc488b54c6273e6f77155eaeff885fb34cfcd1108 + languageName: node + linkType: hard + "@typechain/hardhat@npm:^6.1.2": version: 6.1.6 resolution: "@typechain/hardhat@npm:6.1.6" @@ -2005,12 +2340,10 @@ __metadata: languageName: node linkType: hard -"@types/async-eventemitter@npm:^0.2.1": - version: 0.2.4 - resolution: "@types/async-eventemitter@npm:0.2.4" - dependencies: - "@types/events": "*" - checksum: cee62e258cf02a45688a3f6f517b623270a9c2779dfd2f53b52e0efbcb0282d7078c3ce1fafb2af257aefdb892acc09ba51d93647930885414ec719437430bf7 +"@types/abstract-leveldown@npm:*": + version: 7.2.5 + resolution: "@types/abstract-leveldown@npm:7.2.5" + checksum: 3a99b13c81a53a62b42bea9cff326880de3146b4eeff528b039be69a268515b3120a6c12142e96646fcb0a03c463f298998581e86d9ddb29fbea3612f40edb2b languageName: node linkType: hard @@ -2054,9 +2387,9 @@ __metadata: linkType: hard "@types/chai@npm:*, @types/chai@npm:^4.3.1": - version: 4.3.11 - resolution: "@types/chai@npm:4.3.11" - checksum: d0c05fe5d02b2e6bbca2bd4866a2ab20a59cf729bc04af0060e7a3277eaf2fb65651b90d4c74b0ebf1d152b4b1d49fa8e44143acef276a2bbaa7785fbe5642d3 + version: 4.3.16 + resolution: "@types/chai@npm:4.3.16" + checksum: bb5f52d1b70534ed8b4bf74bd248add003ffe1156303802ea367331607c06b494da885ffbc2b674a66b4f90c9ee88759790a5f243879f6759f124f22328f5e95 languageName: node linkType: hard @@ -2085,13 +2418,6 @@ __metadata: languageName: node linkType: hard -"@types/events@npm:*": - version: 3.0.3 - resolution: "@types/events@npm:3.0.3" - checksum: 50af9312fab001fd6bd4bb3ff65830f940877e6778de140a92481a0d9bf5f4853d44ec758a8800ef60e0598ac43ed1b5688116a3c65906ae54e989278d6c7c82 - languageName: node - linkType: hard - "@types/form-data@npm:0.0.33": version: 0.0.33 resolution: "@types/form-data@npm:0.0.33" @@ -2141,6 +2467,24 @@ __metadata: languageName: node linkType: hard +"@types/level-errors@npm:*": + version: 3.0.2 + resolution: "@types/level-errors@npm:3.0.2" + checksum: 3d9b801f6499f795b60ac723c1b3f93ca105f20ed26966eeb606c804b10c65984c3233fb99914644d75a3223f80f220eca74fda316640a85a5b3d7572cd86925 + languageName: node + linkType: hard + +"@types/levelup@npm:^4.3.0": + version: 4.3.3 + resolution: "@types/levelup@npm:4.3.3" + dependencies: + "@types/abstract-leveldown": "*" + "@types/level-errors": "*" + "@types/node": "*" + checksum: 04969bb805035960b8d6650e8f76893be7ba70267bb7012f6f00d67a0cf096ada552355629791b3f5925e9cdb6912d3fe08892c33c3c583e8fd02099b573bdd7 + languageName: node + linkType: hard + "@types/long@npm:^4.0.1": version: 4.0.2 resolution: "@types/long@npm:4.0.2" @@ -2148,7 +2492,7 @@ __metadata: languageName: node linkType: hard -"@types/lru-cache@npm:^5.1.0": +"@types/lru-cache@npm:5.1.1, @types/lru-cache@npm:^5.1.0": version: 5.1.1 resolution: "@types/lru-cache@npm:5.1.1" checksum: e1d6c0085f61b16ec5b3073ec76ad1be4844ea036561c3f145fc19f71f084b58a6eb600b14128aa95809d057d28f1d147c910186ae51219f58366ffd2ff2e118 @@ -2185,7 +2529,7 @@ __metadata: languageName: node linkType: hard -"@types/node-fetch@npm:^2.5.5": +"@types/node-fetch@npm:^2.5.5, @types/node-fetch@npm:^2.6.1": version: 2.6.11 resolution: "@types/node-fetch@npm:2.6.11" dependencies: @@ -2196,11 +2540,25 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:>=13.7.0": - version: 20.11.16 - resolution: "@types/node@npm:20.11.16" + version: 20.14.5 + resolution: "@types/node@npm:20.14.5" dependencies: undici-types: ~5.26.4 - checksum: 51f0831c1219bf4698e7430aeb9892237bd851deeb25ce23c5bb0ceefcc77c3b114e48f4e98d9fc26def5a87ba9d8079f0281dd37bee691140a93f133812c152 + checksum: b337784407edbdd374b25149e9dfce80368846a9b0dc5b7d88a2591572ec87a5d87c11c9ddc1906294aef26a1ad889d56be8b08de6be3ce1256b8d9a836bc7d8 + languageName: node + linkType: hard + +"@types/node@npm:11.11.6": + version: 11.11.6 + resolution: "@types/node@npm:11.11.6" + checksum: 075f1c011cf568e49701419acbcb55c24906b3bb5a34d9412a3b88f228a7a78401a5ad4d3e1cd6855c99aaea5ef96e37fc86ca097e50f06da92cf822befc1fff + languageName: node + linkType: hard + +"@types/node@npm:18.15.13": + version: 18.15.13 + resolution: "@types/node@npm:18.15.13" + checksum: 79cc5a2b5f98e8973061a4260a781425efd39161a0e117a69cd089603964816c1a14025e1387b4590c8e82d05133b7b4154fa53a7dffb3877890a66145e76515 languageName: node linkType: hard @@ -2219,11 +2577,11 @@ __metadata: linkType: hard "@types/node@npm:^18.6.1": - version: 18.19.14 - resolution: "@types/node@npm:18.19.14" + version: 18.19.36 + resolution: "@types/node@npm:18.19.36" dependencies: undici-types: ~5.26.4 - checksum: 3d42b50e649f18c6ca7044714eaeb51ba5fda463c845eeb1973bcbbfcab8e93179501fbf865e675cb0c7a5e59f7ea18eca8296b52c2455c856aa45c77ae815dc + checksum: 97fce6e862fd1853ae3e0c4ed5c87181d18af1646c367a22befc17697bc68a98401dc037219630a90d2e27032bf1a2306cf876ce709c553c3f42585584fe2c7a languageName: node linkType: hard @@ -2258,19 +2616,9 @@ __metadata: linkType: hard "@types/qs@npm:^6.2.31": - version: 6.9.11 - resolution: "@types/qs@npm:6.9.11" - checksum: 620ca1628bf3da65662c54ed6ebb120b18a3da477d0bfcc872b696685a9bb1893c3c92b53a1190a8f54d52eaddb6af8b2157755699ac83164604329935e8a7f2 - languageName: node - linkType: hard - -"@types/readable-stream@npm:^2.3.13": - version: 2.3.15 - resolution: "@types/readable-stream@npm:2.3.15" - dependencies: - "@types/node": "*" - safe-buffer: ~5.1.1 - checksum: ec36f525cad09b6c65a1dafcb5ad99b9e2ed824ec49b7aa23180ac427e5d35b8a0706193ecd79ab4253a283ad485ba03d5917a98daaaa144f0ea34f4823e9d82 + version: 6.9.15 + resolution: "@types/qs@npm:6.9.15" + checksum: 97d8208c2b82013b618e7a9fc14df6bd40a73e1385ac479b6896bafc7949a46201c15f42afd06e86a05e914f146f495f606b6fb65610cc60cf2e0ff743ec38a2 languageName: node linkType: hard @@ -2301,10 +2649,17 @@ __metadata: languageName: node linkType: hard +"@types/seedrandom@npm:3.0.1": + version: 3.0.1 + resolution: "@types/seedrandom@npm:3.0.1" + checksum: d9755452f224a4f5072a1d8738da6c9de3039fc59a2a449b1f658e51087be7b48ada49bcabc8b0f16633c095f55598c32fcd072c448858422a2f6a0566569e4c + languageName: node + linkType: hard + "@types/semver@npm:^7.3.12": - version: 7.5.6 - resolution: "@types/semver@npm:7.5.6" - checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 languageName: node linkType: hard @@ -2538,6 +2893,64 @@ __metadata: languageName: node linkType: hard +"@uniswap/lib@npm:1.1.1": + version: 1.1.1 + resolution: "@uniswap/lib@npm:1.1.1" + checksum: 2ec6689f606a0cf7dc7acd8b7471997638b2c89202c52743dcb4dfc0df182f6e058ec1a5e4d94a872c81bb85cbcde9e4a46b6de45eea0d34582627d97e743c7b + languageName: node + linkType: hard + +"@uniswap/lib@npm:^4.0.1-alpha": + version: 4.0.1-alpha + resolution: "@uniswap/lib@npm:4.0.1-alpha" + checksum: d7bbacccef40966af16c7e215ab085f575686d316b2802c9e1cfd03f7ad351970e547535670a28b2279c3cfcc4fb02888614c46f94efe2987af2309f3ec86127 + languageName: node + linkType: hard + +"@uniswap/v2-core@npm:1.0.0": + version: 1.0.0 + resolution: "@uniswap/v2-core@npm:1.0.0" + checksum: 41e42ad801dbc058ebf0ab38a8ce3195990e21eff4b2d49cd0a8c8fd25ac067feed55c379f2be22d915a7601d94966ae66127b748b2d3acde20eeb2351e51703 + languageName: node + linkType: hard + +"@uniswap/v2-core@npm:^1.0.1": + version: 1.0.1 + resolution: "@uniswap/v2-core@npm:1.0.1" + checksum: eaa118fe45eac2e80b7468547ce2cde12bd3c8157555d2e40e0462a788c9506c6295247b511382da85e44a89ad92aff7bb3433b23bfbd2eeea23942ecd46e979 + languageName: node + linkType: hard + +"@uniswap/v2-periphery@npm:^1.1.0-beta.0": + version: 1.1.0-beta.0 + resolution: "@uniswap/v2-periphery@npm:1.1.0-beta.0" + dependencies: + "@uniswap/lib": 1.1.1 + "@uniswap/v2-core": 1.0.0 + checksum: af13224c9f28f817be6e5794a7590b8433788e5387912343a8d61227a42b494b431fe6e549505e87d96a6896e96e289f80d92c68788eea4917596ec7fd94734e + languageName: node + linkType: hard + +"@uniswap/v3-core@npm:^1.0.0": + version: 1.0.1 + resolution: "@uniswap/v3-core@npm:1.0.1" + checksum: 4bfd8b218391a3d9efde44e0f984cfec3bc25889cd4d1386766828521006e71b210a3583ee32b52f3c81d384af9e8c39f471f2229e9af4d50da6801446ecb3e4 + languageName: node + linkType: hard + +"@uniswap/v3-periphery@npm:^1.1.0": + version: 1.4.4 + resolution: "@uniswap/v3-periphery@npm:1.4.4" + dependencies: + "@openzeppelin/contracts": 3.4.2-solc-0.7 + "@uniswap/lib": ^4.0.1-alpha + "@uniswap/v2-core": ^1.0.1 + "@uniswap/v3-core": ^1.0.0 + base64-sol: 1.0.1 + checksum: 48b57f1f648cb002935421ac1770666ab3c0263885a03c769985b06501b88d513a435c8edc439b41ac5aef7ad40a11038a3561f7e828cce5ae6ec2c77742f1af + languageName: node + linkType: hard + "@yarnpkg/lockfile@npm:^1.1.0": version: 1.1.0 resolution: "@yarnpkg/lockfile@npm:1.1.0" @@ -2590,6 +3003,21 @@ __metadata: languageName: node linkType: hard +"abitype@npm:1.0.0": + version: 1.0.0 + resolution: "abitype@npm:1.0.0" + peerDependencies: + typescript: ">=5.0.4" + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + checksum: ea2c0548c3ba58c37a6de7483d63389074da498e63d803b742bbe94eb4eaa1f51a35d000c424058b2583aef56698cf07c696eb3bc4dd0303bc20c6f0826a241a + languageName: node + linkType: hard + "abort-controller@npm:^3.0.0": version: 3.0.0 resolution: "abort-controller@npm:3.0.0" @@ -2599,21 +3027,6 @@ __metadata: languageName: node linkType: hard -"abstract-level@npm:^1.0.0, abstract-level@npm:^1.0.2, abstract-level@npm:^1.0.3, abstract-level@npm:^1.0.4": - version: 1.0.4 - resolution: "abstract-level@npm:1.0.4" - dependencies: - buffer: ^6.0.3 - catering: ^2.1.0 - is-buffer: ^2.0.5 - level-supports: ^4.0.0 - level-transcoder: ^1.0.1 - module-error: ^1.0.1 - queue-microtask: ^1.2.3 - checksum: 5b70d08926f5234c3c23ffca848542af4def780dc96d6ca35a81659af80e6439c46f5106bd14a5ea37465173d7dcc8294317048b0194fdf6480103edc4aa9e63 - languageName: node - linkType: hard - "abstract-leveldown@npm:3.0.0": version: 3.0.0 resolution: "abstract-leveldown@npm:3.0.0" @@ -2641,6 +3054,33 @@ __metadata: languageName: node linkType: hard +"abstract-leveldown@npm:^6.2.1": + version: 6.3.0 + resolution: "abstract-leveldown@npm:6.3.0" + dependencies: + buffer: ^5.5.0 + immediate: ^3.2.3 + level-concat-iterator: ~2.0.0 + level-supports: ~1.0.0 + xtend: ~4.0.0 + checksum: 121a8509d8c6a540e656c2a69e5b8d853d4df71072011afefc868b98076991bb00120550e90643de9dc18889c675f62413409eeb4c8c204663124c7d215e4ec3 + languageName: node + linkType: hard + +"abstract-leveldown@npm:^7.2.0": + version: 7.2.0 + resolution: "abstract-leveldown@npm:7.2.0" + dependencies: + buffer: ^6.0.3 + catering: ^2.0.0 + is-buffer: ^2.0.5 + level-concat-iterator: ^3.0.0 + level-supports: ^2.0.1 + queue-microtask: ^1.2.3 + checksum: d558111f2d123da95ac80b8ba3b9b0a5bc8cd87296e64b05dca693f5f4839aa0e2fc97bad56a101766f499824e2962611750f8a76bbac4a5db35801968fbbe02 + languageName: node + linkType: hard + "abstract-leveldown@npm:~2.6.0": version: 2.6.3 resolution: "abstract-leveldown@npm:2.6.3" @@ -2650,6 +3090,19 @@ __metadata: languageName: node linkType: hard +"abstract-leveldown@npm:~6.2.1": + version: 6.2.3 + resolution: "abstract-leveldown@npm:6.2.3" + dependencies: + buffer: ^5.5.0 + immediate: ^3.2.3 + level-concat-iterator: ~2.0.0 + level-supports: ~1.0.0 + xtend: ~4.0.0 + checksum: 00202b2eb7955dd7bc04f3e44d225e60160cedb8f96fe6ae0e6dca9c356d57071f001ece8ae1d53f48095c4c036d92b3440f2bc7666730610ddea030f9fbde4a + languageName: node + linkType: hard + "accepts@npm:~1.3.8": version: 1.3.8 resolution: "accepts@npm:1.3.8" @@ -2670,9 +3123,11 @@ __metadata: linkType: hard "acorn-walk@npm:^8.1.1": - version: 8.3.2 - resolution: "acorn-walk@npm:8.3.2" - checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 + version: 8.3.3 + resolution: "acorn-walk@npm:8.3.3" + dependencies: + acorn: ^8.11.0 + checksum: 0f09d351fc30b69b2b9982bf33dc30f3d35a34e030e5f1ed3c49fc4e3814a192bf3101e4c30912a0595410f5e91bb70ddba011ea73398b3ecbfe41c7334c6dd0 languageName: node linkType: hard @@ -2685,19 +3140,12 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.4.1, acorn@npm:^8.9.0": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" +"acorn@npm:^8.11.0, acorn@npm:^8.4.1, acorn@npm:^8.9.0": + version: 8.12.0 + resolution: "acorn@npm:8.12.0" bin: acorn: bin/acorn - checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c - languageName: node - linkType: hard - -"address@npm:^1.0.1": - version: 1.2.2 - resolution: "address@npm:1.2.2" - checksum: ace439960c1e3564d8f523aff23a841904bf33a2a7c2e064f7f60a064194075758b9690e65bd9785692a4ef698a998c57eb74d145881a1cecab8ba658ddb1607 + checksum: ae142de8739ef15a5d936c550c1d267fc4dedcdbe62ad1aa2c0009afed1de84dd0a584684a5d200bb55d8db14f3e09a95c6e92a5303973c04b9a7413c36d1df0 languageName: node linkType: hard @@ -2715,6 +3163,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:4.0.0-beta.5": + version: 4.0.0-beta.5 + resolution: "aes-js@npm:4.0.0-beta.5" + checksum: cc2ea969d77df939c32057f7e361b6530aa6cb93cb10617a17a45cd164e6d761002f031ff6330af3e67e58b1f0a3a8fd0b63a720afd591a653b02f649470e15b + languageName: node + linkType: hard + "aes-js@npm:^3.1.1": version: 3.1.2 resolution: "aes-js@npm:3.1.2" @@ -2731,12 +3186,12 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" dependencies: debug: ^4.3.4 - checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + checksum: 51c158769c5c051482f9ca2e6e1ec085ac72b5a418a9b31b4e82fe6c0a6699adb94c1c42d246699a587b3335215037091c79e0de512c516f73b6ea844202f037 languageName: node linkType: hard @@ -2763,27 +3218,27 @@ __metadata: linkType: hard "ajv@npm:^8.0.1": - version: 8.12.0 - resolution: "ajv@npm:8.12.0" + version: 8.16.0 + resolution: "ajv@npm:8.16.0" dependencies: - fast-deep-equal: ^3.1.1 + fast-deep-equal: ^3.1.3 json-schema-traverse: ^1.0.0 require-from-string: ^2.0.2 - uri-js: ^4.2.2 - checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001 + uri-js: ^4.4.1 + checksum: bdf3d4c9f1d11e220850051ef4cd89346e951cfb933d6d41be36d45053c1092af1523ee6c62525cce567355caf0a4f4c19a08a93851649c1fa32b4a39b7c4858 languageName: node linkType: hard -"amazon-cognito-identity-js@npm:^6.0.1": - version: 6.3.10 - resolution: "amazon-cognito-identity-js@npm:6.3.10" +"amazon-cognito-identity-js@npm:^6.0.1, amazon-cognito-identity-js@npm:^6.3.6": + version: 6.3.13 + resolution: "amazon-cognito-identity-js@npm:6.3.13" dependencies: "@aws-crypto/sha256-js": 1.2.2 buffer: 4.9.2 fast-base64-decode: ^1.0.0 isomorphic-unfetch: ^3.0.0 js-cookie: ^2.2.1 - checksum: c82aaaff8a0e9485d00c3c2541d5bfdea0112c2eced27bc9cbdf9a92c31aa6bcc2e389e429582e6aa115f5fd0394843f47c09bae84ec0c649ddcac16d6fa6756 + checksum: 8a608ef1b99fca57d87103ceb2706d38e499a548d7724f194d50a709fa564ec63dbc703ded6a106e112d5443d06859f40e242815c25c465fdee4806bbce79459 languageName: node linkType: hard @@ -2794,6 +3249,15 @@ __metadata: languageName: node linkType: hard +"ampleforth-contracts@https://github.com/ampleforth/ampleforth-contracts#master": + version: 0.0.1 + resolution: "ampleforth-contracts@https://github.com/ampleforth/ampleforth-contracts.git#commit=d6cbb023e670159edf85fb6386c47fd7b6b0f6e9" + dependencies: + "@openzeppelin/contracts-upgradeable": ^4.7.3 + checksum: c5d1283826fd8057d1c14ca37e83c5a918d8da2e330b5da7ebb6cd944027285f4fd01009e72bbf496769aff7303e776c81067654246a8b25c8c1b0de494efb5d + languageName: node + linkType: hard + "ansi-align@npm:^3.0.0": version: 3.0.1 resolution: "ansi-align@npm:3.0.1" @@ -3035,7 +3499,7 @@ __metadata: languageName: node linkType: hard -"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1": +"array-buffer-byte-length@npm:^1.0.1": version: 1.0.1 resolution: "array-buffer-byte-length@npm:1.0.1" dependencies: @@ -3053,15 +3517,16 @@ __metadata: linkType: hard "array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 is-string: ^1.0.7 - checksum: 06f9e4598fac12a919f7c59a3f04f010ea07f0b7f0585465ed12ef528a60e45f374e79d1bddbb34cdd4338357d00023ddbd0ac18b0be36964f5e726e8965d7fc + checksum: eb39ba5530f64e4d8acab39297c11c1c5be2a4ea188ab2b34aba5fb7224d918f77717a9d57a3e2900caaa8440e59431bdaf5c974d5212ef65d97f132e38e2d91 languageName: node linkType: hard @@ -3086,42 +3551,31 @@ __metadata: languageName: node linkType: hard -"array.prototype.filter@npm:^1.0.3": - version: 1.0.3 - resolution: "array.prototype.filter@npm:1.0.3" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-array-method-boxes-properly: ^1.0.0 - is-string: ^1.0.7 - checksum: 5443cde6ad64596649e5751252b1b2f5242b41052980c2fb2506ba485e3ffd7607e8f6f2f1aefa0cb1cfb9b8623b2b2be103579cb367a161a3426400619b6e73 - languageName: node - linkType: hard - "array.prototype.findlast@npm:^1.2.2": - version: 1.2.3 - resolution: "array.prototype.findlast@npm:1.2.3" + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.2.1 - checksum: 853d359bac5c4ce7354e5f2f2930f09eb47eeed18b6d6fb630cf6fa1fe4f32217fd27d07ee4aeeb3d1fd710538cf7bc00d4efc34df64da49fff0b13f57b0d66f + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-shim-unscopables: ^1.0.2 + checksum: 83ce4ad95bae07f136d316f5a7c3a5b911ac3296c3476abe60225bc4a17938bf37541972fcc37dd5adbc99cbb9c928c70bbbfc1c1ce549d41a415144030bb446 languageName: node linkType: hard "array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.3 - resolution: "array.prototype.findlastindex@npm:1.2.3" + version: 1.2.5 + resolution: "array.prototype.findlastindex@npm:1.2.5" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.2.1 - checksum: 31f35d7b370c84db56484618132041a9af401b338f51899c2e78ef7690fbba5909ee7ca3c59a7192085b328cc0c68c6fd1f6d1553db01a689a589ae510f3966e + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-shim-unscopables: ^1.0.2 + checksum: 2c81cff2a75deb95bf1ed89b6f5f2bfbfb882211e3b7cc59c3d6b87df774cd9d6b36949a8ae39ac476e092c1d4a4905f5ee11a86a456abb10f35f8211ae4e710 languageName: node linkType: hard @@ -3150,19 +3604,21 @@ __metadata: linkType: hard "array.prototype.reduce@npm:^1.0.6": - version: 1.0.6 - resolution: "array.prototype.reduce@npm:1.0.6" + version: 1.0.7 + resolution: "array.prototype.reduce@npm:1.0.7" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 es-array-method-boxes-properly: ^1.0.0 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 is-string: ^1.0.7 - checksum: c709c3f5caa2aac4fb10e0c6c1982cca50328a2a48658d53b1da8ee3a78069ad67cdac21296d6285521aa3a932a8178c0e192b5fc831fae2977b69a5a8a64ad7 + checksum: 90303617bd70c8e9a81ebff041d3e10fad1a97f163699cb015b7c84a3f9e6960d9bb161a30f1d0309d6e476f166af5668c1e24f7add3202213d25f7c7f15475d languageName: node linkType: hard -"arraybuffer.prototype.slice@npm:^1.0.2": +"arraybuffer.prototype.slice@npm:^1.0.3": version: 1.0.3 resolution: "arraybuffer.prototype.slice@npm:1.0.3" dependencies: @@ -3185,15 +3641,14 @@ __metadata: languageName: node linkType: hard -"asn1.js@npm:^5.2.0": - version: 5.4.1 - resolution: "asn1.js@npm:5.4.1" +"asn1.js@npm:^4.10.1": + version: 4.10.1 + resolution: "asn1.js@npm:4.10.1" dependencies: bn.js: ^4.0.0 inherits: ^2.0.1 minimalistic-assert: ^1.0.0 - safer-buffer: ^2.1.0 - checksum: 3786a101ac6f304bd4e9a7df79549a7561950a13d4bcaec0c7790d44c80d147c1a94ba3d4e663673406064642a40b23fcd6c82a9952468e386c1a1376d747f9a + checksum: 9289a1a55401238755e3142511d7b8f6fc32f08c86ff68bd7100da8b6c186179dd6b14234fba2f7f6099afcd6758a816708485efe44bc5b2a6ec87d9ceeddbb5 languageName: node linkType: hard @@ -3219,7 +3674,7 @@ __metadata: bin: asc: bin/asc asinit: bin/asinit - checksum: 8a407db6179addfaa5fcc637543a755ecc22ae8dd5e8259492305afd0d2bb73eae019d4178f79b515f75648d71dfda2c1ceb0c7421bff7817aebb2e2f5c8bfe7 + checksum: 08fde3fd50e3c67c2e057c83963f65f9f4a710380b6040727fd87b3a162795c498de603a3bc68ceb1da7ec4b5e31e9d61ec6ea961a0ba228b91584f18c197e98 languageName: node linkType: hard @@ -3338,10 +3793,12 @@ __metadata: languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.5, available-typed-arrays@npm:^1.0.6": - version: 1.0.6 - resolution: "available-typed-arrays@npm:1.0.6" - checksum: 8295571eb86447138adf64a0df0c08ae61250b17190bba30e1fae8c80a816077a6d028e5506f602c382c0197d3080bae131e92e331139d55460989580eeae659 +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: ^1.0.0 + checksum: 1aa3ffbfe6578276996de660848b6e95669d9a95ad149e3dd0c0cda77db6ee1dbd9d1dd723b65b6d277b882dd0c4b91a654ae9d3cf9e1254b7e93e4908d78fd3 languageName: node linkType: hard @@ -3353,9 +3810,9 @@ __metadata: linkType: hard "aws4@npm:^1.8.0": - version: 1.12.0 - resolution: "aws4@npm:1.12.0" - checksum: 68f79708ac7c335992730bf638286a3ee0a645cf12575d557860100767c500c08b30e24726b9f03265d74116417f628af78509e1333575e9f8d52a80edfe8cbc + version: 1.13.0 + resolution: "aws4@npm:1.13.0" + checksum: 71594a17a5f7b1a9151ef515500c18f1029caa51e2cb65c1b5b324d9bd8dac89896a9e296825d4e6befdcd612d7fc3b0d8042c667555a56df3ee1ab15d4d9b35 languageName: node linkType: hard @@ -3368,14 +3825,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.4.0, axios@npm:^1.5.1": - version: 1.6.7 - resolution: "axios@npm:1.6.7" +"axios@npm:^1.4.0, axios@npm:^1.5.1, axios@npm:^1.6.7, axios@npm:^1.6.8": + version: 1.7.2 + resolution: "axios@npm:1.7.2" dependencies: - follow-redirects: ^1.15.4 + follow-redirects: ^1.15.6 form-data: ^4.0.0 proxy-from-env: ^1.1.0 - checksum: 87d4d429927d09942771f3b3a6c13580c183e31d7be0ee12f09be6d5655304996bb033d85e54be81606f4e89684df43be7bf52d14becb73a12727bf33298a082 + checksum: e457e2b0ab748504621f6fa6609074ac08c824bf0881592209dfa15098ece7e88495300e02cd22ba50b3468fd712fe687e629dcb03d6a3f6a51989727405aedf languageName: node linkType: hard @@ -4040,6 +4497,13 @@ __metadata: languageName: node linkType: hard +"base64-sol@npm:1.0.1": + version: 1.0.1 + resolution: "base64-sol@npm:1.0.1" + checksum: be0f9e8cf3c744256913223fbae8187773f530cc096e98a77f49ef0bd6cedeb294d15a784e439419f7cb99f07bf85b08999169feafafa1a9e29c3affc0bc6d0a + languageName: node + linkType: hard + "base@npm:^0.11.1": version: 0.11.2 resolution: "base@npm:0.11.2" @@ -4071,13 +4535,6 @@ __metadata: languageName: node linkType: hard -"bigint-crypto-utils@npm:^3.0.23": - version: 3.3.0 - resolution: "bigint-crypto-utils@npm:3.3.0" - checksum: 9598ce57b23f776c8936d44114c9f051e62b5fa654915b664784cbcbacc5aa0485f4479571c51ff58008abb1210c0d6a234853742f07cf84bda890f2a1e01000 - languageName: node - linkType: hard - "bignumber.js@npm:^9.0.0": version: 9.1.2 resolution: "bignumber.js@npm:9.1.2" @@ -4086,9 +4543,9 @@ __metadata: linkType: hard "binary-extensions@npm:^2.0.0": - version: 2.2.0 - resolution: "binary-extensions@npm:2.2.0" - checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 + version: 2.3.0 + resolution: "binary-extensions@npm:2.3.0" + checksum: bcad01494e8a9283abf18c1b967af65ee79b0c6a9e6fcfafebfe91dbe6e0fc7272bafb73389e198b310516ae04f7ad17d79aacf6cb4c0d5d5202a7e2e52c7d98 languageName: node linkType: hard @@ -4116,6 +4573,18 @@ __metadata: languageName: node linkType: hard +"bip39@npm:3.0.4": + version: 3.0.4 + resolution: "bip39@npm:3.0.4" + dependencies: + "@types/node": 11.11.6 + create-hash: ^1.1.0 + pbkdf2: ^3.0.9 + randombytes: ^2.0.1 + checksum: 79ce1600a03d1ba5053bdd4e6323f9463ec340764c7e52918b6c6b9dca81221940f2d9a65656447f108f9bc2c8d9ae8df319cca83bbd1dad63f53ef2768d9bae + languageName: node + linkType: hard + "bl@npm:^1.0.0": version: 1.2.3 resolution: "bl@npm:1.2.3" @@ -4156,7 +4625,7 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.10.0, bn.js@npm:^4.11.0, bn.js@npm:^4.11.6, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9, bn.js@npm:^4.8.0": +"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.10.0, bn.js@npm:^4.11.0, bn.js@npm:^4.11.1, bn.js@npm:^4.11.6, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9, bn.js@npm:^4.8.0": version: 4.12.0 resolution: "bn.js@npm:4.12.0" checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 @@ -4170,27 +4639,7 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:1.20.1": - version: 1.20.1 - resolution: "body-parser@npm:1.20.1" - dependencies: - bytes: 3.1.2 - content-type: ~1.0.4 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: ~1.6.18 - unpipe: 1.0.0 - checksum: f1050dbac3bede6a78f0b87947a8d548ce43f91ccc718a50dd774f3c81f2d8b04693e52acf62659fad23101827dd318da1fb1363444ff9a8482b886a3e4a5266 - languageName: node - linkType: hard - -"body-parser@npm:^1.16.0": +"body-parser@npm:1.20.2, body-parser@npm:^1.16.0": version: 1.20.2 resolution: "body-parser@npm:1.20.2" dependencies: @@ -4263,12 +4712,12 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2, braces@npm:~3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" +"braces@npm:^3.0.3, braces@npm:~3.0.2": + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + fill-range: ^7.1.1 + checksum: b95aa0b3bd909f6cd1720ffcf031aeaf46154dd88b4da01f9a1d3f7ea866a79eba76a6d01cbc3c422b2ee5cdc39a4f02491058d5df0d7bf6e6a162a832df1f69 languageName: node linkType: hard @@ -4279,15 +4728,10 @@ __metadata: languageName: node linkType: hard -"browser-level@npm:^1.0.1": - version: 1.0.1 - resolution: "browser-level@npm:1.0.1" - dependencies: - abstract-level: ^1.0.2 - catering: ^2.1.1 - module-error: ^1.0.2 - run-parallel-limit: ^1.1.0 - checksum: 67fbc77ce832940bfa25073eccff279f512ad56f545deb996a5b23b02316f5e76f4a79d381acc27eda983f5c9a2566aaf9c97e4fdd0748288c4407307537a29b +"brotli-wasm@npm:^2.0.1": + version: 2.0.1 + resolution: "brotli-wasm@npm:2.0.1" + checksum: 3a0506c66ad3a27512deebee3a9c9a0c59cd1dc7de0c1934c37f0a7b8772de8aa22093fb1fb466c8fdd1cd80f99e5a7c814ff1235350853fb1cd4129d99609f5 languageName: node linkType: hard @@ -4305,7 +4749,7 @@ __metadata: languageName: node linkType: hard -"browserify-aes@npm:^1.0.0, browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": +"browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": version: 1.2.0 resolution: "browserify-aes@npm:1.2.0" dependencies: @@ -4353,19 +4797,20 @@ __metadata: linkType: hard "browserify-sign@npm:^4.0.0": - version: 4.2.2 - resolution: "browserify-sign@npm:4.2.2" + version: 4.2.3 + resolution: "browserify-sign@npm:4.2.3" dependencies: bn.js: ^5.2.1 browserify-rsa: ^4.1.0 create-hash: ^1.2.0 create-hmac: ^1.1.7 - elliptic: ^6.5.4 + elliptic: ^6.5.5 + hash-base: ~3.0 inherits: ^2.0.4 - parse-asn1: ^5.1.6 - readable-stream: ^3.6.2 + parse-asn1: ^5.1.7 + readable-stream: ^2.3.8 safe-buffer: ^5.2.1 - checksum: b622730c0fc183328c3a1c9fdaaaa5118821ed6822b266fa6b0375db7e20061ebec87301d61931d79b9da9a96ada1cab317fce3c68f233e5e93ed02dbb35544c + checksum: 403a8061d229ae31266670345b4a7c00051266761d2c9bbeb68b1a9bcb05f68143b16110cf23a171a5d6716396a1f41296282b3e73eeec0a1871c77f0ff4ee6b languageName: node linkType: hard @@ -4486,6 +4931,16 @@ __metadata: languageName: node linkType: hard +"bufferutil@npm:4.0.5": + version: 4.0.5 + resolution: "bufferutil@npm:4.0.5" + dependencies: + node-gyp: latest + node-gyp-build: ^4.3.0 + checksum: 37d5bef7cb38d29f9377b8891ff8a57f53ae6057313d77a8aa2a7417df37a72f16987100796cb2f1e1862f3eb80057705f3c052615ec076a0dcc7aa6c83b68c9 + languageName: node + linkType: hard + "bufferutil@npm:^4.0.1": version: 4.0.8 resolution: "bufferutil@npm:4.0.8" @@ -4497,11 +4952,11 @@ __metadata: linkType: hard "builtins@npm:^5.0.1": - version: 5.0.1 - resolution: "builtins@npm:5.0.1" + version: 5.1.0 + resolution: "builtins@npm:5.1.0" dependencies: semver: ^7.0.0 - checksum: 66d204657fe36522822a95b288943ad11b58f5eaede235b11d8c4edaa28ce4800087d44a2681524c340494aadb120a0068011acabe99d30e8f11a7d826d83515 + checksum: 76327fa85b8e253b26e52f79988148013ea742691b4ab15f7228ebee47dd757832da308c9d4e4fc89763a1773e3f25a9836fff6315df85c7c6c72190436bf11d languageName: node linkType: hard @@ -4532,8 +4987,8 @@ __metadata: linkType: hard "cacache@npm:^18.0.0": - version: 18.0.2 - resolution: "cacache@npm:18.0.2" + version: 18.0.3 + resolution: "cacache@npm:18.0.3" dependencies: "@npmcli/fs": ^3.1.0 fs-minipass: ^3.0.0 @@ -4547,7 +5002,7 @@ __metadata: ssri: ^10.0.0 tar: ^6.1.11 unique-filename: ^3.0.0 - checksum: 0250df80e1ad0c828c956744850c5f742c24244e9deb5b7dc81bca90f8c10e011e132ecc58b64497cc1cad9a98968676147fb6575f4f94722f7619757b17a11b + checksum: b717fd9b36e9c3279bfde4545c3a8f6d5a539b084ee26a9504d48f83694beb724057d26e090b97540f9cc62bea18b9f6cf671c50e18fb7dac60eda9db691714f languageName: node linkType: hard @@ -4615,14 +5070,16 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:~1.0.2": - version: 1.0.5 - resolution: "call-bind@npm:1.0.5" +"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7, call-bind@npm:~1.0.2": + version: 1.0.7 + resolution: "call-bind@npm:1.0.7" dependencies: + es-define-property: ^1.0.0 + es-errors: ^1.3.0 function-bind: ^1.1.2 - get-intrinsic: ^1.2.1 - set-function-length: ^1.1.1 - checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 + get-intrinsic: ^1.2.4 + set-function-length: ^1.2.1 + checksum: 295c0c62b90dd6522e6db3b0ab1ce26bdf9e7404215bda13cfee25b626b5ff1a7761324d58d38b1ef1607fc65aca2d06e44d2e18d0dfc6c14b465b00d8660029 languageName: node linkType: hard @@ -4655,16 +5112,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30000844": - version: 1.0.30001584 - resolution: "caniuse-lite@npm:1.0.30001584" - checksum: de7018759561795ef31864b0d1584735eef267033d4e9b5f046b976756e06c43e85afd46705c5d63c63e3c36484c26794c259b9748eefffa582750b4ad0822ce - languageName: node - linkType: hard - -"case@npm:^1.6.3": - version: 1.6.3 - resolution: "case@npm:1.6.3" - checksum: febe73278f910b0d28aab7efd6f51c235f9aa9e296148edb56dfb83fd58faa88308c30ce9a0122b6e53e0362c44f4407105bd5ef89c46860fc2b184e540fd68d + version: 1.0.30001636 + resolution: "caniuse-lite@npm:1.0.30001636" + checksum: b0347fd2c8d346680a64d98b061c59cb8fbf149cdd03005a447fae4d21e6286d5bd161b43eefe3221c6624aacb3cda4e838ae83c95ff5313a547f84ca93bcc70 languageName: node linkType: hard @@ -4675,7 +5125,7 @@ __metadata: languageName: node linkType: hard -"catering@npm:^2.1.0, catering@npm:^2.1.1": +"catering@npm:^2.0.0, catering@npm:^2.1.0": version: 2.1.1 resolution: "catering@npm:2.1.1" checksum: 205daefa69c935b0c19f3d8f2e0a520dd69aebe9bda55902958003f7c9cff8f967dfb90071b421bd6eb618576f657a89d2bc0986872c9bc04bbd66655e9d4bd6 @@ -4710,13 +5160,13 @@ __metadata: linkType: hard "chai-as-promised@npm:^7.1.1": - version: 7.1.1 - resolution: "chai-as-promised@npm:7.1.1" + version: 7.1.2 + resolution: "chai-as-promised@npm:7.1.2" dependencies: check-error: ^1.0.2 peerDependencies: - chai: ">= 2.1.2 < 5" - checksum: 7262868a5b51a12af4e432838ddf97a893109266a505808e1868ba63a12de7ee1166e9d43b5c501a190c377c1b11ecb9ff8e093c89f097ad96c397e8ec0f8d6a + chai: ">= 2.1.2 < 6" + checksum: 671ee980054eb23a523875c1d22929a2ac05d89b5428e1fd12800f54fc69baf41014667b87e2368e2355ee2a3140d3e3d7d5a1f8638b07cfefd7fe38a149e3f6 languageName: node linkType: hard @@ -4735,6 +5185,16 @@ __metadata: languageName: node linkType: hard +"chalk@npm:4.1.2, chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc + languageName: node + linkType: hard + "chalk@npm:^1.1.3": version: 1.1.3 resolution: "chalk@npm:1.1.3" @@ -4769,16 +5229,6 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: ^4.1.0 - supports-color: ^7.1.0 - checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc - languageName: node - linkType: hard - "chardet@npm:^0.7.0": version: 0.7.0 resolution: "chardet@npm:0.7.0" @@ -4811,7 +5261,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:3.5.3, chokidar@npm:^3.0.2, chokidar@npm:^3.4.0": +"chokidar@npm:3.5.3": version: 3.5.3 resolution: "chokidar@npm:3.5.3" dependencies: @@ -4830,6 +5280,25 @@ __metadata: languageName: node linkType: hard +"chokidar@npm:^3.0.2, chokidar@npm:^3.4.0": + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" + dependencies: + anymatch: ~3.1.2 + braces: ~3.0.2 + fsevents: ~2.3.2 + glob-parent: ~5.1.2 + is-binary-path: ~2.1.0 + is-glob: ~4.0.1 + normalize-path: ~3.0.0 + readdirp: ~3.6.0 + dependenciesMeta: + fsevents: + optional: true + checksum: d2f29f499705dcd4f6f3bbed79a9ce2388cf530460122eed3b9c48efeab7a4e28739c6551fd15bec9245c6b9eeca7a32baa64694d64d9b6faeb74ddb8c4a413d + languageName: node + linkType: hard + "chownr@npm:^1.0.1, chownr@npm:^1.1.4": version: 1.1.4 resolution: "chownr@npm:1.1.4" @@ -4893,20 +5362,6 @@ __metadata: languageName: node linkType: hard -"classic-level@npm:^1.2.0": - version: 1.4.1 - resolution: "classic-level@npm:1.4.1" - dependencies: - abstract-level: ^1.0.2 - catering: ^2.1.0 - module-error: ^1.0.1 - napi-macros: ^2.2.2 - node-gyp: latest - node-gyp-build: ^4.3.0 - checksum: 62e7e07297fcd656941eb88f92b91df0046ebb2b34987e98ec870cb736f096e212ef109a25541deba2f30866b9d5df550594ed04948614815dd5964933da50a9 - languageName: node - linkType: hard - "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -4951,6 +5406,19 @@ __metadata: languageName: node linkType: hard +"cli-table3@npm:^0.6.3": + version: 0.6.5 + resolution: "cli-table3@npm:0.6.5" + dependencies: + "@colors/colors": 1.5.0 + string-width: ^4.2.0 + dependenciesMeta: + "@colors/colors": + optional: true + checksum: ab7afbf4f8597f1c631f3ee6bb3481d0bfeac8a3b81cffb5a578f145df5c88003b6cfff46046a7acae86596fdd03db382bfa67f20973b6b57425505abc47e42c + languageName: node + linkType: hard + "cli-width@npm:^3.0.0": version: 3.0.0 resolution: "cli-width@npm:3.0.0" @@ -5144,6 +5612,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^8.1.0": + version: 8.3.0 + resolution: "commander@npm:8.3.0" + checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0 + languageName: node + linkType: hard + "compare-versions@npm:^6.0.0": version: 6.1.0 resolution: "compare-versions@npm:6.1.0" @@ -5218,10 +5693,10 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0": - version: 0.5.0 - resolution: "cookie@npm:0.5.0" - checksum: 1f4bd2ca5765f8c9689a7e8954183f5332139eb72b6ff783d8947032ec1fdf43109852c178e21a953a30c0dd42257828185be01b49d1eb1a67fd054ca588a180 +"cookie@npm:0.6.0": + version: 0.6.0 + resolution: "cookie@npm:0.6.0" + checksum: f56a7d32a07db5458e79c726b77e3c2eff655c36792f2b6c58d351fb5f61531e5b1ab7f46987150136e366c65213cbe31729e02a3eaed630c3bf7334635fb410 languageName: node linkType: hard @@ -5247,9 +5722,9 @@ __metadata: linkType: hard "core-js-pure@npm:^3.0.1": - version: 3.35.1 - resolution: "core-js-pure@npm:3.35.1" - checksum: 2fb360757c403b1487e746bb3648c7f0be45c196640552767f4e2a55a962411a33093cd8babf5e0416de7f4c38d1b05bbaf576c0a3bf2d6565935bab749d3fb5 + version: 3.37.1 + resolution: "core-js-pure@npm:3.37.1" + checksum: a13a40e3951975cffef12a0933d3dbf1ecedbf9821e1ec8024884b587744951ad30e3762a86bcb8e2a18fdd4b8d7c8971b2391605329799fc04e1fc1e1397dc1 languageName: node linkType: hard @@ -5427,13 +5902,13 @@ __metadata: languageName: node linkType: hard -"d@npm:1, d@npm:^1.0.1": - version: 1.0.1 - resolution: "d@npm:1.0.1" +"d@npm:1, d@npm:^1.0.1, d@npm:^1.0.2": + version: 1.0.2 + resolution: "d@npm:1.0.2" dependencies: - es5-ext: ^0.10.50 - type: ^1.0.1 - checksum: 49ca0639c7b822db670de93d4fbce44b4aa072cd848c76292c9978a8cd0fff1028763020ff4b0f147bd77bfe29b4c7f82e0f71ade76b2a06100543cdfd948d19 + es5-ext: ^0.10.64 + type: ^2.7.2 + checksum: 775db1e8ced6707cddf64a5840522fcf5475d38ef49a5d615be0ac47f86ef64d15f5a73de1522b09327cc466d4dc35ea83dbfeed456f7a0fdcab138deb800355 languageName: node linkType: hard @@ -5446,6 +5921,39 @@ __metadata: languageName: node linkType: hard +"data-view-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-buffer@npm:1.0.1" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: ce24348f3c6231223b216da92e7e6a57a12b4af81a23f27eff8feabdf06acfb16c00639c8b705ca4d167f761cfc756e27e5f065d0a1f840c10b907fdaf8b988c + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: dbb3200edcb7c1ef0d68979834f81d64fd8cab2f7691b3a4c6b97e67f22182f3ec2c8602efd7b76997b55af6ff8bce485829c1feda4fa2165a6b71fb7baa4269 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "data-view-byte-offset@npm:1.0.0" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: 7f0bf8720b7414ca719eedf1846aeec392f2054d7af707c5dc9a753cc77eb8625f067fa901e0b5127e831f9da9056138d894b9c2be79c27a21f6db5824f009c2 + languageName: node + linkType: hard + "death@npm:^1.1.0": version: 1.1.0 resolution: "death@npm:1.1.0" @@ -5471,7 +5979,19 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.1, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:^4.0.1, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": + version: 4.3.5 + resolution: "debug@npm:4.3.5" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 7c002b51e256257f936dda09eb37167df952758c57badf6bf44bdc40b89a4bcb8e5a0a2e4c7b53f97c69e2970dd5272d33a757378a12c8f8e64ea7bf99e8e86e + languageName: node + linkType: hard + +"debug@npm:4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -5532,11 +6052,11 @@ __metadata: linkType: hard "deep-eql@npm:^4.0.1, deep-eql@npm:^4.1.3": - version: 4.1.3 - resolution: "deep-eql@npm:4.1.3" + version: 4.1.4 + resolution: "deep-eql@npm:4.1.4" dependencies: type-detect: ^4.0.0 - checksum: 7f6d30cb41c713973dc07eaadded848b2ab0b835e518a88b91bea72f34e08c4c71d167a722a6f302d3a6108f05afd8e6d7650689a84d5d29ec7fe6220420397f + checksum: 01c3ca78ff40d79003621b157054871411f94228ceb9b2cab78da913c606631c46e8aa79efc4aa0faf3ace3092acd5221255aab3ef0e8e7b438834f0ca9a16c7 languageName: node linkType: hard @@ -5610,18 +6130,28 @@ __metadata: languageName: node linkType: hard -"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": - version: 1.1.1 - resolution: "define-data-property@npm:1.1.1" +"deferred-leveldown@npm:~5.3.0": + version: 5.3.0 + resolution: "deferred-leveldown@npm:5.3.0" dependencies: - get-intrinsic: ^1.2.1 + abstract-leveldown: ~6.2.1 + inherits: ^2.0.3 + checksum: 5631e153528bb9de1aa60d59a5065d1a519374c5e4c1d486f2190dba4008dcf5c2ee8dd7f2f81396fc4d5a6bb6e7d0055e3dfe68afe00da02adaa3bf329addf7 + languageName: node + linkType: hard + +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1, define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" + dependencies: + es-define-property: ^1.0.0 + es-errors: ^1.3.0 gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - checksum: a29855ad3f0630ea82e3c5012c812efa6ca3078d5c2aa8df06b5f597c1cde6f7254692df41945851d903e05a1668607b6d34e778f402b9ff9ffb38111f1a3f0d + checksum: 8068ee6cab694d409ac25936eb861eea704b7763f7f342adbdfe337fc27c78d7ae0eff2364b2917b58c508d723c7a074326d068eef2e45c4edcd85cf94d0313b languageName: node linkType: hard -"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": +"define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -5714,19 +6244,6 @@ __metadata: languageName: node linkType: hard -"detect-port@npm:^1.3.0": - version: 1.5.1 - resolution: "detect-port@npm:1.5.1" - dependencies: - address: ^1.0.1 - debug: 4 - bin: - detect: bin/detect-port.js - detect-port: bin/detect-port.js - checksum: b48da9340481742547263d5d985e65d078592557863402ecf538511735e83575867e94f91fe74405ea19b61351feb99efccae7e55de9a151d5654e3417cea05b - languageName: node - linkType: hard - "diff@npm:5.0.0": version: 5.0.0 resolution: "diff@npm:5.0.0" @@ -5742,9 +6259,9 @@ __metadata: linkType: hard "diff@npm:^5.0.0": - version: 5.1.0 - resolution: "diff@npm:5.1.0" - checksum: c7bf0df7c9bfbe1cf8a678fd1b2137c4fb11be117a67bc18a0e03ae75105e8533dbfb1cda6b46beb3586ef5aed22143ef9d70713977d5fb1f9114e21455fba90 + version: 5.2.0 + resolution: "diff@npm:5.2.0" + checksum: 12b63ca9c36c72bafa3effa77121f0581b4015df18bc16bac1f8e263597735649f1a173c26f7eba17fb4162b073fee61788abe49610e6c70a2641fe1895443fd languageName: node linkType: hard @@ -5846,9 +6363,9 @@ __metadata: linkType: hard "dotenv@npm:^16.0.1": - version: 16.4.1 - resolution: "dotenv@npm:16.4.1" - checksum: a343f0a1d156deef8c60034f797969867af4dbccfacedd4ac15fad04547e7ffe0553b58fc3b27a5837950f0d977e38e9234943fbcec4aeced4e3d044309a76ab + version: 16.4.5 + resolution: "dotenv@npm:16.4.5" + checksum: 301a12c3d44fd49888b74eb9ccf9f07a1f5df43f489e7fcb89647a2edcd84c42d6bc349dc8df099cd18f07c35c7b04685c1a4f3e6a6a9e6b30f8d48c15b7f49c languageName: node linkType: hard @@ -5911,13 +6428,13 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.3.47": - version: 1.4.656 - resolution: "electron-to-chromium@npm:1.4.656" - checksum: b9e00c81e74ee307141a216ef971efeff8784232a9eaa9074a65687b631029725f8f4ddeefd98c43287339cdadb6c7aba92c01806122f9cae813a95735fcd432 + version: 1.4.805 + resolution: "electron-to-chromium@npm:1.4.805" + checksum: a881787fb4f3300442aa10e88689f153b2f68a99bdf60325967017c78c0ae50440ecfe768245fd3aa6dbc7b9c39e376027e1cda205bf9cda358f56ad9d8220c6 languageName: node linkType: hard -"elliptic@npm:6.5.4, elliptic@npm:^6.4.0, elliptic@npm:^6.5.2, elliptic@npm:^6.5.3, elliptic@npm:^6.5.4": +"elliptic@npm:6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" dependencies: @@ -5932,6 +6449,28 @@ __metadata: languageName: node linkType: hard +"elliptic@npm:^6.4.0, elliptic@npm:^6.5.2, elliptic@npm:^6.5.3, elliptic@npm:^6.5.4, elliptic@npm:^6.5.5": + version: 6.5.5 + resolution: "elliptic@npm:6.5.5" + dependencies: + bn.js: ^4.11.9 + brorand: ^1.1.0 + hash.js: ^1.0.0 + hmac-drbg: ^1.0.1 + inherits: ^2.0.4 + minimalistic-assert: ^1.0.1 + minimalistic-crypto-utils: ^1.0.1 + checksum: ec9105e4469eb3b32b0ee2579756c888ddf3f99d259aa0d65fccb906ee877768aaf8880caae73e3e669c9a4adeb3eb1945703aa974ec5000d2d33a239f4567eb + languageName: node + linkType: hard + +"emittery@npm:0.10.0": + version: 0.10.0 + resolution: "emittery@npm:0.10.0" + checksum: 2616a802df51e3f412b9b33f1b43161f7bc96037142cada6ecdbf35ddef1368e30d4f8e47fddc10b0753ccf91d3483b20ebca535b4b1e47526440e13150e2bc7 + languageName: node + linkType: hard + "emoji-regex@npm:^7.0.1": version: 7.0.3 resolution: "emoji-regex@npm:7.0.3" @@ -5973,6 +6512,18 @@ __metadata: languageName: node linkType: hard +"encoding-down@npm:^6.3.0": + version: 6.3.0 + resolution: "encoding-down@npm:6.3.0" + dependencies: + abstract-leveldown: ^6.2.1 + inherits: ^2.0.3 + level-codec: ^9.0.0 + level-errors: ^2.0.0 + checksum: 74043e6d9061a470614ff61d708c849259ab32932a428fd5ddfb0878719804f56a52f59b31cccd95fddc2e636c0fd22dc3e02481fb98d5bf1bdbbbc44ca09bdc + languageName: node + linkType: hard + "encoding@npm:^0.1.11, encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -6051,50 +6602,57 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3": - version: 1.22.3 - resolution: "es-abstract@npm:1.22.3" +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" dependencies: - array-buffer-byte-length: ^1.0.0 - arraybuffer.prototype.slice: ^1.0.2 - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.5 - es-set-tostringtag: ^2.0.1 + array-buffer-byte-length: ^1.0.1 + arraybuffer.prototype.slice: ^1.0.3 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + data-view-buffer: ^1.0.1 + data-view-byte-length: ^1.0.1 + data-view-byte-offset: ^1.0.0 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-set-tostringtag: ^2.0.3 es-to-primitive: ^1.2.1 function.prototype.name: ^1.1.6 - get-intrinsic: ^1.2.2 - get-symbol-description: ^1.0.0 + get-intrinsic: ^1.2.4 + get-symbol-description: ^1.0.2 globalthis: ^1.0.3 gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - has-proto: ^1.0.1 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 has-symbols: ^1.0.3 - hasown: ^2.0.0 - internal-slot: ^1.0.5 - is-array-buffer: ^3.0.2 + hasown: ^2.0.2 + internal-slot: ^1.0.7 + is-array-buffer: ^3.0.4 is-callable: ^1.2.7 - is-negative-zero: ^2.0.2 + is-data-view: ^1.0.1 + is-negative-zero: ^2.0.3 is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.2 + is-shared-array-buffer: ^1.0.3 is-string: ^1.0.7 - is-typed-array: ^1.1.12 + is-typed-array: ^1.1.13 is-weakref: ^1.0.2 object-inspect: ^1.13.1 object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.5.1 - safe-array-concat: ^1.0.1 - safe-regex-test: ^1.0.0 - string.prototype.trim: ^1.2.8 - string.prototype.trimend: ^1.0.7 - string.prototype.trimstart: ^1.0.7 - typed-array-buffer: ^1.0.0 - typed-array-byte-length: ^1.0.0 - typed-array-byte-offset: ^1.0.0 - typed-array-length: ^1.0.4 + object.assign: ^4.1.5 + regexp.prototype.flags: ^1.5.2 + safe-array-concat: ^1.1.2 + safe-regex-test: ^1.0.3 + string.prototype.trim: ^1.2.9 + string.prototype.trimend: ^1.0.8 + string.prototype.trimstart: ^1.0.8 + typed-array-buffer: ^1.0.2 + typed-array-byte-length: ^1.0.1 + typed-array-byte-offset: ^1.0.2 + typed-array-length: ^1.0.6 unbox-primitive: ^1.0.2 - which-typed-array: ^1.1.13 - checksum: b1bdc962856836f6e72be10b58dc128282bdf33771c7a38ae90419d920fc3b36cc5d2b70a222ad8016e3fc322c367bf4e9e89fc2bc79b7e933c05b218e83d79a + which-typed-array: ^1.1.15 + checksum: f840cf161224252512f9527306b57117192696571e07920f777cb893454e32999206198b4f075516112af6459daca282826d1735c450528470356d09eff3a9ae languageName: node linkType: hard @@ -6105,25 +6663,43 @@ __metadata: languageName: node linkType: hard -"es-errors@npm:^1.0.0, es-errors@npm:^1.2.1": +"es-define-property@npm:^1.0.0": + version: 1.0.0 + resolution: "es-define-property@npm:1.0.0" + dependencies: + get-intrinsic: ^1.2.4 + checksum: f66ece0a887b6dca71848fa71f70461357c0e4e7249696f81bad0a1f347eed7b31262af4a29f5d726dc026426f085483b6b90301855e647aa8e21936f07293c6 + languageName: node + linkType: hard + +"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": version: 1.3.0 resolution: "es-errors@npm:1.3.0" checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 languageName: node linkType: hard -"es-set-tostringtag@npm:^2.0.1": - version: 2.0.2 - resolution: "es-set-tostringtag@npm:2.0.2" +"es-object-atoms@npm:^1.0.0": + version: 1.0.0 + resolution: "es-object-atoms@npm:1.0.0" dependencies: - get-intrinsic: ^1.2.2 - has-tostringtag: ^1.0.0 - hasown: ^2.0.0 - checksum: afcec3a4c9890ae14d7ec606204858441c801ff84f312538e1d1ccf1e5493c8b17bd672235df785f803756472cb4f2d49b87bde5237aef33411e74c22f194e07 + es-errors: ^1.3.0 + checksum: 26f0ff78ab93b63394e8403c353842b2272836968de4eafe97656adfb8a7c84b9099bf0fe96ed58f4a4cddc860f6e34c77f91649a58a5daa4a9c40b902744e3c + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.3": + version: 2.0.3 + resolution: "es-set-tostringtag@npm:2.0.3" + dependencies: + get-intrinsic: ^1.2.4 + has-tostringtag: ^1.0.2 + hasown: ^2.0.1 + checksum: 7227fa48a41c0ce83e0377b11130d324ac797390688135b8da5c28994c0165be8b252e15cd1de41e1325e5a5412511586960213e88f9ab4a5e7d028895db5129 languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.0": +"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2": version: 1.0.2 resolution: "es-shim-unscopables@npm:1.0.2" dependencies: @@ -6143,14 +6719,15 @@ __metadata: languageName: node linkType: hard -"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50": - version: 0.10.62 - resolution: "es5-ext@npm:0.10.62" +"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50, es5-ext@npm:^0.10.62, es5-ext@npm:^0.10.63, es5-ext@npm:^0.10.64, es5-ext@npm:~0.10.14": + version: 0.10.64 + resolution: "es5-ext@npm:0.10.64" dependencies: es6-iterator: ^2.0.3 es6-symbol: ^3.1.3 + esniff: ^2.0.1 next-tick: ^1.1.0 - checksum: 25f42f6068cfc6e393cf670bc5bba249132c5f5ec2dd0ed6e200e6274aca2fed8e9aec8a31c76031744c78ca283c57f0b41c7e737804c6328c7b8d3fbcba7983 + checksum: 01179fab0769fdbef213062222f99d0346724dbaccf04b87c0e6ee7f0c97edabf14be647ca1321f0497425ea7145de0fd278d1b3f3478864b8933e7136a5c645 languageName: node linkType: hard @@ -6182,19 +6759,19 @@ __metadata: linkType: hard "es6-symbol@npm:^3.1.1, es6-symbol@npm:^3.1.3": - version: 3.1.3 - resolution: "es6-symbol@npm:3.1.3" + version: 3.1.4 + resolution: "es6-symbol@npm:3.1.4" dependencies: - d: ^1.0.1 - ext: ^1.1.2 - checksum: cd49722c2a70f011eb02143ef1c8c70658d2660dead6641e160b94619f408b9cf66425515787ffe338affdf0285ad54f4eae30ea5bd510e33f8659ec53bcaa70 + d: ^1.0.2 + ext: ^1.7.0 + checksum: 52125ec4b5d1b6b93b8d3d42830bb19f8da21080ffcf45253b614bc6ff3e31349be202fb745d4d1af6778cdf5e38fea30e0c7e7dc37e2aecd44acc43502055f9 languageName: node linkType: hard "escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 1ec0977aa2772075493002bdbd549d595ff6e9393b1cb0d7d6fcaf78c750da0c158f180938365486f75cb69fba20294351caddfce1b46552a7b6c3cde52eaa02 languageName: node linkType: hard @@ -6286,14 +6863,14 @@ __metadata: linkType: hard "eslint-module-utils@npm:^2.8.0": - version: 2.8.0 - resolution: "eslint-module-utils@npm:2.8.0" + version: 2.8.1 + resolution: "eslint-module-utils@npm:2.8.1" dependencies: debug: ^3.2.7 peerDependenciesMeta: eslint: optional: true - checksum: 74c6dfea7641ebcfe174be61168541a11a14aa8d72e515f5f09af55cd0d0862686104b0524aa4b8e0ce66418a44aa38a94d2588743db5fd07a6b49ffd16921d2 + checksum: 3cecd99b6baf45ffc269167da0f95dcb75e5aa67b93d73a3bab63e2a7eedd9cdd6f188eed048e2f57c1b77db82c9cbf2adac20b512fa70e597d863dd3720170d languageName: node linkType: hard @@ -6405,26 +6982,26 @@ __metadata: linkType: hard "eslint-plugin-promise@npm:^6.0.0": - version: 6.1.1 - resolution: "eslint-plugin-promise@npm:6.1.1" + version: 6.2.0 + resolution: "eslint-plugin-promise@npm:6.2.0" peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - checksum: 46b9a4f79dae5539987922afc27cc17cbccdecf4f0ba19c0ccbf911b0e31853e9f39d9959eefb9637461b52772afa1a482f1f87ff16c1ba38bdb6fcf21897e9a + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + checksum: 4ce2ee365044aaeac7feb7c4b62f7d432594960bf96be703f871fa5fdd61f358d6620222e7c907f7ee43ff54b0b2ff392c1f70680bce335f6396c8c7af79c141 languageName: node linkType: hard "eslint-plugin-unused-imports@npm:^3.0.0": - version: 3.0.0 - resolution: "eslint-plugin-unused-imports@npm:3.0.0" + version: 3.2.0 + resolution: "eslint-plugin-unused-imports@npm:3.2.0" dependencies: eslint-rule-composer: ^0.3.0 peerDependencies: - "@typescript-eslint/eslint-plugin": ^6.0.0 - eslint: ^8.0.0 + "@typescript-eslint/eslint-plugin": 6 - 7 + eslint: 8 peerDependenciesMeta: "@typescript-eslint/eslint-plugin": optional: true - checksum: 51666f62cc8dccba2895ced83f3c1e0b78b68c357e17360e156c4db548bfdeda34cbd8725192fb4903f22d5069400fb22ded6039631df01ee82fd618dc307247 + checksum: e85ae4f3af489294ef5e0969ab904fa87f9fa7c959ca0804f30845438db4aeb0428ddad7ab06a70608e93121626799977241b442fdf126a4d0667be57390c3d6 languageName: node linkType: hard @@ -6553,14 +7130,14 @@ __metadata: linkType: hard "eslint@npm:^8.20.0": - version: 8.56.0 - resolution: "eslint@npm:8.56.0" + version: 8.57.0 + resolution: "eslint@npm:8.57.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 "@eslint/eslintrc": ^2.1.4 - "@eslint/js": 8.56.0 - "@humanwhocodes/config-array": ^0.11.13 + "@eslint/js": 8.57.0 + "@humanwhocodes/config-array": ^0.11.14 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 "@ungap/structured-clone": ^1.2.0 @@ -6596,7 +7173,19 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 883436d1e809b4a25d9eb03d42f584b84c408dbac28b0019f6ea07b5177940bf3cca86208f749a6a1e0039b63e085ee47aca1236c30721e91f0deef5cc5a5136 + checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 + languageName: node + linkType: hard + +"esniff@npm:^2.0.1": + version: 2.0.1 + resolution: "esniff@npm:2.0.1" + dependencies: + d: ^1.0.1 + es5-ext: ^0.10.62 + event-emitter: ^0.3.5 + type: ^2.7.2 + checksum: d814c0e5c39bce9925b2e65b6d8767af72c9b54f35a65f9f3d6e8c606dce9aebe35a9599d30f15b0807743f88689f445163cfb577a425de4fb8c3c5bc16710cc languageName: node linkType: hard @@ -6869,11 +7458,11 @@ __metadata: linkType: hard "ethereum-bloom-filters@npm:^1.0.6": - version: 1.0.10 - resolution: "ethereum-bloom-filters@npm:1.0.10" + version: 1.1.0 + resolution: "ethereum-bloom-filters@npm:1.1.0" dependencies: - js-sha3: ^0.8.0 - checksum: 4019cc6f9274ae271a52959194a72f6e9b013366f168f922dc3b349319faf7426bf1010125ee0676b4f75714fe4a440edd4e7e62342c121a046409f4cd4c0af9 + "@noble/hashes": ^1.4.0 + checksum: 9565cd1e2002509852a05461cc93ee6874e8f961e0f66929cfc34d05f6f451fcfa4df287f8735ee184e4ba5f6e63a76a3c69bbeda5dda5bdf486f68fb9fa61f3 languageName: node linkType: hard @@ -6926,15 +7515,15 @@ __metadata: languageName: node linkType: hard -"ethereum-cryptography@npm:^2.0.0, ethereum-cryptography@npm:^2.1.2": - version: 2.1.3 - resolution: "ethereum-cryptography@npm:2.1.3" +"ethereum-cryptography@npm:^2.0.0, ethereum-cryptography@npm:^2.1.2, ethereum-cryptography@npm:^2.1.3": + version: 2.2.0 + resolution: "ethereum-cryptography@npm:2.2.0" dependencies: - "@noble/curves": 1.3.0 - "@noble/hashes": 1.3.3 - "@scure/bip32": 1.3.3 - "@scure/bip39": 1.2.2 - checksum: 7f9c14f868a588641179cace3eb86c332c4743290865db699870710253cabc4dc74bd4bce5e7bc6db667482e032e94d6f79521219eb6be5dc422059d279a27b7 + "@noble/curves": 1.4.0 + "@noble/hashes": 1.4.0 + "@scure/bip32": 1.4.0 + "@scure/bip39": 1.3.0 + checksum: 529d05a47fe0ff86ab36022a286c3a280e09d386fc92ff183aa4b095e97d190dd875022a004898686a798bac56e73601dd91356298edc56e5eeded7846f8ec12 languageName: node linkType: hard @@ -6953,6 +7542,24 @@ __metadata: languageName: node linkType: hard +"ethereum-waffle@npm:latest": + version: 4.0.10 + resolution: "ethereum-waffle@npm:4.0.10" + dependencies: + "@ethereum-waffle/chai": 4.0.10 + "@ethereum-waffle/compiler": 4.0.3 + "@ethereum-waffle/mock-contract": 4.0.4 + "@ethereum-waffle/provider": 4.0.5 + solc: 0.8.15 + typechain: ^8.0.0 + peerDependencies: + ethers: "*" + bin: + waffle: bin/waffle + checksum: 680df4f5cf61f2f64b740d7724323e0872b1b1462e7ee2f1de6a1c9732155b28c4ac25c669ba557f72e1bb20204f81696a1fd543aece03654d71a9d9ebe1fc53 + languageName: node + linkType: hard + "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": version: 0.6.8 resolution: "ethereumjs-abi@https://github.com/ethereumjs/ethereumjs-abi.git#commit=ee3994657fa7a427238e6ba92a84d0b529bbcde0" @@ -7098,6 +7705,19 @@ __metadata: languageName: node linkType: hard +"ethereumjs-util@npm:7.1.3": + version: 7.1.3 + resolution: "ethereumjs-util@npm:7.1.3" + dependencies: + "@types/bn.js": ^5.1.0 + bn.js: ^5.1.2 + create-hash: ^1.1.2 + ethereum-cryptography: ^0.1.3 + rlp: ^2.2.4 + checksum: 6de7a32af05c7265c96163ecd15ad97327afab9deb36092ef26250616657a8c0b5df8e698328247c8193e7b87c643c967f64f0b3cff2b2937cafa870ff5fcb41 + languageName: node + linkType: hard + "ethereumjs-util@npm:^4.3.0": version: 4.5.1 resolution: "ethereumjs-util@npm:4.5.1" @@ -7126,7 +7746,7 @@ __metadata: languageName: node linkType: hard -"ethereumjs-util@npm:^7.0.2, ethereumjs-util@npm:^7.0.3": +"ethereumjs-util@npm:^7.0.2, ethereumjs-util@npm:^7.0.3, ethereumjs-util@npm:^7.1.1, ethereumjs-util@npm:^7.1.3, ethereumjs-util@npm:^7.1.4, ethereumjs-util@npm:^7.1.5": version: 7.1.5 resolution: "ethereumjs-util@npm:7.1.5" dependencies: @@ -7198,7 +7818,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:^5.0.1, ethers@npm:^5.0.2, ethers@npm:^5.5.2, ethers@npm:^5.6.9, ethers@npm:^5.7.1, ethers@npm:^5.7.2": +"ethers-v5@npm:ethers@^5.7.0, ethers@npm:^5.0.1, ethers@npm:^5.0.2, ethers@npm:^5.5.2, ethers@npm:^5.6.9, ethers@npm:^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" dependencies: @@ -7236,6 +7856,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.6.0": + version: 6.13.1 + resolution: "ethers@npm:6.13.1" + dependencies: + "@adraffy/ens-normalize": 1.10.1 + "@noble/curves": 1.2.0 + "@noble/hashes": 1.3.2 + "@types/node": 18.15.13 + aes-js: 4.0.0-beta.5 + tslib: 2.4.0 + ws: 8.17.1 + checksum: beef4b6d117f64c369f44be631e0f666b966374eac0cc0446fa7abe114b11d6b3019060022eec65c031f150711f4913d249de507ff3da3204e654635db80a07e + languageName: node + linkType: hard + "ethjs-unit@npm:0.1.6": version: 0.1.6 resolution: "ethjs-unit@npm:0.1.6" @@ -7256,6 +7891,16 @@ __metadata: languageName: node linkType: hard +"event-emitter@npm:^0.3.5": + version: 0.3.5 + resolution: "event-emitter@npm:0.3.5" + dependencies: + d: 1 + es5-ext: ~0.10.14 + checksum: 27c1399557d9cd7e0aa0b366c37c38a4c17293e3a10258e8b692a847dd5ba9fb90429c3a5a1eeff96f31f6fa03ccbd31d8ad15e00540b22b22f01557be706030 + languageName: node + linkType: hard + "event-target-shim@npm:^5.0.0": version: 5.0.1 resolution: "event-target-shim@npm:5.0.1" @@ -7344,15 +7989,15 @@ __metadata: linkType: hard "express@npm:^4.14.0": - version: 4.18.2 - resolution: "express@npm:4.18.2" + version: 4.19.2 + resolution: "express@npm:4.19.2" dependencies: accepts: ~1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.1 + body-parser: 1.20.2 content-disposition: 0.5.4 content-type: ~1.0.4 - cookie: 0.5.0 + cookie: 0.6.0 cookie-signature: 1.0.6 debug: 2.6.9 depd: 2.0.0 @@ -7378,11 +8023,11 @@ __metadata: type-is: ~1.6.18 utils-merge: 1.0.1 vary: ~1.1.2 - checksum: 3c4b9b076879442f6b968fe53d85d9f1eeacbb4f4c41e5f16cc36d77ce39a2b0d81b3f250514982110d815b2f7173f5561367f9110fcc541f9371948e8c8b037 + checksum: 212dbd6c2c222a96a61bc927639c95970a53b06257080bb9e2838adb3bffdb966856551fdad1ab5dd654a217c35db94f987d0aa88d48fb04d306340f5f34dca5 languageName: node linkType: hard -"ext@npm:^1.1.2": +"ext@npm:^1.7.0": version: 1.7.0 resolution: "ext@npm:1.7.0" dependencies: @@ -7586,12 +8231,12 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + checksum: b4abfbca3839a3d55e4ae5ec62e131e2e356bf4859ce8480c64c4876100f4df292a63e5bb1618e1d7460282ca2b305653064f01654474aa35c68000980f17798 languageName: node linkType: hard @@ -7725,9 +8370,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.2.9 - resolution: "flatted@npm:3.2.9" - checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 85ae7181650bb728c221e7644cbc9f4bf28bc556f2fc89bb21266962bdf0ce1029cc7acc44bb646cd469d9baac7c317f64e841c4c4c00516afa97320cdac7f94 languageName: node linkType: hard @@ -7738,13 +8383,13 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.4": - version: 1.15.5 - resolution: "follow-redirects@npm:1.15.5" +"follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.6": + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: debug: optional: true - checksum: 5ca49b5ce6f44338cbfc3546823357e7a70813cecc9b7b768158a1d32c1e62e7407c944402a918ea8c38ae2e78266312d617dc68783fac502cbb55e1047b34ec + checksum: a62c378dfc8c00f60b9c80cab158ba54e99ba0239a5dd7c81245e5a5b39d10f0c35e249c3379eae719ff0285fff88c365dd446fab19dee771f1d76252df1bbf5 languageName: node linkType: hard @@ -7765,12 +8410,12 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" + version: 3.2.1 + resolution: "foreground-child@npm:3.2.1" dependencies: cross-spawn: ^7.0.0 signal-exit: ^4.0.1 - checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + checksum: 3e2e844d6003c96d70affe8ae98d7eaaba269a868c14d997620c088340a8775cd5d2d9043e6ceebae1928d8d9a874911c4d664b9a267e8995945df20337aebc0 languageName: node linkType: hard @@ -8019,7 +8664,7 @@ __metadata: languageName: node linkType: hard -"ganache-cli@npm:^6.12.2": +"ganache-cli@npm:^6.12.2, ganache-cli@npm:latest": version: 6.12.2 resolution: "ganache-cli@npm:6.12.2" dependencies: @@ -8075,6 +8720,32 @@ __metadata: languageName: node linkType: hard +"ganache@npm:7.4.3": + version: 7.4.3 + resolution: "ganache@npm:7.4.3" + dependencies: + "@trufflesuite/bigint-buffer": 1.1.10 + "@types/bn.js": ^5.1.0 + "@types/lru-cache": 5.1.1 + "@types/seedrandom": 3.0.1 + bufferutil: 4.0.5 + emittery: 0.10.0 + keccak: 3.0.2 + leveldown: 6.1.0 + secp256k1: 4.0.3 + utf-8-validate: 5.0.7 + dependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + bin: + ganache: dist/node/cli.js + ganache-cli: dist/node/cli.js + checksum: 170dde8c2ecd88e7f02a92bf582149e6497a2fdfb05abe9ab63a5b7cf33c061d71390f9719ef3d716dad4149299f8a87c71612ab4b40d1c57c55d7a185314630 + languageName: node + linkType: hard + "get-caller-file@npm:^1.0.1": version: 1.0.3 resolution: "get-caller-file@npm:1.0.3" @@ -8096,16 +8767,16 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3": - version: 1.2.3 - resolution: "get-intrinsic@npm:1.2.3" +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": + version: 1.2.4 + resolution: "get-intrinsic@npm:1.2.4" dependencies: - es-errors: ^1.0.0 + es-errors: ^1.3.0 function-bind: ^1.1.2 has-proto: ^1.0.1 has-symbols: ^1.0.3 hasown: ^2.0.0 - checksum: 497fe6e444a2c570d174486c2450fc2b8c5020ae33a945a4b3d06c88bd69fb02a4611163e7a5bd9a5f61162e85ee83e55f06400dd3de108d6407eea32c6330b7 + checksum: 414e3cdf2c203d1b9d7d33111df746a4512a1aa622770b361dadddf8ed0b5aeb26c560f49ca077e24bfafb0acb55ca908d1f709216ccba33ffc548ec8a79a951 languageName: node linkType: hard @@ -8148,13 +8819,14 @@ __metadata: languageName: node linkType: hard -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" +"get-symbol-description@npm:^1.0.2": + version: 1.0.2 + resolution: "get-symbol-description@npm:1.0.2" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 + call-bind: ^1.0.5 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + checksum: e1cb53bc211f9dbe9691a4f97a46837a553c4e7caadd0488dc24ac694db8a390b93edd412b48dcdd0b4bbb4c595de1709effc75fc87c0839deedc6968f5bd973 languageName: node linkType: hard @@ -8232,18 +8904,31 @@ __metadata: languageName: node linkType: hard +"glob@npm:8.1.0, glob@npm:^8.0.3": + version: 8.1.0 + resolution: "glob@npm:8.1.0" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^5.0.1 + once: ^1.3.0 + checksum: 92fbea3221a7d12075f26f0227abac435de868dd0736a17170663783296d0dd8d3d532a5672b4488a439bf5d7fb85cdd07c11185d6cd39184f0385cbdfb86a47 + languageName: node + linkType: hard + "glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" + version: 10.4.1 + resolution: "glob@npm:10.4.1" dependencies: foreground-child: ^3.1.0 - jackspeak: ^2.3.5 - minimatch: ^9.0.1 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - path-scurry: ^1.10.1 + jackspeak: ^3.1.2 + minimatch: ^9.0.4 + minipass: ^7.1.2 + path-scurry: ^1.11.1 bin: glob: dist/esm/bin.mjs - checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + checksum: 5d33c686c80bf6877f4284adf99a8c3cbb2a6eccbc92342943fe5d4b42c01d78c1881f2223d950c92a938d0f857e12e37b86a8e5483ab2141822e053b67d0dde languageName: node linkType: hard @@ -8274,19 +8959,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^8.0.3": - version: 8.1.0 - resolution: "glob@npm:8.1.0" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^5.0.1 - once: ^1.3.0 - checksum: 92fbea3221a7d12075f26f0227abac435de868dd0736a17170663783296d0dd8d3d532a5672b4488a439bf5d7fb85cdd07c11185d6cd39184f0385cbdfb86a47 - languageName: node - linkType: hard - "global-modules@npm:^2.0.0": version: 2.0.0 resolution: "global-modules@npm:2.0.0" @@ -8343,11 +9015,12 @@ __metadata: linkType: hard "globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" dependencies: - define-properties: ^1.1.3 - checksum: fbd7d760dc464c886d0196166d92e5ffb4c84d0730846d6621a39fbbc068aeeb9c8d1421ad330e94b7bca4bb4ea092f5f21f3d36077812af5d098b4dc006c998 + define-properties: ^1.2.1 + gopd: ^1.0.1 + checksum: 39ad667ad9f01476474633a1834a70842041f70a55571e8dcef5fb957980a92da5022db5430fca8aecc5d47704ae30618c0bc877a579c70710c904e9ef06108a languageName: node linkType: hard @@ -8537,22 +9210,41 @@ __metadata: languageName: node linkType: hard -"hardhat@npm:^2.19.4": - version: 2.19.5 - resolution: "hardhat@npm:2.19.5" +"hardhat-gas-reporter@npm:latest": + version: 2.2.0 + resolution: "hardhat-gas-reporter@npm:2.2.0" + dependencies: + "@ethersproject/abi": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/units": ^5.7.0 + "@solidity-parser/parser": ^0.18.0 + axios: ^1.6.7 + brotli-wasm: ^2.0.1 + chalk: 4.1.2 + cli-table3: ^0.6.3 + ethereum-cryptography: ^2.1.3 + glob: ^10.3.10 + jsonschema: ^1.4.1 + lodash: ^4.17.21 + markdown-table: 2.0.0 + sha1: ^1.1.1 + viem: 2.7.14 + peerDependencies: + hardhat: ^2.16.0 + checksum: b0f07ac3dcbfb88cd1a77385755fe23d8af467fc4110021bc1f890f8672a9a005f547592976ef92de3948377ab5405265ced6a40966e991ed859fa22abbde8ea + languageName: node + linkType: hard + +"hardhat@npm:^2.19.4, hardhat@npm:^2.22.1": + version: 2.22.5 + resolution: "hardhat@npm:2.22.5" dependencies: "@ethersproject/abi": ^5.1.2 "@metamask/eth-sig-util": ^4.0.0 - "@nomicfoundation/ethereumjs-block": 5.0.2 - "@nomicfoundation/ethereumjs-blockchain": 7.0.2 - "@nomicfoundation/ethereumjs-common": 4.0.2 - "@nomicfoundation/ethereumjs-evm": 2.0.2 - "@nomicfoundation/ethereumjs-rlp": 5.0.2 - "@nomicfoundation/ethereumjs-statemanager": 2.0.2 - "@nomicfoundation/ethereumjs-trie": 6.0.2 - "@nomicfoundation/ethereumjs-tx": 5.0.2 - "@nomicfoundation/ethereumjs-util": 9.0.2 - "@nomicfoundation/ethereumjs-vm": 7.0.2 + "@nomicfoundation/edr": ^0.4.0 + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-tx": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 "@nomicfoundation/solidity-analyzer": ^0.1.0 "@sentry/node": ^5.18.1 "@types/bn.js": ^5.1.0 @@ -8600,7 +9292,7 @@ __metadata: optional: true bin: hardhat: internal/cli/bootstrap.js - checksum: 316b03a1d090360e6ed471fe125360ec0c66c5bb62e29492898932b1a9a5227c12d7a18343877c59725f321647a01fde0841649bf7d8a4a746148a0d38b0ee27 + checksum: 34ab9ae3820c26ea4c92db43aefb15668d0575787d214a408b3274d445a7626775f2966dca2cf82a8fa8d9f39ebfdc90f3fb7189409b9582e373ce5b66ec3855 languageName: node linkType: hard @@ -8641,19 +9333,19 @@ __metadata: languageName: node linkType: hard -"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1": - version: 1.0.1 - resolution: "has-property-descriptors@npm:1.0.1" +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" dependencies: - get-intrinsic: ^1.2.2 - checksum: 2bcc6bf6ec6af375add4e4b4ef586e43674850a91ad4d46666d0b28ba8e1fd69e424c7677d24d60f69470ad0afaa2f3197f508b20b0bb7dd99a8ab77ffc4b7c4 + es-define-property: ^1.0.0 + checksum: fcbb246ea2838058be39887935231c6d5788babed499d0e9d0cc5737494c48aba4fe17ba1449e0d0fbbb1e36175442faa37f9c427ae357d6ccb1d895fbcd3de3 languageName: node linkType: hard -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e +"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: fe7c3d50b33f50f3933a04413ed1f69441d21d2d2944f81036276d30635cad9279f6b43bc8f32036c31ebdfcf6e731150f46c1907ad90c669ffe9b066c3ba5c4 languageName: node linkType: hard @@ -8664,7 +9356,7 @@ __metadata: languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.1": +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": version: 1.0.2 resolution: "has-tostringtag@npm:1.0.2" dependencies: @@ -8730,6 +9422,16 @@ __metadata: languageName: node linkType: hard +"hash-base@npm:~3.0": + version: 3.0.4 + resolution: "hash-base@npm:3.0.4" + dependencies: + inherits: ^2.0.1 + safe-buffer: ^5.0.1 + checksum: 878465a0dfcc33cce195c2804135352c590d6d10980adc91a9005fd377e77f2011256c2b7cfce472e3f2e92d561d1bf3228d2da06348a9017ce9a258b3b49764 + languageName: node + linkType: hard + "hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3, hash.js@npm:^1.1.7": version: 1.1.7 resolution: "hash.js@npm:1.1.7" @@ -8740,12 +9442,12 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0": - version: 2.0.0 - resolution: "hasown@npm:2.0.0" +"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" dependencies: function-bind: ^1.1.2 - checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 + checksum: e8516f776a15149ca6c6ed2ae3110c417a00b62260e222590e54aa367cbcd6ed99122020b37b7fbdf05748df57b265e70095d7bf35a47660587619b15ffb93db languageName: node linkType: hard @@ -8840,12 +9542,12 @@ __metadata: linkType: hard "http-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "http-proxy-agent@npm:7.0.0" + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" dependencies: agent-base: ^7.1.0 debug: ^4.3.4 - checksum: 48d4fac997917e15f45094852b63b62a46d0c8a4f0b9c6c23ca26d27b8df8d178bed88389e604745e748bd9a01f5023e25093722777f0593c3f052009ff438b6 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 languageName: node linkType: hard @@ -8890,12 +9592,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.2 - resolution: "https-proxy-agent@npm:7.0.2" + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" dependencies: agent-base: ^7.0.2 debug: 4 - checksum: 088969a0dd476ea7a0ed0a2cf1283013682b08f874c3bc6696c83fa061d2c157d29ef0ad3eb70a2046010bb7665573b2388d10fdcb3e410a66995e5248444292 + checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 languageName: node linkType: hard @@ -8976,9 +9678,9 @@ __metadata: linkType: hard "immutable@npm:^4.0.0-rc.12": - version: 4.3.5 - resolution: "immutable@npm:4.3.5" - checksum: 0e25dd5c314421faede9e1122ab26cdb638cc3edc8678c4a75dee104279b12621a30c80a480fae7f68bc7e81672f1e672e454dc0fdc7e6cf0af10809348387b8 + version: 4.3.6 + resolution: "immutable@npm:4.3.6" + checksum: 3afd020be988ec9ba42c1e585b88858970beba91332ac04ac11446722c7e5da03d5956f5049806573d29dfee25f69262297cb7f3bd6b16fc83a175a0176c6c2a languageName: node linkType: hard @@ -9069,14 +9771,14 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.5": - version: 1.0.6 - resolution: "internal-slot@npm:1.0.6" +"internal-slot@npm:^1.0.7": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" dependencies: - get-intrinsic: ^1.2.2 + es-errors: ^1.3.0 hasown: ^2.0.0 side-channel: ^1.0.4 - checksum: 7872454888047553ce97a3fa1da7cc054a28ec5400a9c2e9f4dbe4fe7c1d041cb8e8301467614b80d4246d50377aad2fb58860b294ed74d6700cc346b6f89549 + checksum: cadc5eea5d7d9bc2342e93aae9f31f04c196afebb11bde97448327049f492cd7081e18623ae71388aac9cd237b692ca3a105be9c68ac39c1dec679d7409e33eb languageName: node linkType: hard @@ -9119,6 +9821,16 @@ __metadata: languageName: node linkType: hard +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: 1.1.0 + sprintf-js: ^1.1.3 + checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc + languageName: node + linkType: hard + "ip-regex@npm:^4.0.0": version: 4.3.0 resolution: "ip-regex@npm:4.3.0" @@ -9126,13 +9838,6 @@ __metadata: languageName: node linkType: hard -"ip@npm:^2.0.0": - version: 2.0.0 - resolution: "ip@npm:2.0.0" - checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349 - languageName: node - linkType: hard - "ipaddr.js@npm:1.9.1": version: 1.9.1 resolution: "ipaddr.js@npm:1.9.1" @@ -9259,7 +9964,7 @@ __metadata: languageName: node linkType: hard -"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4": +"is-array-buffer@npm:^3.0.4": version: 3.0.4 resolution: "is-array-buffer@npm:3.0.4" dependencies: @@ -9354,6 +10059,15 @@ __metadata: languageName: node linkType: hard +"is-data-view@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-view@npm:1.0.1" + dependencies: + is-typed-array: ^1.1.13 + checksum: 4ba4562ac2b2ec005fefe48269d6bd0152785458cd253c746154ffb8a8ab506a29d0cfb3b74af87513843776a88e4981ae25c89457bf640a33748eab1a7216b5 + languageName: node + linkType: hard + "is-date-object@npm:^1.0.1, is-date-object@npm:^1.0.5": version: 1.0.5 resolution: "is-date-object@npm:1.0.5" @@ -9505,10 +10219,10 @@ __metadata: languageName: node linkType: hard -"is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: c1e6b23d2070c0539d7b36022d5a94407132411d01aba39ec549af824231f3804b1aea90b5e4e58e807a65d23ceb538ed6e355ce76b267bdd86edb757ffcbdcd languageName: node linkType: hard @@ -9570,12 +10284,12 @@ __metadata: languageName: node linkType: hard -"is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" +"is-shared-array-buffer@npm:^1.0.2, is-shared-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" dependencies: - call-bind: ^1.0.2 - checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a + call-bind: ^1.0.7 + checksum: a4fff602c309e64ccaa83b859255a43bb011145a42d3f56f67d9268b55bc7e6d98a5981a1d834186ad3105d6739d21547083fe7259c76c0468483fc538e716d8 languageName: node linkType: hard @@ -9611,7 +10325,7 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.9": +"is-typed-array@npm:^1.1.13": version: 1.1.13 resolution: "is-typed-array@npm:1.1.13" dependencies: @@ -9750,6 +10464,15 @@ __metadata: languageName: node linkType: hard +"isows@npm:1.0.3": + version: 1.0.3 + resolution: "isows@npm:1.0.3" + peerDependencies: + ws: "*" + checksum: 9cacd5cf59f67deb51e825580cd445ab1725ecb05a67c704050383fb772856f3cd5e7da8ad08f5a3bd2823680d77d099459d0c6a7037972a74d6429af61af440 + languageName: node + linkType: hard + "isstream@npm:~0.1.2": version: 0.1.2 resolution: "isstream@npm:0.1.2" @@ -9816,16 +10539,16 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.3.5": - version: 2.3.6 - resolution: "jackspeak@npm:2.3.6" +"jackspeak@npm:^3.1.2": + version: 3.4.0 + resolution: "jackspeak@npm:3.4.0" dependencies: "@isaacs/cliui": ^8.0.2 "@pkgjs/parseargs": ^0.11.0 dependenciesMeta: "@pkgjs/parseargs": optional: true - checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 + checksum: 350f6f311018bb175ffbe736b19c26ac0b134bb5a17a638169e89594eb0c24ab1c658ab3a2fda24ff63b3b19292e1a5ec19d2255bc526df704e8168d392bef85 languageName: node linkType: hard @@ -9858,13 +10581,6 @@ __metadata: languageName: node linkType: hard -"js-sdsl@npm:^4.1.4": - version: 4.4.2 - resolution: "js-sdsl@npm:4.4.2" - checksum: ba705adc1788bf3c6f6c8e5077824f2bb4f0acab5a984420ce5cc492c7fff3daddc26335ad2c9a67d4f5e3241ec790f9e5b72a625adcf20cf321d2fd85e62b8b - languageName: node - linkType: hard - "js-sha3@npm:0.8.0, js-sha3@npm:^0.8.0": version: 0.8.0 resolution: "js-sha3@npm:0.8.0" @@ -9916,6 +10632,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 + languageName: node + linkType: hard + "jsbn@npm:~0.1.0": version: 0.1.1 resolution: "jsbn@npm:0.1.1" @@ -9941,6 +10664,15 @@ __metadata: languageName: node linkType: hard +"json-bigint@npm:^1.0.0": + version: 1.0.0 + resolution: "json-bigint@npm:1.0.0" + dependencies: + bignumber.js: ^9.0.0 + checksum: c67bb93ccb3c291e60eb4b62931403e378906aab113ec1c2a8dd0f9a7f065ad6fd9713d627b732abefae2e244ac9ce1721c7a3142b2979532f12b258634ce6f6 + languageName: node + linkType: hard + "json-buffer@npm:3.0.0": version: 3.0.0 resolution: "json-buffer@npm:3.0.0" @@ -10110,7 +10842,7 @@ __metadata: languageName: node linkType: hard -"jsonschema@npm:^1.2.4": +"jsonschema@npm:^1.2.4, jsonschema@npm:^1.4.1": version: 1.4.1 resolution: "jsonschema@npm:1.4.1" checksum: 1ef02a6cd9bc32241ec86bbf1300bdbc3b5f2d8df6eb795517cf7d1cd9909e7beba1e54fdf73990fd66be98a182bda9add9607296b0cb00b1348212988e424b2 @@ -10140,6 +10872,18 @@ __metadata: languageName: node linkType: hard +"keccak@npm:3.0.2": + version: 3.0.2 + resolution: "keccak@npm:3.0.2" + dependencies: + node-addon-api: ^2.0.0 + node-gyp: latest + node-gyp-build: ^4.2.0 + readable-stream: ^3.6.0 + checksum: 39a7d6128b8ee4cb7dcd186fc7e20c6087cc39f573a0f81b147c323f688f1f7c2b34f62c4ae189fe9b81c6730b2d1228d8a399cdc1f3d8a4c8f030cdc4f20272 + languageName: node + linkType: hard + "keccak@npm:^3.0.0, keccak@npm:^3.0.2": version: 3.0.4 resolution: "keccak@npm:3.0.4" @@ -10250,6 +10994,22 @@ __metadata: languageName: node linkType: hard +"level-concat-iterator@npm:^3.0.0": + version: 3.1.0 + resolution: "level-concat-iterator@npm:3.1.0" + dependencies: + catering: ^2.1.0 + checksum: a15bc4c5fbbb30c1efa7fad06b72feaac84d90990b356b461593c198a833336f31f6daff8f40c3908fabd14cfd8856d1c5ecae9e1cb0575037b65fa607e760e9 + languageName: node + linkType: hard + +"level-concat-iterator@npm:~2.0.0": + version: 2.0.1 + resolution: "level-concat-iterator@npm:2.0.1" + checksum: 562583ef1292215f8e749c402510cb61c4d6fccf4541082b3d21dfa5ecde9fcccfe52bdcb5cfff9d2384e7ce5891f44df9439a6ddb39b0ffe31015600b4a828a + languageName: node + linkType: hard + "level-errors@npm:^1.0.3": version: 1.1.2 resolution: "level-errors@npm:1.1.2" @@ -10311,6 +11071,17 @@ __metadata: languageName: node linkType: hard +"level-iterator-stream@npm:~4.0.0": + version: 4.0.2 + resolution: "level-iterator-stream@npm:4.0.2" + dependencies: + inherits: ^2.0.4 + readable-stream: ^3.4.0 + xtend: ^4.0.2 + checksum: 239e2c7e62bffb485ed696bcd3b98de7a2bc455d13be4fce175ae3544fe9cda81c2ed93d3e88b61380ae6d28cce02511862d77b86fb2ba5b5cf00471f3c1eccc + languageName: node + linkType: hard + "level-mem@npm:^3.0.1": version: 3.0.1 resolution: "level-mem@npm:3.0.1" @@ -10321,6 +11092,26 @@ __metadata: languageName: node linkType: hard +"level-mem@npm:^5.0.1": + version: 5.0.1 + resolution: "level-mem@npm:5.0.1" + dependencies: + level-packager: ^5.0.3 + memdown: ^5.0.0 + checksum: 37a38163b0c7cc55f64385fdff78438669f953bc08dc751739e2f1edd401472a89001a73a95cc8b81f38f989e46279797c11eb82e702690ea9a171e02bf31e84 + languageName: node + linkType: hard + +"level-packager@npm:^5.0.3": + version: 5.1.1 + resolution: "level-packager@npm:5.1.1" + dependencies: + encoding-down: ^6.3.0 + levelup: ^4.3.2 + checksum: befe2aa54f2010a6ecf7ddce392c8dee225e1839205080a2704d75e560e28b01191b345494696196777b70d376e3eaae4c9e7c330cc70d3000839f5b18dd78f2 + languageName: node + linkType: hard + "level-packager@npm:~4.0.0": version: 4.0.1 resolution: "level-packager@npm:4.0.1" @@ -10358,20 +11149,19 @@ __metadata: languageName: node linkType: hard -"level-supports@npm:^4.0.0": - version: 4.0.1 - resolution: "level-supports@npm:4.0.1" - checksum: d4552b42bb8cdeada07b0f6356c7a90fefe76279147331f291aceae26e3e56d5f927b09ce921647c0230bfe03ddfbdcef332be921e5c2194421ae2bfa3cf6368 +"level-supports@npm:^2.0.1": + version: 2.1.0 + resolution: "level-supports@npm:2.1.0" + checksum: f7b16aea7ddd13326ee4fbc2c1099bcaf8a74dc95346af9ebedea4e02518c6f7a438e829b79b7890d67489b59f615a9428369a0a065021797aa7cb6b6bd84d75 languageName: node linkType: hard -"level-transcoder@npm:^1.0.1": +"level-supports@npm:~1.0.0": version: 1.0.1 - resolution: "level-transcoder@npm:1.0.1" + resolution: "level-supports@npm:1.0.1" dependencies: - buffer: ^6.0.3 - module-error: ^1.0.1 - checksum: 304f08d802faf3491a533b6d87ad8be3cabfd27f2713bbe9d4c633bf50fcb9460eab5a6776bf015e101ead7ba1c1853e05e7f341112f17a9d0cb37ee5a421a25 + xtend: ^4.0.2 + checksum: 5d6bdb88cf00c3d9adcde970db06a548c72c5a94bf42c72f998b58341a105bfe2ea30d313ce1e84396b98cc9ddbc0a9bd94574955a86e929f73c986e10fc0df0 languageName: node linkType: hard @@ -10396,14 +11186,26 @@ __metadata: languageName: node linkType: hard -"level@npm:^8.0.0": - version: 8.0.1 - resolution: "level@npm:8.0.1" +"level-ws@npm:^2.0.0": + version: 2.0.0 + resolution: "level-ws@npm:2.0.0" + dependencies: + inherits: ^2.0.3 + readable-stream: ^3.1.0 + xtend: ^4.0.1 + checksum: 4e5cbf090a07367373f693c98ad5b4797e7e694ea801ce5cd4103e06837ec883bdce9588ac11e0b9963ca144b96c95c6401c9e43583028ba1e4f847e81ec9ad6 + languageName: node + linkType: hard + +"leveldown@npm:6.1.0": + version: 6.1.0 + resolution: "leveldown@npm:6.1.0" dependencies: - abstract-level: ^1.0.4 - browser-level: ^1.0.1 - classic-level: ^1.2.0 - checksum: c5641cbba666ef9eb0292aad01d86a4f1af18e637d1fc097c65bf0109ab8d7e6fba8c8faf6c74ae4e48edac4310f7dd87def26ffeebfe395c7afd9bd2461ab97 + abstract-leveldown: ^7.2.0 + napi-macros: ~2.0.0 + node-gyp: latest + node-gyp-build: ^4.3.0 + checksum: e984b61e9fbe057cfd5c81ac0afe5d7e35d695ff130a95991e0ecb66390e4c4ff6aa3980a65b6c53edaba80527a47790bb26e3cfbd52a054957b3546d9941fe4 languageName: node linkType: hard @@ -10434,6 +11236,19 @@ __metadata: languageName: node linkType: hard +"levelup@npm:^4.3.2": + version: 4.4.0 + resolution: "levelup@npm:4.4.0" + dependencies: + deferred-leveldown: ~5.3.0 + level-errors: ~2.0.0 + level-iterator-stream: ~4.0.0 + level-supports: ~1.0.0 + xtend: ~4.0.0 + checksum: 5a09e34c78cd7c23f9f6cb73563f1ebe8121ffc5f9f5f232242529d4fbdd40e8d1ffb337d2defa0b842334e0dbd4028fbfe7a072eebfe2c4d07174f0aa4aabca + languageName: node + linkType: hard + "levn@npm:^0.3.0, levn@npm:~0.3.0": version: 0.3.0 resolution: "levn@npm:0.3.0" @@ -10747,10 +11562,10 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.2.0 - resolution: "lru-cache@npm:10.2.0" - checksum: eee7ddda4a7475deac51ac81d7dd78709095c6fa46e8350dc2d22462559a1faa3b81ed931d5464b13d48cbd7e08b46100b6f768c76833912bc444b99c37e25db +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.2.2 + resolution: "lru-cache@npm:10.2.2" + checksum: 98e8fc93691c546f719a76103ef2bee5a3ac823955c755a47641ec41f8c7fafa1baeaba466937cc1cbfa9cfd47e03536d10e2db3158a64ad91ff3a58a32c893e languageName: node linkType: hard @@ -10763,15 +11578,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: ^4.0.0 - checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 - languageName: node - linkType: hard - "lru_map@npm:^0.3.3": version: 0.3.3 resolution: "lru_map@npm:0.3.3" @@ -10801,8 +11607,8 @@ __metadata: linkType: hard "make-fetch-happen@npm:^13.0.0": - version: 13.0.0 - resolution: "make-fetch-happen@npm:13.0.0" + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" dependencies: "@npmcli/agent": ^2.0.0 cacache: ^18.0.0 @@ -10813,9 +11619,10 @@ __metadata: minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 negotiator: ^0.6.3 + proc-log: ^4.2.0 promise-retry: ^2.0.1 ssri: ^10.0.0 - checksum: 7c7a6d381ce919dd83af398b66459a10e2fe8f4504f340d1d090d3fa3d1b0c93750220e1d898114c64467223504bd258612ba83efbc16f31b075cd56de24b4af + checksum: 5c9fad695579b79488fa100da05777213dd9365222f85e4757630f8dd2a21a79ddd3206c78cfd6f9b37346819681782b67900ac847a57cf04190f52dda5343fd languageName: node linkType: hard @@ -10844,6 +11651,15 @@ __metadata: languageName: node linkType: hard +"markdown-table@npm:2.0.0": + version: 2.0.0 + resolution: "markdown-table@npm:2.0.0" + dependencies: + repeat-string: ^1.0.0 + checksum: 9bb634a9300016cbb41216c1eab44c74b6b7083ac07872e296f900a29449cf0e260ece03fa10c3e9784ab94c61664d1d147da0315f95e1336e2bdcc025615c90 + languageName: node + linkType: hard + "markdown-table@npm:^1.1.3": version: 1.1.3 resolution: "markdown-table@npm:1.1.3" @@ -10901,6 +11717,20 @@ __metadata: languageName: node linkType: hard +"memdown@npm:^5.0.0": + version: 5.1.0 + resolution: "memdown@npm:5.1.0" + dependencies: + abstract-leveldown: ~6.2.1 + functional-red-black-tree: ~1.0.1 + immediate: ~3.2.3 + inherits: ~2.0.1 + ltgt: ~2.2.0 + safe-buffer: ~5.2.0 + checksum: 23e4414034e975eae1edd6864874bbe77501d41814fc27e8ead946c3379cb1cbea303d724083d08a6a269af9bf5d55073f1f767dfa7ad6e70465769f87e29794 + languageName: node + linkType: hard + "memdown@npm:~3.0.0": version: 3.0.0 resolution: "memdown@npm:3.0.0" @@ -10915,17 +11745,6 @@ __metadata: languageName: node linkType: hard -"memory-level@npm:^1.0.0": - version: 1.0.0 - resolution: "memory-level@npm:1.0.0" - dependencies: - abstract-level: ^1.0.0 - functional-red-black-tree: ^1.0.1 - module-error: ^1.0.1 - checksum: 80b1b7aedaf936e754adbcd7b9303018c3684fb32f9992fd967c448f145d177f16c724fbba9ed3c3590a9475fd563151eae664d69b83d2ad48714852e9fc5c72 - languageName: node - linkType: hard - "memorystream@npm:^0.3.1": version: 0.3.1 resolution: "memorystream@npm:0.3.1" @@ -10994,6 +11813,20 @@ __metadata: languageName: node linkType: hard +"merkle-patricia-tree@npm:^4.2.2, merkle-patricia-tree@npm:^4.2.4": + version: 4.2.4 + resolution: "merkle-patricia-tree@npm:4.2.4" + dependencies: + "@types/levelup": ^4.3.0 + ethereumjs-util: ^7.1.4 + level-mem: ^5.0.1 + level-ws: ^2.0.0 + readable-stream: ^3.6.0 + semaphore-async-await: ^1.5.1 + checksum: acedc7eea7bb14b97da01e8e023406ed55742f8e82bdd28d1ed821e3bd0cfed9e92f18c7cb300aee0d38f319c960026fd4d4e601f61e2a8665b73c0786d9f799 + languageName: node + linkType: hard + "methods@npm:~1.1.2": version: 1.1.2 resolution: "methods@npm:1.1.2" @@ -11030,12 +11863,12 @@ __metadata: linkType: hard "micromatch@npm:^4.0.2, micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" + version: 4.0.7 + resolution: "micromatch@npm:4.0.7" dependencies: - braces: ^3.0.2 + braces: ^3.0.3 picomatch: ^2.3.1 - checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc + checksum: 3cde047d70ad80cf60c787b77198d680db3b8c25b23feb01de5e2652205d9c19f43bd81882f69a0fd1f0cde6a7a122d774998aad3271ddb1b8accf8a0f480cf7 languageName: node linkType: hard @@ -11147,12 +11980,12 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.1": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" +"minimatch@npm:^9.0.4": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" dependencies: brace-expansion: ^2.0.1 - checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + checksum: cf717f597ec3eed7dabc33153482a2e8d49f4fd3c26e58fd9c71a94c5029a0838728841b93f46bf1263b65a8010e2ee800d0dc9b004ab8ba8b6d1ec07cc115b5 languageName: node linkType: hard @@ -11173,8 +12006,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^3.0.0": - version: 3.0.4 - resolution: "minipass-fetch@npm:3.0.4" + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" dependencies: encoding: ^0.1.13 minipass: ^7.0.3 @@ -11183,7 +12016,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: af7aad15d5c128ab1ebe52e043bdf7d62c3c6f0cecb9285b40d7b395e1375b45dcdfd40e63e93d26a0e8249c9efd5c325c65575aceee192883970ff8cb11364a + checksum: 8047d273236157aab27ab7cd8eab7ea79e6ecd63e8f80c3366ec076cb9a0fed550a6935bab51764369027c414647fd8256c2a20c5445fb250c483de43350de83 languageName: node linkType: hard @@ -11240,10 +12073,10 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": - version: 7.0.4 - resolution: "minipass@npm:7.0.4" - checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 2bfd325b95c555f2b4d2814d49325691c7bee937d753814861b0b49d5edcda55cbbf22b6b6a60bb91eddac8668771f03c5ff647dcd9d0f798e9548b9cdc46ee3 languageName: node linkType: hard @@ -11324,8 +12157,8 @@ __metadata: linkType: hard "mocha@npm:^10.0.0, mocha@npm:^10.2.0": - version: 10.2.0 - resolution: "mocha@npm:10.2.0" + version: 10.4.0 + resolution: "mocha@npm:10.4.0" dependencies: ansi-colors: 4.1.1 browser-stdout: 1.3.1 @@ -11334,13 +12167,12 @@ __metadata: diff: 5.0.0 escape-string-regexp: 4.0.0 find-up: 5.0.0 - glob: 7.2.0 + glob: 8.1.0 he: 1.2.0 js-yaml: 4.1.0 log-symbols: 4.1.0 minimatch: 5.0.1 ms: 2.1.3 - nanoid: 3.3.3 serialize-javascript: 6.0.0 strip-json-comments: 3.1.1 supports-color: 8.1.1 @@ -11351,7 +12183,7 @@ __metadata: bin: _mocha: bin/_mocha mocha: bin/mocha.js - checksum: 406c45eab122ffd6ea2003c2f108b2bc35ba036225eee78e0c784b6fa2c7f34e2b13f1dbacef55a4fdf523255d76e4f22d1b5aacda2394bd11666febec17c719 + checksum: 090771d6d42a65a934c7ed448d524bcc663836351af9f0678578caa69943b01a9535a73192d24fd625b3fdb5979cce5834dfe65e3e1ee982444d65e19975b81c languageName: node linkType: hard @@ -11376,13 +12208,6 @@ __metadata: languageName: node linkType: hard -"module-error@npm:^1.0.1, module-error@npm:^1.0.2": - version: 1.0.2 - resolution: "module-error@npm:1.0.2" - checksum: 5d653e35bd55b3e95f8aee2cdac108082ea892e71b8f651be92cde43e4ee86abee4fa8bd7fc3fe5e68b63926d42f63c54cd17b87a560c31f18739295575a3962 - languageName: node - linkType: hard - "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -11507,15 +12332,6 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:3.3.3": - version: 3.3.3 - resolution: "nanoid@npm:3.3.3" - bin: - nanoid: bin/nanoid.cjs - checksum: ada019402a07464a694553c61d2dca8a4353645a7d92f2830f0d487fedff403678a0bee5323a46522752b2eab95a0bc3da98b6cccaa7c0c55cd9975130e6d6f0 - languageName: node - linkType: hard - "nanoid@npm:^3.0.2, nanoid@npm:^3.1.20, nanoid@npm:^3.1.23": version: 3.3.7 resolution: "nanoid@npm:3.3.7" @@ -11544,10 +12360,10 @@ __metadata: languageName: node linkType: hard -"napi-macros@npm:^2.2.2": - version: 2.2.2 - resolution: "napi-macros@npm:2.2.2" - checksum: c6f9bd71cdbbc37ddc3535aa5be481238641d89585b8a3f4d301cb89abf459e2d294810432bb7d12056d1f9350b1a0899a5afcf460237a3da6c398cf0fec7629 +"napi-macros@npm:~2.0.0": + version: 2.0.0 + resolution: "napi-macros@npm:2.0.0" + checksum: 30384819386977c1f82034757014163fa60ab3c5a538094f778d38788bebb52534966279956f796a92ea771c7f8ae072b975df65de910d051ffbdc927f62320c languageName: node linkType: hard @@ -11653,20 +12469,42 @@ __metadata: languageName: node linkType: hard +"node-gyp-build@npm:4.3.0": + version: 4.3.0 + resolution: "node-gyp-build@npm:4.3.0" + bin: + node-gyp-build: bin.js + node-gyp-build-optional: optional.js + node-gyp-build-test: build-test.js + checksum: 1ecab16d9f275174d516e223f60f65ebe07540347d5c04a6a7d6921060b7f2e3af4f19463d9d1dcedc452e275c2ae71354a99405e55ebd5b655bb2f38025c728 + languageName: node + linkType: hard + +"node-gyp-build@npm:4.4.0": + version: 4.4.0 + resolution: "node-gyp-build@npm:4.4.0" + bin: + node-gyp-build: bin.js + node-gyp-build-optional: optional.js + node-gyp-build-test: build-test.js + checksum: 972a059f960253d254e0b23ce10f54c8982236fc0edcab85166d0b7f87443b2ce98391c877cfb2f6eeafcf03c538c5f4dd3e0bfff03828eb48634f58f4c64343 + languageName: node + linkType: hard + "node-gyp-build@npm:^4.2.0, node-gyp-build@npm:^4.3.0": - version: 4.8.0 - resolution: "node-gyp-build@npm:4.8.0" + version: 4.8.1 + resolution: "node-gyp-build@npm:4.8.1" bin: node-gyp-build: bin.js node-gyp-build-optional: optional.js node-gyp-build-test: build-test.js - checksum: b82a56f866034b559dd3ed1ad04f55b04ae381b22ec2affe74b488d1582473ca6e7f85fccf52da085812d3de2b0bf23109e752a57709ac7b9963951c710fea40 + checksum: fe6e95da6f4608c1a98655f6bf2fe4e8dd9c877cd13256056a8acaf585cc7f98718823fe9366be11b78c2f332d5a184b00cf07a4af96c9d8fea45f640c019f98 languageName: node linkType: hard "node-gyp@npm:latest": - version: 10.0.1 - resolution: "node-gyp@npm:10.0.1" + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 @@ -11680,7 +12518,7 @@ __metadata: which: ^4.0.0 bin: node-gyp: bin/node-gyp.js - checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f + checksum: 72e2ab4b23fc32007a763da94018f58069fc0694bf36115d49a2b195c8831e12cf5dd1e7a3718fa85c06969aedf8fc126722d3b672ec1cb27e06ed33caee3c60 languageName: node linkType: hard @@ -11703,13 +12541,13 @@ __metadata: linkType: hard "nopt@npm:^7.0.0": - version: 7.2.0 - resolution: "nopt@npm:7.2.0" + version: 7.2.1 + resolution: "nopt@npm:7.2.1" dependencies: abbrev: ^2.0.0 bin: nopt: bin/nopt.js - checksum: a9c0f57fb8cb9cc82ae47192ca2b7ef00e199b9480eed202482c962d61b59a7fbe7541920b2a5839a97b42ee39e288c0aed770e38057a608d7f579389dfde410 + checksum: 6fa729cc77ce4162cfad8abbc9ba31d4a0ff6850c3af61d59b505653bef4781ec059f8890ecfe93ee8aa0c511093369cca88bfc998101616a2904e715bbbb7c9 languageName: node linkType: hard @@ -11806,7 +12644,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.1, object-inspect@npm:^1.9.0": +"object-inspect@npm:^1.13.1": version: 1.13.1 resolution: "object-inspect@npm:1.13.1" checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f @@ -11821,12 +12659,12 @@ __metadata: linkType: hard "object-is@npm:^1.1.5": - version: 1.1.5 - resolution: "object-is@npm:1.1.5" + version: 1.1.6 + resolution: "object-is@npm:1.1.6" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe + call-bind: ^1.0.7 + define-properties: ^1.2.1 + checksum: 3ea22759967e6f2380a2cbbd0f737b42dc9ddb2dfefdb159a1b927fea57335e1b058b564bfa94417db8ad58cddab33621a035de6f5e5ad56d89f2dd03e66c6a1 languageName: node linkType: hard @@ -11853,7 +12691,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.4": +"object.assign@npm:^4.1.5": version: 4.1.5 resolution: "object.assign@npm:4.1.5" dependencies: @@ -11866,39 +12704,40 @@ __metadata: linkType: hard "object.fromentries@npm:^2.0.7": - version: 2.0.7 - resolution: "object.fromentries@npm:2.0.7" + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 7341ce246e248b39a431b87a9ddd331ff52a454deb79afebc95609f94b1f8238966cf21f52188f2a353f0fdf83294f32f1ebf1f7826aae915ebad21fd0678065 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: 29b2207a2db2782d7ced83f93b3ff5d425f901945f3665ffda1821e30a7253cd1fd6b891a64279976098137ddfa883d748787a6fea53ecdb51f8df8b8cec0ae1 languageName: node linkType: hard "object.getownpropertydescriptors@npm:^2.1.6": - version: 2.1.7 - resolution: "object.getownpropertydescriptors@npm:2.1.7" + version: 2.1.8 + resolution: "object.getownpropertydescriptors@npm:2.1.8" dependencies: array.prototype.reduce: ^1.0.6 - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - safe-array-concat: ^1.0.0 - checksum: 8e7ae1d522a3874d2d23a3d0fb75828cbcee60958b65c2ad8e58ce227f4efba8cc2b59c7431a0fd48b20d9e04ec075bc0e0d694b1d2c2296e534daf558beb10b + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + gopd: ^1.0.1 + safe-array-concat: ^1.1.2 + checksum: 073e492700a7f61ff6c471a2ed96e72473b030a7a105617f03cab192fb4bbc0e6068ef76534ec56afd34baf26b5dc5408de59cb0140ec8abde781e00faa3e63e languageName: node linkType: hard "object.groupby@npm:^1.0.1": - version: 1.0.2 - resolution: "object.groupby@npm:1.0.2" + version: 1.0.3 + resolution: "object.groupby@npm:1.0.3" dependencies: - array.prototype.filter: ^1.0.3 - call-bind: ^1.0.5 + call-bind: ^1.0.7 define-properties: ^1.2.1 - es-abstract: ^1.22.3 - es-errors: ^1.0.0 - checksum: 5f95c2a3a5f60a1a8c05fdd71455110bd3d5e6af0350a20b133d8cd70f9c3385d5c7fceb6a17b940c3c61752d9c202d10d5e2eb5ce73b89002656a87e7bf767a + es-abstract: ^1.23.2 + checksum: 0d30693ca3ace29720bffd20b3130451dca7a56c612e1926c0a1a15e4306061d84410bdb1456be2656c5aca53c81b7a3661eceaa362db1bba6669c2c9b6d1982 languageName: node linkType: hard @@ -11912,13 +12751,13 @@ __metadata: linkType: hard "object.values@npm:^1.1.7": - version: 1.1.7 - resolution: "object.values@npm:1.1.7" + version: 1.2.0 + resolution: "object.values@npm:1.2.0" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: f3e4ae4f21eb1cc7cebb6ce036d4c67b36e1c750428d7b7623c56a0db90edced63d08af8a316d81dfb7c41a3a5fa81b05b7cc9426e98d7da986b1682460f0777 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 51fef456c2a544275cb1766897f34ded968b22adfc13ba13b5e4815fdaf4304a90d42a3aee114b1f1ede048a4890381d47a5594d84296f2767c6a0364b9da8fa languageName: node linkType: hard @@ -11999,16 +12838,16 @@ __metadata: linkType: hard "optionator@npm:^0.9.3": - version: 0.9.3 - resolution: "optionator@npm:0.9.3" + version: 0.9.4 + resolution: "optionator@npm:0.9.4" dependencies: - "@aashutoshrathi/word-wrap": ^1.2.3 deep-is: ^0.1.3 fast-levenshtein: ^2.0.6 levn: ^0.4.1 prelude-ls: ^1.2.1 type-check: ^0.4.0 - checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + word-wrap: ^1.2.5 + checksum: ecbd010e3dc73e05d239976422d9ef54a82a13f37c11ca5911dff41c98a6c7f0f163b27f922c37e7f8340af9d36febd3b6e9cef508f3339d4c393d7276d716bb languageName: node linkType: hard @@ -12214,16 +13053,17 @@ __metadata: languageName: node linkType: hard -"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.6": - version: 5.1.6 - resolution: "parse-asn1@npm:5.1.6" +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.7": + version: 5.1.7 + resolution: "parse-asn1@npm:5.1.7" dependencies: - asn1.js: ^5.2.0 - browserify-aes: ^1.0.0 - evp_bytestokey: ^1.0.0 - pbkdf2: ^3.0.3 - safe-buffer: ^5.1.1 - checksum: 9243311d1f88089bc9f2158972aa38d1abd5452f7b7cabf84954ed766048fe574d434d82c6f5a39b988683e96fb84cd933071dda38927e03469dc8c8d14463c7 + asn1.js: ^4.10.1 + browserify-aes: ^1.2.0 + evp_bytestokey: ^1.0.3 + hash-base: ~3.0 + pbkdf2: ^3.1.2 + safe-buffer: ^5.2.1 + checksum: 93c7194c1ed63a13e0b212d854b5213ad1aca0ace41c66b311e97cca0519cf9240f79435a0306a3b412c257f0ea3f1953fd0d9549419a0952c9e995ab361fd6c languageName: node linkType: hard @@ -12387,13 +13227,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" dependencies: - lru-cache: ^9.1.1 || ^10.0.0 + lru-cache: ^10.2.0 minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + checksum: 890d5abcd593a7912dcce7cf7c6bf7a0b5648e3dee6caf0712c126ca0a65c7f3d7b9d769072a4d1baf370f61ce493ab5b038d59988688e0c5f3f646ee3c69023 languageName: node linkType: hard @@ -12429,7 +13269,7 @@ __metadata: languageName: node linkType: hard -"pbkdf2@npm:^3.0.17, pbkdf2@npm:^3.0.3, pbkdf2@npm:^3.0.9": +"pbkdf2@npm:^3.0.17, pbkdf2@npm:^3.0.3, pbkdf2@npm:^3.0.9, pbkdf2@npm:^3.1.2": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" dependencies: @@ -12449,6 +13289,13 @@ __metadata: languageName: node linkType: hard +"picocolors@npm:^1.0.0": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 + languageName: node + linkType: hard + "picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" @@ -12507,6 +13354,13 @@ __metadata: languageName: node linkType: hard +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: b32d403ece71e042385cc7856385cecf1cd8e144fa74d2f1de40d1e16035dba097bc189715925e79b67bdd1472796ff168d3a90d296356c9c94d272d5b95f3ae + languageName: node + linkType: hard + "postinstall-postinstall@npm:^2.1.0": version: 2.1.0 resolution: "postinstall-postinstall@npm:2.1.0" @@ -12596,6 +13450,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 98f6cd012d54b5334144c5255ecb941ee171744f45fca8b43b58ae5a0c1af07352475f481cadd9848e7f0250376ee584f6aa0951a856ff8f021bdfbff4eb33fc + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -12846,11 +13707,11 @@ __metadata: linkType: hard "qs@npm:^6.11.2, qs@npm:^6.4.0": - version: 6.11.2 - resolution: "qs@npm:6.11.2" + version: 6.12.1 + resolution: "qs@npm:6.12.1" dependencies: - side-channel: ^1.0.4 - checksum: e812f3c590b2262548647d62f1637b6989cc56656dc960b893fe2098d96e1bd633f36576f4cd7564dfbff9db42e17775884db96d846bebe4f37420d073ecdc0b + side-channel: ^1.0.6 + checksum: aa761d99e65b6936ba2dd2187f2d9976afbcda38deb3ff1b3fe331d09b0c578ed79ca2abdde1271164b5be619c521ec7db9b34c23f49a074e5921372d16242d5 languageName: node linkType: hard @@ -12912,18 +13773,6 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.1": - version: 2.5.1 - resolution: "raw-body@npm:2.5.1" - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - checksum: 5362adff1575d691bb3f75998803a0ffed8c64eabeaa06e54b4ada25a0cd1b2ae7f4f5ec46565d1bec337e08b5ac90c76eaa0758de6f72a633f025d754dec29e - languageName: node - linkType: hard - "raw-body@npm:2.5.2, raw-body@npm:^2.4.1": version: 2.5.2 resolution: "raw-body@npm:2.5.2" @@ -12978,7 +13827,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.5, readable-stream@npm:^2.2.2, readable-stream@npm:^2.2.8, readable-stream@npm:^2.2.9, readable-stream@npm:^2.3.0, readable-stream@npm:^2.3.5, readable-stream@npm:^2.3.6, readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.5, readable-stream@npm:^2.2.2, readable-stream@npm:^2.2.8, readable-stream@npm:^2.2.9, readable-stream@npm:^2.3.0, readable-stream@npm:^2.3.5, readable-stream@npm:^2.3.6, readable-stream@npm:^2.3.8, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -12993,7 +13842,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.0.6, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": +"readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.0, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -13094,14 +13943,15 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.1": - version: 1.5.1 - resolution: "regexp.prototype.flags@npm:1.5.1" +"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2": + version: 1.5.2 + resolution: "regexp.prototype.flags@npm:1.5.2" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - set-function-name: ^2.0.0 - checksum: 869edff00288442f8d7fa4c9327f91d85f3b3acf8cbbef9ea7a220345cf23e9241b6def9263d2c1ebcf3a316b0aa52ad26a43a84aa02baca3381717b3e307f47 + call-bind: ^1.0.6 + define-properties: ^1.2.1 + es-errors: ^1.3.0 + set-function-name: ^2.0.1 + checksum: d7f333667d5c564e2d7a97c56c3075d64c722c9bb51b2b4df6822b2e8096d623a5e63088fb4c83df919b6951ef8113841de8b47de7224872fa6838bc5d8a7d64 languageName: node linkType: hard @@ -13155,7 +14005,7 @@ __metadata: languageName: node linkType: hard -"repeat-string@npm:^1.6.1": +"repeat-string@npm:^1.0.0, repeat-string@npm:^1.6.1": version: 1.6.1 resolution: "repeat-string@npm:1.6.1" checksum: 1b809fc6db97decdc68f5b12c4d1a671c8e3f65ec4a40c238bc5200e44e85bcc52a54f78268ab9c29fcf5fe4f1343e805420056d1f30fa9a9ee4c2d93e3cc6c0 @@ -13423,7 +14273,7 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.0, rimraf@npm:^3.0.2": +"rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" dependencies: @@ -13444,6 +14294,17 @@ __metadata: languageName: node linkType: hard +"rlp@npm:2.2.6": + version: 2.2.6 + resolution: "rlp@npm:2.2.6" + dependencies: + bn.js: ^4.11.1 + bin: + rlp: bin/rlp + checksum: 2601225df0fe7aa3b497b33a12fd9fbaf8fb1d2989ecc5c091918ed93ee77d1c3fab20ddd3891a9ca66a8ba66d993e6079be6fb31f450fcf38ba30873102ca46 + languageName: node + linkType: hard + "rlp@npm:^2.0.0, rlp@npm:^2.2.1, rlp@npm:^2.2.2, rlp@npm:^2.2.3, rlp@npm:^2.2.4": version: 2.2.7 resolution: "rlp@npm:2.2.7" @@ -13462,15 +14323,6 @@ __metadata: languageName: node linkType: hard -"run-parallel-limit@npm:^1.1.0": - version: 1.1.0 - resolution: "run-parallel-limit@npm:1.1.0" - dependencies: - queue-microtask: ^1.2.2 - checksum: 672c3b87e7f939c684b9965222b361421db0930223ed1e43ebf0e7e48ccc1a022ea4de080bef4d5468434e2577c33b7681e3f03b7593fdc49ad250a55381123c - languageName: node - linkType: hard - "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -13505,15 +14357,15 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.0, safe-array-concat@npm:^1.0.1": - version: 1.1.0 - resolution: "safe-array-concat@npm:1.1.0" +"safe-array-concat@npm:^1.0.0, safe-array-concat@npm:^1.1.2": + version: 1.1.2 + resolution: "safe-array-concat@npm:1.1.2" dependencies: - call-bind: ^1.0.5 - get-intrinsic: ^1.2.2 + call-bind: ^1.0.7 + get-intrinsic: ^1.2.4 has-symbols: ^1.0.3 isarray: ^2.0.5 - checksum: 5c71eaa999168ee7474929f1cd3aae80f486353a651a094d9968936692cf90aa065224929a6486dcda66334a27dce4250a83612f9e0fef6dced1a925d3ac7296 + checksum: a3b259694754ddfb73ae0663829e396977b99ff21cbe8607f35a469655656da8e271753497e59da8a7575baa94d2e684bea3e10ddd74ba046c0c9b4418ffa0c4 languageName: node linkType: hard @@ -13540,14 +14392,14 @@ __metadata: languageName: node linkType: hard -"safe-regex-test@npm:^1.0.0": - version: 1.0.2 - resolution: "safe-regex-test@npm:1.0.2" +"safe-regex-test@npm:^1.0.3": + version: 1.0.3 + resolution: "safe-regex-test@npm:1.0.3" dependencies: - call-bind: ^1.0.5 - get-intrinsic: ^1.2.2 + call-bind: ^1.0.6 + es-errors: ^1.3.0 is-regex: ^1.1.4 - checksum: 4af5ce05a2daa4f6d4bfd5a3c64fc33d6b886f6592122e93c0efad52f7147b9b605e5ffc03c269a1e3d1f8db2a23bc636628a961c9fd65bafdc09503330673fd + checksum: 6c7d392ff1ae7a3ae85273450ed02d1d131f1d2c76e177d6b03eb88e6df8fa062639070e7d311802c1615f351f18dc58f9454501c58e28d5ffd9b8f502ba6489 languageName: node linkType: hard @@ -13607,7 +14459,7 @@ __metadata: languageName: node linkType: hard -"secp256k1@npm:^4.0.1": +"secp256k1@npm:4.0.3, secp256k1@npm:^4.0.1": version: 4.0.3 resolution: "secp256k1@npm:4.0.3" dependencies: @@ -13626,6 +14478,20 @@ __metadata: languageName: node linkType: hard +"seedrandom@npm:3.0.5": + version: 3.0.5 + resolution: "seedrandom@npm:3.0.5" + checksum: 728b56bc3bc1b9ddeabd381e449b51cb31bdc0aa86e27fcd0190cea8c44613d5bcb2f6bb63ed79f78180cbe791c20b8ec31a9627f7b7fc7f476fd2bdb7e2da9f + languageName: node + linkType: hard + +"semaphore-async-await@npm:^1.5.1": + version: 1.5.1 + resolution: "semaphore-async-await@npm:1.5.1" + checksum: 2dedf7c59ba5f2da860fed95a81017189de6257cbe06c9de0ff2e610a3ae427e9bde1ab7685a62b03ebc28982dee437110492215d75fd6dc8257ce7a38e66b74 + languageName: node + linkType: hard + "semaphore@npm:>=1.0.1, semaphore@npm:^1.0.3, semaphore@npm:^1.1.0": version: 1.1.0 resolution: "semaphore@npm:1.1.0" @@ -13652,13 +14518,11 @@ __metadata: linkType: hard "semver@npm:^7.0.0, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.2, semver@npm:^7.5.4": - version: 7.5.4 - resolution: "semver@npm:7.5.4" - dependencies: - lru-cache: ^6.0.0 + version: 7.6.2 + resolution: "semver@npm:7.6.2" bin: semver: bin/semver.js - checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 + checksum: 40f6a95101e8d854357a644da1b8dd9d93ce786d5c6a77227bc69dbb17bea83d0d1d1d7c4cd5920a6df909f48e8bd8a5909869535007f90278289f2451d0292d languageName: node linkType: hard @@ -13733,27 +14597,29 @@ __metadata: languageName: node linkType: hard -"set-function-length@npm:^1.1.1": - version: 1.2.0 - resolution: "set-function-length@npm:1.2.0" +"set-function-length@npm:^1.2.1": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" dependencies: - define-data-property: ^1.1.1 + define-data-property: ^1.1.4 + es-errors: ^1.3.0 function-bind: ^1.1.2 - get-intrinsic: ^1.2.2 + get-intrinsic: ^1.2.4 gopd: ^1.0.1 - has-property-descriptors: ^1.0.1 - checksum: 63e34b45a2ff9abb419f52583481bf8ba597d33c0c85e56999085eb6078a0f7fbb4222051981c287feceeb358aa7789e7803cea2c82ac94c0ab37059596aff79 + has-property-descriptors: ^1.0.2 + checksum: a8248bdacdf84cb0fab4637774d9fb3c7a8e6089866d04c817583ff48e14149c87044ce683d7f50759a8c50fb87c7a7e173535b06169c87ef76f5fb276dfff72 languageName: node linkType: hard -"set-function-name@npm:^2.0.0": - version: 2.0.1 - resolution: "set-function-name@npm:2.0.1" +"set-function-name@npm:^2.0.1": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" dependencies: - define-data-property: ^1.0.1 + define-data-property: ^1.1.4 + es-errors: ^1.3.0 functions-have-names: ^1.2.3 - has-property-descriptors: ^1.0.0 - checksum: 4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 + has-property-descriptors: ^1.0.2 + checksum: d6229a71527fd0404399fc6227e0ff0652800362510822a291925c9d7b48a1ca1a468b11b281471c34cd5a2da0db4f5d7ff315a61d26655e77f6e971e6d0c80f languageName: node linkType: hard @@ -13857,14 +14723,15 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" +"side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" dependencies: - call-bind: ^1.0.0 - get-intrinsic: ^1.0.2 - object-inspect: ^1.9.0 - checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 + call-bind: ^1.0.7 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + object-inspect: ^1.13.1 + checksum: bfc1afc1827d712271453e91b7cd3878ac0efd767495fd4e594c4c2afaa7963b7b510e249572bfd54b0527e66e4a12b61b80c061389e129755f34c493aad9b97 languageName: node linkType: hard @@ -13986,24 +14853,24 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.1": - version: 8.0.2 - resolution: "socks-proxy-agent@npm:8.0.2" +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" dependencies: - agent-base: ^7.0.2 + agent-base: ^7.1.1 debug: ^4.3.4 socks: ^2.7.1 - checksum: 4fb165df08f1f380881dcd887b3cdfdc1aba3797c76c1e9f51d29048be6e494c5b06d68e7aea2e23df4572428f27a3ec22b3d7c75c570c5346507433899a4b6d + checksum: 8fab38821c327c190c28f1658087bc520eb065d55bc07b4a0fdf8d1e0e7ad5d115abbb22a95f94f944723ea969dd771ad6416b1e3cde9060c4c71f705c8b85c5 languageName: node linkType: hard "socks@npm:^2.7.1": - version: 2.7.1 - resolution: "socks@npm:2.7.1" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: - ip: ^2.0.0 + ip-address: ^9.0.5 smart-buffer: ^4.2.0 - checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 + checksum: 7a6b7f6eedf7482b9e4597d9a20e09505824208006ea8f2c49b71657427f3c137ca2ae662089baa73e1971c62322d535d9d0cf1c9235cf6f55e315c18203eadd languageName: node linkType: hard @@ -14026,6 +14893,23 @@ __metadata: languageName: node linkType: hard +"solc@npm:0.8.15": + version: 0.8.15 + resolution: "solc@npm:0.8.15" + dependencies: + command-exists: ^1.2.8 + commander: ^8.1.0 + follow-redirects: ^1.12.1 + js-sha3: 0.8.0 + memorystream: ^0.3.1 + semver: ^5.5.0 + tmp: 0.0.33 + bin: + solcjs: solc.js + checksum: a11de198bc5d481485a4a4803fb08a81a56dd9ffa7cdc62f8d6d5fc669f72e7cb4b22789004d54481353463421f6e6e3d1dffe7365b6d0ed5f37baee303266db + languageName: node + linkType: hard + "solc@npm:^0.4.20": version: 0.4.26 resolution: "solc@npm:0.4.26" @@ -14091,11 +14975,11 @@ __metadata: linkType: hard "solidity-ast@npm:^0.4.51": - version: 0.4.55 - resolution: "solidity-ast@npm:0.4.55" + version: 0.4.56 + resolution: "solidity-ast@npm:0.4.56" dependencies: array.prototype.findlast: ^1.2.2 - checksum: a33f50b48039ca6a980eeb5d2e55a32d93c48bacbe33494faad8d50262f734cdb5c10b6d01d8bda289e702e0f9d144dd120fca1aa954c5390be8300a74a48af6 + checksum: 124cd54dc187860c83f4e8a3cbc41f890fbd0aaad4695356763034bdc782046eac414b161b7f354e423e075dba303d6bef213682df8932fee5d143d52135cd4e languageName: node linkType: hard @@ -14107,21 +14991,20 @@ __metadata: linkType: hard "solidity-coverage@npm:^0.8.5": - version: 0.8.6 - resolution: "solidity-coverage@npm:0.8.6" + version: 0.8.12 + resolution: "solidity-coverage@npm:0.8.12" dependencies: "@ethersproject/abi": ^5.0.9 "@solidity-parser/parser": ^0.18.0 chalk: ^2.4.2 death: ^1.1.0 - detect-port: ^1.3.0 difflib: ^0.2.4 fs-extra: ^8.1.0 ghost-testrpc: ^0.0.2 global-modules: ^2.0.0 globby: ^10.0.1 jsonschema: ^1.2.4 - lodash: ^4.17.15 + lodash: ^4.17.21 mocha: ^10.2.0 node-emoji: ^1.10.0 pify: ^4.0.1 @@ -14134,7 +15017,7 @@ __metadata: hardhat: ^2.11.0 bin: solidity-coverage: plugins/bin.js - checksum: 178bab95b9b41683131bf05c23ec213aca38fb65973d93a19d56ec3be3675b79e63219e2e9b1ae05ad723eb301952cc2a3c53247c676b5236262e87249a5895f + checksum: 8839416986fc76d27931dca885d915717fea3d7bae3cd2506f315f8b0583b50e05bd25a0d481262ad6cf2786966f603b6481b1658810e4add5761ce96cf5ffe4 languageName: node linkType: hard @@ -14221,9 +15104,9 @@ __metadata: linkType: hard "spdx-exceptions@npm:^2.1.0": - version: 2.4.0 - resolution: "spdx-exceptions@npm:2.4.0" - checksum: b1b650a8d94424473bf9629cf972c86a91c03cccc260f5c901bce0e4b92d831627fec28c9e0a1e9c34c5ebad0a12cf2eab887bec088e0a862abb9d720c2fd0a1 + version: 2.5.0 + resolution: "spdx-exceptions@npm:2.5.0" + checksum: bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15 languageName: node linkType: hard @@ -14238,9 +15121,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.16 - resolution: "spdx-license-ids@npm:3.0.16" - checksum: 5cdaa85aaa24bd02f9353a2e357b4df0a4f205cb35655f3fd0a5674a4fb77081f28ffd425379214bc3be2c2b7593ce1215df6bcc75884aeee0a9811207feabe2 + version: 3.0.18 + resolution: "spdx-license-ids@npm:3.0.18" + checksum: 457825df5dd1fc0135b0bb848c896143f70945cc2da148afc71c73ed0837d1d651f809006e406d82109c9dd71a8cb39785a3604815fe46bc0548e9d3976f6b69 languageName: node linkType: hard @@ -14260,6 +15143,13 @@ __metadata: languageName: node linkType: hard +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + "sprintf-js@npm:~1.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -14289,11 +15179,11 @@ __metadata: linkType: hard "ssri@npm:^10.0.0": - version: 10.0.5 - resolution: "ssri@npm:10.0.5" + version: 10.0.6 + resolution: "ssri@npm:10.0.6" dependencies: minipass: ^7.0.3 - checksum: 0a31b65f21872dea1ed3f7c200d7bc1c1b91c15e419deca14f282508ba917cbb342c08a6814c7f68ca4ca4116dd1a85da2bbf39227480e50125a1ceffeecb750 + checksum: 4603d53a05bcd44188747d38f1cc43833b9951b5a1ee43ba50535bdfc5fe4a0897472dbe69837570a5417c3c073377ef4f8c1a272683b401857f72738ee57299 languageName: node linkType: hard @@ -14410,36 +15300,37 @@ __metadata: languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.8, string.prototype.trim@npm:~1.2.8": - version: 1.2.8 - resolution: "string.prototype.trim@npm:1.2.8" +"string.prototype.trim@npm:^1.2.9, string.prototype.trim@npm:~1.2.8": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 49eb1a862a53aba73c3fb6c2a53f5463173cb1f4512374b623bcd6b43ad49dd559a06fb5789bdec771a40fc4d2a564411c0a75d35fb27e76bbe738c211ecff07 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.0 + es-object-atoms: ^1.0.0 + checksum: ea2df6ec1e914c9d4e2dc856fa08228e8b1be59b59e50b17578c94a66a176888f417264bb763d4aac638ad3b3dad56e7a03d9317086a178078d131aa293ba193 languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimend@npm:1.0.7" +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 2375516272fd1ba75992f4c4aa88a7b5f3c7a9ca308d963bcd5645adf689eba6f8a04ebab80c33e30ec0aefc6554181a3a8416015c38da0aa118e60ec896310c + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: cc3bd2de08d8968a28787deba9a3cb3f17ca5f9f770c91e7e8fa3e7d47f079bad70fadce16f05dda9f261788be2c6e84a942f618c3bed31e42abc5c1084f8dfd languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 13d0c2cb0d5ff9e926fa0bec559158b062eed2b68cd5be777ffba782c96b2b492944e47057274e064549b94dd27cf81f48b27a31fee8af5b574cff253e7eb613 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: df1007a7f580a49d692375d996521dc14fd103acda7f3034b3c558a60b82beeed3a64fa91e494e164581793a8ab0ae2f59578a49896a7af6583c1f20472bce96 languageName: node linkType: hard @@ -14673,15 +15564,15 @@ __metadata: linkType: hard "table@npm:^6.8.0, table@npm:^6.8.1": - version: 6.8.1 - resolution: "table@npm:6.8.1" + version: 6.8.2 + resolution: "table@npm:6.8.2" dependencies: ajv: ^8.0.1 lodash.truncate: ^4.4.2 slice-ansi: ^4.0.0 string-width: ^4.2.3 strip-ansi: ^6.0.1 - checksum: 08249c7046125d9d0a944a6e96cfe9ec66908d6b8a9db125531be6eb05fa0de047fd5542e9d43b4f987057f00a093b276b8d3e19af162a9c40db2681058fd306 + checksum: 61188652f53a980d1759ca460ca8dea5c5322aece3210457e7084882f053c2b6a870041295e08a82cb1d676e31b056406845d94b0abf3c79a4b104777bec413b languageName: node linkType: hard @@ -14754,8 +15645,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: ^2.0.0 fs-minipass: ^2.0.0 @@ -14763,7 +15654,7 @@ __metadata: minizlib: ^2.1.1 mkdirp: ^1.0.3 yallist: ^4.0.0 - checksum: db4d9fe74a2082c3a5016630092c54c8375ff3b280186938cfd104f2e089c4fd9bad58688ef6be9cf186a889671bf355c7cda38f09bbf60604b281715ca57f5c + checksum: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c languageName: node linkType: hard @@ -14873,11 +15764,9 @@ __metadata: linkType: hard "tmp@npm:^0.2.0": - version: 0.2.1 - resolution: "tmp@npm:0.2.1" - dependencies: - rimraf: ^3.0.0 - checksum: 8b1214654182575124498c87ca986ac53dc76ff36e8f0e0b67139a8d221eaecfdec108c0e6ec54d76f49f1f72ab9325500b246f562b926f85bcdfca8bf35df9e + version: 0.2.3 + resolution: "tmp@npm:0.2.3" + checksum: 73b5c96b6e52da7e104d9d44afb5d106bb1e16d9fa7d00dbeb9e6522e61b571fbdb165c756c62164be9a3bbe192b9b268c236d370a2a0955c7689cd2ae377b95 languageName: node linkType: hard @@ -14966,6 +15855,19 @@ __metadata: languageName: node linkType: hard +"tranche@https://github.com/buttonwood-protocol/tranche.git#main": + version: 1.0.0 + resolution: "tranche@https://github.com/buttonwood-protocol/tranche.git#commit=3b9b6be224b5220fe5e08a4dfa76a27b9684f259" + dependencies: + "@openzeppelin/contracts-upgradeable": ^4.1.0 + "@rari-capital/solmate": ^6.4.0 + "@uniswap/v2-periphery": ^1.1.0-beta.0 + "@uniswap/v3-periphery": ^1.1.0 + lodash: ^4.17.21 + checksum: 52706d5b87a74289206073d4d7cda9ec36d0b1fed34a4a8d67baecb2572f5a4ef63c565a7d79ba7f956147c9a7bd9550fd4b58a31d3e42012ccbb41966127240 + languageName: node + linkType: hard + "trim-right@npm:^1.0.1": version: 1.0.1 resolution: "trim-right@npm:1.0.1" @@ -15081,6 +15983,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:2.4.0": + version: 2.4.0 + resolution: "tslib@npm:2.4.0" + checksum: 8c4aa6a3c5a754bf76aefc38026134180c053b7bd2f81338cb5e5ebf96fefa0f417bff221592bf801077f5bf990562f6264fecbc42cd3309b33872cb6fc3b113 + languageName: node + linkType: hard + "tslib@npm:^1.11.1, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" @@ -15088,10 +15997,10 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.5.0": - version: 2.6.2 - resolution: "tslib@npm:2.6.2" - checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad +"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.6.2": + version: 2.6.3 + resolution: "tslib@npm:2.6.3" + checksum: 74fce0e100f1ebd95b8995fbbd0e6c91bdd8f4c35c00d4da62e285a3363aaa534de40a80db30ecfd388ed7c313c42d930ee0eaf108e8114214b180eec3dbe6f5 languageName: node linkType: hard @@ -15206,17 +16115,10 @@ __metadata: languageName: node linkType: hard -"type@npm:^1.0.1": - version: 1.2.0 - resolution: "type@npm:1.2.0" - checksum: dae8c64f82c648b985caf321e9dd6e8b7f4f2e2d4f846fc6fd2c8e9dc7769382d8a52369ddbaccd59aeeceb0df7f52fb339c465be5f2e543e81e810e413451ee - languageName: node - linkType: hard - "type@npm:^2.7.2": - version: 2.7.2 - resolution: "type@npm:2.7.2" - checksum: 0f42379a8adb67fe529add238a3e3d16699d95b42d01adfe7b9a7c5da297f5c1ba93de39265ba30ffeb37dfd0afb3fb66ae09f58d6515da442219c086219f6f4 + version: 2.7.3 + resolution: "type@npm:2.7.3" + checksum: 69cfda3248847998f93b9d292fd251c10facf8d29513e2047d4684509d67bae82d910d7a00c1e9d9bbf2af242d36425b6616807d6c652c5c370c2be1f0008a47 languageName: node linkType: hard @@ -15237,7 +16139,7 @@ __metadata: languageName: node linkType: hard -"typechain@npm:^8.1.0": +"typechain@npm:^8.0.0, typechain@npm:^8.1.0": version: 8.3.2 resolution: "typechain@npm:8.3.2" dependencies: @@ -15259,50 +16161,55 @@ __metadata: languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-buffer@npm:1.0.0" +"typed-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-buffer@npm:1.0.2" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.1 - is-typed-array: ^1.1.10 - checksum: 3e0281c79b2a40cd97fe715db803884301993f4e8c18e8d79d75fd18f796e8cd203310fec8c7fdb5e6c09bedf0af4f6ab8b75eb3d3a85da69328f28a80456bd3 + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-typed-array: ^1.1.13 + checksum: 02ffc185d29c6df07968272b15d5319a1610817916ec8d4cd670ded5d1efe72901541ff2202fcc622730d8a549c76e198a2f74e312eabbfb712ed907d45cbb0b languageName: node linkType: hard -"typed-array-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-length@npm:1.0.0" +"typed-array-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "typed-array-byte-length@npm:1.0.1" dependencies: - call-bind: ^1.0.2 + call-bind: ^1.0.7 for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: b03db16458322b263d87a702ff25388293f1356326c8a678d7515767ef563ef80e1e67ce648b821ec13178dd628eb2afdc19f97001ceae7a31acf674c849af94 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: f65e5ecd1cf76b1a2d0d6f631f3ea3cdb5e08da106c6703ffe687d583e49954d570cc80434816d3746e18be889ffe53c58bf3e538081ea4077c26a41055b216d languageName: node linkType: hard -"typed-array-byte-offset@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-offset@npm:1.0.0" +"typed-array-byte-offset@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-byte-offset@npm:1.0.2" dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: 04f6f02d0e9a948a95fbfe0d5a70b002191fae0b8fe0fe3130a9b2336f043daf7a3dda56a31333c35a067a97e13f539949ab261ca0f3692c41603a46a94e960b + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: c8645c8794a621a0adcc142e0e2c57b1823bbfa4d590ad2c76b266aa3823895cf7afb9a893bf6685e18454ab1b0241e1a8d885a2d1340948efa4b56add4b5f67 languageName: node linkType: hard -"typed-array-length@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-length@npm:1.0.4" +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" dependencies: - call-bind: ^1.0.2 + call-bind: ^1.0.7 for-each: ^0.3.3 - is-typed-array: ^1.1.9 - checksum: 2228febc93c7feff142b8c96a58d4a0d7623ecde6c7a24b2b98eb3170e99f7c7eff8c114f9b283085cd59dcd2bd43aadf20e25bba4b034a53c5bb292f71f8956 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + possible-typed-array-names: ^1.0.0 + checksum: f0315e5b8f0168c29d390ff410ad13e4d511c78e6006df4a104576844812ee447fcc32daab1f3a76c9ef4f64eff808e134528b5b2439de335586b392e9750e5c languageName: node linkType: hard @@ -15407,11 +16314,11 @@ __metadata: linkType: hard "uglify-js@npm:^3.1.4": - version: 3.17.4 - resolution: "uglify-js@npm:3.17.4" + version: 3.18.0 + resolution: "uglify-js@npm:3.18.0" bin: uglifyjs: bin/uglifyjs - checksum: 7b3897df38b6fc7d7d9f4dcd658599d81aa2b1fb0d074829dd4e5290f7318dbca1f4af2f45acb833b95b1fe0ed4698662ab61b87e94328eb4c0a0d3435baf924 + checksum: 887733d05d4139a94dffd04a5f07ee7d8be70201c016ea48cb82703778b5c48fadbe6e5e7ac956425522f72e657d3eade23f06ae8a0e2eeed2d684bf6cc25e36 languageName: node linkType: hard @@ -15458,11 +16365,18 @@ __metadata: linkType: hard "undici@npm:^5.14.0": - version: 5.28.3 - resolution: "undici@npm:5.28.3" + version: 5.28.4 + resolution: "undici@npm:5.28.4" dependencies: "@fastify/busboy": ^2.0.0 - checksum: fa1e65aff896c5e2ee23637b632e306f9e3a2b32a3dc0b23ea71e5555ad350bcc25713aea894b3dccc0b7dc2c5e92a5a58435ebc2033b731a5524506f573dfd2 + checksum: a8193132d84540e4dc1895ecc8dbaa176e8a49d26084d6fbe48a292e28397cd19ec5d13bc13e604484e76f94f6e334b2bdc740d5f06a6e50c44072818d0c19f9 + languageName: node + linkType: hard + +"undici@npm:^6.11.1": + version: 6.19.2 + resolution: "undici@npm:6.19.2" + checksum: 024ff60791bef86646730dc0f240e8a643219d18c6070d7e067d4f7fd311cea85b485b79ebeabff2bb60f4a7ca18fa7ae37da1cc008b23e7b6f17b289c728771 languageName: node linkType: hard @@ -15541,7 +16455,7 @@ __metadata: languageName: node linkType: hard -"uri-js@npm:^4.2.2": +"uri-js@npm:^4.2.2, uri-js@npm:^4.4.1": version: 4.4.1 resolution: "uri-js@npm:4.4.1" dependencies: @@ -15590,6 +16504,16 @@ __metadata: languageName: node linkType: hard +"utf-8-validate@npm:5.0.7": + version: 5.0.7 + resolution: "utf-8-validate@npm:5.0.7" + dependencies: + node-gyp: latest + node-gyp-build: ^4.3.0 + checksum: 588d272b359bf555a0c4c2ffe97286edc73126de132f63f4f0c80110bd06b67d3ce44d2b3d24feea6da13ced50c04d774ba4d25fe28576371cd714cd013bd3b7 + languageName: node + linkType: hard + "utf-8-validate@npm:^5.0.2": version: 5.0.10 resolution: "utf-8-validate@npm:5.0.10" @@ -15719,6 +16643,27 @@ __metadata: languageName: node linkType: hard +"viem@npm:2.7.14": + version: 2.7.14 + resolution: "viem@npm:2.7.14" + dependencies: + "@adraffy/ens-normalize": 1.10.0 + "@noble/curves": 1.2.0 + "@noble/hashes": 1.3.2 + "@scure/bip32": 1.3.2 + "@scure/bip39": 1.2.1 + abitype: 1.0.0 + isows: 1.0.3 + ws: 8.13.0 + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: a6bfb53a579345e92dfaadd47d38112a981284a645df45a6e7f68daff75a23d7af5458c7ee34fd36f9e7279ae3b5fc8165aea63d5323cec58ebe366b5fefe256 + languageName: node + linkType: hard + "wcwidth@npm:^1.0.1": version: 1.0.1 resolution: "wcwidth@npm:1.0.1" @@ -16075,16 +17020,16 @@ __metadata: linkType: hard "websocket@npm:^1.0.31": - version: 1.0.34 - resolution: "websocket@npm:1.0.34" + version: 1.0.35 + resolution: "websocket@npm:1.0.35" dependencies: bufferutil: ^4.0.1 debug: ^2.2.0 - es5-ext: ^0.10.50 + es5-ext: ^0.10.63 typedarray-to-buffer: ^3.1.5 utf-8-validate: ^5.0.2 yaeti: ^0.0.6 - checksum: 8a0ce6d79cc1334bb6ea0d607f0092f3d32700b4dd19e4d5540f2a85f3b50e1f8110da0e4716737056584dde70bbebcb40bbd94bbb437d7468c71abfbfa077d8 + checksum: 760ad7b090dee914336069cdf4fb78c1a96f5a452b2a5459b68d596af088959bb48113914667123d9662388c0398980955c875c950177c51fcf0d22cc92d935c languageName: node linkType: hard @@ -16132,16 +17077,16 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14": - version: 1.1.14 - resolution: "which-typed-array@npm:1.1.14" +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" dependencies: - available-typed-arrays: ^1.0.6 - call-bind: ^1.0.5 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 for-each: ^0.3.3 gopd: ^1.0.1 - has-tostringtag: ^1.0.1 - checksum: efe30c143c58630dde8ab96f9330e20165bacd77ca843c602b510120a415415573bcdef3ccbc30a0e5aaf20f257360cfe24712aea0008f149ce5bb99834c0c0b + has-tostringtag: ^1.0.2 + checksum: 65227dcbfadf5677aacc43ec84356d17b5500cb8b8753059bb4397de5cd0c2de681d24e1a7bd575633f976a95f88233abfd6549c2105ef4ebd58af8aa1807c75 languageName: node linkType: hard @@ -16196,7 +17141,7 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:~1.2.3": +"word-wrap@npm:^1.2.5, word-wrap@npm:~1.2.3": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" checksum: f93ba3586fc181f94afdaff3a6fef27920b4b6d9eaefed0f428f8e07adea2a7f54a5f2830ce59406c8416f033f86902b91eb824072354645eea687dff3691ccb @@ -16301,6 +17246,36 @@ __metadata: languageName: node linkType: hard +"ws@npm:8.13.0": + version: 8.13.0 + resolution: "ws@npm:8.13.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 53e991bbf928faf5dc6efac9b8eb9ab6497c69feeb94f963d648b7a3530a720b19ec2e0ec037344257e05a4f35bd9ad04d9de6f289615ffb133282031b18c61c + languageName: node + linkType: hard + +"ws@npm:8.17.1": + version: 8.17.1 + resolution: "ws@npm:8.17.1" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 442badcce1f1178ec87a0b5372ae2e9771e07c4929a3180321901f226127f252441e8689d765aa5cfba5f50ac60dd830954afc5aeae81609aefa11d3ddf5cecf + languageName: node + linkType: hard + "ws@npm:^3.0.0": version: 3.3.3 resolution: "ws@npm:3.3.3" @@ -16313,17 +17288,17 @@ __metadata: linkType: hard "ws@npm:^5.1.1": - version: 5.2.3 - resolution: "ws@npm:5.2.3" + version: 5.2.4 + resolution: "ws@npm:5.2.4" dependencies: async-limiter: ~1.0.0 - checksum: bdb2223a40c2c68cf91b25a6c9b8c67d5275378ec6187f343314d3df7530e55b77cb9fe79fb1c6a9758389ac5aefc569d24236924b5c65c5dbbaff409ef739fc + checksum: a0c39704a752593ce603b0b3d28a3d3901839cd20560503b2c7257d63ee448677a4e00a2b7f69d775363a08700f041e84fe1f77b00931bb471f54380ab6dd50e languageName: node linkType: hard "ws@npm:^7.4.5, ws@npm:^7.4.6": - version: 7.5.9 - resolution: "ws@npm:7.5.9" + version: 7.5.10 + resolution: "ws@npm:7.5.10" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -16332,7 +17307,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: c3c100a181b731f40b7f2fddf004aa023f79d64f489706a28bc23ff88e87f6a64b3c6651fbec3a84a53960b75159574d7a7385709847a62ddb7ad6af76f49138 + checksum: f9bb062abf54cc8f02d94ca86dcd349c3945d63851f5d07a3a61c2fcb755b15a88e943a63cf580cbdb5b74436d67ef6b67f745b8f7c0814e411379138e1863cb languageName: node linkType: hard @@ -16381,7 +17356,7 @@ __metadata: languageName: node linkType: hard -"xtend@npm:^4.0.0, xtend@npm:^4.0.1, xtend@npm:~4.0.0, xtend@npm:~4.0.1": +"xtend@npm:^4.0.0, xtend@npm:^4.0.1, xtend@npm:^4.0.2, xtend@npm:~4.0.0, xtend@npm:~4.0.1": version: 4.0.2 resolution: "xtend@npm:4.0.2" checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a