From c4a2b1329029da543f539413c4c80b0d438daeb5 Mon Sep 17 00:00:00 2001 From: Jay Jie Date: Mon, 4 Aug 2025 19:03:08 -0700 Subject: [PATCH 1/2] fix: batchDeposit --- POST_MORTEM.md | 90 +++++++++++++++++ src/EthMultiVault.sol | 30 ++++-- src/libraries/Errors.sol | 1 + .../EthMultiVault/BatchDepositExploit.t.sol | 79 +++++++++++++++ .../EthMultiVault/BatchDepositFixTest.t.sol | 98 +++++++++++++++++++ 5 files changed, 289 insertions(+), 9 deletions(-) create mode 100644 POST_MORTEM.md create mode 100644 test/unit/EthMultiVault/BatchDepositExploit.t.sol create mode 100644 test/unit/EthMultiVault/BatchDepositFixTest.t.sol diff --git a/POST_MORTEM.md b/POST_MORTEM.md new file mode 100644 index 00000000..62dfc919 --- /dev/null +++ b/POST_MORTEM.md @@ -0,0 +1,90 @@ +# EthMultiVault Critical Vulnerability Unofficial Post-Mortem + +## Executive Summary + +On Aug 4, 2025, a critical vulnerability was discovered in the EthMultiVault contract deployed at `0x430bbf52503bd4801e51182f4cb9f8f534225de5` on the Base chain. The vulnerability allowed attackers to inflate vault accounting by claiming arbitrary deposit amounts without sending the corresponding ETH. This resulted in vault 512 reporting 5,848 ETH in totalAssets while the entire contract held only 68 ETH. + +## Timeline of Events + +### Discovery + +- Initial Report: Critical discrepancy identified where vault 512 showed 5,848.409 ETH in totalAssets despite only 68 ETH total deposits across the entire contract +- Investigation Started: Deep dive into potential attack vectors including share inflation, fee manipulation, and state corruption + +### Root Cause Analysis + +- Block 33761654: Attack transaction identified (`0x00f12744f4dfe2885ca157c37f043551eec2ede47e524af4e034b341c639c98f`) +- Attack Method: Multicall pattern exploiting missing validation in `batchDeposit` function +- Vulnerability: `batchDeposit` and `batchDepositCurve` functions accepted user-supplied deposit amounts without validating `msg.value` + +## Technical Details + +### The Vulnerability + +The `batchDeposit` function processed deposits based on an `amounts` array parameter but never verified that the actual ETH sent (`msg.value`) matched the claimed amounts: + +```solidity +for (uint256 i = 0; i < termIds.length; i++) { + uint256 protocolFee = protocolFeeAmount(amounts[i], termIds[i]); + uint256 userDepositAfterprotocolFee = amounts[i] - protocolFee; + + // BUG: Uses amounts[i] without checking msg.value + shares[i] = _deposit(receiver, termIds[i], userDepositAfterprotocolFee); + _transferFeesToProtocolMultisig(protocolFee); +} +``` + +### Attack Execution + +The attacker exploited this through a multicall transaction: + +1. Called `batchDeposit([512], [5908.47 ETH])` with `msg.value = 0` +2. Called `depositAtom(512, 0.0288 ETH)` with actual ETH to appear legitimate +3. Result: Vault 512's totalAssets inflated from 0.010 ETH to 5,848.412 ETH + +## Impact Assessment + +### Direct Impact + +- No direct loss of funds as the contract's actual ETH balance remained unchanged +- Vault 512's share price and totalAssets severely inflated +- Protocol integrity compromised with false accounting data + +## Resolution + +### Immediate Fix + +Added validation to ensure `msg.value` matches the sum of claimed deposit amounts: + +```solidity +uint256 totalRequired = 0; +for (uint256 i = 0; i < termIds.length; i++) { + if (termIds[i] == 0 || termIds[i] > count) { + revert Errors.EthMultiVault_VaultDoesNotExist(); + } + if (amounts[i] < generalConfig.minDeposit) { + revert Errors.EthMultiVault_MinimumDeposit(); + } + totalRequired += amounts[i]; +} + +if (msg.value != totalRequired) { + revert Errors.EthMultiVault_IncorrectETHAmount(); +} +``` + +### Defense in Depth + +Previously implemented protection in `_setVaultTotals` prevented totalAssets from exceeding contract balance, providing an additional safety layer. + +## Lessons Learned + +### What Went Wrong + +1. Input Validation Gap: Critical assumption that user-supplied array values would match msg.value +2. Insufficient Testing: Edge case of mismatched values not covered in test suite +3. Code Review Miss: Vulnerability in high-value functions not caught during review + +## Conclusion + +This vulnerability highlighted the critical importance of validating all user inputs, especially in financial functions. While the defense-in-depth approach prevented catastrophic failure, the root cause allowed significant accounting manipulation. The swift resolution and comprehensive fix demonstrate the team's commitment to security, but this incident reinforces the need for exhaustive input validation and testing of edge cases in DeFi protocols. diff --git a/src/EthMultiVault.sol b/src/EthMultiVault.sol index a34aa7a0..d06aee64 100644 --- a/src/EthMultiVault.sol +++ b/src/EthMultiVault.sol @@ -389,7 +389,7 @@ contract EthMultiVault is IEthMultiVault, Initializable, ReentrancyGuardUpgradea /// (number to be divided by `generalConfig.feeDenominator`) /// @param atomDepositFractionForTriple new atom deposit percentage function setAtomDepositFractionForTriple(uint256 atomDepositFractionForTriple) external onlyAdmin { - uint256 maxAtomDepositFractionForTriple = generalConfig.feeDenominator * 9 / 10; // 90% of the fee denominator + uint256 maxAtomDepositFractionForTriple = (generalConfig.feeDenominator * 9) / 10; // 90% of the fee denominator if (atomDepositFractionForTriple > maxAtomDepositFractionForTriple) { revert Errors.EthMultiVault_InvalidAtomDepositFractionForTriple(); @@ -1249,19 +1249,24 @@ contract EthMultiVault is IEthMultiVault, Initializable, ReentrancyGuardUpgradea revert Errors.EthMultiVault_SenderNotApproved(); } - shares = new uint256[](termIds.length); - - // To simplify UX in 1.5, compute fees iteratively - // 2.0 will always use batch methods internally + uint256 totalRequired = 0; for (uint256 i = 0; i < termIds.length; i++) { if (termIds[i] == 0 || termIds[i] > count) { revert Errors.EthMultiVault_VaultDoesNotExist(); } - if (amounts[i] < generalConfig.minDeposit) { revert Errors.EthMultiVault_MinimumDeposit(); } + totalRequired += amounts[i]; + } + if (msg.value != totalRequired) { + revert Errors.EthMultiVault_IncorrectETHAmount(); + } + + shares = new uint256[](termIds.length); + + for (uint256 i = 0; i < termIds.length; i++) { uint256 protocolFee = protocolFeeAmount(amounts[i], termIds[i]); uint256 userDepositAfterprotocolFee = amounts[i] - protocolFee; @@ -1302,17 +1307,24 @@ contract EthMultiVault is IEthMultiVault, Initializable, ReentrancyGuardUpgradea revert Errors.EthMultiVault_ArraysNotSameLength(); } - shares = new uint256[](termIds.length); - + uint256 totalRequired = 0; for (uint256 i = 0; i < termIds.length; i++) { if (termIds[i] == 0 || termIds[i] > count) { revert Errors.EthMultiVault_VaultDoesNotExist(); } - if (amounts[i] < generalConfig.minDeposit) { revert Errors.EthMultiVault_MinimumDeposit(); } + totalRequired += amounts[i]; + } + if (msg.value != totalRequired) { + revert Errors.EthMultiVault_IncorrectETHAmount(); + } + + shares = new uint256[](termIds.length); + + for (uint256 i = 0; i < termIds.length; i++) { uint256 protocolFee = protocolFeeAmount(amounts[i], termIds[i]); uint256 userDepositAfterprotocolFee = amounts[i] - protocolFee; diff --git a/src/libraries/Errors.sol b/src/libraries/Errors.sol index 9b604efd..3ecbf263 100644 --- a/src/libraries/Errors.sol +++ b/src/libraries/Errors.sol @@ -42,6 +42,7 @@ library Errors { error EthMultiVault_VaultNotAtom(); error EthMultiVault_VaultNotTriple(); error EthMultiVault_InvalidRegistry(); + error EthMultiVault_IncorrectETHAmount(); ///////// ATOMWALLET ERRORS ///////////////////////////////////////////////////////////// error AtomWallet_InvalidCallDataLength(); diff --git a/test/unit/EthMultiVault/BatchDepositExploit.t.sol b/test/unit/EthMultiVault/BatchDepositExploit.t.sol new file mode 100644 index 00000000..b3c92ea4 --- /dev/null +++ b/test/unit/EthMultiVault/BatchDepositExploit.t.sol @@ -0,0 +1,79 @@ +pragma solidity ^0.8.21; + +import { Test } from "forge-std/Test.sol"; +import { console } from "forge-std/console.sol"; +import { EthMultiVaultBase } from "../../EthMultiVaultBase.sol"; +import { Errors } from "../../../src/libraries/Errors.sol"; + +contract BatchDepositExploitTest is EthMultiVaultBase { + address attacker = address(0x1337); + uint256 vaultId; + + function setUp() public { + _setUp(); + + vm.deal(attacker, 10 ether); + + vm.deal(address(this), 10 ether); + vaultId = ethMultiVault.createAtom{ value: getAtomCost() }("TestVault"); + console.log("Created vault ID:", vaultId); + } + + function testBatchDepositExploitPrevented() public { + uint256 initialAssets = vaultTotalAssets(vaultId); + uint256 initialShares = vaultTotalShares(vaultId); + console.log("Initial vault state:"); + console.log(" Total Assets:", initialAssets); + console.log(" Total Shares:", initialShares); + console.log(" Contract Balance:", address(ethMultiVault).balance); + + uint256[] memory ids = new uint256[](1); + ids[0] = vaultId; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 5908.47 ether; + + vm.startPrank(attacker); + + vm.expectRevert(Errors.EthMultiVault_IncorrectETHAmount.selector); + ethMultiVault.batchDeposit{ value: 0 }(attacker, ids, amounts); + + vm.stopPrank(); + + console.log("\n[SUCCESS] Exploit prevented - batchDeposit now validates msg.value"); + } + + function testBatchDepositCurveExploitPrevented() public { + uint256[] memory ids = new uint256[](1); + ids[0] = vaultId; + + uint256[] memory curveIds = new uint256[](1); + curveIds[0] = 1; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1000 ether; + + vm.prank(attacker); + + vm.expectRevert(Errors.EthMultiVault_IncorrectETHAmount.selector); + ethMultiVault.batchDepositCurve{ value: 0 }(attacker, ids, curveIds, amounts); + + console.log("\n[SUCCESS] Exploit prevented - batchDepositCurve now validates msg.value"); + } + + function testIncorrectETHRejected() public { + uint256[] memory ids = new uint256[](2); + ids[0] = vaultId; + ids[1] = vaultId; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1 ether; + amounts[1] = 2 ether; + + vm.prank(attacker); + vm.expectRevert(Errors.EthMultiVault_IncorrectETHAmount.selector); + ethMultiVault.batchDeposit{ value: 2 ether }(attacker, ids, amounts); + + console.log("\n[SUCCESS] Incorrect ETH amount rejected"); + } +} diff --git a/test/unit/EthMultiVault/BatchDepositFixTest.t.sol b/test/unit/EthMultiVault/BatchDepositFixTest.t.sol new file mode 100644 index 00000000..e7f84634 --- /dev/null +++ b/test/unit/EthMultiVault/BatchDepositFixTest.t.sol @@ -0,0 +1,98 @@ +pragma solidity ^0.8.21; + +import {Test} from "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; +import {EthMultiVaultBase} from "../../EthMultiVaultBase.sol"; +import {Errors} from "../../../src/libraries/Errors.sol"; + +contract BatchDepositFixTest is EthMultiVaultBase { + address attacker = address(0x1337); + uint256 vaultId; + + function setUp() public { + _setUp(); + + vm.deal(attacker, 10 ether); + + vm.deal(address(this), 10 ether); + vaultId = ethMultiVault.createAtom{value: getAtomCost()}("TestVault"); + console.log("Created vault ID:", vaultId); + } + + function testBatchDepositExploitPrevented() public { + uint256[] memory ids = new uint256[](1); + ids[0] = vaultId; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 5908.47 ether; + + vm.startPrank(attacker); + + vm.expectRevert(Errors.EthMultiVault_IncorrectETHAmount.selector); + ethMultiVault.batchDeposit{value: 0}(attacker, ids, amounts); + + vm.stopPrank(); + + console.log("[PASS] Exploit prevented - batchDeposit now validates msg.value"); + } + + function testBatchDepositCurveExploitPrevented() public { + uint256[] memory ids = new uint256[](1); + ids[0] = vaultId; + + uint256[] memory curveIds = new uint256[](1); + curveIds[0] = 1; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1000 ether; + + vm.prank(attacker); + + vm.expectRevert(Errors.EthMultiVault_IncorrectETHAmount.selector); + ethMultiVault.batchDepositCurve{value: 0}(attacker, ids, curveIds, amounts); + + console.log("[PASS] Exploit prevented - batchDepositCurve now validates msg.value"); + } + + function testBatchDepositValidDeposit() public { + uint256[] memory ids = new uint256[](2); + ids[0] = vaultId; + ids[1] = vaultId; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1 ether; + amounts[1] = 2 ether; + + uint256 totalRequired = 3 ether; + + vm.prank(attacker); + + uint256[] memory shares = ethMultiVault.batchDeposit{value: totalRequired}(attacker, ids, amounts); + + assertGt(shares[0], 0, "First deposit should mint shares"); + assertGt(shares[1], 0, "Second deposit should mint shares"); + + uint256 totalAssets = vaultTotalAssets(vaultId); + console.log("Total assets after valid deposits:", totalAssets); + + assertGt(totalAssets, 2.9 ether, "Total assets should reflect deposits"); + assertLt(totalAssets, 3.1 ether, "Total assets should be reasonable"); + + console.log("[PASS] Valid deposits work correctly"); + } + + function testExcessETHRejected() public { + uint256[] memory ids = new uint256[](1); + ids[0] = vaultId; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1 ether; + + vm.prank(attacker); + + vm.expectRevert(Errors.EthMultiVault_IncorrectETHAmount.selector); + ethMultiVault.batchDeposit{value: 2 ether}(attacker, ids, amounts); + + console.log("[PASS] Excess ETH rejected"); + } +} From 11ea70c886db1315fab67320a3374ef597b2af78 Mon Sep 17 00:00:00 2001 From: Kames Date: Wed, 6 Aug 2025 11:58:43 -0700 Subject: [PATCH 2/2] deploy: fix base sepolia ethmultivault implementation --- .env_sample | 10 +- package.json | 4 + pnpm-lock.yaml | 1001 +++++++++++++++++ script/V1.5FixBatchDepositPrep.s.sol | 31 + .../generate-fix-batch-deposit-upgrade.ts | 92 ++ 5 files changed, 1137 insertions(+), 1 deletion(-) create mode 100644 pnpm-lock.yaml create mode 100644 script/V1.5FixBatchDepositPrep.s.sol create mode 100644 script/proxy-upgrades/sepolia/generate-fix-batch-deposit-upgrade.ts diff --git a/.env_sample b/.env_sample index c52240b0..91066407 100644 --- a/.env_sample +++ b/.env_sample @@ -1,3 +1,11 @@ +ETHERSCAN_API_KEY= DEFENDER_KEY= DEFENDER_SECRET= -FUZZ_API_KEY= \ No newline at end of file +FUZZ_API_KEY= + +BASE_SEPOLIA_CHAIN_ID=84_532 +BASE_SEPOLIA_RPC_URL=https://sepolia.base.org +BASE_CHAIN_ID=8453 +BASE_RPC_URL=https://mainnet.base.org + +DEPLOYER_PRIVATE_KEY= \ No newline at end of file diff --git a/package.json b/package.json index a8f44257..ecd5cab4 100644 --- a/package.json +++ b/package.json @@ -39,5 +39,9 @@ } } ] + }, + "dependencies": { + "dotenv": "^17.2.1", + "ethers": "5.6.9" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..88a1fb0c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1001 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + dotenv: + specifier: ^17.2.1 + version: 17.2.1 + ethers: + specifier: 5.6.9 + version: 5.6.9 + devDependencies: + '@account-abstraction/contracts': + specifier: ^0.6.0 + version: 0.6.0 + '@opengsn/contracts': + specifier: ^3.0.0-beta.10 + version: 3.0.0-beta.10 + '@openzeppelin/contracts': + specifier: ^5.0.2 + version: 5.3.0 + '@openzeppelin/contracts-upgradeable': + specifier: ^5.0.2 + version: 5.3.0(@openzeppelin/contracts@5.3.0) + prettier: + specifier: ^3.4.2 + version: 3.5.3 + prettier-plugin-solidity: + specifier: ^1.4.2 + version: 1.4.3(prettier@3.5.3) + +packages: + + '@account-abstraction/contracts@0.6.0': + resolution: {integrity: sha512-8ooRJuR7XzohMDM4MV34I12Ci2bmxfE9+cixakRL7lA4BAwJKQ3ahvd8FbJa9kiwkUPCUNtj+/zxDQWYYalLMQ==} + + '@ethersproject/abi@5.6.4': + resolution: {integrity: sha512-TTeZUlCeIHG6527/2goZA6gW5F8Emoc7MrZDC7hhP84aRGvW3TEdTnZR08Ls88YXM1m2SuK42Osw/jSi3uO8gg==} + + '@ethersproject/abi@5.8.0': + resolution: {integrity: sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==} + + '@ethersproject/abstract-provider@5.6.1': + resolution: {integrity: sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ==} + + '@ethersproject/abstract-provider@5.8.0': + resolution: {integrity: sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==} + + '@ethersproject/abstract-signer@5.6.2': + resolution: {integrity: sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ==} + + '@ethersproject/abstract-signer@5.8.0': + resolution: {integrity: sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==} + + '@ethersproject/address@5.6.1': + resolution: {integrity: sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==} + + '@ethersproject/address@5.8.0': + resolution: {integrity: sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==} + + '@ethersproject/base64@5.6.1': + resolution: {integrity: sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw==} + + '@ethersproject/base64@5.8.0': + resolution: {integrity: sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==} + + '@ethersproject/basex@5.6.1': + resolution: {integrity: sha512-a52MkVz4vuBXR06nvflPMotld1FJWSj2QT0985v7P/emPZO00PucFAkbcmq2vpVU7Ts7umKiSI6SppiLykVWsA==} + + '@ethersproject/basex@5.8.0': + resolution: {integrity: sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==} + + '@ethersproject/bignumber@5.6.2': + resolution: {integrity: sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw==} + + '@ethersproject/bignumber@5.8.0': + resolution: {integrity: sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==} + + '@ethersproject/bytes@5.6.1': + resolution: {integrity: sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==} + + '@ethersproject/bytes@5.8.0': + resolution: {integrity: sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==} + + '@ethersproject/constants@5.6.1': + resolution: {integrity: sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg==} + + '@ethersproject/constants@5.8.0': + resolution: {integrity: sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==} + + '@ethersproject/contracts@5.6.2': + resolution: {integrity: sha512-hguUA57BIKi6WY0kHvZp6PwPlWF87MCeB4B7Z7AbUpTxfFXFdn/3b0GmjZPagIHS+3yhcBJDnuEfU4Xz+Ks/8g==} + + '@ethersproject/contracts@5.8.0': + resolution: {integrity: sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==} + + '@ethersproject/hash@5.6.1': + resolution: {integrity: sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA==} + + '@ethersproject/hash@5.8.0': + resolution: {integrity: sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==} + + '@ethersproject/hdnode@5.6.2': + resolution: {integrity: sha512-tERxW8Ccf9CxW2db3WsN01Qao3wFeRsfYY9TCuhmG0xNpl2IO8wgXU3HtWIZ49gUWPggRy4Yg5axU0ACaEKf1Q==} + + '@ethersproject/hdnode@5.8.0': + resolution: {integrity: sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==} + + '@ethersproject/json-wallets@5.6.1': + resolution: {integrity: sha512-KfyJ6Zwz3kGeX25nLihPwZYlDqamO6pfGKNnVMWWfEVVp42lTfCZVXXy5Ie8IZTN0HKwAngpIPi7gk4IJzgmqQ==} + + '@ethersproject/json-wallets@5.8.0': + resolution: {integrity: sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==} + + '@ethersproject/keccak256@5.6.1': + resolution: {integrity: sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA==} + + '@ethersproject/keccak256@5.8.0': + resolution: {integrity: sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==} + + '@ethersproject/logger@5.6.0': + resolution: {integrity: sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==} + + '@ethersproject/logger@5.8.0': + resolution: {integrity: sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==} + + '@ethersproject/networks@5.6.4': + resolution: {integrity: sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ==} + + '@ethersproject/networks@5.8.0': + resolution: {integrity: sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==} + + '@ethersproject/pbkdf2@5.6.1': + resolution: {integrity: sha512-k4gRQ+D93zDRPNUfmduNKq065uadC2YjMP/CqwwX5qG6R05f47boq6pLZtV/RnC4NZAYOPH1Cyo54q0c9sshRQ==} + + '@ethersproject/pbkdf2@5.8.0': + resolution: {integrity: sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==} + + '@ethersproject/properties@5.6.0': + resolution: {integrity: sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==} + + '@ethersproject/properties@5.8.0': + resolution: {integrity: sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==} + + '@ethersproject/providers@5.6.8': + resolution: {integrity: sha512-Wf+CseT/iOJjrGtAOf3ck9zS7AgPmr2fZ3N97r4+YXN3mBePTG2/bJ8DApl9mVwYL+RpYbNxMEkEp4mPGdwG/w==} + + '@ethersproject/providers@5.8.0': + resolution: {integrity: sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==} + + '@ethersproject/random@5.6.1': + resolution: {integrity: sha512-/wtPNHwbmng+5yi3fkipA8YBT59DdkGRoC2vWk09Dci/q5DlgnMkhIycjHlavrvrjJBkFjO/ueLyT+aUDfc4lA==} + + '@ethersproject/random@5.8.0': + resolution: {integrity: sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==} + + '@ethersproject/rlp@5.6.1': + resolution: {integrity: sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ==} + + '@ethersproject/rlp@5.8.0': + resolution: {integrity: sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==} + + '@ethersproject/sha2@5.6.1': + resolution: {integrity: sha512-5K2GyqcW7G4Yo3uenHegbXRPDgARpWUiXc6RiF7b6i/HXUoWlb7uCARh7BAHg7/qT/Q5ydofNwiZcim9qpjB6g==} + + '@ethersproject/sha2@5.8.0': + resolution: {integrity: sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==} + + '@ethersproject/signing-key@5.6.2': + resolution: {integrity: sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ==} + + '@ethersproject/signing-key@5.8.0': + resolution: {integrity: sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==} + + '@ethersproject/solidity@5.6.1': + resolution: {integrity: sha512-KWqVLkUUoLBfL1iwdzUVlkNqAUIFMpbbeH0rgCfKmJp0vFtY4AsaN91gHKo9ZZLkC4UOm3cI3BmMV4N53BOq4g==} + + '@ethersproject/solidity@5.8.0': + resolution: {integrity: sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==} + + '@ethersproject/strings@5.6.1': + resolution: {integrity: sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw==} + + '@ethersproject/strings@5.8.0': + resolution: {integrity: sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==} + + '@ethersproject/transactions@5.6.2': + resolution: {integrity: sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q==} + + '@ethersproject/transactions@5.8.0': + resolution: {integrity: sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==} + + '@ethersproject/units@5.6.1': + resolution: {integrity: sha512-rEfSEvMQ7obcx3KWD5EWWx77gqv54K6BKiZzKxkQJqtpriVsICrktIQmKl8ReNToPeIYPnFHpXvKpi068YFZXw==} + + '@ethersproject/units@5.8.0': + resolution: {integrity: sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==} + + '@ethersproject/wallet@5.6.2': + resolution: {integrity: sha512-lrgh0FDQPuOnHcF80Q3gHYsSUODp6aJLAdDmDV0xKCN/T7D99ta1jGVhulg3PY8wiXEngD0DfM0I2XKXlrqJfg==} + + '@ethersproject/wallet@5.8.0': + resolution: {integrity: sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==} + + '@ethersproject/web@5.6.1': + resolution: {integrity: sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA==} + + '@ethersproject/web@5.8.0': + resolution: {integrity: sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==} + + '@ethersproject/wordlists@5.6.1': + resolution: {integrity: sha512-wiPRgBpNbNwCQFoCr8bcWO8o5I810cqO6mkdtKfLKFlLxeCWcnzDi4Alu8iyNzlhYuS9npCwivMbRWF19dyblw==} + + '@ethersproject/wordlists@5.8.0': + resolution: {integrity: sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==} + + '@opengsn/contracts@3.0.0-beta.10': + resolution: {integrity: sha512-phnrtNmLO1dre2MniOcbNelNN5GnBMNsIDeFRHKrkFpcgwzf8PTCqfDCVT7pKGoQOwP526m6gDTV1Fj2Wz5SYw==} + + '@openzeppelin/contracts-upgradeable@5.3.0': + resolution: {integrity: sha512-yVzSSyTMWO6rapGI5tuqkcLpcGGXA0UA1vScyV5EhE5yw8By3Ewex9rDUw8lfVw0iTkvR/egjfcW5vpk03lqZg==} + peerDependencies: + '@openzeppelin/contracts': 5.3.0 + + '@openzeppelin/contracts@4.9.6': + resolution: {integrity: sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==} + + '@openzeppelin/contracts@5.3.0': + resolution: {integrity: sha512-zj/KGoW7zxWUE8qOI++rUM18v+VeLTTzKs/DJFkSzHpQFPD/jKKF0TrMxBfGLl3kpdELCNccvB3zmofSzm4nlA==} + + '@solidity-parser/parser@0.20.1': + resolution: {integrity: sha512-58I2sRpzaQUN+jJmWbHfbWf9AKfzqCI8JAdFB0vbyY+u8tBRcuTt9LxzasvR0LGQpcRv97eyV7l61FQ3Ib7zVw==} + + aes-js@3.0.0: + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + + bech32@1.1.4: + resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + + bn.js@4.12.2: + resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==} + + bn.js@5.2.2: + resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} + + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + dotenv@17.2.1: + resolution: {integrity: sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==} + engines: {node: '>=12'} + + elliptic@6.5.4: + resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + + ethers@5.6.9: + resolution: {integrity: sha512-lMGC2zv9HC5EC+8r429WaWu3uWJUCgUCt8xxKCFqkrFuBDZXDYIdzDUECxzjf2BMF8IVBByY1EBoGSL3RTm8RA==} + + ethers@5.8.0: + resolution: {integrity: sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + + prettier-plugin-solidity@1.4.3: + resolution: {integrity: sha512-Mrr/iiR9f9IaeGRMZY2ApumXcn/C5Gs3S7B7hWB3gigBFML06C0yEyW86oLp0eqiA0qg+46FaChgLPJCj/pIlg==} + engines: {node: '>=18'} + peerDependencies: + prettier: '>=2.3.0' + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + scrypt-js@3.0.1: + resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + ws@7.4.6: + resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + +snapshots: + + '@account-abstraction/contracts@0.6.0': {} + + '@ethersproject/abi@5.6.4': + dependencies: + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/abi@5.8.0': + dependencies: + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/abstract-provider@5.6.1': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/web': 5.8.0 + + '@ethersproject/abstract-provider@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/web': 5.8.0 + + '@ethersproject/abstract-signer@5.6.2': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + + '@ethersproject/abstract-signer@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + + '@ethersproject/address@5.6.1': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/rlp': 5.8.0 + + '@ethersproject/address@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/rlp': 5.8.0 + + '@ethersproject/base64@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + + '@ethersproject/base64@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + + '@ethersproject/basex@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/properties': 5.8.0 + + '@ethersproject/basex@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/properties': 5.8.0 + + '@ethersproject/bignumber@5.6.2': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + bn.js: 5.2.2 + + '@ethersproject/bignumber@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + bn.js: 5.2.2 + + '@ethersproject/bytes@5.6.1': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/bytes@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/constants@5.6.1': + dependencies: + '@ethersproject/bignumber': 5.8.0 + + '@ethersproject/constants@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + + '@ethersproject/contracts@5.6.2': + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/transactions': 5.8.0 + + '@ethersproject/contracts@5.8.0': + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/transactions': 5.8.0 + + '@ethersproject/hash@5.6.1': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/hash@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/hdnode@5.6.2': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + + '@ethersproject/hdnode@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + + '@ethersproject/json-wallets@5.6.1': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + aes-js: 3.0.0 + scrypt-js: 3.0.1 + + '@ethersproject/json-wallets@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + aes-js: 3.0.0 + scrypt-js: 3.0.1 + + '@ethersproject/keccak256@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + js-sha3: 0.8.0 + + '@ethersproject/keccak256@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + js-sha3: 0.8.0 + + '@ethersproject/logger@5.6.0': {} + + '@ethersproject/logger@5.8.0': {} + + '@ethersproject/networks@5.6.4': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/networks@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/pbkdf2@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/sha2': 5.8.0 + + '@ethersproject/pbkdf2@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/sha2': 5.8.0 + + '@ethersproject/properties@5.6.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/properties@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/providers@5.6.8': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/web': 5.8.0 + bech32: 1.1.4 + ws: 7.4.6 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@ethersproject/providers@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/web': 5.8.0 + bech32: 1.1.4 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@ethersproject/random@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/random@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/rlp@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/rlp@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/sha2@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + hash.js: 1.1.7 + + '@ethersproject/sha2@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + hash.js: 1.1.7 + + '@ethersproject/signing-key@5.6.2': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + bn.js: 5.2.2 + elliptic: 6.5.4 + hash.js: 1.1.7 + + '@ethersproject/signing-key@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + bn.js: 5.2.2 + elliptic: 6.6.1 + hash.js: 1.1.7 + + '@ethersproject/solidity@5.6.1': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/solidity@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/strings@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/strings@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/transactions@5.6.2': + dependencies: + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + + '@ethersproject/transactions@5.8.0': + dependencies: + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + + '@ethersproject/units@5.6.1': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/units@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/wallet@5.6.2': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/json-wallets': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + + '@ethersproject/wallet@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/json-wallets': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + + '@ethersproject/web@5.6.1': + dependencies: + '@ethersproject/base64': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/web@5.8.0': + dependencies: + '@ethersproject/base64': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/wordlists@5.6.1': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/wordlists@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@opengsn/contracts@3.0.0-beta.10': + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/providers': 5.8.0 + '@openzeppelin/contracts': 4.9.6 + ethers: 5.8.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@openzeppelin/contracts-upgradeable@5.3.0(@openzeppelin/contracts@5.3.0)': + dependencies: + '@openzeppelin/contracts': 5.3.0 + + '@openzeppelin/contracts@4.9.6': {} + + '@openzeppelin/contracts@5.3.0': {} + + '@solidity-parser/parser@0.20.1': {} + + aes-js@3.0.0: {} + + bech32@1.1.4: {} + + bn.js@4.12.2: {} + + bn.js@5.2.2: {} + + brorand@1.1.0: {} + + dotenv@17.2.1: {} + + elliptic@6.5.4: + dependencies: + bn.js: 4.12.2 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + elliptic@6.6.1: + dependencies: + bn.js: 4.12.2 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + ethers@5.6.9: + dependencies: + '@ethersproject/abi': 5.6.4 + '@ethersproject/abstract-provider': 5.6.1 + '@ethersproject/abstract-signer': 5.6.2 + '@ethersproject/address': 5.6.1 + '@ethersproject/base64': 5.6.1 + '@ethersproject/basex': 5.6.1 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.1 + '@ethersproject/contracts': 5.6.2 + '@ethersproject/hash': 5.6.1 + '@ethersproject/hdnode': 5.6.2 + '@ethersproject/json-wallets': 5.6.1 + '@ethersproject/keccak256': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/networks': 5.6.4 + '@ethersproject/pbkdf2': 5.6.1 + '@ethersproject/properties': 5.6.0 + '@ethersproject/providers': 5.6.8 + '@ethersproject/random': 5.6.1 + '@ethersproject/rlp': 5.6.1 + '@ethersproject/sha2': 5.6.1 + '@ethersproject/signing-key': 5.6.2 + '@ethersproject/solidity': 5.6.1 + '@ethersproject/strings': 5.6.1 + '@ethersproject/transactions': 5.6.2 + '@ethersproject/units': 5.6.1 + '@ethersproject/wallet': 5.6.2 + '@ethersproject/web': 5.6.1 + '@ethersproject/wordlists': 5.6.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + ethers@5.8.0: + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/contracts': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/json-wallets': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/providers': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/solidity': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/units': 5.8.0 + '@ethersproject/wallet': 5.8.0 + '@ethersproject/web': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + inherits@2.0.4: {} + + js-sha3@0.8.0: {} + + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + + prettier-plugin-solidity@1.4.3(prettier@3.5.3): + dependencies: + '@solidity-parser/parser': 0.20.1 + prettier: 3.5.3 + semver: 7.7.2 + + prettier@3.5.3: {} + + scrypt-js@3.0.1: {} + + semver@7.7.2: {} + + ws@7.4.6: {} + + ws@8.18.0: {} diff --git a/script/V1.5FixBatchDepositPrep.s.sol b/script/V1.5FixBatchDepositPrep.s.sol new file mode 100644 index 00000000..151aa7a9 --- /dev/null +++ b/script/V1.5FixBatchDepositPrep.s.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.21; + +import {Script, console} from "forge-std/Script.sol"; +import {EthMultiVault} from "src/EthMultiVault.sol"; + +/* To run this: +forge script script/V1.5FixBatchDepositPrep.s.sol:V1_5FixBatchDepositPrep \ +--broadcast \ +--verify \ +--etherscan-api-key $ETHERSCAN_API_KEY +*/ +contract V1_5FixBatchDepositPrep is Script { + error UnsupportedChainId(); + + EthMultiVault public ethMultiVault; + + function run() external { + vm.createSelectFork(vm.envString("BASE_SEPOLIA_RPC_URL")); + vm.startBroadcast(vm.envUint("DEPLOYER_PRIVATE_KEY")); + + if (block.chainid != 84_532) { + revert UnsupportedChainId(); + } + + ethMultiVault = new EthMultiVault(); + console.log("EthMultiVault deployed at: ", address(ethMultiVault)); + + vm.stopBroadcast(); + } +} diff --git a/script/proxy-upgrades/sepolia/generate-fix-batch-deposit-upgrade.ts b/script/proxy-upgrades/sepolia/generate-fix-batch-deposit-upgrade.ts new file mode 100644 index 00000000..644f8532 --- /dev/null +++ b/script/proxy-upgrades/sepolia/generate-fix-batch-deposit-upgrade.ts @@ -0,0 +1,92 @@ +import { ethers } from "ethers"; +import * as dotenv from "dotenv"; +dotenv.config(); + +const BASE_SEPOLIA_RPC_URL = process.env.BASE_SEPOLIA_RPC_URL || ""; +if (!BASE_SEPOLIA_RPC_URL) { + throw new Error("Missing BASE_SEPOLIA_RPC_URL in .env"); +} + +/* +To run this: +pnpx tsx script/proxy-upgrades/generate-fix-batch-deposit-upgrade.ts +*/ + +async function main() { + // Constants for the TimelockController and schedule parameters + const timelockControllerAddress = + "0xe6BE2A42cCAeB73909A79CC89299eBDA7bAa7Ea2"; // TimelockController contract address on Base sepolia + const target = "0xD4436f981D2dcE0C074Eca869fdA1650227c7Efe"; // ProxyAdmin contract address on Base sepolia + const value = 0; + const predecessor = + "0x0000000000000000000000000000000000000000000000000000000000000000"; + const salt = + "0x0000000000000000000000000000000000000000000000000000000000000000"; + + // Reinitialize calldata (can be left empty if no reinitialization call is needed) + const reinitializeCalldata = process.argv[2] + ? process.argv[2] + : "0x" + + // To be replaced with actual values as needed + const proxy = process.argv[3] + ? process.argv[3] + : "0x1A6950807E33d5bC9975067e6D6b5Ea4cD661665"; // EthMultiVault proxy contract address on Base sepolia + const implementation = process.argv[4] + ? process.argv[4] + : "0x812D12A1f56B00722979F70cF05858d983FB1Cf7"; // Replace with the actual implementation address you want to upgrade to once it's deployed + + // Validate proxy and implementation addresses are provided and are valid + if (!proxy || !implementation) { + throw new Error("Proxy and implementation addresses must be provided."); + } + + if ( + !ethers.utils.isAddress(proxy) || + !ethers.utils.isAddress(implementation) + ) { + throw new Error("Invalid proxy or implementation address."); + } + + // Initialize the provider + const provider = new ethers.providers.JsonRpcProvider(BASE_SEPOLIA_RPC_URL); + + // Fetch the minimum delay from the TimelockController contract + const timelockABI = [ + "function getMinDelay() external view returns (uint256)", + ]; + const timelockContract = new ethers.Contract( + timelockControllerAddress, + timelockABI, + // @ts-ignore + provider + ); + const delay = await timelockContract.getMinDelay(); + + // Generate the calldata for the upgradeAndCall function + const proxyAdminABI = [ + "function upgradeAndCall(address proxy, address implementation, bytes data) external payable", + ]; + const proxyAdminInterface = new ethers.utils.Interface(proxyAdminABI); + const data = proxyAdminInterface.encodeFunctionData("upgradeAndCall", [ + proxy, + implementation, + reinitializeCalldata, + ]); + + // Log the schedule parameters + console.log("Schedule Parameters:\n"); + console.log(`Target: ${target}\n`); + console.log(`Value: ${value}\n`); + console.log(`Data: ${data}\n`); + console.log(`Predecessor: ${predecessor}\n`); + console.log(`Salt: ${salt}\n`); + console.log(`Delay: ${delay}\n`); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + });