diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml new file mode 100644 index 000000000..5343d7bce --- /dev/null +++ b/.github/workflows/format-check.yml @@ -0,0 +1,31 @@ +name: Format Check + +on: + pull_request: + paths: + - '**.sol' + +jobs: + check: + name: Check Code Formatting + runs-on: ubuntu-latest + + steps: + - name: 📥 Checkout code + uses: actions/checkout@v4 + + - name: 🔧 Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: 🔍 Check formatting + run: | + if ! forge fmt --check; then + echo "" + echo "❌ Code is not properly formatted!" + echo "💡 Run 'forge fmt' locally and commit the changes" + echo "" + exit 1 + fi + echo "✅ All code is properly formatted!" diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..462d4e258 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,19 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +echo "" +echo "🔨 Formatting Solidity code..." + +# Run forge fmt +forge fmt + +# Check for changes and stage them +if [ -n "$(git diff --name-only *.sol **/*.sol 2>/dev/null)" ]; then + echo "✨ Code formatted! Adding to commit..." + git add *.sol **/*.sol 2>/dev/null || true + echo "✅ Formatted files staged" +else + echo "✅ No formatting needed" +fi + +echo "" diff --git a/foundry.toml b/foundry.toml index 56297c8d3..99b196bbe 100644 --- a/foundry.toml +++ b/foundry.toml @@ -26,3 +26,104 @@ goerli = { key = "${ETHERSCAN_API_KEY}" } # Used for verifying contracts on Tenderly Virtual Testnet unknown_chain = { key = "${TENDERLY_ACCESS_KEY}", chain =1, url = "${TENDERLY_VIRTUAL_TESTNET_RPC_URL}/verify/etherscan" } +# ============================================================================== +# FORMATTER CONFIGURATION (forge fmt) +# ============================================================================== +# Comprehensive Solidity code formatting settings for consistent style across +# the entire codebase. These settings control how `forge fmt` formats your code. +[fmt] +# Maximum line length before wrapping (set very high to prevent line splitting) +# Setting to 999 essentially disables line wrapping, keeping code on single lines +# where possible. This prevents the formatter from splitting long statements. +line_length = 999 + +# Number of spaces per indentation level +# Controls the width of each indentation level. 4 spaces is the Solidity +# community standard and provides good readability while keeping code compact. +tab_width = 4 + +# Whether to add spaces inside array/function call brackets +# true: function( arg1, arg2 ) or array[ index ] +# false: function(arg1, arg2) or array[index] +# true improves readability, especially with complex expressions +bracket_spacing = false + +# String literal quote style: "double" or "single" +# "double" uses "string" (standard for most languages) +# "single" uses 'string' (some prefer this for Solidity) +# Double quotes are the Solidity convention and default compiler behavior +quote_style = "double" + +# Number formatting: where to place underscores in numeric literals +# "thousands": 1_000_000 (groups by thousands - most readable for large numbers) +# "none": 1000000 (no underscores - compact but harder to read) +# "decimal": 1000.000 (groups only around decimal point) +# Thousands separator improves readability for large numbers like wei amounts +number_underscore = "thousands" + +# Whether function bodies can be on a single line +# false: Always use braces and newlines even for single-statement functions +# true: Allows single-line bodies like "function f() external { doSomething(); }" +# false is safer and more consistent, enforcing explicit structure +multiline_func_body = false + +# Opening brace placement for code blocks +# false: Opening brace on same line (K&R style) +# if (condition) { +# code +# } +# true: Opening brace on new line (Allman style) +# if (condition) +# { +# code +# } +# Same-line braces are more compact and standard in Solidity community +multiline_block_brace = false + +# Whether single-line statement blocks are allowed +# "preserve": Keeps existing formatting (no change) +# "single": Allows single-line blocks without braces: if (condition) doSomething(); +# "multi": Always requires braces and multi-line formatting (safer, prevents bugs) +# if (condition) { +# doSomething(); +# } +# "preserve" maintains your existing formatting style without forcing changes +single_line_statement_blocks = "preserve" + +# Whether to add blank lines between contract/interface/library definitions +# false: No extra lines between definitions (compact) +# true: Adds blank lines between contracts for visual separation +# false keeps the file more compact, which helps with navigation +contract_new_lines = false + +# Whether to format inline Yul assembly code +# false: Leave Yul code as-is (assembly formatting is tricky) +# true: Attempt to format Yul code (may break some assembly) +# false is recommended as assembly often requires precise formatting +yul = false + +# Whether to sort imports alphabetically, preventing duplicate imports +sort_imports = true + +# true: import {Foo} -> import { Foo } (Solidity standard) +# false: import { Foo } -> import {Foo} (Solidity standard) +# false is recommended as it is the Solidity standard +import_spacing = false + +# Integer type preference: "long" (uint256) or "short" (uint) +# "long" uses explicit types like uint256, int256, bytes32 +# "short" uses aliases like uint, int, bytes32 (bytes32 stays same) +# Long is preferred for clarity and avoids confusion (uint is uint256, not uint8) +# int_types = "long" + +# Multiline function header formatting style +# "params_first": Parameters start on new line, type comes first +# function transfer( +# address to, +# uint256 amount +# ) external +# "all_one_line": Everything on one line if possible +# "types_first": Type comes before parameter name +# Since line_length is high, this mainly affects explicitly multiline functions +# multiline_func_header = "all_one_line" + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..15d4e17db --- /dev/null +++ b/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "smart-contracts", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "husky": "^9.1.7" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..8d3ecd712 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "husky": "^9.1.7" + } +} diff --git a/script/ContractCodeChecker.sol b/script/ContractCodeChecker.sol index 9ca038068..380738904 100644 --- a/script/ContractCodeChecker.sol +++ b/script/ContractCodeChecker.sol @@ -4,15 +4,8 @@ pragma solidity ^0.8.13; import {console} from "forge-std/console.sol"; import {console2} from "forge-std/console2.sol"; - contract ContractCodeChecker { - - event ByteMismatchSegment( - uint256 startIndex, - uint256 endIndex, - bytes aSegment, - bytes bSegment - ); + event ByteMismatchSegment(uint256 startIndex, uint256 endIndex, bytes aSegment, bytes bSegment); function compareBytes(bytes memory a, bytes memory b) internal returns (bool) { if (a.length != b.length) { @@ -50,12 +43,7 @@ contract ContractCodeChecker { return !anyMismatch; } - function emitMismatchSegment( - bytes memory a, - bytes memory b, - uint256 start, - uint256 end - ) internal { + function emitMismatchSegment(bytes memory a, bytes memory b, uint256 start, uint256 end) internal { // endIndex is inclusive uint256 segmentLength = end - start + 1; @@ -82,8 +70,8 @@ contract ContractCodeChecker { // Every byte corresponds to two hex characters bytes memory str = new bytes(2 + data.length * 2); - str[0] = '0'; - str[1] = 'x'; + str[0] = "0"; + str[1] = "x"; for (uint256 i = 0; i < data.length; i++) { str[2 + i * 2] = alphabet[uint8(data[i] >> 4)]; str[3 + i * 2] = alphabet[uint8(data[i] & 0x0f)]; @@ -110,7 +98,7 @@ contract ContractCodeChecker { // Fetch runtime bytecode from on-chain addresses bytes memory localBytecode = localDeployed.code; bytes memory onchainRuntimeBytecode = deployedImpl.code; - + // Optionally check length first (not strictly necessary if doing a partial match) if (localBytecode.length == 0 || onchainRuntimeBytecode.length == 0) { revert("One of the bytecode arrays is empty, cannot verify."); @@ -155,11 +143,11 @@ contract ContractCodeChecker { // This is a heuristic based on known patterns in the metadata. function trimMetadata(bytes memory code) internal pure returns (bytes memory) { // Metadata usually starts with 0xa2 or a similar tag near the end. - // We can scan backward for a known marker. + // We can scan backward for a known marker. // In Solidity 0.8.x, metadata often starts near the end with 0xa2 0x64 ... pattern. // This is a simplified approach and may need refinement. - - // For a more robust approach, you'd analyze the last bytes. + + // For a more robust approach, you'd analyze the last bytes. // Typically, the CBOR metadata is at the very end of the bytecode. uint256 length = code.length; if (length < 4) { @@ -190,5 +178,4 @@ contract ContractCodeChecker { // If no metadata marker found, return as is. return code; } - } diff --git a/script/DeployHoodiContracts.s.sol b/script/DeployHoodiContracts.s.sol index 50d5fb228..811c53036 100644 --- a/script/DeployHoodiContracts.s.sol +++ b/script/DeployHoodiContracts.s.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "forge-std/Script.sol"; -import "../src/EtherFiNodesManager.sol"; import "../src/EtherFiNode.sol"; +import "../src/EtherFiNodesManager.sol"; import "../src/EtherFiRateLimiter.sol"; +import "forge-std/Script.sol"; interface IUpgradable { function upgradeTo(address newImplementation) external; @@ -18,20 +18,20 @@ contract DeployHoodiContracts is Script { // Known addresses on Hoodi testnet address stakingManagerProxy = 0xEcf3C0Dc644DBC7d0fbf7f69651D90f2177D0dFf; - + address roleRegistryProxy = 0x62247D29B4B9BECf4BB73E0c722cf6445cfC7cE9; address liquidityPoolProxy = 0x308861A430be4cce5502d0A12724771Fc6DaF216; address eigenPodManagerProxy = 0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338; address delegationManagerProxy = 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A; address etherFiNodesManagerProxy = 0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F; address etherFiNodeProxy = 0xfD4Ff2942e183161a5920749CD5A8B0cFD4164AC; - address etherFiRateLimiterProxy = address(0x0); - + address etherFiRateLimiterProxy = address(0x0); + // Deploy EtherFiRateLimiter first console.log("Deploying EtherFiRateLimiter implementation..."); EtherFiRateLimiter rateLimiterImpl = new EtherFiRateLimiter(roleRegistryProxy); console.log("EtherFiRateLimiter implementation deployed at:", address(rateLimiterImpl)); - + // Deploy new EtherFiNodesManager implementation console.log("Deploying new EtherFiNodesManager implementation..."); EtherFiNodesManager newNodesManagerImpl = new EtherFiNodesManager(stakingManagerProxy, roleRegistryProxy, address(etherFiRateLimiterProxy)); @@ -41,16 +41,9 @@ contract DeployHoodiContracts is Script { // Deploy new EtherFiNode implementation console.log("Deploying new EtherFiNode implementation..."); - EtherFiNode newNode = new EtherFiNode( - liquidityPoolProxy, - etherFiNodesManagerProxy, - eigenPodManagerProxy, - delegationManagerProxy, - roleRegistryProxy - ); + EtherFiNode newNode = new EtherFiNode(liquidityPoolProxy, etherFiNodesManagerProxy, eigenPodManagerProxy, delegationManagerProxy, roleRegistryProxy); console.log("EtherFiNode deployed at:", address(newNode)); - console.log("Upgrading NodesManager proxy..."); IUpgradable(etherFiNodesManagerProxy).upgradeTo(address(newNodesManagerImpl)); console.log(" -> NodesManager proxy upgraded"); @@ -61,10 +54,10 @@ contract DeployHoodiContracts is Script { console.log(" -> EtherFiNode beacon upgraded"); vm.stopBroadcast(); - + // Log the addresses for upgrade transactions console.log("\n=== Deployment Summary ==="); console.log("New EtherFiNodesManager implementation:", address(newNodesManagerImpl)); console.log("New EtherFiNode implementation:", address(newNode)); } -} \ No newline at end of file +} diff --git a/script/DeployV3Prelude.s.sol b/script/DeployV3Prelude.s.sol index bb79753ce..45c2ea957 100644 --- a/script/DeployV3Prelude.s.sol +++ b/script/DeployV3Prelude.s.sol @@ -2,20 +2,21 @@ pragma solidity ^0.8.27; import "forge-std/Script.sol"; -import "forge-std/console.sol"; + import "forge-std/StdJson.sol"; +import "forge-std/console.sol"; import "../script/Create2Factory.sol"; +import "../src/EETH.sol"; +import "../src/EtherFiAdmin.sol"; import "../src/EtherFiNode.sol"; -import "../src/RoleRegistry.sol"; -import "../src/StakingManager.sol"; import "../src/EtherFiNodesManager.sol"; +import "../src/EtherFiOracle.sol"; import "../src/LiquidityPool.sol"; +import "../src/RoleRegistry.sol"; +import "../src/StakingManager.sol"; import "../src/WeETH.sol"; -import "../src/EETH.sol"; -import "../src/EtherFiAdmin.sol"; -import "../src/EtherFiOracle.sol"; interface ICreate2Factory { function deploy(bytes memory code, bytes32 salt) external payable returns (address); @@ -57,17 +58,8 @@ contract DeployScript is Script { vm.startBroadcast(); { string memory contractName = "EtherFiNode"; - bytes memory constructorArgs = abi.encode( - address(liquidityPool), - address(etherFiNodesManager), - address(eigenPodManager), - address(delegationManager), - address(roleRegistry) - ); - bytes memory bytecode = abi.encodePacked( - type(EtherFiNode).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(address(liquidityPool), address(etherFiNodesManager), address(eigenPodManager), address(delegationManager), address(roleRegistry)); + bytes memory bytecode = abi.encodePacked(type(EtherFiNode).creationCode, constructorArgs); address deployedAddress = deploy(contractName, constructorArgs, bytecode, commitHashSalt, true); verify(deployedAddress, bytecode, commitHashSalt); } @@ -75,18 +67,8 @@ contract DeployScript is Script { // StakingManager { string memory contractName = "StakingManager"; - bytes memory constructorArgs = abi.encode( - address(liquidityPool), - address(etherFiNodesManager), - address(stakingDepositContract), - address(auctionManager), - address(etherFiNodeBeacon), - address(roleRegistry) - ); - bytes memory bytecode = abi.encodePacked( - type(StakingManager).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(address(liquidityPool), address(etherFiNodesManager), address(stakingDepositContract), address(auctionManager), address(etherFiNodeBeacon), address(roleRegistry)); + bytes memory bytecode = abi.encodePacked(type(StakingManager).creationCode, constructorArgs); address deployedAddress = deploy(contractName, constructorArgs, bytecode, commitHashSalt, true); verify(deployedAddress, bytecode, commitHashSalt); } @@ -94,14 +76,8 @@ contract DeployScript is Script { // EtherFiNodesManager { string memory contractName = "EtherFiNodesManager"; - bytes memory constructorArgs = abi.encode( - address(stakingManager), - address(roleRegistry) - ); - bytes memory bytecode = abi.encodePacked( - type(EtherFiNodesManager).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(address(stakingManager), address(roleRegistry)); + bytes memory bytecode = abi.encodePacked(type(EtherFiNodesManager).creationCode, constructorArgs); address deployedAddress = deploy(contractName, constructorArgs, bytecode, commitHashSalt, true); verify(deployedAddress, bytecode, commitHashSalt); } @@ -110,10 +86,7 @@ contract DeployScript is Script { { string memory contractName = "LiquidityPool"; bytes memory constructorArgs; - bytes memory bytecode = abi.encodePacked( - type(LiquidityPool).creationCode, - constructorArgs - ); + bytes memory bytecode = abi.encodePacked(type(LiquidityPool).creationCode, constructorArgs); address deployedAddress = deploy(contractName, constructorArgs, bytecode, commitHashSalt, true); verify(deployedAddress, bytecode, commitHashSalt); } @@ -121,13 +94,8 @@ contract DeployScript is Script { // WeETH { string memory contractName = "WeETH"; - bytes memory constructorArgs = abi.encode( - address(roleRegistry) - ); - bytes memory bytecode = abi.encodePacked( - type(WeETH).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(address(roleRegistry)); + bytes memory bytecode = abi.encodePacked(type(WeETH).creationCode, constructorArgs); address deployedAddress = deploy(contractName, constructorArgs, bytecode, commitHashSalt, true); verify(deployedAddress, bytecode, commitHashSalt); } @@ -135,13 +103,8 @@ contract DeployScript is Script { // eETH { string memory contractName = "EETH"; - bytes memory constructorArgs = abi.encode( - address(roleRegistry) - ); - bytes memory bytecode = abi.encodePacked( - type(EETH).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(address(roleRegistry)); + bytes memory bytecode = abi.encodePacked(type(EETH).creationCode, constructorArgs); address deployedAddress = deploy(contractName, constructorArgs, bytecode, commitHashSalt, true); verify(deployedAddress, bytecode, commitHashSalt); } @@ -150,10 +113,7 @@ contract DeployScript is Script { { string memory contractName = "EtherFiOracle"; bytes memory constructorArgs; - bytes memory bytecode = abi.encodePacked( - type(EtherFiOracle).creationCode, - constructorArgs - ); + bytes memory bytecode = abi.encodePacked(type(EtherFiOracle).creationCode, constructorArgs); address deployedAddress = deploy(contractName, constructorArgs, bytecode, commitHashSalt, true); verify(deployedAddress, bytecode, commitHashSalt); } @@ -162,10 +122,7 @@ contract DeployScript is Script { { string memory contractName = "EtherFiAdmin"; bytes memory constructorArgs; - bytes memory bytecode = abi.encodePacked( - type(EtherFiAdmin).creationCode, - constructorArgs - ); + bytes memory bytecode = abi.encodePacked(type(EtherFiAdmin).creationCode, constructorArgs); address deployedAddress = deploy(contractName, constructorArgs, bytecode, commitHashSalt, true); verify(deployedAddress, bytecode, commitHashSalt); } @@ -180,31 +137,15 @@ contract DeployScript is Script { require(deployedAddress == predictedAddress, "Deployment address mismatch"); if (logging) { - // 5. Create JSON deployment log (exact same format) - string memory deployLog = string.concat( - "{\n", - ' "contractName": "', contractName, '",\n', - ' "deploymentParameters": {\n', - ' "factory": "', vm.toString(address(factory)), '",\n', - ' "salt": "', vm.toString(salt), '",\n', - formatConstructorArgs(constructorArgs, contractName), '\n', - ' },\n', - ' "deployedAddress": "', vm.toString(deployedAddress), '"\n', - "}" - ); + string memory deployLog = string.concat("{\n", ' "contractName": "', contractName, '",\n', ' "deploymentParameters": {\n', ' "factory": "', vm.toString(address(factory)), '",\n', ' "salt": "', vm.toString(salt), '",\n', formatConstructorArgs(constructorArgs, contractName), "\n", " },\n", ' "deployedAddress": "', vm.toString(deployedAddress), '"\n', "}"); // 6. Save deployment log string memory root = vm.projectRoot(); string memory logFileDir = string.concat(root, "/deployment/", contractName); vm.createDir(logFileDir, true); - string memory logFileName = string.concat( - logFileDir, - "/", - getTimestampString(), - ".json" - ); + string memory logFileName = string.concat(logFileDir, "/", getTimestampString(), ".json"); vm.writeFile(logFileName, deployLog); // 7. Console output @@ -224,11 +165,7 @@ contract DeployScript is Script { // Parse and format constructor arguments into JSON //------------------------------------------------------------------------- - function formatConstructorArgs(bytes memory constructorArgs, string memory contractName) - internal - view - returns (string memory) - { + function formatConstructorArgs(bytes memory constructorArgs, string memory contractName) internal view returns (string memory) { // 1. Load artifact JSON string memory artifactJson = readArtifact(contractName); @@ -262,11 +199,7 @@ contract DeployScript is Script { /** * @dev Extracts all `name` and `type` fields from the constructor inputs */ - function getConstructorMetadata(string memory artifactJson, uint256 inputCount) - internal - pure - returns (string[] memory, string[] memory) - { + function getConstructorMetadata(string memory artifactJson, uint256 inputCount) internal pure returns (string[] memory, string[] memory) { string[] memory names = new string[](inputCount); string[] memory typesArr = new string[](inputCount); @@ -283,15 +216,7 @@ contract DeployScript is Script { /** * @dev Decodes each provided constructorArg and builds the JSON lines */ - function decodeParamsJson( - bytes memory constructorArgs, - string[] memory names, - string[] memory typesArr - ) - internal - pure - returns (string memory) - { + function decodeParamsJson(bytes memory constructorArgs, string[] memory names, string[] memory typesArr) internal pure returns (string memory) { uint256 offset; string memory json = ' "constructorArgs": {\n'; @@ -299,11 +224,7 @@ contract DeployScript is Script { (string memory val, uint256 newOffset) = decodeParam(constructorArgs, offset, typesArr[i]); offset = newOffset; - json = string.concat( - json, - ' "', names[i], '": "', val, '"', - (i < names.length - 1) ? ",\n" : "\n" - ); + json = string.concat(json, ' "', names[i], '": "', val, '"', (i < names.length - 1) ? ",\n" : "\n"); } return string.concat(json, " }"); } @@ -312,11 +233,7 @@ contract DeployScript is Script { // Decoder logic (same as before) //------------------------------------------------------------------------- - function decodeParam(bytes memory data, uint256 offset, string memory t) - internal - pure - returns (string memory, uint256) - { + function decodeParam(bytes memory data, uint256 offset, string memory t) internal pure returns (string memory, uint256) { if (!isDynamicType(t)) { // For static params, read 32 bytes directly bytes memory chunk = slice(data, offset, 32); @@ -395,7 +312,7 @@ contract DeployScript is Script { function endsWithArray(string memory t) internal pure returns (bool) { bytes memory b = bytes(t); - return b.length >= 2 && (b[b.length - 2] == '[' && b[b.length - 1] == ']'); + return b.length >= 2 && (b[b.length - 2] == "[" && b[b.length - 1] == "]"); } //------------------------------------------------------------------------- @@ -449,13 +366,13 @@ contract DeployScript is Script { // The timestamp is in UTC (Coordinated Universal Time). This is because block.timestamp returns a Unix timestamp, which is always in UTC. function getTimestampString() internal view returns (string memory) { uint256 ts = block.timestamp; - string memory year = vm.toString((ts / 31536000) + 1970); - string memory month = pad(vm.toString(((ts % 31536000) / 2592000) + 1)); - string memory day = pad(vm.toString(((ts % 2592000) / 86400) + 1)); - string memory hour = pad(vm.toString((ts % 86400) / 3600)); + string memory year = vm.toString((ts / 31_536_000) + 1970); + string memory month = pad(vm.toString(((ts % 31_536_000) / 2_592_000) + 1)); + string memory day = pad(vm.toString(((ts % 2_592_000) / 86_400) + 1)); + string memory hour = pad(vm.toString((ts % 86_400) / 3600)); string memory minute = pad(vm.toString((ts % 3600) / 60)); string memory second = pad(vm.toString(ts % 60)); - return string.concat(year,"-",month,"-",day,"-",hour,"-",minute,"-",second); + return string.concat(year, "-", month, "-", day, "-", hour, "-", minute, "-", second); } function pad(string memory n) internal pure returns (string memory) { diff --git a/script/DeployWeETHWithdrawAdapter.s.sol b/script/DeployWeETHWithdrawAdapter.s.sol index e01aaeaed..786232c48 100644 --- a/script/DeployWeETHWithdrawAdapter.s.sol +++ b/script/DeployWeETHWithdrawAdapter.s.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; +import "../src/UUPSProxy.sol"; +import "../src/helpers/WeETHWithdrawAdapter.sol"; import "forge-std/Script.sol"; -import "forge-std/console.sol"; import "forge-std/StdJson.sol"; -import "../src/helpers/WeETHWithdrawAdapter.sol"; -import "../src/UUPSProxy.sol"; +import "forge-std/console.sol"; interface ICreate2Factory { function deploy(bytes memory code, bytes32 salt) external payable returns (address); @@ -16,7 +16,7 @@ interface ICreate2Factory { /** * @title Deploy WeETH Withdraw Adapter * @notice Deploys the WeETHWithdrawAdapter implementation and UUPS proxy using Create2Factory - * + * * This script will: * 1. Compute and display predicted deployment addresses (deterministic across all chains) * 2. Deploy the WeETHWithdrawAdapter implementation using Create2 @@ -24,18 +24,18 @@ interface ICreate2Factory { * 4. Transfer ownership to the EtherFi Timelock * 5. Verify the deployment * 6. Save deployment logs to ./deployment/{contractName}/{timestamp}.json - * + * * Key Features: * - Uses Create2Factory (0x356d1B83970CeF2018F2c9337cDdb67dff5AEF99) for deterministic addresses * - Same addresses across all EVM chains (Mainnet, Base, Arbitrum, etc.) * - Commit hash salt: 5bb56076faac983d51c2145b4de117335f6e4fa5 - * + * * Usage: - * + * * 1. Dry run (compute addresses without deploying): * forge script ./script/DeployWeETHWithdrawAdapter.s.sol:DeployWeETHWithdrawAdapter * Note: Will fail at deployment step but shows predicted addresses - * + * * 2. Mainnet deployment: * source .env && forge script ./script/DeployWeETHWithdrawAdapter.s.sol:DeployWeETHWithdrawAdapter \ * --rpc-url $MAINNET_RPC_URL \ @@ -44,23 +44,23 @@ interface ICreate2Factory { * --etherscan-api-key $ETHERSCAN_API_KEY \ * --slow \ * -vvvv - * + * * 3. Other chains (Base, Arbitrum, etc.): * forge script ./script/DeployWeETHWithdrawAdapter.s.sol:DeployWeETHWithdrawAdapter \ * --rpc-url $CHAIN_RPC_URL \ * --broadcast \ * --verify \ * -vvvv - * + * * Important: The contract addresses MUST match across all chains for the deployment to work. * Update the constants if deploying to chains with different addresses. */ contract DeployWeETHWithdrawAdapter is Script { using stdJson for string; - + // Create2Factory address (same as in DeployV3Prelude.s.sol) ICreate2Factory constant factory = ICreate2Factory(0x356d1B83970CeF2018F2c9337cDdb67dff5AEF99); - + // Mainnet contract addresses address constant weETHAddress = 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee; address constant eETHAddress = 0x35fA164735182de50811E8e2E824cFb9B6118ac2; @@ -68,7 +68,7 @@ contract DeployWeETHWithdrawAdapter is Script { address constant withdrawRequestNFTAddress = 0x7d5706f6ef3F89B3951E23e557CDFBC3239D4E2c; address constant roleRegistryAddress = 0x62247D29B4B9BECf4BB73E0c722cf6445cfC7cE9; address constant timelockAddress = 0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761; - + // Commit hash salt bytes32 constant commitHashSalt = bytes32(bytes20(hex"97cd063025712908c02476f03a21565e2fd4f801")); @@ -85,86 +85,59 @@ contract DeployWeETHWithdrawAdapter is Script { // Display addresses for verification displayAddresses(); - + // Compute and display predicted addresses console.log("\n========================================"); console.log("Predicted Deployment Addresses"); console.log("========================================"); computePredictedAddresses(); - + // Start deployment vm.startBroadcast(deployerPrivateKey); - + // Deploy WeETHWithdrawAdapter implementation { string memory contractName = "WeETHWithdrawAdapter"; - bytes memory constructorArgs = abi.encode( - weETHAddress, - eETHAddress, - liquidityPoolAddress, - withdrawRequestNFTAddress, - roleRegistryAddress - ); - bytes memory bytecode = abi.encodePacked( - type(WeETHWithdrawAdapter).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(weETHAddress, eETHAddress, liquidityPoolAddress, withdrawRequestNFTAddress, roleRegistryAddress); + bytes memory bytecode = abi.encodePacked(type(WeETHWithdrawAdapter).creationCode, constructorArgs); address deployedAddress = deployContract(contractName, constructorArgs, bytecode, commitHashSalt); verifyContract(deployedAddress, bytecode, commitHashSalt); } - + // Deploy UUPSProxy { string memory contractName = "WeETHWithdrawAdapter_Proxy"; - + // Get implementation address (we need to recalculate it) - bytes memory implConstructorArgs = abi.encode( - weETHAddress, - eETHAddress, - liquidityPoolAddress, - withdrawRequestNFTAddress, - roleRegistryAddress - ); - bytes memory implBytecode = abi.encodePacked( - type(WeETHWithdrawAdapter).creationCode, - implConstructorArgs - ); + bytes memory implConstructorArgs = abi.encode(weETHAddress, eETHAddress, liquidityPoolAddress, withdrawRequestNFTAddress, roleRegistryAddress); + bytes memory implBytecode = abi.encodePacked(type(WeETHWithdrawAdapter).creationCode, implConstructorArgs); address implementationAddress = factory.computeAddress(commitHashSalt, implBytecode); - + // Prepare initialization data with timelock as initial owner - bytes memory initializerData = abi.encodeWithSelector( - WeETHWithdrawAdapter.initialize.selector, - timelockAddress - ); - - bytes memory constructorArgs = abi.encode( - implementationAddress, - initializerData - ); - bytes memory bytecode = abi.encodePacked( - type(UUPSProxy).creationCode, - constructorArgs - ); + bytes memory initializerData = abi.encodeWithSelector(WeETHWithdrawAdapter.initialize.selector, timelockAddress); + + bytes memory constructorArgs = abi.encode(implementationAddress, initializerData); + bytes memory bytecode = abi.encodePacked(type(UUPSProxy).creationCode, constructorArgs); address proxyAddress = deployContract(contractName, constructorArgs, bytecode, commitHashSalt); verifyContract(proxyAddress, bytecode, commitHashSalt); - + // Wrap proxy in implementation interface WeETHWithdrawAdapter adapter = WeETHWithdrawAdapter(proxyAddress); - + // Verify ownership is already set to timelock (no transfer needed) console.log("\nVerifying ownership..."); address currentOwner = adapter.owner(); require(currentOwner == timelockAddress, "Owner should be timelock"); console.log("Owner correctly set to timelock:", currentOwner); - + // Final verification console.log("\nVerifying deployment..."); verifyDeployment(adapter, implementationAddress); } - + vm.stopBroadcast(); } - + function displayAddresses() internal pure { console.log("\nUsing Mainnet Contract Addresses:"); console.log("-------------------"); @@ -177,151 +150,107 @@ contract DeployWeETHWithdrawAdapter is Script { console.log("\nCreate2Factory: ", address(factory)); console.log("Commit Hash Salt: ", vm.toString(commitHashSalt)); } - + function computePredictedAddresses() internal { // Compute implementation address - bytes memory implConstructorArgs = abi.encode( - weETHAddress, - eETHAddress, - liquidityPoolAddress, - withdrawRequestNFTAddress, - roleRegistryAddress - ); - bytes memory implBytecode = abi.encodePacked( - type(WeETHWithdrawAdapter).creationCode, - implConstructorArgs - ); + bytes memory implConstructorArgs = abi.encode(weETHAddress, eETHAddress, liquidityPoolAddress, withdrawRequestNFTAddress, roleRegistryAddress); + bytes memory implBytecode = abi.encodePacked(type(WeETHWithdrawAdapter).creationCode, implConstructorArgs); address predictedImpl = factory.computeAddress(commitHashSalt, implBytecode); console.log("Implementation: ", predictedImpl); - + // Compute proxy address (with timelock as initial owner) - bytes memory initializerData = abi.encodeWithSelector( - WeETHWithdrawAdapter.initialize.selector, - timelockAddress - ); - bytes memory proxyConstructorArgs = abi.encode( - predictedImpl, - initializerData - ); - bytes memory proxyBytecode = abi.encodePacked( - type(UUPSProxy).creationCode, - proxyConstructorArgs - ); + bytes memory initializerData = abi.encodeWithSelector(WeETHWithdrawAdapter.initialize.selector, timelockAddress); + bytes memory proxyConstructorArgs = abi.encode(predictedImpl, initializerData); + bytes memory proxyBytecode = abi.encodePacked(type(UUPSProxy).creationCode, proxyConstructorArgs); address predictedProxy = factory.computeAddress(commitHashSalt, proxyBytecode); console.log("Proxy: ", predictedProxy); console.log("Initial Owner: ", timelockAddress); console.log("-------------------"); console.log("Note: These addresses are deterministic across all EVM chains"); } - - function deployContract( - string memory contractName, - bytes memory constructorArgs, - bytes memory bytecode, - bytes32 salt - ) internal returns (address) { + + function deployContract(string memory contractName, bytes memory constructorArgs, bytes memory bytecode, bytes32 salt) internal returns (address) { address predictedAddress = factory.computeAddress(salt, bytecode); console.log("\nDeploying", contractName); console.log("Predicted address:", predictedAddress); - + address deployedAddress = factory.deploy(bytecode, salt); require(deployedAddress == predictedAddress, "Deployment address mismatch"); - + console.log("Deployed at:", deployedAddress); - + // Save deployment log saveDeploymentLog(contractName, deployedAddress, constructorArgs, salt); - + return deployedAddress; } - + function verifyContract(address addr, bytes memory bytecode, bytes32 salt) internal view returns (bool) { bool verified = factory.verify(addr, salt, bytecode); require(verified, "Contract verification failed"); console.log("Verification: PASS"); return verified; } - - function saveDeploymentLog( - string memory contractName, - address deployedAddress, - bytes memory constructorArgs, - bytes32 salt - ) internal { - string memory deployLog = string.concat( - "{\n", - ' "contractName": "', contractName, '",\n', - ' "deploymentParameters": {\n', - ' "factory": "', vm.toString(address(factory)), '",\n', - ' "salt": "', vm.toString(salt), '",\n', - ' "constructorArgsEncoded": "', vm.toString(constructorArgs), '"\n', - ' },\n', - ' "deployedAddress": "', vm.toString(deployedAddress), '"\n', - "}" - ); - + + function saveDeploymentLog(string memory contractName, address deployedAddress, bytes memory constructorArgs, bytes32 salt) internal { + string memory deployLog = string.concat("{\n", ' "contractName": "', contractName, '",\n', ' "deploymentParameters": {\n', ' "factory": "', vm.toString(address(factory)), '",\n', ' "salt": "', vm.toString(salt), '",\n', ' "constructorArgsEncoded": "', vm.toString(constructorArgs), '"\n', " },\n", ' "deployedAddress": "', vm.toString(deployedAddress), '"\n', "}"); + string memory root = vm.projectRoot(); string memory logFileDir = string.concat(root, "/deployment/", contractName); vm.createDir(logFileDir, true); - - string memory logFileName = string.concat( - logFileDir, - "/", - getTimestampString(), - ".json" - ); + + string memory logFileName = string.concat(logFileDir, "/", getTimestampString(), ".json"); vm.writeFile(logFileName, deployLog); - + console.log("Deployment log saved to:", logFileName); } - + function verifyDeployment(WeETHWithdrawAdapter adapter, address implementationAddress) internal view { console.log("-------------------"); - + // Verify immutable variables require(address(adapter.weETH()) == weETHAddress, "WeETH address mismatch"); console.log("[PASS] WeETH address verified"); - + require(address(adapter.eETH()) == eETHAddress, "EETH address mismatch"); console.log("[PASS] EETH address verified"); - + require(address(adapter.liquidityPool()) == liquidityPoolAddress, "LiquidityPool address mismatch"); console.log("[PASS] LiquidityPool address verified"); - + require(address(adapter.withdrawRequestNFT()) == withdrawRequestNFTAddress, "WithdrawRequestNFT address mismatch"); console.log("[PASS] WithdrawRequestNFT address verified"); - + require(address(adapter.roleRegistry()) == roleRegistryAddress, "RoleRegistry address mismatch"); console.log("[PASS] RoleRegistry address verified"); - + // Verify initialization state require(!adapter.paused(), "Contract should not be paused"); console.log("[PASS] Contract is not paused"); - + require(adapter.owner() == timelockAddress, "Owner should be timelock"); console.log("[PASS] Owner is timelock"); - + // Verify implementation address actualImpl = adapter.getImplementation(); require(actualImpl == implementationAddress, "Implementation address mismatch"); console.log("[PASS] Implementation address verified:", actualImpl); - + console.log("\n[PASS] All verifications passed!"); } - + function getTimestampString() internal view returns (string memory) { uint256 ts = block.timestamp; - string memory year = vm.toString((ts / 31536000) + 1970); - string memory month = pad(vm.toString(((ts % 31536000) / 2592000) + 1)); - string memory day = pad(vm.toString(((ts % 2592000) / 86400) + 1)); - string memory hour = pad(vm.toString((ts % 86400) / 3600)); + string memory year = vm.toString((ts / 31_536_000) + 1970); + string memory month = pad(vm.toString(((ts % 31_536_000) / 2_592_000) + 1)); + string memory day = pad(vm.toString(((ts % 2_592_000) / 86_400) + 1)); + string memory hour = pad(vm.toString((ts % 86_400) / 3600)); string memory minute = pad(vm.toString((ts % 3600) / 60)); string memory second = pad(vm.toString(ts % 60)); return string.concat(year, "-", month, "-", day, "-", hour, "-", minute, "-", second); } - + function pad(string memory n) internal pure returns (string memory) { return bytes(n).length == 1 ? string.concat("0", n) : n; } } - diff --git a/script/V3PreludeTransactions.sol b/script/V3PreludeTransactions.sol index 0339dcf5e..d10e5faad 100644 --- a/script/V3PreludeTransactions.sol +++ b/script/V3PreludeTransactions.sol @@ -1,23 +1,25 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "forge-std/Script.sol"; -import "../test/TestSetup.sol"; -import "../src/EtherFiTimelock.sol"; +import "../lib/openzeppelin-contracts/contracts/access/IAccessControl.sol"; +import "../src/EETH.sol"; +import "../src/EtherFiAdmin.sol"; import "../src/EtherFiNode.sol"; import "../src/EtherFiNodesManager.sol"; +import "../src/EtherFiOracle.sol"; +import "../src/EtherFiTimelock.sol"; import "../src/LiquidityPool.sol"; + +import "../src/RoleRegistry.sol"; import "../src/StakingManager.sol"; -import "../src/EtherFiOracle.sol"; -import "../src/EtherFiAdmin.sol"; -import "../src/EETH.sol"; import "../src/WeETH.sol"; -import "../src/RoleRegistry.sol"; -import "../lib/openzeppelin-contracts/contracts/access/IAccessControl.sol"; +import "../test/TestSetup.sol"; +import "forge-std/Script.sol"; + import "forge-std/console2.sol"; contract V3PreludeTransactions is Script { - /* +/* EtherFiTimelock etherFiTimelock = EtherFiTimelock(payable(0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761)); diff --git a/script/VerifyV3Upgrade.s.sol b/script/VerifyV3Upgrade.s.sol index 38059e17b..a1d4dfc9e 100644 --- a/script/VerifyV3Upgrade.s.sol +++ b/script/VerifyV3Upgrade.s.sol @@ -1,24 +1,26 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "forge-std/Script.sol"; -import "forge-std/console2.sol"; -import "../src/interfaces/IStakingManager.sol"; -import "../src/interfaces/IEtherFiNodesManager.sol"; -import "../src/interfaces/IEtherFiNode.sol"; -import "../src/interfaces/ILiquidityPool.sol"; -import "../src/interfaces/IEtherFiOracle.sol"; -import "../src/interfaces/IEtherFiAdmin.sol"; -import "../src/interfaces/IeETH.sol"; -import "../src/interfaces/IWeETH.sol"; -import "../src/interfaces/ITNFT.sol"; -import "../src/StakingManager.sol"; -import "../src/EtherFiNodesManager.sol"; +import "../lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "../src/AuctionManager.sol"; import "../src/EtherFiNode.sol"; +import "../src/EtherFiNodesManager.sol"; import "../src/LiquidityPool.sol"; -import "../src/AuctionManager.sol"; import "../src/RoleRegistry.sol"; -import "../lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "../src/StakingManager.sol"; +import "../src/interfaces/IEtherFiAdmin.sol"; +import "../src/interfaces/IEtherFiNode.sol"; +import "../src/interfaces/IEtherFiNodesManager.sol"; + +import "../src/interfaces/IEtherFiOracle.sol"; +import "../src/interfaces/ILiquidityPool.sol"; +import "../src/interfaces/IStakingManager.sol"; + +import "../src/interfaces/ITNFT.sol"; +import "../src/interfaces/IWeETH.sol"; +import "../src/interfaces/IeETH.sol"; +import "forge-std/Script.sol"; +import "forge-std/console2.sol"; interface IUpgrade { function upgradeTo(address) external; @@ -28,18 +30,11 @@ interface IUpgrade { contract VerifyV3Upgrade is Script { // Mainnet addresses - StakingManager stakingManager = - StakingManager(0x25e821b7197B146F7713C3b89B6A4D83516B912d); - ILiquidityPool liquidityPool = - ILiquidityPool(0x308861A430be4cce5502d0A12724771Fc6DaF216); - EtherFiNodesManager etherFiNodesManager = - EtherFiNodesManager( - payable(0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F) - ); - AuctionManager auctionManager = - AuctionManager(0x00C452aFFee3a17d9Cecc1Bcd2B8d5C7635C4CB9); - RoleRegistry roleRegistry = - RoleRegistry(0x62247D29B4B9BECf4BB73E0c722cf6445cfC7cE9); + StakingManager stakingManager = StakingManager(0x25e821b7197B146F7713C3b89B6A4D83516B912d); + ILiquidityPool liquidityPool = ILiquidityPool(0x308861A430be4cce5502d0A12724771Fc6DaF216); + EtherFiNodesManager etherFiNodesManager = EtherFiNodesManager(payable(0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F)); + AuctionManager auctionManager = AuctionManager(0x00C452aFFee3a17d9Cecc1Bcd2B8d5C7635C4CB9); + RoleRegistry roleRegistry = RoleRegistry(0x62247D29B4B9BECf4BB73E0c722cf6445cfC7cE9); // Additional contract addresses to verify address etherFiOracle = 0x57AaF0004C716388B21795431CD7D5f9D3Bb6a41; @@ -49,8 +44,7 @@ contract VerifyV3Upgrade is Script { address TNFT = 0x7B5ae07E2AF1C861BcC4736D23f5f66A61E0cA5e; // ERC1967 storage slot for implementation address - bytes32 constant IMPLEMENTATION_SLOT = - 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; // Track verification results uint256 totalChecks; @@ -110,18 +104,11 @@ contract VerifyV3Upgrade is Script { function verifyRoleRegistryConfiguration() internal { // Check StakingManager has correct RoleRegistry console2.log("Checking StakingManager RoleRegistry..."); - checkCondition( - address(stakingManager.roleRegistry()) == address(roleRegistry), - "StakingManager has correct RoleRegistry" - ); + checkCondition(address(stakingManager.roleRegistry()) == address(roleRegistry), "StakingManager has correct RoleRegistry"); // Check EtherFiNodesManager has correct RoleRegistry console2.log("Checking EtherFiNodesManager RoleRegistry..."); - checkCondition( - address(etherFiNodesManager.roleRegistry()) == - address(roleRegistry), - "EtherFiNodesManager has correct RoleRegistry" - ); + checkCondition(address(etherFiNodesManager.roleRegistry()) == address(roleRegistry), "EtherFiNodesManager has correct RoleRegistry"); // Check a sample EtherFiNode implementation has correct RoleRegistry console2.log("Checking EtherFiNode implementation RoleRegistry..."); @@ -130,45 +117,28 @@ contract VerifyV3Upgrade is Script { if (etherFiNodeImpl != address(0)) { // Create a temporary instance to check the roleRegistry EtherFiNode nodeImpl = EtherFiNode(payable(etherFiNodeImpl)); - checkCondition( - address(nodeImpl.roleRegistry()) == address(roleRegistry), - "EtherFiNode implementation has correct RoleRegistry" - ); + checkCondition(address(nodeImpl.roleRegistry()) == address(roleRegistry), "EtherFiNode implementation has correct RoleRegistry"); } // Check LiquidityPool has correct RoleRegistry console2.log("Checking LiquidityPool RoleRegistry..."); - checkCondition( - address(IUpgrade(address(liquidityPool)).roleRegistry()) == - address(roleRegistry), - "LiquidityPool has correct RoleRegistry" - ); + checkCondition(address(IUpgrade(address(liquidityPool)).roleRegistry()) == address(roleRegistry), "LiquidityPool has correct RoleRegistry"); // AuctionManager does not have RoleRegistry // Check eETH has correct RoleRegistry console2.log("Checking eETH RoleRegistry..."); - checkCondition( - address(IUpgrade(eETH).roleRegistry()) == address(roleRegistry), - "eETH has correct RoleRegistry" - ); + checkCondition(address(IUpgrade(eETH).roleRegistry()) == address(roleRegistry), "eETH has correct RoleRegistry"); // Check weETH has correct RoleRegistry console2.log("Checking weETH RoleRegistry..."); - checkCondition( - address(IUpgrade(weETH).roleRegistry()) == address(roleRegistry), - "weETH has correct RoleRegistry" - ); + checkCondition(address(IUpgrade(weETH).roleRegistry()) == address(roleRegistry), "weETH has correct RoleRegistry"); //EtherFiOracle does not have RoleRegistry // Check EtherFiAdmin has correct RoleRegistry console2.log("Checking EtherFiAdmin RoleRegistry..."); - checkCondition( - address(IUpgrade(etherFiAdmin).roleRegistry()) == - address(roleRegistry), - "EtherFiAdmin has correct RoleRegistry" - ); + checkCondition(address(IUpgrade(etherFiAdmin).roleRegistry()) == address(roleRegistry), "EtherFiAdmin has correct RoleRegistry"); } function verifyUpgradeability() internal { @@ -176,10 +146,7 @@ contract VerifyV3Upgrade is Script { // Individual proxy checks // ──────────────────────────────────────────────────────────────────────────── verifyProxyUpgradeability(address(stakingManager), "StakingManager"); - verifyProxyUpgradeability( - address(etherFiNodesManager), - "EtherFiNodesManager" - ); + verifyProxyUpgradeability(address(etherFiNodesManager), "EtherFiNodesManager"); verifyProxyUpgradeability(address(liquidityPool), "LiquidityPool"); verifyProxyUpgradeability(address(auctionManager), "AuctionManager"); @@ -188,10 +155,7 @@ contract VerifyV3Upgrade is Script { // ──────────────────────────────────────────────────────────────────────────── console2.log("Checking upgrade permissions..."); address protocolUpgrader = roleRegistry.owner(); - checkCondition( - protocolUpgrader != address(0), - "Protocol upgrader (RoleRegistry owner) is set" - ); + checkCondition(protocolUpgrader != address(0), "Protocol upgrader (RoleRegistry owner) is set"); try roleRegistry.onlyProtocolUpgrader(protocolUpgrader) { checkCondition(true, "Protocol upgrader is owner"); } catch { @@ -201,75 +165,44 @@ contract VerifyV3Upgrade is Script { // Pretend to be someone *else* and make sure the upgrade reverts address random = address(0xBEEF); vm.startPrank(random); - bytes memory payload = abi.encodeWithSignature( - "upgradeTo(address)", - protocolUpgrader - ); // any addr - (bool success, ) = address(stakingManager).call(payload); + bytes memory payload = abi.encodeWithSignature("upgradeTo(address)", protocolUpgrader); // any addr + (bool success,) = address(stakingManager).call(payload); vm.stopPrank(); - checkCondition( - !success, - "Only protocol upgrader can execute upgradeTo()" - ); + checkCondition(!success, "Only protocol upgrader can execute upgradeTo()"); address currentImpl = getImplementation(address(stakingManager)); vm.startPrank(protocolUpgrader); payload = abi.encodeWithSignature("upgradeTo(address)", currentImpl); // any addr - (success, ) = address(stakingManager).call(payload); + (success,) = address(stakingManager).call(payload); vm.stopPrank(); checkCondition(success, "Protocol upgrader can execute upgradeTo()"); } - function verifyProxyUpgradeability( - address proxy, - string memory name - ) internal { + function verifyProxyUpgradeability(address proxy, string memory name) internal { console2.log(string.concat("Checking ", name, " upgradeability...")); // 1. Proxy really points to an implementation address impl = getImplementation(proxy); console.log("Implementation:", impl); - checkCondition( - impl != address(0) && impl != proxy, - string.concat(name, " is a proxy with an implementation") - ); + checkCondition(impl != address(0) && impl != proxy, string.concat(name, " is a proxy with an implementation")); // 2. Implementation exposes correct proxiableUUID() - try IERC1822ProxiableUpgradeable(impl).proxiableUUID() returns ( - bytes32 slot - ) { - checkCondition( - slot == IMPLEMENTATION_SLOT, - string.concat(name, " implementation returns correct UUID") - ); + try IERC1822ProxiableUpgradeable(impl).proxiableUUID() returns (bytes32 slot) { + checkCondition(slot == IMPLEMENTATION_SLOT, string.concat(name, " implementation returns correct UUID")); } catch { - checkCondition( - false, - string.concat(name, " implementation missing proxiableUUID()") - ); + checkCondition(false, string.concat(name, " implementation missing proxiableUUID()")); } - (bool ok, bytes memory data) = proxy.staticcall( - abi.encodeWithSignature("upgradeTo(address)", impl) - ); + (bool ok, bytes memory data) = proxy.staticcall(abi.encodeWithSignature("upgradeTo(address)", impl)); - checkCondition( - ok || data.length != 0, - string.concat(name, " proxy exposes upgradeTo()") - ); + checkCondition(ok || data.length != 0, string.concat(name, " proxy exposes upgradeTo()")); vm.prank(address(0xcaffe)); try IUpgrade(proxy).upgradeTo(address(0xbeef)) { - checkCondition( - false, - string.concat(name, " allows a random to upgrade") - ); + checkCondition(false, string.concat(name, " allows a random to upgrade")); } catch { - checkCondition( - true, - string.concat(name, " does not allows a random to upgrade") - ); + checkCondition(true, string.concat(name, " does not allows a random to upgrade")); } } @@ -277,86 +210,41 @@ contract VerifyV3Upgrade is Script { // Define expected roles based on prelude.t.sol // StakingManager roles - bytes32 STAKING_MANAGER_NODE_CREATOR_ROLE = keccak256( - "STAKING_MANAGER_NODE_CREATOR_ROLE" - ); + bytes32 STAKING_MANAGER_NODE_CREATOR_ROLE = keccak256("STAKING_MANAGER_NODE_CREATOR_ROLE"); console2.log("Checking StakingManager roles..."); // At least check that the role exists in the system - checkCondition( - STAKING_MANAGER_NODE_CREATOR_ROLE == - stakingManager.STAKING_MANAGER_NODE_CREATOR_ROLE(), - "STAKING_MANAGER_NODE_CREATOR_ROLE constant matches" - ); + checkCondition(STAKING_MANAGER_NODE_CREATOR_ROLE == stakingManager.STAKING_MANAGER_NODE_CREATOR_ROLE(), "STAKING_MANAGER_NODE_CREATOR_ROLE constant matches"); // EtherFiNodesManager roles - bytes32 ETHERFI_NODES_MANAGER_ADMIN_ROLE = keccak256( - "ETHERFI_NODES_MANAGER_ADMIN_ROLE" - ); - bytes32 ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE = keccak256( - "ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE" - ); - bytes32 ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE = keccak256( - "ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE" - ); + bytes32 ETHERFI_NODES_MANAGER_ADMIN_ROLE = keccak256("ETHERFI_NODES_MANAGER_ADMIN_ROLE"); + bytes32 ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE = keccak256("ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE"); + bytes32 ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE = keccak256("ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE"); console2.log("Checking EtherFiNodesManager roles..."); - checkCondition( - ETHERFI_NODES_MANAGER_ADMIN_ROLE == - etherFiNodesManager.ETHERFI_NODES_MANAGER_ADMIN_ROLE(), - "ETHERFI_NODES_MANAGER_ADMIN_ROLE constant matches" - ); - checkCondition( - ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE == - etherFiNodesManager - .ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE(), - "ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE constant matches" - ); - checkCondition( - ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE == - etherFiNodesManager.ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE(), - "ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE constant matches" - ); + checkCondition(ETHERFI_NODES_MANAGER_ADMIN_ROLE == etherFiNodesManager.ETHERFI_NODES_MANAGER_ADMIN_ROLE(), "ETHERFI_NODES_MANAGER_ADMIN_ROLE constant matches"); + checkCondition(ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE == etherFiNodesManager.ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE(), "ETHERFI_NODES_MANAGER_EIGENLAYER_ADMIN_ROLE constant matches"); + checkCondition(ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE == etherFiNodesManager.ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE(), "ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE constant matches"); // Check protocol pauser/unpauser roles exist bytes32 PROTOCOL_PAUSER = keccak256("PROTOCOL_PAUSER"); bytes32 PROTOCOL_UNPAUSER = keccak256("PROTOCOL_UNPAUSER"); console2.log("Checking protocol pause roles..."); - checkCondition( - PROTOCOL_PAUSER == roleRegistry.PROTOCOL_PAUSER(), - "PROTOCOL_PAUSER constant matches" - ); - checkCondition( - PROTOCOL_UNPAUSER == roleRegistry.PROTOCOL_UNPAUSER(), - "PROTOCOL_UNPAUSER constant matches" - ); + checkCondition(PROTOCOL_PAUSER == roleRegistry.PROTOCOL_PAUSER(), "PROTOCOL_PAUSER constant matches"); + checkCondition(PROTOCOL_UNPAUSER == roleRegistry.PROTOCOL_UNPAUSER(), "PROTOCOL_UNPAUSER constant matches"); } function verifyContractInteractions() internal { // Verify StakingManager knows about other contracts console2.log("Checking StakingManager contract references..."); - checkCondition( - address(stakingManager.liquidityPool()) == address(liquidityPool), - "StakingManager has correct LiquidityPool reference" - ); - checkCondition( - address(stakingManager.etherFiNodesManager()) == - address(etherFiNodesManager), - "StakingManager has correct NodesManager reference" - ); - checkCondition( - address(stakingManager.auctionManager()) == address(auctionManager), - "StakingManager has correct AuctionManager reference" - ); + checkCondition(address(stakingManager.liquidityPool()) == address(liquidityPool), "StakingManager has correct LiquidityPool reference"); + checkCondition(address(stakingManager.etherFiNodesManager()) == address(etherFiNodesManager), "StakingManager has correct NodesManager reference"); + checkCondition(address(stakingManager.auctionManager()) == address(auctionManager), "StakingManager has correct AuctionManager reference"); // Verify EtherFiNodesManager knows about StakingManager console2.log("Checking EtherFiNodesManager contract references..."); - checkCondition( - address(etherFiNodesManager.stakingManager()) == - address(stakingManager), - "EtherFiNodesManager has correct StakingManager reference" - ); + checkCondition(address(etherFiNodesManager.stakingManager()) == address(stakingManager), "EtherFiNodesManager has correct StakingManager reference"); // Verify beacon is set correctly console2.log("Checking EtherFiNode beacon..."); @@ -393,23 +281,15 @@ contract VerifyV3Upgrade is Script { // Additional specific checks for these contracts console2.log("\nChecking EtherFiOracle specific functionality..."); - try IEtherFiOracle(etherFiOracle).consensusVersion() returns ( - uint32 version - ) { - checkCondition( - version > 0, - "EtherFiOracle consensusVersion() is accessible" - ); + try IEtherFiOracle(etherFiOracle).consensusVersion() returns (uint32 version) { + checkCondition(version > 0, "EtherFiOracle consensusVersion() is accessible"); } catch { checkCondition(false, "EtherFiOracle consensusVersion() failed"); } console2.log("\nChecking eETH token functionality..."); try IeETH(eETH).totalShares() returns (uint256 shares) { - checkCondition( - shares > 0, - "eETH totalShares() returns valid value" - ); + checkCondition(shares > 0, "eETH totalShares() returns valid value"); } catch { checkCondition(false, "eETH totalShares() failed"); } @@ -418,19 +298,13 @@ contract VerifyV3Upgrade is Script { console2.log(address(IWeETH(weETH).eETH())); console2.log(eETH); try IWeETH(weETH).eETH() returns (IeETH eethContract) { - checkCondition( - address(eethContract) == eETH, - "weETH correctly references eETH" - ); + checkCondition(address(eethContract) == eETH, "weETH correctly references eETH"); } catch { checkCondition(false, "weETH eETH() reference check failed"); } } - function checkCondition( - bool condition, - string memory description - ) internal { + function checkCondition(bool condition, string memory description) internal { totalChecks++; if (condition) { passedChecks++; diff --git a/script/deploys/DeployCumulativeMerkleRewardsDistributor.sol b/script/deploys/DeployCumulativeMerkleRewardsDistributor.sol index 696909109..1847f4e3b 100644 --- a/script/deploys/DeployCumulativeMerkleRewardsDistributor.sol +++ b/script/deploys/DeployCumulativeMerkleRewardsDistributor.sol @@ -3,35 +3,32 @@ pragma solidity ^0.8.13; import "forge-std/Script.sol"; -import "src/CumulativeMerkleRewardsDistributor.sol"; -import "src/UUPSProxy.sol"; import "../../src/helpers/AddressProvider.sol"; import "forge-std/console.sol"; +import "src/CumulativeMerkleRewardsDistributor.sol"; +import "src/UUPSProxy.sol"; /* Deploy Command * source .env && forge script ./script/deploys/DeployCumulativeMerkleRewardsDistributor.sol:DeployCumulativeMerkleRewardsDistributor --rpc-url MAINNET_RPC_URL --broadcast --etherscan-api-key $ETHERSCAN_API_KEY --verify --slow -vvvv */ contract DeployCumulativeMerkleRewardsDistributor is Script { - AddressProvider public addressProvider; /////////////////////////////////////// - address roleRegistryProxyAddress; + address roleRegistryProxyAddress; ////////////////////////////////////// function run() external { - address addressProviderAddress = vm.envAddress("CONTRACT_REGISTRY"); - vm.startBroadcast(); - + vm.startBroadcast(); addressProvider = AddressProvider(addressProviderAddress); roleRegistryProxyAddress = addressProvider.getContractAddress("RoleRegistry"); address timelockAddress = addressProvider.getContractAddress("EtherFiTimelock"); console2.log("RoleRegistry address:", roleRegistryProxyAddress); - bytes memory initializerData = abi.encodeWithSelector(CumulativeMerkleRewardsDistributor.initialize.selector); + bytes memory initializerData = abi.encodeWithSelector(CumulativeMerkleRewardsDistributor.initialize.selector); CumulativeMerkleRewardsDistributor cumulativeMerkleRewardsDistributorImplementation = new CumulativeMerkleRewardsDistributor(roleRegistryProxyAddress); UUPSProxy cumulativeMerkleRewardsDistributorProxy = new UUPSProxy(address(cumulativeMerkleRewardsDistributorImplementation), initializerData); CumulativeMerkleRewardsDistributor cumulativeMerkleInstance = CumulativeMerkleRewardsDistributor(address(cumulativeMerkleRewardsDistributorProxy)); diff --git a/script/el-exits/DeployPectraUpgradeCreate2.s.sol b/script/el-exits/DeployPectraUpgradeCreate2.s.sol index e31b742db..35cf907c0 100644 --- a/script/el-exits/DeployPectraUpgradeCreate2.s.sol +++ b/script/el-exits/DeployPectraUpgradeCreate2.s.sol @@ -2,17 +2,19 @@ pragma solidity ^0.8.27; import "forge-std/Script.sol"; -import "forge-std/console2.sol"; + import "forge-std/StdJson.sol"; +import "forge-std/console2.sol"; import "../Create2Factory.sol"; import "../../src/EtherFiNode.sol"; import "../../src/EtherFiNodesManager.sol"; import "../../src/EtherFiRateLimiter.sol"; + +import "../../src/RoleRegistry.sol"; import "../../src/StakingManager.sol"; import "../../src/UUPSProxy.sol"; -import "../../src/RoleRegistry.sol"; interface IUpgradable { function upgradeTo(address newImplementation) external; @@ -36,12 +38,12 @@ interface ICurrentEtherFiNodesManager { * @title DeployPectraUpgradeCreate2 * @notice Complete EIP-7002 deployment script using Create2Factory for mainnet * @dev Includes: Rate Limiter deployment, contract implementations, following DeployV3Prelude pattern - * + * * Steps: * 1. Deploy EtherFiRateLimiter (impl + proxy + init) * 2. Deploy new implementations using Create2Factory (StakingManager, EtherFiNodesManager, EtherFiNode) * 3. Generate transaction data for governance execution - * + * * Usage: forge script script/el-exits/DeployPectraUpgradeCreate2.s.sol --rpc-url --broadcast --verify */ contract DeployPectraUpgradeCreate2 is Script { @@ -96,16 +98,13 @@ contract DeployPectraUpgradeCreate2 is Script { function deployRateLimiter() internal { console2.log("=== STEP 1: DEPLOYING ETHERFI RATE LIMITER ==="); - + address rateLimiterImpl; // Deploy implementation using Create2Factory { string memory contractName = "EtherFiRateLimiter"; bytes memory constructorArgs = abi.encode(ROLE_REGISTRY); - bytes memory bytecode = abi.encodePacked( - type(EtherFiRateLimiter).creationCode, - constructorArgs - ); + bytes memory bytecode = abi.encodePacked(type(EtherFiRateLimiter).creationCode, constructorArgs); rateLimiterImpl = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); console2.log("Rate limiter implementation:", rateLimiterImpl); } @@ -113,23 +112,14 @@ contract DeployPectraUpgradeCreate2 is Script { address rateLimiterProxyAddr; // Deploy proxy using Create2Factory { - string memory contractName = "UUPSProxy"; - bytes memory constructorArgs = abi.encode(address(rateLimiterImpl), ""); - bytes memory bytecode = abi.encodePacked( - type(UUPSProxy).creationCode, - constructorArgs - ); - rateLimiterProxyAddr = deployCreate2( - contractName, - constructorArgs, - bytecode, - commitHashSalt, - true - ); + string memory contractName = "UUPSProxy"; + bytes memory constructorArgs = abi.encode(address(rateLimiterImpl), ""); + bytes memory bytecode = abi.encodePacked(type(UUPSProxy).creationCode, constructorArgs); + rateLimiterProxyAddr = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); } rateLimiterProxy = EtherFiRateLimiter(rateLimiterProxyAddr); console2.log("Rate limiter proxy:", address(rateLimiterProxy)); - + // Initialize rateLimiterProxy.initialize(); console2.log(unicode"✓ Rate limiter deployed and initialized"); @@ -138,22 +128,12 @@ contract DeployPectraUpgradeCreate2 is Script { function deployImplementationsCreate2() internal { console2.log("=== STEP 2: DEPLOYING NEW IMPLEMENTATIONS (CREATE2) ==="); - + // StakingManager { string memory contractName = "StakingManager"; - bytes memory constructorArgs = abi.encode( - LIQUIDITY_POOL_PROXY, - ETHERFI_NODES_MANAGER_PROXY, - ETH_DEPOSIT_CONTRACT, - AUCTION_MANAGER, - ETHERFI_NODE_BEACON, - ROLE_REGISTRY - ); - bytes memory bytecode = abi.encodePacked( - type(StakingManager).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(LIQUIDITY_POOL_PROXY, ETHERFI_NODES_MANAGER_PROXY, ETH_DEPOSIT_CONTRACT, AUCTION_MANAGER, ETHERFI_NODE_BEACON, ROLE_REGISTRY); + bytes memory bytecode = abi.encodePacked(type(StakingManager).creationCode, constructorArgs); stakingManagerImpl = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); } @@ -165,27 +145,15 @@ contract DeployPectraUpgradeCreate2 is Script { ROLE_REGISTRY, address(rateLimiterProxy) // New rate limiter integration ); - bytes memory bytecode = abi.encodePacked( - type(EtherFiNodesManager).creationCode, - constructorArgs - ); + bytes memory bytecode = abi.encodePacked(type(EtherFiNodesManager).creationCode, constructorArgs); etherFiNodesManagerImpl = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); } // EtherFiNode { string memory contractName = "EtherFiNode"; - bytes memory constructorArgs = abi.encode( - LIQUIDITY_POOL_PROXY, - ETHERFI_NODES_MANAGER_PROXY, - EIGEN_POD_MANAGER, - DELEGATION_MANAGER, - ROLE_REGISTRY - ); - bytes memory bytecode = abi.encodePacked( - type(EtherFiNode).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(LIQUIDITY_POOL_PROXY, ETHERFI_NODES_MANAGER_PROXY, EIGEN_POD_MANAGER, DELEGATION_MANAGER, ROLE_REGISTRY); + bytes memory bytecode = abi.encodePacked(type(EtherFiNode).creationCode, constructorArgs); etherFiNodeImpl = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); } @@ -198,26 +166,17 @@ contract DeployPectraUpgradeCreate2 is Script { console2.log("GOVERNANCE TRANSACTION DATA"); console2.log("========================================"); console2.log(""); - + console2.log("=== CONTRACT UPGRADE TRANSACTIONS ==="); console2.log("Safe Address: 0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761 (timelock)"); console2.log(""); // Generate upgrade transaction data - bytes memory upgradeStakingManager = abi.encodeWithSelector( - bytes4(keccak256("upgradeTo(address)")), - stakingManagerImpl - ); - - bytes memory upgradeNodesManager = abi.encodeWithSelector( - bytes4(keccak256("upgradeTo(address)")), - etherFiNodesManagerImpl - ); - - bytes memory upgradeEtherFiNode = abi.encodeWithSelector( - StakingManager.upgradeEtherFiNode.selector, - etherFiNodeImpl - ); + bytes memory upgradeStakingManager = abi.encodeWithSelector(bytes4(keccak256("upgradeTo(address)")), stakingManagerImpl); + + bytes memory upgradeNodesManager = abi.encodeWithSelector(bytes4(keccak256("upgradeTo(address)")), etherFiNodesManagerImpl); + + bytes memory upgradeEtherFiNode = abi.encodeWithSelector(StakingManager.upgradeEtherFiNode.selector, etherFiNodeImpl); console2.log("Transaction 1 - Upgrade StakingManager:"); console2.log(" Target:", STAKING_MANAGER_PROXY); @@ -239,13 +198,13 @@ contract DeployPectraUpgradeCreate2 is Script { console2.log("New Contracts Deployed:"); console2.log("- EtherFiRateLimiter Proxy:", address(rateLimiterProxy)); console2.log(""); - + console2.log("New Implementations (Create2):"); console2.log("- StakingManager:", stakingManagerImpl); console2.log("- EtherFiNodesManager:", etherFiNodesManagerImpl); console2.log("- EtherFiNode:", etherFiNodeImpl); console2.log(""); - + console2.log("Updated JSON Files Needed:"); console2.log("Replace placeholder addresses in:"); console2.log("- phase2_contract_upgrades.json:"); @@ -256,14 +215,14 @@ contract DeployPectraUpgradeCreate2 is Script { console2.log("- phase4_rate_limiter_init.json:"); console2.log(" * RATE_LIMITER_PROXY_ADDRESS -> ", address(rateLimiterProxy)); console2.log(""); - + console2.log("New Features:"); console2.log(unicode"✓ EL-triggered exits"); console2.log(unicode"✓ Consolidation requests"); console2.log(unicode"✓ Rate limiting system"); console2.log(unicode"✓ User-specific call forwarding"); console2.log(""); - + console2.log("Next Steps:"); console2.log("1. Update JSON files with deployed addresses"); console2.log("2. Submit phase2_contract_upgrades.json to 3CP process"); @@ -272,43 +231,22 @@ contract DeployPectraUpgradeCreate2 is Script { } // === CREATE2 DEPLOYMENT HELPER (following DeployV3Prelude pattern) === - - function deployCreate2( - string memory contractName, - bytes memory constructorArgs, - bytes memory bytecode, - bytes32 salt, - bool logging - ) internal returns (address) { + + function deployCreate2(string memory contractName, bytes memory constructorArgs, bytes memory bytecode, bytes32 salt, bool logging) internal returns (address) { address predictedAddress = factory.computeAddress(salt, bytecode); address deployedAddress = factory.deploy(bytecode, salt); require(deployedAddress == predictedAddress, "Deployment address mismatch"); if (logging) { // Create JSON deployment log (exact same format as DeployV3Prelude) - string memory deployLog = string.concat( - "{\n", - ' "contractName": "', contractName, '",\n', - ' "deploymentParameters": {\n', - ' "factory": "', vm.toString(address(factory)), '",\n', - ' "salt": "', vm.toString(salt), '",\n', - formatConstructorArgs(constructorArgs, contractName), '\n', - ' },\n', - ' "deployedAddress": "', vm.toString(deployedAddress), '"\n', - "}" - ); + string memory deployLog = string.concat("{\n", ' "contractName": "', contractName, '",\n', ' "deploymentParameters": {\n', ' "factory": "', vm.toString(address(factory)), '",\n', ' "salt": "', vm.toString(salt), '",\n', formatConstructorArgs(constructorArgs, contractName), "\n", " },\n", ' "deployedAddress": "', vm.toString(deployedAddress), '"\n', "}"); // Save deployment log string memory root = vm.projectRoot(); string memory logFileDir = string.concat(root, "/deployment/", contractName); vm.createDir(logFileDir, true); - string memory logFileName = string.concat( - logFileDir, - "/", - getTimestampString(), - ".json" - ); + string memory logFileName = string.concat(logFileDir, "/", getTimestampString(), ".json"); vm.writeFile(logFileName, deployLog); // Console output @@ -329,11 +267,7 @@ contract DeployPectraUpgradeCreate2 is Script { // Constructor args formatting (same as DeployV3Prelude) //------------------------------------------------------------------------- - function formatConstructorArgs(bytes memory constructorArgs, string memory contractName) - internal - view - returns (string memory) - { + function formatConstructorArgs(bytes memory constructorArgs, string memory contractName) internal view returns (string memory) { // Load artifact JSON string memory artifactJson = readArtifact(contractName); @@ -361,11 +295,7 @@ contract DeployPectraUpgradeCreate2 is Script { return vm.readFile(path); } - function getConstructorMetadata(string memory artifactJson, uint256 inputCount) - internal - pure - returns (string[] memory, string[] memory) - { + function getConstructorMetadata(string memory artifactJson, uint256 inputCount) internal pure returns (string[] memory, string[] memory) { string[] memory names = new string[](inputCount); string[] memory typesArr = new string[](inputCount); @@ -377,15 +307,7 @@ contract DeployPectraUpgradeCreate2 is Script { return (names, typesArr); } - function decodeParamsJson( - bytes memory constructorArgs, - string[] memory names, - string[] memory typesArr - ) - internal - pure - returns (string memory) - { + function decodeParamsJson(bytes memory constructorArgs, string[] memory names, string[] memory typesArr) internal pure returns (string memory) { uint256 offset; string memory json = ' "constructorArgs": {\n'; @@ -393,11 +315,7 @@ contract DeployPectraUpgradeCreate2 is Script { (string memory val, uint256 newOffset) = decodeParam(constructorArgs, offset, typesArr[i]); offset = newOffset; - json = string.concat( - json, - ' "', names[i], '": "', val, '"', - (i < names.length - 1) ? ",\n" : "\n" - ); + json = string.concat(json, ' "', names[i], '": "', val, '"', (i < names.length - 1) ? ",\n" : "\n"); } return string.concat(json, " }"); } @@ -406,11 +324,7 @@ contract DeployPectraUpgradeCreate2 is Script { // Parameter decoding helpers (same as DeployV3Prelude) //------------------------------------------------------------------------- - function decodeParam(bytes memory data, uint256 offset, string memory t) - internal - pure - returns (string memory, uint256) - { + function decodeParam(bytes memory data, uint256 offset, string memory t) internal pure returns (string memory, uint256) { if (!isDynamicType(t)) { bytes memory chunk = slice(data, offset, 32); return (formatStaticParam(t, bytes32(chunk)), offset + 32); @@ -487,13 +401,13 @@ contract DeployPectraUpgradeCreate2 is Script { function getTimestampString() internal view returns (string memory) { uint256 ts = block.timestamp; - string memory year = vm.toString((ts / 31536000) + 1970); - string memory month = pad(vm.toString(((ts % 31536000) / 2592000) + 1)); - string memory day = pad(vm.toString(((ts % 2592000) / 86400) + 1)); - string memory hour = pad(vm.toString((ts % 86400) / 3600)); + string memory year = vm.toString((ts / 31_536_000) + 1970); + string memory month = pad(vm.toString(((ts % 31_536_000) / 2_592_000) + 1)); + string memory day = pad(vm.toString(((ts % 2_592_000) / 86_400) + 1)); + string memory hour = pad(vm.toString((ts % 86_400) / 3600)); string memory minute = pad(vm.toString((ts % 3600) / 60)); string memory second = pad(vm.toString(ts % 60)); - return string.concat(year,"-",month,"-",day,"-",hour,"-",minute,"-",second); + return string.concat(year, "-", month, "-", day, "-", hour, "-", minute, "-", second); } function pad(string memory n) internal pure returns (string memory) { @@ -504,16 +418,16 @@ contract DeployPectraUpgradeCreate2 is Script { function onlyUpgradeContracts() external { vm.startBroadcast(); console2.log("=== MANUAL CONTRACT UPGRADES ==="); - + IUpgradable(STAKING_MANAGER_PROXY).upgradeTo(stakingManagerImpl); console2.log(unicode"✓ StakingManager upgraded"); - + IUpgradable(ETHERFI_NODES_MANAGER_PROXY).upgradeTo(etherFiNodesManagerImpl); console2.log(unicode"✓ EtherFiNodesManager upgraded"); - + StakingManager(STAKING_MANAGER_PROXY).upgradeEtherFiNode(etherFiNodeImpl); console2.log(unicode"✓ EtherFiNode upgraded"); - + vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/script/el-exits/ELExitsTransactions.s.sol b/script/el-exits/ELExitsTransactions.s.sol index 8aa400c1f..25dc19e4e 100644 --- a/script/el-exits/ELExitsTransactions.s.sol +++ b/script/el-exits/ELExitsTransactions.s.sol @@ -1,68 +1,56 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "../../test/TestSetup.sol"; -import "../../src/EtherFiTimelock.sol"; +import "../../lib/openzeppelin-contracts/contracts/access/IAccessControl.sol"; +import "../../src/EETH.sol"; +import "../../src/EtherFiAdmin.sol"; import "../../src/EtherFiNode.sol"; import "../../src/EtherFiNodesManager.sol"; +import "../../src/EtherFiOracle.sol"; + +import "../../src/EtherFiRateLimiter.sol"; +import "../../src/EtherFiTimelock.sol"; import "../../src/LiquidityPool.sol"; +import "../../src/RoleRegistry.sol"; import "../../src/StakingManager.sol"; -import "../../src/EtherFiOracle.sol"; -import "../../src/EtherFiAdmin.sol"; -import "../../src/EETH.sol"; import "../../src/WeETH.sol"; -import "../../src/RoleRegistry.sol"; -import "../../src/EtherFiRateLimiter.sol"; -import "../../lib/openzeppelin-contracts/contracts/access/IAccessControl.sol"; +import "../../test/TestSetup.sol"; + import "forge-std/Script.sol"; import "forge-std/console2.sol"; contract ElExitsTransactions is Script { - EtherFiTimelock etherFiTimelock = - EtherFiTimelock(payable(0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761)); + EtherFiTimelock etherFiTimelock = EtherFiTimelock(payable(0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761)); EtherFiTimelock etherFiOperatingTimelock = EtherFiTimelock(payable(ETHERFI_NODES_MANAGER_ADMIN_ROLE)); //-------------------------------------------------------------------------------------- //--------------------- Previous Implementations --------------------------------------- //-------------------------------------------------------------------------------------- - address constant oldStakingManagerImpl = - 0x433d06fFc5EfE0e93daa22fcEF7eD60e65Bf70b4; - address constant oldEtherFiNodeImpl = - 0x5Dae50e686f7CB980E4d0c5E4492c56bC73eD9a2; - address constant oldEtherFiNodesManagerImpl = - 0x158B21148E86470E2075926EbD5528Af2D510cAF; + address constant oldStakingManagerImpl = 0x433d06fFc5EfE0e93daa22fcEF7eD60e65Bf70b4; + address constant oldEtherFiNodeImpl = 0x5Dae50e686f7CB980E4d0c5E4492c56bC73eD9a2; + address constant oldEtherFiNodesManagerImpl = 0x158B21148E86470E2075926EbD5528Af2D510cAF; //-------------------------------------------------------------------------------------- //---------------------------- New Deployments ----------------------------------------- //-------------------------------------------------------------------------------------- - address constant etherFiRateLimiterImpl = - 0x1dd43C32f03f8A74b8160926D559d34358880A89; - address constant etherFiRateLimiterProxy = - 0x6C7c54cfC2225fA985cD25F04d923B93c60a02F8; - address constant stakingManagerImpl = - 0xa38d03ea42F8bc31892336E1F42523e94FB91a7A; - address constant etherFiNodeImpl = - 0x6268728c52aAa4EC670F5fcdf152B50c4B463472; - address constant etherFiNodesManagerImpl = - 0x0f366dF7af5003fC7C6524665ca58bDeAdDC3745; + address constant etherFiRateLimiterImpl = 0x1dd43C32f03f8A74b8160926D559d34358880A89; + address constant etherFiRateLimiterProxy = 0x6C7c54cfC2225fA985cD25F04d923B93c60a02F8; + address constant stakingManagerImpl = 0xa38d03ea42F8bc31892336E1F42523e94FB91a7A; + address constant etherFiNodeImpl = 0x6268728c52aAa4EC670F5fcdf152B50c4B463472; + address constant etherFiNodesManagerImpl = 0x0f366dF7af5003fC7C6524665ca58bDeAdDC3745; //-------------------------------------------------------------------------------------- //------------------------- Existing Users/Proxies ------------------------------------- //-------------------------------------------------------------------------------------- - address constant etherFiNodesManager = - 0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F; - address constant stakingManager = - 0x25e821b7197B146F7713C3b89B6A4D83516B912d; + address constant etherFiNodesManager = 0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F; + address constant stakingManager = 0x25e821b7197B146F7713C3b89B6A4D83516B912d; address constant roleRegistry = 0x62247D29B4B9BECf4BB73E0c722cf6445cfC7cE9; - address constant ETHERFI_OPERATING_ADMIN = - 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC; + address constant ETHERFI_OPERATING_ADMIN = 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC; address constant POD_PROVER = 0x7835fB36A8143a014A2c381363cD1A4DeE586d2A; - address constant EL_TRIGGER_EXITER = - 0x12582A27E5e19492b4FcD194a60F8f5e1aa31B0F; + address constant EL_TRIGGER_EXITER = 0x12582A27E5e19492b4FcD194a60F8f5e1aa31B0F; - address constant ETHERFI_NODES_MANAGER_ADMIN_ROLE = - 0xcD425f44758a08BaAB3C4908f3e3dE5776e45d7a; // Operating Timelock + address constant ETHERFI_NODES_MANAGER_ADMIN_ROLE = 0xcD425f44758a08BaAB3C4908f3e3dE5776e45d7a; // Operating Timelock address constant TIMELOCK_CONTROLLER = 0xcdd57D11476c22d265722F68390b036f3DA48c21; @@ -70,21 +58,13 @@ contract ElExitsTransactions is Script { //------------------------------------- ROLES ---------------------------------------- //-------------------------------------------------------------------------------------- - bytes32 ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE = - EtherFiNodesManager(payable(etherFiNodesManagerImpl)) - .ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(); + bytes32 ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE = EtherFiNodesManager(payable(etherFiNodesManagerImpl)).ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(); - bytes32 ETHERFI_NODES_MANAGER_POD_PROVER_ROLE = - EtherFiNodesManager(payable(etherFiNodesManagerImpl)) - .ETHERFI_NODES_MANAGER_POD_PROVER_ROLE(); + bytes32 ETHERFI_NODES_MANAGER_POD_PROVER_ROLE = EtherFiNodesManager(payable(etherFiNodesManagerImpl)).ETHERFI_NODES_MANAGER_POD_PROVER_ROLE(); - bytes32 STAKING_MANAGER_ADMIN_ROLE = - StakingManager(payable(stakingManagerImpl)) - .STAKING_MANAGER_ADMIN_ROLE(); + bytes32 STAKING_MANAGER_ADMIN_ROLE = StakingManager(payable(stakingManagerImpl)).STAKING_MANAGER_ADMIN_ROLE(); - bytes32 ETHERFI_RATE_LIMITER_ADMIN_ROLE = - EtherFiRateLimiter(payable(etherFiRateLimiterImpl)) - .ETHERFI_RATE_LIMITER_ADMIN_ROLE(); + bytes32 ETHERFI_RATE_LIMITER_ADMIN_ROLE = EtherFiRateLimiter(payable(etherFiRateLimiterImpl)).ETHERFI_RATE_LIMITER_ADMIN_ROLE(); //-------------------------------------------------------------------------------------- //------------------------------- SELECTORS --------------------------------------- @@ -95,8 +75,8 @@ contract ElExitsTransactions is Script { // cast sig "updateAllowedForwardedEigenpodCalls(bytes4,bool)" bytes4 UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR = 0x4cba6c74; - uint256 MIN_DELAY_OPERATING_TIMELOCK = 28800; // 8 hours - uint256 MIN_DELAY_TIMELOCK = 259200; // 72 hours + uint256 MIN_DELAY_OPERATING_TIMELOCK = 28_800; // 8 hours + uint256 MIN_DELAY_TIMELOCK = 259_200; // 72 hours // External calls selectors bytes4 UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_ONE = 0x9a15bf92; @@ -118,7 +98,6 @@ contract ElExitsTransactions is Script { bytes4 UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SIX = 0x0dd8dd02; bytes4 UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SEVEN = 0x9435bb43; - //-------------------------------------------------------------------------------------- //--------------------------------- POST UPGRADE RELATED STUFF ----------------------- //-------------------------------------------------------------------------------------- @@ -126,13 +105,9 @@ contract ElExitsTransactions is Script { //-------------------------------------------------------------------------------------- //--------------------------------- LIMIT IDS ---------------------------------------- //-------------------------------------------------------------------------------------- - bytes32 UNRESTAKING_LIMIT_ID = - EtherFiNodesManager(payable(etherFiNodesManagerImpl)) - .UNRESTAKING_LIMIT_ID(); + bytes32 UNRESTAKING_LIMIT_ID = EtherFiNodesManager(payable(etherFiNodesManagerImpl)).UNRESTAKING_LIMIT_ID(); - bytes32 EXIT_REQUEST_LIMIT_ID = - EtherFiNodesManager(payable(etherFiNodesManagerImpl)) - .EXIT_REQUEST_LIMIT_ID(); + bytes32 EXIT_REQUEST_LIMIT_ID = EtherFiNodesManager(payable(etherFiNodesManagerImpl)).EXIT_REQUEST_LIMIT_ID(); uint64 CAPACITY_RATE_LIMITER = 100_000_000_000_000; uint64 REFILL_RATE_LIMITER = 2_000_000_000; @@ -141,7 +116,7 @@ contract ElExitsTransactions is Script { //--------------------------------- SELECTORS ---------------------------------------- //-------------------------------------------------------------------------------------- - /* + /* External forwarded calls // ------------------------------------------------------------------------------------------------ King rewards claiming from eigen @@ -265,22 +240,10 @@ contract ElExitsTransactions is Script { //-------------------------------------------------------------------------------------- // etherFiNode - data[0] = _encodeRoleGrant( - ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE, - EL_TRIGGER_EXITER - ); - data[1] = _encodeRoleGrant( - ETHERFI_NODES_MANAGER_POD_PROVER_ROLE, - POD_PROVER - ); - data[2] = _encodeRoleGrant( - STAKING_MANAGER_ADMIN_ROLE, - ETHERFI_OPERATING_ADMIN - ); - data[3] = _encodeRoleGrant( - ETHERFI_RATE_LIMITER_ADMIN_ROLE, - ETHERFI_OPERATING_ADMIN - ); + data[0] = _encodeRoleGrant(ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE, EL_TRIGGER_EXITER); + data[1] = _encodeRoleGrant(ETHERFI_NODES_MANAGER_POD_PROVER_ROLE, POD_PROVER); + data[2] = _encodeRoleGrant(STAKING_MANAGER_ADMIN_ROLE, ETHERFI_OPERATING_ADMIN); + data[3] = _encodeRoleGrant(ETHERFI_RATE_LIMITER_ADMIN_ROLE, ETHERFI_OPERATING_ADMIN); for (uint256 i = 0; i < 4; i++) { targets[i] = address(roleRegistry); @@ -291,33 +254,22 @@ contract ElExitsTransactions is Script { //-------------------------------------------------------------------------------------- targets[4] = address(stakingManager); - data[4] = abi.encodeWithSelector( - UUPSUpgradeable.upgradeTo.selector, - stakingManagerImpl - ); + data[4] = abi.encodeWithSelector(UUPSUpgradeable.upgradeTo.selector, stakingManagerImpl); targets[5] = address(etherFiNodesManager); - data[5] = abi.encodeWithSelector( - UUPSUpgradeable.upgradeTo.selector, - etherFiNodesManagerImpl - ); + data[5] = abi.encodeWithSelector(UUPSUpgradeable.upgradeTo.selector, etherFiNodesManagerImpl); //-------------------------------------------------------------------------------------- //------------------------------- ETHERFI NODE UPGRADE ----------------------------------- //-------------------------------------------------------------------------------------- targets[6] = address(stakingManager); - data[6] = abi.encodeWithSelector( - StakingManager.upgradeEtherFiNode.selector, - etherFiNodeImpl - ); + data[6] = abi.encodeWithSelector(StakingManager.upgradeEtherFiNode.selector, etherFiNodeImpl); //-------------------------------------------------------------------------------------- //------------------------------- SCHEDULE TX ----------------------------------- //-------------------------------------------------------------------------------------- - bytes32 timelockSalt = keccak256( - abi.encode(targets, data, block.number) - ); + bytes32 timelockSalt = keccak256(abi.encode(targets, data, block.number)); bytes memory scheduleCalldata = abi.encodeWithSelector( etherFiTimelock.scheduleBatch.selector, targets, @@ -366,126 +318,53 @@ contract ElExitsTransactions is Script { // -------------------------- Whitelisted External Calls -------------------------- targets[0] = address(etherFiNodesManager); - data[0] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_ONE, - 0x035bdAeaB85E47710C27EdA7FD754bA80aD4ad02, - false - ); + data[0] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_ONE, 0x035bdAeaB85E47710C27EdA7FD754bA80aD4ad02, false); targets[1] = address(etherFiNodesManager); - data[1] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_TWO, - 0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83, - false - ); + data[1] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_TWO, 0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83, false); targets[2] = address(etherFiNodesManager); - data[2] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_THREE, - 0x7750d328b314EfFa365A0402CcfD489B80B0adda, - false - ); + data[2] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_THREE, 0x7750d328b314EfFa365A0402CcfD489B80B0adda, false); targets[3] = address(etherFiNodesManager); - data[3] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_FOUR, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - false - ); + data[3] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_FOUR, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, false); targets[4] = address(etherFiNodesManager); - data[4] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_FIVE, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - false - ); + data[4] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_FIVE, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, false); targets[5] = address(etherFiNodesManager); - data[5] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_SIX, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - false - ); + data[5] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_SIX, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, false); targets[6] = address(etherFiNodesManager); - data[6] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_SEVEN, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - false - ); + data[6] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_SEVEN, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, false); targets[7] = address(etherFiNodesManager); - data[7] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_EIGHT, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - false - ); + data[7] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_EIGHT, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, false); targets[8] = address(etherFiNodesManager); - data[8] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_NINE, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - false - ); + data[8] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_NINE, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, false); // -------------------------- Whitelisted Eigenpod Calls -------------------------- targets[9] = address(etherFiNodesManager); - data[9] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_ONE, - false - ); + data[9] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_ONE, false); targets[10] = address(etherFiNodesManager); - data[10] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_TWO, - false - ); + data[10] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_TWO, false); targets[11] = address(etherFiNodesManager); - data[11] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_THREE, - false - ); + data[11] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_THREE, false); targets[12] = address(etherFiNodesManager); - data[12] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_FOUR, - false - ); + data[12] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_FOUR, false); targets[13] = address(etherFiNodesManager); - data[13] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_FIVE, - false - ); + data[13] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_FIVE, false); targets[14] = address(etherFiNodesManager); - data[14] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SIX, - false - ); + data[14] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SIX, false); targets[15] = address(etherFiNodesManager); - data[15] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SEVEN, - false - ); + data[15] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SEVEN, false); // schedule bytes32 timelockSalt = keccak256(abi.encode(targets, data, block.number)); @@ -617,16 +496,12 @@ contract ElExitsTransactions is Script { // uncomment to run against fork // StakingManager(payable(stakingManager)).backfillExistingEtherFiNodes(etherFiNodes); - + address[] memory targets = new address[](1); bytes[] memory data = new bytes[](1); targets[0] = address(stakingManager); - data[0] = abi.encodeWithSelector( - StakingManager.backfillExistingEtherFiNodes.selector, - etherFiNodes - ); - + data[0] = abi.encodeWithSelector(StakingManager.backfillExistingEtherFiNodes.selector, etherFiNodes); console2.log("target: ", targets[0]); console2.log("data: "); @@ -649,30 +524,10 @@ contract ElExitsTransactions is Script { bytes[] memory data = new bytes[](4); uint256[] memory values = new uint256[](4); // Default to 0 - data[0] = abi.encodeWithSelector( - EtherFiRateLimiter.createNewLimiter.selector, - UNRESTAKING_LIMIT_ID, - CAPACITY_RATE_LIMITER, - REFILL_RATE_LIMITER - ); - data[1] = abi.encodeWithSelector( - EtherFiRateLimiter.createNewLimiter.selector, - EXIT_REQUEST_LIMIT_ID, - CAPACITY_RATE_LIMITER, - REFILL_RATE_LIMITER - ); - data[2] = abi.encodeWithSelector( - EtherFiRateLimiter.updateConsumers.selector, - UNRESTAKING_LIMIT_ID, - address(etherFiNodesManager), - true - ); - data[3] = abi.encodeWithSelector( - EtherFiRateLimiter.updateConsumers.selector, - EXIT_REQUEST_LIMIT_ID, - address(etherFiNodesManager), - true - ); + data[0] = abi.encodeWithSelector(EtherFiRateLimiter.createNewLimiter.selector, UNRESTAKING_LIMIT_ID, CAPACITY_RATE_LIMITER, REFILL_RATE_LIMITER); + data[1] = abi.encodeWithSelector(EtherFiRateLimiter.createNewLimiter.selector, EXIT_REQUEST_LIMIT_ID, CAPACITY_RATE_LIMITER, REFILL_RATE_LIMITER); + data[2] = abi.encodeWithSelector(EtherFiRateLimiter.updateConsumers.selector, UNRESTAKING_LIMIT_ID, address(etherFiNodesManager), true); + data[3] = abi.encodeWithSelector(EtherFiRateLimiter.updateConsumers.selector, EXIT_REQUEST_LIMIT_ID, address(etherFiNodesManager), true); for (uint256 i = 0; i < 4; i++) { console2.log("====== Execute Set Up EtherFiRateLimiter Tx:", i); @@ -788,27 +643,16 @@ contract ElExitsTransactions is Script { //-------------------------------------------------------------------------------------- targets[0] = address(stakingManager); - data[0] = abi.encodeWithSelector( - UUPSUpgradeable.upgradeTo.selector, - oldStakingManagerImpl - ); + data[0] = abi.encodeWithSelector(UUPSUpgradeable.upgradeTo.selector, oldStakingManagerImpl); targets[1] = address(etherFiNodesManager); - data[1] = abi.encodeWithSelector( - UUPSUpgradeable.upgradeTo.selector, - oldEtherFiNodesManagerImpl - ); + data[1] = abi.encodeWithSelector(UUPSUpgradeable.upgradeTo.selector, oldEtherFiNodesManagerImpl); targets[2] = address(stakingManager); - data[2] = abi.encodeWithSelector( - StakingManager.upgradeEtherFiNode.selector, - oldEtherFiNodeImpl - ); + data[2] = abi.encodeWithSelector(StakingManager.upgradeEtherFiNode.selector, oldEtherFiNodeImpl); // schedule - bytes32 timelockSalt = keccak256( - abi.encode(targets, data, block.number) - ); + bytes32 timelockSalt = keccak256(abi.encode(targets, data, block.number)); bytes memory scheduleCalldata = abi.encodeWithSelector( etherFiTimelock.scheduleBatch.selector, targets, @@ -858,126 +702,53 @@ contract ElExitsTransactions is Script { // -------------------------- Whitelisted External Calls -------------------------- targets[0] = address(etherFiNodesManager); - data[0] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_ONE, - 0x035bdAeaB85E47710C27EdA7FD754bA80aD4ad02, - true - ); + data[0] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_ONE, 0x035bdAeaB85E47710C27EdA7FD754bA80aD4ad02, true); targets[1] = address(etherFiNodesManager); - data[1] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_TWO, - 0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83, - true - ); + data[1] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_TWO, 0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83, true); targets[2] = address(etherFiNodesManager); - data[2] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_THREE, - 0x7750d328b314EfFa365A0402CcfD489B80B0adda, - true - ); + data[2] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_THREE, 0x7750d328b314EfFa365A0402CcfD489B80B0adda, true); targets[3] = address(etherFiNodesManager); - data[3] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_FOUR, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - true - ); + data[3] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_FOUR, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, true); targets[4] = address(etherFiNodesManager); - data[4] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_FIVE, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - true - ); + data[4] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_FIVE, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, true); targets[5] = address(etherFiNodesManager); - data[5] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_SIX, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - true - ); + data[5] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_SIX, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, true); targets[6] = address(etherFiNodesManager); - data[6] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_SEVEN, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - true - ); + data[6] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_SEVEN, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, true); targets[7] = address(etherFiNodesManager); - data[7] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_EIGHT, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - true - ); + data[7] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_EIGHT, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, true); targets[8] = address(etherFiNodesManager); - data[8] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_NINE, - 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, - true - ); + data[8] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EXTERNAL_CALLS_SELECTOR_NINE, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A, true); // -------------------------- Whitelisted Eigenpod Calls -------------------------- targets[9] = address(etherFiNodesManager); - data[9] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_ONE, - true - ); + data[9] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_ONE, true); targets[10] = address(etherFiNodesManager); - data[10] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_TWO, - true - ); + data[10] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_TWO, true); targets[11] = address(etherFiNodesManager); - data[11] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_THREE, - true - ); + data[11] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_THREE, true); targets[12] = address(etherFiNodesManager); - data[12] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_FOUR, - true - ); + data[12] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_FOUR, true); targets[13] = address(etherFiNodesManager); - data[13] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_FIVE, - true - ); + data[13] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_FIVE, true); targets[14] = address(etherFiNodesManager); - data[14] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SIX, - true - ); + data[14] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SIX, true); targets[15] = address(etherFiNodesManager); - data[15] = abi.encodeWithSelector( - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, - UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SEVEN, - true - ); + data[15] = abi.encodeWithSelector(UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR, UPDATE_ALLOWED_FORWARDED_EIGENPOD_CALLS_SELECTOR_SEVEN, true); // schedule bytes32 timelockSalt = keccak256(abi.encode(targets, data, block.number)); @@ -1024,16 +795,8 @@ contract ElExitsTransactions is Script { //------------------------------- HELPER FUNCTIONS ----------------------------------- //-------------------------------------------------------------------------------------- - function _encodeRoleGrant( - bytes32 role, - address account - ) internal pure returns (bytes memory) { - return - abi.encodeWithSelector( - RoleRegistry.grantRole.selector, - role, - account - ); + function _encodeRoleGrant(bytes32 role, address account) internal pure returns (bytes memory) { + return abi.encodeWithSelector(RoleRegistry.grantRole.selector, role, account); } function _getEtherFiNodes() internal pure returns (address[] memory etherFiNodes) { diff --git a/script/el-exits/PectraUpgradeBytecode.s.sol b/script/el-exits/PectraUpgradeBytecode.s.sol index 4b9549fb0..48494c6d6 100644 --- a/script/el-exits/PectraUpgradeBytecode.s.sol +++ b/script/el-exits/PectraUpgradeBytecode.s.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "forge-std/Script.sol"; -import "forge-std/console2.sol"; -import "../ContractCodeChecker.sol"; import "../../src/EtherFiNode.sol"; import "../../src/EtherFiNodesManager.sol"; -import "../../src/StakingManager.sol"; -import "../../src/EtherFiRateLimiter.sol"; +import "../../src/EtherFiRateLimiter.sol"; +import "../../src/StakingManager.sol"; +import "../ContractCodeChecker.sol"; +import "forge-std/Script.sol"; +import "forge-std/console2.sol"; contract PectraUpgradeBytecode is Script { ContractCodeChecker public contractCodeChecker; - address public stakingManagerProxy; + address public stakingManagerProxy; address public etherFiNodesManagerProxy; address public roleRegistryProxy; address public rateLimiterProxy; @@ -21,7 +21,7 @@ contract PectraUpgradeBytecode is Script { address public etherFiNodeBeacon; address public delegationManager; address public eigenPodManager; - address public stakingDepositContract; + address public stakingDepositContract; address public deployedRateLimiter; @@ -38,7 +38,6 @@ contract PectraUpgradeBytecode is Script { eigenPodManager = 0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338; stakingDepositContract = 0x00000000219ab540356cBB839Cbe05303d7705Fa; deployedRateLimiter = 0x1dd43C32f03f8A74b8160926D559d34358880A89; - } // Run Script: diff --git a/script/el-exits/VerifyPectraUpgradeDeployment.s.sol b/script/el-exits/VerifyPectraUpgradeDeployment.s.sol index 50bf5d64e..9a6d0c047 100644 --- a/script/el-exits/VerifyPectraUpgradeDeployment.s.sol +++ b/script/el-exits/VerifyPectraUpgradeDeployment.s.sol @@ -4,11 +4,12 @@ pragma solidity ^0.8.27; import "forge-std/Script.sol"; import "forge-std/console2.sol"; +import "../../src/EtherFiNode.sol"; import "../../src/EtherFiNodesManager.sol"; import "../../src/EtherFiRateLimiter.sol"; -import "../../src/StakingManager.sol"; import "../../src/RoleRegistry.sol"; -import "../../src/EtherFiNode.sol"; +import "../../src/StakingManager.sol"; + import "../../src/UUPSProxy.sol"; interface ICreate2Factory { @@ -19,7 +20,7 @@ interface ICreate2Factory { * @title VerifyPectraUpgradeDeployment * @notice Verification script to check EIP-7002 deployment status * @dev Run after deployment to verify all components are properly configured - * + * * Usage: forge script script/el-exits/VerifyPectraUpgradeDeployment.s.sol --rpc-url */ contract VerifyPectraUpgradeDeployment is Script { @@ -49,11 +50,9 @@ contract VerifyPectraUpgradeDeployment is Script { // === ROLE ADDRESSES === // address constant ETHERFI_ADMIN_EXECUTER = 0x12582A27E5e19492b4FcD194a60F8f5e1aa31B0F; address constant ETHERFI_ADMIN = 0xcD425f44758a08BaAB3C4908f3e3dE5776e45d7a; - address constant ETHERFI_OPERATING_ADMIN = - 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC; + address constant ETHERFI_OPERATING_ADMIN = 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC; address constant POD_PROVER = 0x7835fB36A8143a014A2c381363cD1A4DeE586d2A; - address constant EL_TRIGGER_EXITER = - 0x12582A27E5e19492b4FcD194a60F8f5e1aa31B0F; + address constant EL_TRIGGER_EXITER = 0x12582A27E5e19492b4FcD194a60F8f5e1aa31B0F; function run() external { console2.log("========================================"); @@ -69,7 +68,7 @@ contract VerifyPectraUpgradeDeployment is Script { printVerificationSummary(); } - + function verifyAddress() internal { console2.log("=== VERIFYING ADDRESS ==="); console2.log("ETHERFI_NODES_MANAGER_PROXY:", ETHERFI_NODES_MANAGER_PROXY); @@ -83,21 +82,11 @@ contract VerifyPectraUpgradeDeployment is Script { address etherFiNodesManagerImpl; address etherFiNodeImpl; - // StakingManager + // StakingManager { string memory contractName = "StakingManager"; - bytes memory constructorArgs = abi.encode( - LIQUIDITY_POOL_PROXY, - ETHERFI_NODES_MANAGER_PROXY, - ETH_DEPOSIT_CONTRACT, - AUCTION_MANAGER, - ETHERFI_NODE_BEACON, - ROLE_REGISTRY - ); - bytes memory bytecode = abi.encodePacked( - type(StakingManager).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(LIQUIDITY_POOL_PROXY, ETHERFI_NODES_MANAGER_PROXY, ETH_DEPOSIT_CONTRACT, AUCTION_MANAGER, ETHERFI_NODE_BEACON, ROLE_REGISTRY); + bytes memory bytecode = abi.encodePacked(type(StakingManager).creationCode, constructorArgs); stakingManagerImpl = verifyCreate2Address(contractName, constructorArgs, bytecode, commitHashSalt, true); // stakingManagerImpl = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); } @@ -110,10 +99,7 @@ contract VerifyPectraUpgradeDeployment is Script { ROLE_REGISTRY, address(RATE_LIMITER_PROXY) // New rate limiter integration ); - bytes memory bytecode = abi.encodePacked( - type(EtherFiNodesManager).creationCode, - constructorArgs - ); + bytes memory bytecode = abi.encodePacked(type(EtherFiNodesManager).creationCode, constructorArgs); etherFiNodesManagerImpl = verifyCreate2Address(contractName, constructorArgs, bytecode, commitHashSalt, true); // etherFiNodesManagerImpl = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); } @@ -121,17 +107,8 @@ contract VerifyPectraUpgradeDeployment is Script { // EtherFiNode { string memory contractName = "EtherFiNode"; - bytes memory constructorArgs = abi.encode( - LIQUIDITY_POOL_PROXY, - ETHERFI_NODES_MANAGER_PROXY, - EIGEN_POD_MANAGER, - DELEGATION_MANAGER, - ROLE_REGISTRY - ); - bytes memory bytecode = abi.encodePacked( - type(EtherFiNode).creationCode, - constructorArgs - ); + bytes memory constructorArgs = abi.encode(LIQUIDITY_POOL_PROXY, ETHERFI_NODES_MANAGER_PROXY, EIGEN_POD_MANAGER, DELEGATION_MANAGER, ROLE_REGISTRY); + bytes memory bytecode = abi.encodePacked(type(EtherFiNode).creationCode, constructorArgs); etherFiNodeImpl = verifyCreate2Address(contractName, constructorArgs, bytecode, commitHashSalt, true); // etherFiNodeImpl = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); } @@ -141,10 +118,7 @@ contract VerifyPectraUpgradeDeployment is Script { { string memory contractName = "EtherFiRateLimiter"; bytes memory constructorArgs = abi.encode(ROLE_REGISTRY); - bytes memory bytecode = abi.encodePacked( - type(EtherFiRateLimiter).creationCode, - constructorArgs - ); + bytes memory bytecode = abi.encodePacked(type(EtherFiRateLimiter).creationCode, constructorArgs); rateLimiterImpl = verifyCreate2Address(contractName, constructorArgs, bytecode, commitHashSalt, true); // rateLimiterImpl = deployCreate2(contractName, constructorArgs, bytecode, commitHashSalt, true); console2.log("Rate limiter implementation:", rateLimiterImpl); @@ -153,19 +127,10 @@ contract VerifyPectraUpgradeDeployment is Script { address rateLimiterProxyAddr; // Deploy proxy using Create2Factory { - string memory contractName = "UUPSProxy"; - bytes memory constructorArgs = abi.encode(address(rateLimiterImpl), ""); - bytes memory bytecode = abi.encodePacked( - type(UUPSProxy).creationCode, - constructorArgs - ); - rateLimiterProxyAddr = verifyCreate2Address( - contractName, - constructorArgs, - bytecode, - commitHashSalt, - true - ); + string memory contractName = "UUPSProxy"; + bytes memory constructorArgs = abi.encode(address(rateLimiterImpl), ""); + bytes memory bytecode = abi.encodePacked(type(UUPSProxy).creationCode, constructorArgs); + rateLimiterProxyAddr = verifyCreate2Address(contractName, constructorArgs, bytecode, commitHashSalt, true); } console2.log(""); @@ -316,7 +281,7 @@ contract VerifyPectraUpgradeDeployment is Script { console2.log("VERIFICATION SUMMARY"); console2.log("========================================"); console2.log(""); - + console2.log("Verified Components:"); console2.log(unicode"✓ Contract upgrade verification"); console2.log(unicode"✓ Role assignment verification"); @@ -327,7 +292,7 @@ contract VerifyPectraUpgradeDeployment is Script { } console2.log(unicode"✓ New functionality availability verification"); console2.log(""); - + console2.log("Key Addresses Verified:"); console2.log("- StakingManager Proxy:", STAKING_MANAGER_PROXY); console2.log("- EtherFiNodesManager Proxy:", ETHERFI_NODES_MANAGER_PROXY); @@ -336,12 +301,12 @@ contract VerifyPectraUpgradeDeployment is Script { console2.log("- EtherFiRateLimiter:", RATE_LIMITER_PROXY); } console2.log(""); - + console2.log("Key Role Holders:"); console2.log("- EL Exit Trigger:", EL_TRIGGER_EXITER); console2.log("- Rate Limiter Admin:", ETHERFI_OPERATING_ADMIN); console2.log(""); - + console2.log("Manual Testing Recommendations:"); console2.log("1. Test EL-triggered withdrawal with proper role"); console2.log("2. Test consolidation request functionality"); @@ -349,7 +314,7 @@ contract VerifyPectraUpgradeDeployment is Script { console2.log("4. Test user-specific call forwarding permissions"); console2.log("5. Verify old whitelist mappings are cleared"); console2.log(""); - + console2.log(unicode"✓ EIP-7002 deployment verification complete!"); } @@ -357,7 +322,7 @@ contract VerifyPectraUpgradeDeployment is Script { function checkRateLimiterOnly(address _rateLimiterAddress) external view { console2.log("=== RATE LIMITER SPOT CHECK ==="); console2.log("Rate Limiter Address:", _rateLimiterAddress); - + EtherFiRateLimiter rateLimiter = EtherFiRateLimiter(_rateLimiterAddress); EtherFiNodesManager nodesManager = EtherFiNodesManager(payable(ETHERFI_NODES_MANAGER_PROXY)); @@ -382,15 +347,9 @@ contract VerifyPectraUpgradeDeployment is Script { } } - // Helper function to verify Create2 address - function verifyCreate2Address( - string memory contractName, - bytes memory constructorArgs, - bytes memory bytecode, - bytes32 salt, - bool logging - ) internal view returns (address) { + // Helper function to verify Create2 address + function verifyCreate2Address(string memory contractName, bytes memory constructorArgs, bytes memory bytecode, bytes32 salt, bool logging) internal view returns (address) { address predictedAddress = factory.computeAddress(salt, bytecode); return predictedAddress; } -} \ No newline at end of file +} diff --git a/script/el-exits/forwarding-scripts/CleanupOldWhitelist.s.sol b/script/el-exits/forwarding-scripts/CleanupOldWhitelist.s.sol index 78fbff689..af7cb6ef7 100644 --- a/script/el-exits/forwarding-scripts/CleanupOldWhitelist.s.sol +++ b/script/el-exits/forwarding-scripts/CleanupOldWhitelist.s.sol @@ -22,7 +22,6 @@ interface ICurrentEtherFiNodesManager { * Run the discovery script first to identify what needs to be cleared */ contract CleanupOldWhitelist is Script { - ICurrentEtherFiNodesManager constant nodesManager = ICurrentEtherFiNodesManager(0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F); function run() external { @@ -52,7 +51,7 @@ contract CleanupOldWhitelist is Script { clearEigenPodCall(0x0dd8dd02); // Replace with the found selector clearEigenPodCall(0x88676cad); // Replace with the found selector - // Clear External calls that were found whitelisted + // Clear External calls that were found whitelisted // Update these based on actual discovery script results clearExternalCall(0x3ccc861d, 0x7750d328b314EfFa365A0402CcfD489B80B0adda); // processClaim on RewardsCoordinator clearExternalCall(0x0dd8dd02, 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A); // on DelegationManager @@ -106,7 +105,7 @@ contract CleanupOldWhitelist is Script { console2.log("Check admin permissions and rerun cleanup if needed"); } } - + // Helper function to clear specific items manually if needed function clearSpecific(bytes4 eigenPodSelector, bytes4 externalSelector, address target) external { vm.startBroadcast(); @@ -125,4 +124,4 @@ contract CleanupOldWhitelist is Script { vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/script/el-exits/forwarding-scripts/DiscoverCurrentWhitelist.s.sol b/script/el-exits/forwarding-scripts/DiscoverCurrentWhitelist.s.sol index da8bab23c..2b7cf2042 100644 --- a/script/el-exits/forwarding-scripts/DiscoverCurrentWhitelist.s.sol +++ b/script/el-exits/forwarding-scripts/DiscoverCurrentWhitelist.s.sol @@ -14,7 +14,6 @@ interface ICurrentEtherFiNodesManager { * @notice Discover what's ACTUALLY whitelisted in the current (pre-upgrade) contract */ contract DiscoverCurrentWhitelist is Script { - ICurrentEtherFiNodesManager constant nodesManager = ICurrentEtherFiNodesManager(0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F); function run() external view { @@ -95,7 +94,7 @@ contract DiscoverCurrentWhitelist is Script { selectors[10] = bytes4(keccak256("claimRewards(address,address)")); selectors[11] = bytes4(keccak256("submitRoot(bytes32,uint32)")); - // DelegationManager functions + // DelegationManager functions selectors[12] = bytes4(keccak256("delegate(address)")); selectors[13] = bytes4(keccak256("undelegate()")); selectors[14] = bytes4(keccak256("queueWithdrawals((address[],uint256[],address)[])")); @@ -124,7 +123,7 @@ contract DiscoverCurrentWhitelist is Script { targets[5] = 0x308861A430be4cce5502d0A12724771Fc6DaF216; // EtherFi LiquidityPool targets[6] = 0x25e821b7197B146F7713C3b89B6A4D83516B912d; // EtherFi StakingManager targets[7] = 0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F; // EtherFi NodesManager - + return targets; } @@ -132,4 +131,4 @@ contract DiscoverCurrentWhitelist is Script { function checkSpecific(bytes4 selector, address target) external view returns (bool) { return nodesManager.allowedForwardedExternalCalls(selector, target); } -} \ No newline at end of file +} diff --git a/script/hoodi/SetRole.s.sol b/script/hoodi/SetRole.s.sol index dcfd08ecc..4ced1f72f 100644 --- a/script/hoodi/SetRole.s.sol +++ b/script/hoodi/SetRole.s.sol @@ -1,22 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; +import "../../src/interfaces/IRoleRegistry.sol"; import "forge-std/Script.sol"; import "forge-std/console.sol"; -import "../../src/interfaces/IRoleRegistry.sol"; /** * @title Set Role Script * @notice Script for granting or revoking roles in the EtherFi protocol - * + * * Notice: Ensure to set ENV vars for action, roleName, and address before running and add --private-key $PRIVATE_KEY of admin(found in 1Password) - * + * * This script allows you to: * 1. Grant a role to an address * 2. Revoke a role from an address * 3. Check if an address has a role * 4. List all addresses with a specific role - * + * * Available roles: * - PROTOCOL_PAUSER: Can pause protocol contracts * - PROTOCOL_UNPAUSER: Can unpause protocol contracts @@ -39,25 +39,25 @@ import "../../src/interfaces/IRoleRegistry.sol"; * - ETHERFI_NODE_EIGENLAYER_ADMIN_ROLE: EigenLayer admin for individual nodes * - ETHERFI_NODE_CALL_FORWARDER_ROLE: Call forwarder for individual nodes * - ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE: Executes Execution Layer Withdrawals - * + * * Usage Examples: - * + * * 1. Grant PROTOCOL_PAUSER role: * ROLE_NAME=PROTOCOL_PAUSER ADDRESS=0x123... ACTION=grant forge script script/SetRole.s.sol:SetRole --rpc-url $RPC_URL --broadcast - * + * * 2. Revoke PROTOCOL_PAUSER role: * ROLE_NAME=PROTOCOL_PAUSER ADDRESS=0x123... ACTION=revoke forge script script/SetRole.s.sol:SetRole --rpc-url $RPC_URL --broadcast - * + * * 3. Check if address has role: * ROLE_NAME=PROTOCOL_PAUSER ADDRESS=0x123... ACTION=check forge script script/SetRole.s.sol:SetRole --rpc-url $RPC_URL - * + * * 4. List all addresses with role: * ROLE_NAME=PROTOCOL_PAUSER ACTION=list forge script script/SetRole.s.sol:SetRole --rpc-url $RPC_URL */ contract SetRole is Script { // Contract addresses - UPDATE THESE FOR YOUR DEPLOYMENT address constant ROLE_REGISTRY = 0x7279853cA1804d4F705d885FeA7f1662323B5Aab; // Hoodi testnet - + // Role definitions bytes32 constant PROTOCOL_PAUSER = keccak256("PROTOCOL_PAUSER"); bytes32 constant PROTOCOL_UNPAUSER = keccak256("PROTOCOL_UNPAUSER"); @@ -82,19 +82,19 @@ contract SetRole is Script { bytes32 constant ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE = keccak256("ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE"); IRoleRegistry roleRegistry; - + function run() external { // Initialize contracts roleRegistry = IRoleRegistry(ROLE_REGISTRY); - + // Get environment variables - string memory roleName = "ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE";//vm.envString("ROLE_NAME"); - string memory action = "grant";//vm.envString("ACTION"); - + string memory roleName = "ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE"; //vm.envString("ROLE_NAME"); + string memory action = "grant"; //vm.envString("ACTION"); + bytes32 role = keccak256(abi.encodePacked(roleName)); require(role != bytes32(0), "Invalid role name"); - - if (keccak256(abi.encodePacked(action)) == keccak256(abi.encodePacked("grant"))) { + + if (keccak256(abi.encodePacked(action)) == keccak256(abi.encodePacked("grant"))) { grantRole(role); } else if (keccak256(abi.encodePacked(action)) == keccak256(abi.encodePacked("revoke"))) { revokeRole(role); @@ -106,64 +106,64 @@ contract SetRole is Script { revert("Invalid action. Use: grant, revoke, check, or list"); } } - + function grantRole(bytes32 role) internal { address target = vm.envAddress("ADDRESS"); require(target != address(0), "ADDRESS environment variable required"); - + vm.startBroadcast(); - + console.log("Granting role", vm.toString(role)); console.log("To address:", target); - + roleRegistry.grantRole(role, target); - + vm.stopBroadcast(); - + console.log("Role granted successfully!"); - + // Verify the role was granted bool hasRole = roleRegistry.hasRole(role, target); console.log("Verification - Has role:", hasRole); } - + function revokeRole(bytes32 role) internal { address target = vm.envAddress("ADDRESS"); require(target != address(0), "ADDRESS environment variable required"); - + vm.startBroadcast(); - + console.log("Revoking role", vm.toString(role)); console.log("From address:", target); - + roleRegistry.revokeRole(role, target); - + vm.stopBroadcast(); - + console.log("Role revoked successfully!"); - + // Verify the role was revoked bool hasRole = roleRegistry.hasRole(role, target); console.log("Verification - Has role:", hasRole); } - + function checkRole(bytes32 role) internal view { address target = vm.envAddress("ADDRESS"); require(target != address(0), "ADDRESS environment variable required"); - + bool hasRole = roleRegistry.hasRole(role, target); - + console.log("Role:", vm.toString(role)); console.log("Address:", target); console.log("Has role:", hasRole); } - + function listRoleHolders(bytes32 role) internal view { address[] memory holders = roleRegistry.roleHolders(role); - + console.log("Role:", vm.toString(role)); console.log("Number of holders:", holders.length); - + for (uint256 i = 0; i < holders.length; i++) { console.log("Holder", i + 1, ":", holders[i]); } diff --git a/script/hoodi/StakingPart1_Setup.s.sol b/script/hoodi/StakingPart1_Setup.s.sol index 6dd7b64ba..f89e27377 100644 --- a/script/hoodi/StakingPart1_Setup.s.sol +++ b/script/hoodi/StakingPart1_Setup.s.sol @@ -1,35 +1,38 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "forge-std/Script.sol"; -import "forge-std/console.sol"; -import "../../src/interfaces/ILiquidityPool.sol"; import {LiquidityPool} from "../../src/LiquidityPool.sol"; -import "../../src/interfaces/IStakingManager.sol"; -import "../../src/interfaces/IEtherFiNodesManager.sol"; -import "../../src/interfaces/IAuctionManager.sol"; -import "../../src/interfaces/INodeOperatorManager.sol"; + import {NodeOperatorManager} from "../../src/NodeOperatorManager.sol"; + +import {StakingManager} from "../../src/StakingManager.sol"; +import "../../src/interfaces/IAuctionManager.sol"; import "../../src/interfaces/IEtherFiNode.sol"; +import "../../src/interfaces/IEtherFiNodesManager.sol"; +import "../../src/interfaces/ILiquidityPool.sol"; + +import "../../src/interfaces/INodeOperatorManager.sol"; import "../../src/interfaces/IRoleRegistry.sol"; -import {StakingManager} from "../../src/StakingManager.sol"; +import "../../src/interfaces/IStakingManager.sol"; +import "forge-std/Script.sol"; +import "forge-std/console.sol"; /** * @title Staking Part 1: Setup & Get EigenPod Address * @notice First part of the staking process - creates everything needed before key generation - * + * * This script will: * 1. Deposit ETH to liquidity pool (if needed) * 2. Register you as node operator * 3. Create your bid * 4. Create EtherFi node and get EigenPod address * 5. Save all data to a file for Part 2 - * - * Usage: + * + * Usage: * 1. Set environment variables in .env: * PRIVATE_KEY= * NODE_OPERATOR_KEY= (can be same as PRIVATE_KEY) - * + * * 2. Run: forge script script/StakingPart1_Setup.s.sol:StakingPart1 --rpc-url https://rpc.hoodi.ethpandaops.io --broadcast */ contract StakingPart1 is Script { @@ -40,10 +43,10 @@ contract StakingPart1 is Script { address constant AUCTION_MANAGER = 0x261315c176864cE29D582f38DdA4930ED17CD95A; address constant NODE_OPERATOR_MANAGER = 0x3e17543CaE3366cc67a3CBeD5Aa42d9d09D59b39; address constant ROLE_REGISTRY = 0x7279853cA1804d4F705d885FeA7f1662323B5Aab; - + // Role definition bytes32 constant STAKING_MANAGER_NODE_CREATOR_ROLE = keccak256("STAKING_MANAGER_NODE_CREATOR_ROLE"); - + // Contract interfaces LiquidityPool liquidityPool; StakingManager stakingManager; @@ -51,7 +54,7 @@ contract StakingPart1 is Script { IAuctionManager auctionManager; NodeOperatorManager nodeOperatorManager; IRoleRegistry roleRegistry; - + function run() external { // Initialize interfaces liquidityPool = LiquidityPool(payable(LIQUIDITY_POOL)); @@ -60,43 +63,43 @@ contract StakingPart1 is Script { auctionManager = IAuctionManager(AUCTION_MANAGER); nodeOperatorManager = NodeOperatorManager(NODE_OPERATOR_MANAGER); roleRegistry = IRoleRegistry(ROLE_REGISTRY); - + console.log("\n========== EtherFi Staking Setup - Part 1 =========="); console.log("This script prepares everything needed before key generation\n"); - + // Get addresses address depositor = vm.addr(vm.envUint("PRIVATE_KEY")); address nodeOp = vm.addr(vm.envUint("NODE_OPERATOR_KEY")); - + console.log("Depositor address: %s", depositor); console.log("Node operator address: %s", nodeOp); console.log("Current depositor balance: %s ETH", depositor.balance / 1e18); - + // Step 1: Check liquidity pool balance and deposit if needed uint256 poolBalance = LIQUIDITY_POOL.balance; console.log("\nStep 1: Checking liquidity pool"); console.log("Current pool balance: %s ETH", poolBalance / 1e18); - + if (poolBalance < 32 ether) { uint256 needed = 32 ether - poolBalance; console.log("Pool needs %s more ETH. Depositing...", needed / 1e18); - + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); liquidityPool.deposit{value: 32 ether}(); vm.stopBroadcast(); - + console.log("Deposited 32 ETH to liquidity pool"); } else { console.log("Pool has sufficient liquidity"); } - + // Step 2: Whitelist and register node operator console.log("\nStep 2: Node operator setup"); - + // Check if already whitelisted if (!nodeOperatorManager.isWhitelisted(nodeOp)) { console.log("Whitelisting node operator..."); - + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); // Add admin rights if needed if (!nodeOperatorManager.admins(depositor)) { @@ -105,7 +108,7 @@ contract StakingPart1 is Script { nodeOperatorManager.addToWhitelist(nodeOp); vm.stopBroadcast(); } - + // Register node operator if not already registered if (nodeOperatorManager.registered(nodeOp)) { console.log("Node operator already registered"); @@ -116,17 +119,17 @@ contract StakingPart1 is Script { vm.stopBroadcast(); console.log("Registered with 10% commission"); } - + // Step 3: Create bid console.log("\nStep 3: Creating bid"); vm.startBroadcast(vm.envUint("NODE_OPERATOR_KEY")); uint256[] memory bidIds = auctionManager.createBid{value: 0.001 ether}(1, 0.001 ether); uint256 bidId = bidIds[0]; vm.stopBroadcast(); - + console.log("Created bid with ID: %s", bidId); console.log("Bid amount: 0.001 ETH"); - + // Step 4: Register as validator spawner if needed console.log("\nStep 4: Checking validator spawner registration"); bool spawner = liquidityPool.validatorSpawner(depositor); @@ -139,14 +142,14 @@ contract StakingPart1 is Script { } else { console.log("Already registered as validator spawner"); } - + // Step 5: Create EtherFi node and get EigenPod address console.log("\nStep 5: Creating EtherFi node"); - + // Check if depositor has the required role if (!roleRegistry.hasRole(STAKING_MANAGER_NODE_CREATOR_ROLE, depositor)) { console.log("Depositor doesn't have STAKING_MANAGER_NODE_CREATOR_ROLE"); - + // Check if we're the owner and can grant the role address owner = roleRegistry.owner(); if (owner == depositor) { @@ -163,16 +166,16 @@ contract StakingPart1 is Script { console.log("Depositor already has STAKING_MANAGER_NODE_CREATOR_ROLE"); } - console.log("Has role?",roleRegistry.hasRole(stakingManager.STAKING_MANAGER_NODE_CREATOR_ROLE(), vm.addr(vm.envUint("PRIVATE_KEY")))); + console.log("Has role?", roleRegistry.hasRole(stakingManager.STAKING_MANAGER_NODE_CREATOR_ROLE(), vm.addr(vm.envUint("PRIVATE_KEY")))); vm.startBroadcast(vm.envUint("PRIVATE_KEY")); - console.log("Role reg: %s",address(stakingManager.roleRegistry())); - console.log("Role Reg: %s",address(roleRegistry)); + console.log("Role reg: %s", address(stakingManager.roleRegistry())); + console.log("Role Reg: %s", address(roleRegistry)); address etherFiNode = stakingManager.instantiateEtherFiNode(true); address eigenPod = address(IEtherFiNode(etherFiNode).getEigenPod()); - + vm.stopBroadcast(); - + // Save setup data console.log("\n========== SETUP COMPLETE =========="); console.log("SAVE THIS INFORMATION:"); @@ -190,7 +193,5 @@ contract StakingPart1 is Script { console.log(" export ETHERFI_NODE=%s", etherFiNode); console.log("\n forge script script/StakingPart2_CreateValidator.s.sol:StakingPart2 --rpc-url https://rpc.hoodi.ethpandaops.io --broadcast"); console.log("====================================\n"); - - } -} \ No newline at end of file +} diff --git a/script/hoodi/StakingPart2_CreateValidator.s.sol b/script/hoodi/StakingPart2_CreateValidator.s.sol index 96e6c11b0..3f056f709 100644 --- a/script/hoodi/StakingPart2_CreateValidator.s.sol +++ b/script/hoodi/StakingPart2_CreateValidator.s.sol @@ -1,23 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "forge-std/Script.sol"; -import "forge-std/console.sol"; -import "../../src/interfaces/IStakingManager.sol"; +import {LiquidityPool} from "../../src/LiquidityPool.sol"; import "../../src/interfaces/IEtherFiNodesManager.sol"; import "../../src/interfaces/ILiquidityPool.sol"; -import {LiquidityPool} from "../../src/LiquidityPool.sol"; import "../../src/interfaces/IRoleRegistry.sol"; +import "../../src/interfaces/IStakingManager.sol"; +import "forge-std/Script.sol"; +import "forge-std/console.sol"; /** * @title Staking Part 2: Create Validator * @notice Second part - creates the validator after you've generated keys - * + * * Prerequisites: * 1. You've run StakingPart1_Setup.s.sol * 2. You've generated validator keys with the EigenPod address * 3. You have the pubkey and signature from deposit_data-*.json - * + * * Usage: * 1. Set environment variables: * PRIVATE_KEY= @@ -25,7 +25,7 @@ import "../../src/interfaces/IRoleRegistry.sol"; * VALIDATOR_SIGNATURE=<96-byte signature from deposit data, no 0x prefix> * BID_ID= * ETHERFI_NODE= - * + * * 2. Run: forge script script/StakingPart2_CreateValidator.s.sol:StakingPart2 --rpc-url https://rpc.hoodi.ethpandaops.io --broadcast */ contract StakingPart2 is Script { @@ -39,12 +39,12 @@ contract StakingPart2 is Script { address constant ROLE_REGISTRY = 0x7279853cA1804d4F705d885FeA7f1662323B5Aab; address constant DEPOSIT_CONTRACT = 0x00000000219ab540356cBB839Cbe05303d7705Fa; - + LiquidityPool liquidityPool; IStakingManager stakingManager; IEtherFiNodesManager etherFiNodesManager; IRoleRegistry roleRegistry; - + function run() external { // Initialize interfaces liquidityPool = LiquidityPool(payable(LIQUIDITY_POOL)); @@ -54,69 +54,59 @@ contract StakingPart2 is Script { console.log("\n========== EtherFi Staking - Part 2 =========="); console.log("Creating validator with your generated keys\n"); - + // Get parameters bytes memory pubkey = vm.envBytes("VALIDATOR_PUBKEY"); bytes memory signature = vm.envBytes("VALIDATOR_SIGNATURE"); uint256 bidId = vm.envUint("BID_ID"); address etherFiNode = vm.envAddress("ETHERFI_NODE"); - + // Validate inputs require(pubkey.length == 48, "Invalid pubkey length"); require(signature.length == 96, "Invalid signature length"); require(etherFiNode != address(0), "Invalid EtherFi node address"); - + console.log("Using parameters:"); console.log("- Bid ID: %s", bidId); console.log("- EtherFi Node: %s", etherFiNode); console.log("- Validator pubkey: %s", vm.toString(pubkey)); - + // Get withdrawal credentials from EtherFi node's EigenPod address eigenPod = address(IEtherFiNode(etherFiNode).getEigenPod()); console.log("EigenPod: %s", eigenPod); bytes memory withdrawalCredentials = etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod); - + console.log("- EigenPod: %s", eigenPod); console.log("- Withdrawal credentials: %s", vm.toString(withdrawalCredentials)); - + // Generate deposit data root - bytes32 depositRoot = stakingManager.generateDepositDataRoot( - pubkey, - signature, - withdrawalCredentials, - 1 ether - ); - + bytes32 depositRoot = stakingManager.generateDepositDataRoot(pubkey, signature, withdrawalCredentials, 1 ether); + console.log("!Ensure that this root matches the one in deposit_data.json! - Deposit root: %s", vm.toString(depositRoot)); - + // Prepare deposit data - IStakingManager.DepositData memory depositData = IStakingManager.DepositData({ - publicKey: pubkey, - signature: signature, - depositDataRoot: depositRoot, - ipfsHashForEncryptedValidatorKey: "hoodi_testnet_validator" - }); - + IStakingManager.DepositData memory depositData = IStakingManager.DepositData({publicKey: pubkey, signature: signature, depositDataRoot: depositRoot, ipfsHashForEncryptedValidatorKey: "hoodi_testnet_validator"}); + IStakingManager.DepositData[] memory depositDataArray = new IStakingManager.DepositData[](1); depositDataArray[0] = depositData; - + uint256[] memory bidIdArray = new uint256[](1); bidIdArray[0] = bidId; - + // Check deposit contract balance before uint256 depositContractBefore = DEPOSIT_CONTRACT.balance; - + console.log("\nCreating validator with 1 ETH initial deposit..."); - + // Check if msg.sender is registered as validator spawner - + { - address depositor = vm.addr(vm.envUint("PRIVATE_KEY")); - bool isSpawner = liquidityPool.validatorSpawner(depositor); + address depositor = vm.addr(vm.envUint("PRIVATE_KEY")); + bool isSpawner = liquidityPool.validatorSpawner(depositor); - bool isLiquidityPoolAdmin = roleRegistry.hasRole(keccak256("LIQUIDITY_POOL_ADMIN_ROLE"),depositor); + bool isLiquidityPoolAdmin = roleRegistry.hasRole(keccak256("LIQUIDITY_POOL_ADMIN_ROLE"), depositor); - if (!isLiquidityPoolAdmin){ + if (!isLiquidityPoolAdmin) { vm.startBroadcast(vm.envUint("PRIVATE_KEY")); roleRegistry.grantRole(keccak256("LIQUIDITY_POOL_ADMIN_ROLE"), depositor); @@ -128,20 +118,15 @@ contract StakingPart2 is Script { liquidityPool.registerValidatorSpawner(depositor); vm.stopBroadcast(); console.log("fail-2"); - } } // Create validator through LiquidityPool vm.startBroadcast(vm.envUint("PRIVATE_KEY")); - liquidityPool.batchRegister( - depositDataArray, - bidIdArray, - etherFiNode - ); + liquidityPool.batchRegister(depositDataArray, bidIdArray, etherFiNode); vm.stopBroadcast(); - + uint256 depositContractAfter = DEPOSIT_CONTRACT.balance; - + console.log("\n========== VALIDATOR CREATED =========="); console.log("- 1 ETH sent to beacon chain deposit contract"); console.log("- Deposit contract balance increased by: %s ETH", (depositContractAfter - depositContractBefore) / 1e18); @@ -156,4 +141,4 @@ contract StakingPart2 is Script { console.log("- Validator Pubkey: %s", vm.toString(pubkey)); console.log("=====================================\n"); } -} \ No newline at end of file +} diff --git a/src/AssetRecovery.sol b/src/AssetRecovery.sol index b107dcfe9..3e8be732c 100644 --- a/src/AssetRecovery.sol +++ b/src/AssetRecovery.sol @@ -1,10 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; +import "../lib/solady/src/utils/ReentrancyGuardTransient.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import "../lib/solady/src/utils/ReentrancyGuardTransient.sol"; - /** * @title AssetRecovery @@ -12,19 +11,18 @@ import "../lib/solady/src/utils/ReentrancyGuardTransient.sol"; * mistakenly sent to this contract. */ abstract contract AssetRecovery is ReentrancyGuardTransient { - using SafeERC20 for IERC20; - + /** * @dev Emitted when ETH is recovered */ event ETHRecovered(address indexed to, uint256 amount); - + /** * @dev Emitted when ERC20 tokens are recovered */ event ERC20Recovered(address indexed token, address indexed to, uint256 amount); - + /** * @dev Emitted when an ERC721 token is recovered */ @@ -73,9 +71,9 @@ abstract contract AssetRecovery is ReentrancyGuardTransient { if (to == address(0) || amount == 0) revert InvalidInput(); if (amount > address(this).balance) revert InsufficientBalance(); - (bool success, ) = to.call{value: amount}(""); + (bool success,) = to.call{value: amount}(""); if (!success) revert EthTransferFailed(); - + emit ETHRecovered(to, amount); } @@ -88,9 +86,9 @@ abstract contract AssetRecovery is ReentrancyGuardTransient { function _recoverERC20(address token, address to, uint256 amount) internal nonReentrant { if (token == address(0) || to == address(0) || amount == 0) revert InvalidInput(); if (amount > IERC20(token).balanceOf(address(this))) revert InsufficientBalance(); - + IERC20(token).safeTransfer(to, amount); - + emit ERC20Recovered(token, to, amount); } @@ -103,9 +101,9 @@ abstract contract AssetRecovery is ReentrancyGuardTransient { function _recoverERC721(address token, address to, uint256 tokenId) internal nonReentrant { if (token == address(0) || to == address(0)) revert InvalidInput(); if (IERC721(token).ownerOf(tokenId) != address(this)) revert ContractIsNotOwnerOfERC721Token(); - + IERC721(token).safeTransferFrom(address(this), to, tokenId); - + emit ERC721Recovered(token, to, tokenId); } } diff --git a/src/AuctionManager.sol b/src/AuctionManager.sol index a5078a8da..0e732e06f 100644 --- a/src/AuctionManager.sol +++ b/src/AuctionManager.sol @@ -4,20 +4,14 @@ pragma solidity ^0.8.13; import "./interfaces/IAuctionManager.sol"; import "./interfaces/INodeOperatorManager.sol"; import "./interfaces/IProtocolRevenueManager.sol"; -import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; + import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; -contract AuctionManager is - Initializable, - IAuctionManager, - PausableUpgradeable, - OwnableUpgradeable, - ReentrancyGuardUpgradeable, - UUPSUpgradeable -{ +contract AuctionManager is Initializable, IAuctionManager, PausableUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { //-------------------------------------------------------------------------------------- //--------------------------------- STATE-VARIABLES ---------------------------------- //-------------------------------------------------------------------------------------- @@ -65,11 +59,9 @@ contract AuctionManager is //-------------------------------------------------------------------------------------- /// @notice Initialize to set variables on deployment - function initialize( - address _nodeOperatorManagerContract - ) external initializer { + function initialize(address _nodeOperatorManagerContract) external initializer { require(_nodeOperatorManagerContract != address(0), "No Zero Addresses"); - + whitelistBidAmount = 0.001 ether; minBidAmount = 0.01 ether; maxBidAmount = 5 ether; @@ -84,7 +76,7 @@ contract AuctionManager is __ReentrancyGuard_init(); } - function initializeOnUpgrade(address _membershipManagerContractAddress, uint128 _accumulatedRevenueThreshold, address _etherFiAdminContractAddress, address _nodeOperatorManagerAddress) external onlyOwner { + function initializeOnUpgrade(address _membershipManagerContractAddress, uint128 _accumulatedRevenueThreshold, address _etherFiAdminContractAddress, address _nodeOperatorManagerAddress) external onlyOwner { require(_membershipManagerContractAddress != address(0) && _etherFiAdminContractAddress != address(0) && _nodeOperatorManagerAddress != address(0), "No Zero Addresses"); membershipManagerContractAddress = _membershipManagerContractAddress; nodeOperatorManager = INodeOperatorManager(_nodeOperatorManagerAddress); @@ -97,39 +89,16 @@ contract AuctionManager is /// @param _bidSize the number of bids that the node operator would like to create /// @param _bidAmountPerBid the ether value of each bid that is created /// @return bidIdArray array of the bidIDs that were created - function createBid( - uint256 _bidSize, - uint256 _bidAmountPerBid - ) external payable whenNotPaused nonReentrant returns (uint256[] memory) { + function createBid(uint256 _bidSize, uint256 _bidAmountPerBid) external payable whenNotPaused nonReentrant returns (uint256[] memory) { require(_bidSize > 0, "Bid size is too small"); if (whitelistEnabled) { - require( - nodeOperatorManager.isWhitelisted(msg.sender), - "Only whitelisted addresses" - ); - require( - msg.value == _bidSize * _bidAmountPerBid && - _bidAmountPerBid >= whitelistBidAmount && - _bidAmountPerBid <= maxBidAmount, - "Incorrect bid value" - ); + require(nodeOperatorManager.isWhitelisted(msg.sender), "Only whitelisted addresses"); + require(msg.value == _bidSize * _bidAmountPerBid && _bidAmountPerBid >= whitelistBidAmount && _bidAmountPerBid <= maxBidAmount, "Incorrect bid value"); } else { - if ( - nodeOperatorManager.isWhitelisted(msg.sender) - ) { - require( - msg.value == _bidSize * _bidAmountPerBid && - _bidAmountPerBid >= whitelistBidAmount && - _bidAmountPerBid <= maxBidAmount, - "Incorrect bid value" - ); + if (nodeOperatorManager.isWhitelisted(msg.sender)) { + require(msg.value == _bidSize * _bidAmountPerBid && _bidAmountPerBid >= whitelistBidAmount && _bidAmountPerBid <= maxBidAmount, "Incorrect bid value"); } else { - require( - msg.value == _bidSize * _bidAmountPerBid && - _bidAmountPerBid >= minBidAmount && - _bidAmountPerBid <= maxBidAmount, - "Incorrect bid value" - ); + require(msg.value == _bidSize * _bidAmountPerBid && _bidAmountPerBid >= minBidAmount && _bidAmountPerBid <= maxBidAmount, "Incorrect bid value"); } } uint64 keysRemaining = nodeOperatorManager.getNumKeysRemaining(msg.sender); @@ -145,12 +114,7 @@ contract AuctionManager is ipfsIndexArray[i] = ipfsIndex; //Creates a bid object for storage and lookup in future - bids[bidId] = Bid({ - amount: _bidAmountPerBid, - bidderPubKeyIndex: ipfsIndex, - bidderAddress: msg.sender, - isActive: true - }); + bids[bidId] = Bid({amount: _bidAmountPerBid, bidderPubKeyIndex: ipfsIndex, bidderAddress: msg.sender, isActive: true}); } numberOfBids += _bidSize; numberOfActiveBids += _bidSize; @@ -178,9 +142,7 @@ contract AuctionManager is /// @notice Updates the details of the bid which has been used in a stake match /// @dev Called by batchDepositWithBidIds() in StakingManager.sol /// @param _bidId the ID of the bid being removed from the auction (since it has been selected) - function updateSelectedBidInformation( - uint256 _bidId - ) external onlyStakingManagerContract { + function updateSelectedBidInformation(uint256 _bidId) external onlyStakingManagerContract { Bid storage bid = bids[_bidId]; require(bid.isActive, "The bid is not active"); @@ -190,9 +152,7 @@ contract AuctionManager is /// @notice Lets a bid that was matched to a cancelled stake re-enter the auction /// @param _bidId the ID of the bid which was matched to the cancelled stake. - function reEnterAuction( - uint256 _bidId - ) external onlyStakingManagerContract { + function reEnterAuction(uint256 _bidId) external onlyStakingManagerContract { Bid storage bid = bids[_bidId]; require(!bid.isActive, "Bid already active"); @@ -204,14 +164,12 @@ contract AuctionManager is /// @notice Transfer the auction fee received from the node operator to the membership NFT contract when above the threshold /// @dev Called by registerValidator() in StakingManager.sol /// @param _bidId the ID of the validator - function processAuctionFeeTransfer( - uint256 _bidId - ) external onlyStakingManagerContract { + function processAuctionFeeTransfer(uint256 _bidId) external onlyStakingManagerContract { uint256 amount = bids[_bidId].amount; uint256 newAccumulatedRevenue = accumulatedRevenue + amount; if (newAccumulatedRevenue >= accumulatedRevenueThreshold) { accumulatedRevenue = 0; - (bool sent, ) = membershipManagerContractAddress.call{value: newAccumulatedRevenue}(""); + (bool sent,) = membershipManagerContractAddress.call{value: newAccumulatedRevenue}(""); require(sent, "Failed to send Ether"); } else { accumulatedRevenue = uint128(newAccumulatedRevenue); @@ -221,7 +179,7 @@ contract AuctionManager is function transferAccumulatedRevenue() external onlyAdmin { uint256 transferAmount = accumulatedRevenue; accumulatedRevenue = 0; - (bool sent, ) = membershipManagerContractAddress.call{value: transferAmount}(""); + (bool sent,) = membershipManagerContractAddress.call{value: transferAmount}(""); require(sent, "Failed to send Ether"); } @@ -263,7 +221,7 @@ contract AuctionManager is numberOfActiveBids--; // Refund the user with their bid amount - (bool sent, ) = msg.sender.call{value: bid.amount}(""); + (bool sent,) = msg.sender.call{value: bid.amount}(""); require(sent, "Failed to send Ether"); emit BidCancelled(_bidId); @@ -301,9 +259,7 @@ contract AuctionManager is /// @notice Sets the staking managers contract address in the current contract /// @param _stakingManagerContractAddress new stakingManagerContract address - function setStakingManagerContractAddress( - address _stakingManagerContractAddress - ) external onlyOwner { + function setStakingManagerContractAddress(address _stakingManagerContractAddress) external onlyOwner { require(address(stakingManagerContractAddress) == address(0), "Address already set"); require(_stakingManagerContractAddress != address(0), "No zero addresses"); stakingManagerContractAddress = _stakingManagerContractAddress; @@ -332,17 +288,13 @@ contract AuctionManager is /// @notice Updates the minimum bid price for a whitelisted address /// @param _newAmount the new amount to set the minimum bid price as - function updateWhitelistMinBidAmount( - uint128 _newAmount - ) external onlyOwner { + function updateWhitelistMinBidAmount(uint128 _newAmount) external onlyOwner { require(_newAmount < minBidAmount && _newAmount > 0, "Invalid Amount"); whitelistBidAmount = _newAmount; } function updateNodeOperatorManager(address _address) external onlyOwner { - nodeOperatorManager = INodeOperatorManager( - _address - ); + nodeOperatorManager = INodeOperatorManager(_address); } /// @notice Updates the address of the admin diff --git a/src/BNFT.sol b/src/BNFT.sol index b0910b65c..969579a02 100644 --- a/src/BNFT.sol +++ b/src/BNFT.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/token/ERC721/ERC721Upgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/token/ERC721/ERC721Upgradeable.sol"; contract BNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { //-------------------------------------------------------------------------------------- @@ -23,7 +23,7 @@ contract BNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { //-------------------------------------------------------------------------------------- /// @notice initialize to set variables on deployment - function initialize(address _stakingManagerAddress) initializer external { + function initialize(address _stakingManagerAddress) external initializer { require(_stakingManagerAddress != address(0), "No zero addresses"); __ERC721_init("Bond NFT", "BNFT"); __Ownable_init(); @@ -33,7 +33,7 @@ contract BNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { } /// @notice initialization function that should be called after phase 2.0 contract upgrade - function initializeOnUpgrade(address _etherFiNodesManagerAddress) onlyOwner external { + function initializeOnUpgrade(address _etherFiNodesManagerAddress) external onlyOwner { require(_etherFiNodesManagerAddress != address(0), "Cannot initialize to zero address"); etherFiNodesManagerAddress = _etherFiNodesManagerAddress; @@ -62,8 +62,8 @@ contract BNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { address from, address to, uint256, // firstTokenId - uint256 // batchSize - ) internal virtual override(ERC721Upgradeable ){ + uint256 // batchSize + ) internal virtual override(ERC721Upgradeable) { // only allow mint or burn require(from == address(0) || to == address(0), "Err: token is SOUL BOUND"); } @@ -72,9 +72,7 @@ contract BNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { //------------------------------- INTERNAL FUNCTIONS -------------------------------- //-------------------------------------------------------------------------------------- - function _authorizeUpgrade( - address newImplementation - ) internal override onlyOwner {} + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} //-------------------------------------------------------------------------------------- //-------------------------------------- GETTER -------------------------------------- diff --git a/src/BucketRateLimiter.sol b/src/BucketRateLimiter.sol index b643074e7..4c1ae84b0 100644 --- a/src/BucketRateLimiter.sol +++ b/src/BucketRateLimiter.sol @@ -1,16 +1,15 @@ pragma solidity ^0.8.20; -import "@openzeppelin/contracts/utils/math/SafeCast.sol"; -import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; +import "@openzeppelin/contracts/utils/math/SafeCast.sol"; -import "src/interfaces/IRateLimiter.sol"; import "lib/BucketLimiter.sol"; +import "src/interfaces/IRateLimiter.sol"; contract BucketRateLimiter is IRateLimiter, Initializable, PausableUpgradeable, OwnableUpgradeable, UUPSUpgradeable { - BucketLimiter.Limit public limit; address public consumer; @@ -109,5 +108,4 @@ contract BucketRateLimiter is IRateLimiter, Initializable, PausableUpgradeable, } function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} - -} \ No newline at end of file +} diff --git a/src/CumulativeMerkleRewardsDistributor.sol b/src/CumulativeMerkleRewardsDistributor.sol index 3e33437c1..b79286a55 100644 --- a/src/CumulativeMerkleRewardsDistributor.sol +++ b/src/CumulativeMerkleRewardsDistributor.sol @@ -1,15 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {RoleRegistry} from "./RoleRegistry.sol"; +import {ICumulativeMerkleRewardsDistributor} from "./interfaces/ICumulativeMerkleRewardsDistributor.sol"; import {OwnableUpgradeable} from "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import {UUPSUpgradeable} from "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import {RoleRegistry} from "./RoleRegistry.sol"; -import {ICumulativeMerkleRewardsDistributor} from "./interfaces/ICumulativeMerkleRewardsDistributor.sol"; +import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract CumulativeMerkleRewardsDistributor is ICumulativeMerkleRewardsDistributor, OwnableUpgradeable, UUPSUpgradeable { -using SafeERC20 for IERC20; - + using SafeERC20 for IERC20; //-------------------------------------------------------------------------------------- //--------------------------------- STATE-VARIABLES ---------------------------------- @@ -25,7 +24,6 @@ using SafeERC20 for IERC20; uint256 public claimDelay; bool public paused; - //-------------------------------------------------------------------------------------- //------------------------------------- ROLES --------------------------------------- //-------------------------------------------------------------------------------------- @@ -35,9 +33,9 @@ using SafeERC20 for IERC20; bytes32 public constant CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_CLAIM_DELAY_SETTER_ROLE = keccak256("CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_CLAIM_DELAY_SETTER_ROLE"); RoleRegistry public immutable roleRegistry; -//-------------------------------------------------------------------------------------- -//---------------------------- STATE-CHANGING FUNCTIONS ------------------------------ -//-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- + //---------------------------- STATE-CHANGING FUNCTIONS ------------------------------ + //-------------------------------------------------------------------------------------- constructor(address _roleRegistry) { _disableInitializers(); @@ -48,39 +46,41 @@ using SafeERC20 for IERC20; __Ownable_init(); __UUPSUpgradeable_init(); paused = false; - claimDelay = 172800; // 48 hours + claimDelay = 172_800; // 48 hours } function setClaimDelay(uint256 _claimDelay) external { - if(!roleRegistry.hasRole(CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_CLAIM_DELAY_SETTER_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_CLAIM_DELAY_SETTER_ROLE, msg.sender)) revert IncorrectRole(); claimDelay = _claimDelay; emit ClaimDelayUpdated(claimDelay); } -/** -* @notice Sets a new pending Merkle root for token rewards distribution -* @dev Only callable by accounts with CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE role -* @dev The pending root must be finalized after CLAIM_DELAY blocks before it becomes active -* @param _token Address of the reward token (use ETH_ADDRESS for ETH rewards) -* @param _merkleRoot New Merkle root containing the reward data -**/ + /** + * @notice Sets a new pending Merkle root for token rewards distribution + * @dev Only callable by accounts with CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE role + * @dev The pending root must be finalized after CLAIM_DELAY blocks before it becomes active + * @param _token Address of the reward token (use ETH_ADDRESS for ETH rewards) + * @param _merkleRoot New Merkle root containing the reward data + * + */ + function setPendingMerkleRoot(address _token, bytes32 _merkleRoot) external whenNotPaused { - if(!roleRegistry.hasRole(CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); pendingMerkleRoots[_token] = _merkleRoot; lastPendingMerkleUpdatedToTimestamp[_token] = block.timestamp; emit PendingMerkleRootUpdated(_token, _merkleRoot); } -/** -* @notice Finalizes a pending Merkle root after the required delay period -* @dev Only callable by accounts with CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE role -* @dev Must wait CLAIM_DELAY blocks after setPendingMerkleRoot before finalizing -* @param _token Address of the reward token (use ETH_ADDRESS for ETH rewards) -* @param _finalizedBlock Block number up to which rewards are calculated -*/ + /** + * @notice Finalizes a pending Merkle root after the required delay period + * @dev Only callable by accounts with CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE role + * @dev Must wait CLAIM_DELAY blocks after setPendingMerkleRoot before finalizing + * @param _token Address of the reward token (use ETH_ADDRESS for ETH rewards) + * @param _finalizedBlock Block number up to which rewards are calculated + */ function finalizeMerkleRoot(address _token, uint256 _finalizedBlock) external whenNotPaused { - if(!roleRegistry.hasRole(CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); - if(!(block.timestamp >= lastPendingMerkleUpdatedToTimestamp[_token] + claimDelay)) revert InsufficentDelay(); - if(_finalizedBlock < lastRewardsCalculatedToBlock[_token] || _finalizedBlock > block.number) revert InvalidFinalizedBlock(); + if (!roleRegistry.hasRole(CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!(block.timestamp >= lastPendingMerkleUpdatedToTimestamp[_token] + claimDelay)) revert InsufficentDelay(); + if (_finalizedBlock < lastRewardsCalculatedToBlock[_token] || _finalizedBlock > block.number) revert InvalidFinalizedBlock(); bytes32 oldClaimableMerkleRoot = claimableMerkleRoots[_token]; claimableMerkleRoots[_token] = pendingMerkleRoots[_token]; lastRewardsCalculatedToBlock[_token] = _finalizedBlock; @@ -88,22 +88,17 @@ using SafeERC20 for IERC20; } /** - * @notice Claims rewards for an account using Merkle proof verification - * @dev Supports both ERC20 tokens and ETH (using ETH_ADDRESS) - * @dev Uses cumulative amounts to prevent double-claiming and allow partial claims - * @param token Address of the reward token (use ETH_ADDRESS for ETH) - * @param account Address that will receive the rewards - * @param cumulativeAmount Total amount claimable by account, including previous claims - * @param expectedMerkleRoot The Merkle root containing the reward data - * @param merkleProof Array of hashes proving the claim's inclusion in the Merkle tree - **/ - function claim( - address token, - address account, - uint256 cumulativeAmount, - bytes32 expectedMerkleRoot, - bytes32[] calldata merkleProof - ) external whenNotPaused override { + * @notice Claims rewards for an account using Merkle proof verification + * @dev Supports both ERC20 tokens and ETH (using ETH_ADDRESS) + * @dev Uses cumulative amounts to prevent double-claiming and allow partial claims + * @param token Address of the reward token (use ETH_ADDRESS for ETH) + * @param account Address that will receive the rewards + * @param cumulativeAmount Total amount claimable by account, including previous claims + * @param expectedMerkleRoot The Merkle root containing the reward data + * @param merkleProof Array of hashes proving the claim's inclusion in the Merkle tree + * + */ + function claim(address token, address account, uint256 cumulativeAmount, bytes32 expectedMerkleRoot, bytes32[] calldata merkleProof) external override whenNotPaused { if (claimableMerkleRoots[token] != expectedMerkleRoot) revert MerkleRootWasUpdated(); if (!whitelistedRecipient[account]) revert NonWhitelistedUser(); @@ -116,13 +111,12 @@ using SafeERC20 for IERC20; if (preclaimed >= cumulativeAmount) revert NothingToClaim(); cumulativeClaimed[token][account] = cumulativeAmount; - uint256 amount = cumulativeAmount - preclaimed; // Send the token - if(token == ETH_ADDRESS){ - (bool success, ) = account.call{value: amount}(""); - if(!success) { - revert ETHTransferFailed(); + if (token == ETH_ADDRESS) { + (bool success,) = account.call{value: amount}(""); + if (!success) { + revert ETHTransferFailed(); } } else { IERC20(token).safeTransfer(account, amount); @@ -131,26 +125,26 @@ using SafeERC20 for IERC20; } function updateWhitelistedRecipient(address user, bool isWhitelisted) external { - if(!roleRegistry.hasRole(CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(CUMULATIVE_MERKLE_REWARDS_DISTRIBUTOR_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); whitelistedRecipient[user] = isWhitelisted; emit RecipientStatusUpdated(user, isWhitelisted); } function pause() external { - if(!roleRegistry.hasRole(roleRegistry.PROTOCOL_PAUSER(), msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(roleRegistry.PROTOCOL_PAUSER(), msg.sender)) revert IncorrectRole(); paused = true; emit Paused(msg.sender); } function unpause() external { - if(!roleRegistry.hasRole(roleRegistry.PROTOCOL_UNPAUSER(), msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(roleRegistry.PROTOCOL_UNPAUSER(), msg.sender)) revert IncorrectRole(); paused = false; emit UnPaused(msg.sender); } - - function getImplementation() external view returns (address) {return _getImplementation();} - + function getImplementation() external view returns (address) { + return _getImplementation(); + } //-------------------------------------------------------------------------------------- //------------------------------ INTERNAL FUNCTIONS ---------------------------------- @@ -161,8 +155,9 @@ using SafeERC20 for IERC20; } function _verifyAsm(bytes32[] calldata proof, bytes32 root, bytes32 leaf) private pure returns (bool valid) { - if(proof.length > 1000) revert InvalidProof(); - assembly ("memory-safe") { // solhint-disable-line no-inline-assembly + if (proof.length > 1000) revert InvalidProof(); + assembly ("memory-safe") { + // solhint-disable-line no-inline-assembly let ptr := proof.offset for { let end := add(ptr, mul(0x20, proof.length)) } lt(ptr, end) { ptr := add(ptr, 0x20) } { @@ -185,8 +180,8 @@ using SafeERC20 for IERC20; } } - function _requireNotPaused() internal view virtual { - if(paused) revert ContractPaused(); + function _requireNotPaused() internal view virtual { + if (paused) revert ContractPaused(); } //-------------------------------------------------------------------------------------- @@ -197,5 +192,4 @@ using SafeERC20 for IERC20; _requireNotPaused(); _; } - -} \ No newline at end of file +} diff --git a/src/DepositAdapter.sol b/src/DepositAdapter.sol index f20ecc05b..6f381dab3 100644 --- a/src/DepositAdapter.sol +++ b/src/DepositAdapter.sol @@ -1,20 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; import "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol"; import "./interfaces/ILiquidityPool.sol"; import "./interfaces/ILiquifier.sol"; -import "./interfaces/IeETH.sol"; -import "./interfaces/IWeETH.sol"; + import "./interfaces/IWETH.sol"; +import "./interfaces/IWeETH.sol"; +import "./interfaces/IeETH.sol"; + import "./interfaces/IwstETH.sol"; contract DepositAdapter is UUPSUpgradeable, OwnableUpgradeable { - ILiquidityPool public immutable liquidityPool; ILiquifier public immutable liquifier; IeETH public immutable eETH; @@ -23,7 +24,7 @@ contract DepositAdapter is UUPSUpgradeable, OwnableUpgradeable { IERC20Upgradeable public immutable stETH; IwstETH public immutable wstETH; - enum SourceOfFunds { + enum SourceOfFunds { ETH, WETH, STETH, @@ -44,7 +45,7 @@ contract DepositAdapter is UUPSUpgradeable, OwnableUpgradeable { _disableInitializers(); } - function initialize() initializer external { + function initialize() external initializer { __Ownable_init(); __UUPSUpgradeable_init(); } @@ -54,37 +55,37 @@ contract DepositAdapter is UUPSUpgradeable, OwnableUpgradeable { /// @return weEthAmount weETH received by the depositer function depositETHForWeETH(address _referral) external payable returns (uint256) { uint256 eETHShares = liquidityPool.deposit{value: msg.value}(_referral); - + emit AdapterDeposit(msg.sender, msg.value, SourceOfFunds.ETH, _referral); return _wrapAndReturn(eETHShares); } /// @notice Deposit WETH for weETH /// @dev WETH doesn't support permit, so this function requires an explicit approval before use - /// @param _amount Amount of WETH to deposit + /// @param _amount Amount of WETH to deposit /// @param _referral Address to credit referral /// @return weEthAmount weETH received by the depositer function depositWETHForWeETH(uint256 _amount, address _referral) external returns (uint256) { require(wETH.allowance(msg.sender, address(this)) >= _amount, "ALLOWANCE_EXCEEDED"); require(wETH.balanceOf(msg.sender) >= _amount, "INSUFFICIENT_BALANCE"); - + wETH.transferFrom(msg.sender, address(this), _amount); wETH.withdraw(_amount); uint256 eETHShares = liquidityPool.deposit{value: _amount}(_referral); - + emit AdapterDeposit(msg.sender, _amount, SourceOfFunds.WETH, _referral); return _wrapAndReturn(eETHShares); } /// @notice Deposit stETH to liquifier for weETH - /// @dev Permit must be created to this contract + /// @dev Permit must be created to this contract /// @param _amount Amount of stETH to deposit /// @param _referral Address to credit referral /// @param _permit Permit signature /// @return weEthAmount weETH received by the depositer function depositStETHForWeETHWithPermit(uint256 _amount, address _referral, ILiquifier.PermitInput calldata _permit) external returns (uint256) { - try IERC20PermitUpgradeable(address(stETH)).permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s) {} + try IERC20PermitUpgradeable(address(stETH)).permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s) {} catch { if (_permit.deadline < block.timestamp) revert("PERMIT_EXPIRED"); } @@ -96,7 +97,7 @@ contract DepositAdapter is UUPSUpgradeable, OwnableUpgradeable { stETH.approve(address(liquifier), actualTransferredAmount); uint256 eETHShares = liquifier.depositWithERC20(address(stETH), actualTransferredAmount, _referral); - + emit AdapterDeposit(msg.sender, actualTransferredAmount, SourceOfFunds.STETH, _referral); return _wrapAndReturn(eETHShares); } @@ -108,7 +109,7 @@ contract DepositAdapter is UUPSUpgradeable, OwnableUpgradeable { /// @param _permit Permit signature /// @return weEthAmount weETH received by the depositer function depositWstETHForWeETHWithPermit(uint256 _amount, address _referral, ILiquifier.PermitInput calldata _permit) external returns (uint256) { - try wstETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s) {} + try wstETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s) {} catch { if (_permit.deadline < block.timestamp) revert("PERMIT_EXPIRED"); } @@ -122,7 +123,7 @@ contract DepositAdapter is UUPSUpgradeable, OwnableUpgradeable { stETH.approve(address(liquifier), actualTransferredAmount); uint256 eETHShares = liquifier.depositWithERC20(address(stETH), actualTransferredAmount, _referral); - + emit AdapterDeposit(msg.sender, actualTransferredAmount, SourceOfFunds.WSTETH, _referral); return _wrapAndReturn(eETHShares); } diff --git a/src/EETH.sol b/src/EETH.sol index 586384e60..0a4ad5c09 100644 --- a/src/EETH.sol +++ b/src/EETH.sol @@ -1,27 +1,29 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/utils/CountersUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; + import "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/utils/CountersUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/utils/cryptography/ECDSAUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol"; -import "./interfaces/IeETH.sol"; -import "./interfaces/ILiquidityPool.sol"; import "./AssetRecovery.sol"; +import "./interfaces/ILiquidityPool.sol"; import "./interfaces/IRoleRegistry.sol"; +import "./interfaces/IeETH.sol"; contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20PermitUpgradeable, IeETH, AssetRecovery { using CountersUpgradeable for CountersUpgradeable.Counter; + ILiquidityPool public liquidityPool; uint256 public totalShares; - mapping (address => uint256) public shares; - mapping (address => mapping (address => uint256)) public allowances; - mapping (address => CountersUpgradeable.Counter) private _nonces; + mapping(address => uint256) public shares; + mapping(address => mapping(address => uint256)) public allowances; + mapping(address => CountersUpgradeable.Counter) private _nonces; bytes32 private constant _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); @@ -39,7 +41,7 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P bytes32 public constant EETH_OPERATING_ADMIN_ROLE = keccak256("EETH_OPERATING_ADMIN_ROLE"); - event TransferShares( address indexed from, address indexed to, uint256 sharesValue); + event TransferShares(address indexed from, address indexed to, uint256 sharesValue); error IncorrectRole(); @@ -58,12 +60,12 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P require(_roleRegistry != address(0), "must set role registry"); roleRegistry = IRoleRegistry(_roleRegistry); - _disableInitializers(); + _disableInitializers(); } function initialize(address _liquidityPool) external initializer { require(_liquidityPool != address(0), "No zero addresses"); - + __UUPSUpgradeable_init(); __Ownable_init(); liquidityPool = ILiquidityPool(_liquidityPool); @@ -104,7 +106,7 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P function increaseAllowance(address _spender, uint256 _increaseAmount) external returns (bool) { address owner = msg.sender; uint256 currentAllowance = allowance(owner, _spender); - _approve(owner, _spender,currentAllowance + _increaseAmount); + _approve(owner, _spender, currentAllowance + _increaseAmount); return true; } @@ -128,15 +130,7 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P return true; } - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) public virtual override(IeETH, IERC20PermitUpgradeable) { + function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override(IeETH, IERC20PermitUpgradeable) { require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); @@ -150,21 +144,21 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P } function recoverETH(address payable to, uint256 amount) external { - if(!roleRegistry.hasRole(EETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(EETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); _recoverETH(to, amount); } function recoverERC20(address token, address to, uint256 amount) external { - if(!roleRegistry.hasRole(EETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(EETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); _recoverERC20(token, to, amount); } function recoverERC721(address token, address to, uint256 tokenId) external { - if(!roleRegistry.hasRole(EETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(EETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); _recoverERC721(token, to, tokenId); } - // [INTERNAL FUNCTIONS] + // [INTERNAL FUNCTIONS] function _transfer(address _sender, address _recipient, uint256 _amount) internal { uint256 _sharesToTransfer = liquidityPool.sharesForAmount(_amount); _transferShares(_sender, _recipient, _sharesToTransfer); @@ -190,9 +184,7 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P emit TransferShares(_sender, _recipient, _sharesAmount); } - function _authorizeUpgrade( - address /* newImplementation */ - ) internal view override { + function _authorizeUpgrade(address /* newImplementation */ ) internal view override { roleRegistry.onlyProtocolUpgrader(msg.sender); } @@ -203,9 +195,17 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P } // [GETTERS] - function name() public pure returns (string memory) { return "ether.fi ETH"; } - function symbol() public pure returns (string memory) { return "eETH"; } - function decimals() public pure returns (uint8) { return 18; } + function name() public pure returns (string memory) { + return "ether.fi ETH"; + } + + function symbol() public pure returns (string memory) { + return "eETH"; + } + + function decimals() public pure returns (uint8) { + return 18; + } function totalSupply() public view returns (uint256) { return liquidityPool.getTotalPooledEther(); @@ -235,11 +235,7 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P } } - function _buildDomainSeparator( - bytes32 typeHash, - bytes32 nameHash, - bytes32 versionHash - ) private view returns (bytes32) { + function _buildDomainSeparator(bytes32 typeHash, bytes32 nameHash, bytes32 versionHash) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } diff --git a/src/EarlyAdopterPool.sol b/src/EarlyAdopterPool.sol index 0c1976181..c6cff51ca 100644 --- a/src/EarlyAdopterPool.sol +++ b/src/EarlyAdopterPool.sol @@ -1,11 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/utils/math/Math.sol"; -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; + import "@openzeppelin/contracts/security/Pausable.sol"; +import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/math/Math.sol"; contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { using Math for uint256; @@ -55,18 +56,8 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { event Withdrawn(address indexed sender); event ClaimReceiverContractSet(address indexed receiverAddress); event ClaimingOpened(uint256 deadline); - event Fundsclaimed( - address indexed user, - uint256 indexed pointsAccumulated - ); - event ERC20TVLUpdated( - uint256 rETHBal, - uint256 wstETHBal, - uint256 sfrxETHBal, - uint256 cbETHBal, - uint256 ETHBal, - uint256 tvl - ); + event Fundsclaimed(address indexed user, uint256 indexed pointsAccumulated); + event ERC20TVLUpdated(uint256 rETHBal, uint256 wstETHBal, uint256 sfrxETHBal, uint256 cbETHBal, uint256 ETHBal, uint256 tvl); event EthTVLUpdated(uint256 ETHBal, uint256 tvl); @@ -82,12 +73,7 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { /// @param _wstETH address of the wstEth contract to receive /// @param _sfrxETH address of the sfrxEth contract to receive /// @param _cbETH address of the _cbEth contract to receive - constructor( - address _rETH, - address _wstETH, - address _sfrxETH, - address _cbETH - ) { + constructor(address _rETH, address _wstETH, address _sfrxETH, address _cbETH) { rETH = _rETH; wstETH = _wstETH; sfrxETH = _sfrxETH; @@ -107,19 +93,8 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { /// @dev User must have approved contract before /// @param _erc20Contract erc20 token contract being deposited /// @param _amount amount of the erc20 token being deposited - function deposit(address _erc20Contract, uint256 _amount) - external - OnlyCorrectAmount(_amount) - DepositingOpen - whenNotPaused - { - require( - (_erc20Contract == rETH || - _erc20Contract == sfrxETH || - _erc20Contract == wstETH || - _erc20Contract == cbETH), - "Unsupported token" - ); + function deposit(address _erc20Contract, uint256 _amount) external OnlyCorrectAmount(_amount) DepositingOpen whenNotPaused { + require((_erc20Contract == rETH || _erc20Contract == sfrxETH || _erc20Contract == wstETH || _erc20Contract == cbETH), "Unsupported token"); depositInfo[msg.sender].depositTime = block.timestamp; depositInfo[msg.sender].totalERC20Balance += _amount; @@ -127,24 +102,11 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { require(IERC20(_erc20Contract).transferFrom(msg.sender, address(this), _amount), "Transfer failed"); emit DepositERC20(msg.sender, _amount); - emit ERC20TVLUpdated( - rETHInstance.balanceOf(address(this)), - wstETHInstance.balanceOf(address(this)), - sfrxETHInstance.balanceOf(address(this)), - cbETHInstance.balanceOf(address(this)), - address(this).balance, - getContractTVL() - ); + emit ERC20TVLUpdated(rETHInstance.balanceOf(address(this)), wstETHInstance.balanceOf(address(this)), sfrxETHInstance.balanceOf(address(this)), cbETHInstance.balanceOf(address(this)), address(this).balance, getContractTVL()); } /// @notice deposits Ether into contract - function depositEther() - external - payable - OnlyCorrectAmount(msg.value) - DepositingOpen - whenNotPaused - { + function depositEther() external payable OnlyCorrectAmount(msg.value) DepositingOpen whenNotPaused { depositInfo[msg.sender].depositTime = block.timestamp; depositInfo[msg.sender].etherBalance += msg.value; @@ -164,10 +126,7 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { /// @dev can only call once receiver contract is ready and claiming is open function claim() public nonReentrant { require(claimingOpen == 1, "Claiming not open"); - require( - claimReceiverContract != address(0), - "Claiming address not set" - ); + require(claimReceiverContract != address(0), "Claiming address not set"); require(block.timestamp <= claimDeadline, "Claiming is complete"); require(depositInfo[msg.sender].depositTime != 0, "No deposit stored"); @@ -179,8 +138,8 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { /// @notice Sets claiming to be open, to allow users to claim their points /// @param _claimDeadline the amount of time in days until claiming will close - function setClaimingOpen(uint256 _claimDeadline) public onlyOwner { - claimDeadline = block.timestamp + (_claimDeadline * 86400); + function setClaimingOpen(uint256 _claimDeadline) public onlyOwner { + claimDeadline = block.timestamp + (_claimDeadline * 86_400); claimingOpen = 1; endTime = block.timestamp; @@ -189,10 +148,7 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { /// @notice Set the contract which will receive claimed funds /// @param _receiverContract contract address for where claiming will send the funds - function setClaimReceiverContract(address _receiverContract) - public - onlyOwner - { + function setClaimReceiverContract(address _receiverContract) public onlyOwner { require(_receiverContract != address(0), "Cannot set as address zero"); claimReceiverContract = _receiverContract; @@ -211,17 +167,11 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { } //Scaled by 1000, therefore, 1005 would be 1.005 - uint256 userMultiplier = Math.min( - 2000, - 1000 + ((lengthOfDeposit * 10) / 2592) / 10 - ); - uint256 totalUserBalance = depositInfo[_user].etherBalance + - depositInfo[_user].totalERC20Balance; + uint256 userMultiplier = Math.min(2000, 1000 + ((lengthOfDeposit * 10) / 2592) / 10); + uint256 totalUserBalance = depositInfo[_user].etherBalance + depositInfo[_user].totalERC20Balance; //Formula for calculating points total - return - ((Math.sqrt(totalUserBalance) * lengthOfDeposit) * - userMultiplier) / 1e14; + return ((Math.sqrt(totalUserBalance) * lengthOfDeposit) * userMultiplier) / 1e14; } //Pauses the contract @@ -270,7 +220,7 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { require(sfrxETHInstance.transfer(receiver, sfrxEthbal), "Transfer failed"); require(cbETHInstance.transfer(receiver, cbEthBal), "Transfer failed"); - (bool sent, ) = receiver.call{value: ethBalance}(""); + (bool sent,) = receiver.call{value: ethBalance}(""); require(sent, "Failed to send Ether"); } @@ -280,25 +230,10 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { /// @dev Returns the total value locked of all currencies in contract function getContractTVL() public view returns (uint256 tvl) { - tvl = (rETHInstance.balanceOf(address(this)) + - wstETHInstance.balanceOf(address(this)) + - sfrxETHInstance.balanceOf(address(this)) + - cbETHInstance.balanceOf(address(this)) + - address(this).balance); + tvl = (rETHInstance.balanceOf(address(this)) + wstETHInstance.balanceOf(address(this)) + sfrxETHInstance.balanceOf(address(this)) + cbETHInstance.balanceOf(address(this)) + address(this).balance); } - function getUserTVL(address _user) - public - view - returns ( - uint256 rETHBal, - uint256 wstETHBal, - uint256 sfrxETHBal, - uint256 cbETHBal, - uint256 ethBal, - uint256 totalBal - ) - { + function getUserTVL(address _user) public view returns (uint256 rETHBal, uint256 wstETHBal, uint256 sfrxETHBal, uint256 cbETHBal, uint256 ethBal, uint256 totalBal) { rETHBal = userToErc20Balance[_user][rETH]; wstETHBal = userToErc20Balance[_user][wstETH]; sfrxETHBal = userToErc20Balance[_user][sfrxETH]; @@ -312,10 +247,7 @@ contract EarlyAdopterPool is Ownable, ReentrancyGuard, Pausable { //-------------------------------------------------------------------------------------- modifier OnlyCorrectAmount(uint256 _amount) { - require( - _amount >= 0.1 ether && _amount <= 100 ether, - "Incorrect Deposit Amount" - ); + require(_amount >= 0.1 ether && _amount <= 100 ether, "Incorrect Deposit Amount"); _; } diff --git a/src/EtherFiAdmin.sol b/src/EtherFiAdmin.sol index 2e9883a04..4dcd6380a 100644 --- a/src/EtherFiAdmin.sol +++ b/src/EtherFiAdmin.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "./RoleRegistry.sol"; -import "./interfaces/IEtherFiOracle.sol"; -import "./interfaces/IStakingManager.sol"; import "./interfaces/IAuctionManager.sol"; import "./interfaces/IEtherFiNodesManager.sol"; +import "./interfaces/IEtherFiOracle.sol"; import "./interfaces/ILiquidityPool.sol"; import "./interfaces/IMembershipManager.sol"; +import "./interfaces/IStakingManager.sol"; import "./interfaces/IWithdrawRequestNFT.sol"; interface IEtherFiPausable { @@ -20,8 +20,6 @@ interface IEtherFiPausable { } contract EtherFiAdmin is Initializable, OwnableUpgradeable, UUPSUpgradeable { - - struct TaskStatus { bool completed; bool exists; @@ -70,17 +68,7 @@ contract EtherFiAdmin is Initializable, OwnableUpgradeable, UUPSUpgradeable { _disableInitializers(); } - function initialize( - address _etherFiOracle, - address _stakingManager, - address _auctionManager, - address _etherFiNodesManager, - address _liquidityPool, - address _membershipManager, - address _withdrawRequestNft, - int32 _acceptableRebaseAprInBps, - uint16 _postReportWaitTimeInSlots - ) external initializer { + function initialize(address _etherFiOracle, address _stakingManager, address _auctionManager, address _etherFiNodesManager, address _liquidityPool, address _membershipManager, address _withdrawRequestNft, int32 _acceptableRebaseAprInBps, uint16 _postReportWaitTimeInSlots) external initializer { __Ownable_init(); __UUPSUpgradeable_init(); @@ -100,7 +88,7 @@ contract EtherFiAdmin is Initializable, OwnableUpgradeable, UUPSUpgradeable { // if true, pause, // else, unpuase function pause(bool _etherFiOracle, bool _stakingManager, bool _auctionManager, bool _etherFiNodesManager, bool _liquidityPool, bool _membershipManager) external { - if( !roleRegistry.hasRole(roleRegistry.PROTOCOL_PAUSER(), msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(roleRegistry.PROTOCOL_PAUSER(), msg.sender)) revert IncorrectRole(); if (_etherFiOracle && !IEtherFiPausable(address(etherFiOracle)).paused()) { etherFiOracle.pauseContract(); } @@ -127,7 +115,7 @@ contract EtherFiAdmin is Initializable, OwnableUpgradeable, UUPSUpgradeable { } function unPause(bool _etherFiOracle, bool _stakingManager, bool _auctionManager, bool _etherFiNodesManager, bool _liquidityPool, bool _membershipManager) external { - if( !roleRegistry.hasRole(roleRegistry.PROTOCOL_UNPAUSER(), msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(roleRegistry.PROTOCOL_UNPAUSER(), msg.sender)) revert IncorrectRole(); if (_etherFiOracle && IEtherFiPausable(address(etherFiOracle)).paused()) { etherFiOracle.unPauseContract(); } @@ -159,9 +147,8 @@ contract EtherFiAdmin is Initializable, OwnableUpgradeable, UUPSUpgradeable { validatorTaskBatchSize = 100; } - function setValidatorTaskBatchSize(uint16 _batchSize) external { - if(!roleRegistry.hasRole(ETHERFI_ORACLE_EXECUTOR_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(ETHERFI_ORACLE_EXECUTOR_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); validatorTaskBatchSize = _batchSize; } @@ -221,15 +208,15 @@ contract EtherFiAdmin is Initializable, OwnableUpgradeable, UUPSUpgradeable { emit ValidatorApprovalTaskInvalidated(taskHash, _reportHash, _validators); } - //protocol owns the eth that was distributed to NO and treasury in eigenpods and etherfinodes - function _handleProtocolFees(IEtherFiOracle.OracleReport calldata _report) internal { + //protocol owns the eth that was distributed to NO and treasury in eigenpods and etherfinodes + function _handleProtocolFees(IEtherFiOracle.OracleReport calldata _report) internal { require(_report.protocolFees >= 0, "EtherFiAdmin: protocol fees can't be negative"); - if(_report.protocolFees == 0) { + if (_report.protocolFees == 0) { return; } int128 totalRewards = _report.protocolFees + _report.accruedRewards; // protocol fees are less than 20% of total rewards - require( _report.protocolFees * 5 <= totalRewards, "EtherFiAdmin: protocol fees exceed 20% total rewards"); + require(_report.protocolFees * 5 <= totalRewards, "EtherFiAdmin: protocol fees exceed 20% total rewards"); liquidityPool.payProtocolFees(uint128(_report.protocolFees)); } @@ -251,9 +238,9 @@ contract EtherFiAdmin is Initializable, OwnableUpgradeable, UUPSUpgradeable { int256 currentTVL = int128(uint128(liquidityPool.getTotalPooledEther())); int256 apr; if (currentTVL > 0) { - apr = 10000 * (_report.accruedRewards * 365 days) / (currentTVL * elapsedTime); + apr = 10_000 * (_report.accruedRewards * 365 days) / (currentTVL * elapsedTime); } - int256 absApr = (apr > 0) ? apr : - apr; + int256 absApr = (apr > 0) ? apr : -apr; require(absApr <= acceptableRebaseAprInBps, "EtherFiAdmin: TVL changed too much"); membershipManager.rebase(_report.accruedRewards); @@ -262,7 +249,7 @@ contract EtherFiAdmin is Initializable, OwnableUpgradeable, UUPSUpgradeable { function _enqueueValidatorApprovalTask(bytes32 _reportHash, uint256[] calldata _validators) internal { uint256 numBatches = (_validators.length + validatorTaskBatchSize - 1) / validatorTaskBatchSize; - if(_validators.length == 0) { + if (_validators.length == 0) { return; } for (uint256 i = 0; i < numBatches; i++) { diff --git a/src/EtherFiNode.sol b/src/EtherFiNode.sol index 9b6433ea5..22fb4d850 100644 --- a/src/EtherFiNode.sol +++ b/src/EtherFiNode.sol @@ -3,13 +3,15 @@ pragma solidity ^0.8.27; import {IEtherFiNode} from "../src/interfaces/IEtherFiNode.sol"; import {IEtherFiNodesManager} from "../src/interfaces/IEtherFiNodesManager.sol"; -import {IRoleRegistry} from "../src/interfaces/IRoleRegistry.sol"; + import {ILiquidityPool} from "../src/interfaces/ILiquidityPool.sol"; +import {IRoleRegistry} from "../src/interfaces/IRoleRegistry.sol"; import {IDelegationManager} from "../src/eigenlayer-interfaces/IDelegationManager.sol"; import {IDelegationManagerTypes} from "../src/eigenlayer-interfaces/IDelegationManager.sol"; -import {IEigenPodManager} from "../src/eigenlayer-interfaces/IEigenPodManager.sol"; + import {IEigenPod} from "../src/eigenlayer-interfaces/IEigenPod.sol"; +import {IEigenPodManager} from "../src/eigenlayer-interfaces/IEigenPodManager.sol"; import {IStrategy} from "../src/eigenlayer-interfaces/IStrategy.sol"; import {BeaconChainProofs} from "../src/eigenlayer-libraries/BeaconChainProofs.sol"; @@ -17,7 +19,6 @@ import {IERC20} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC20. import {LibCall} from "../lib/solady/src/utils/LibCall.sol"; contract EtherFiNode is IEtherFiNode { - ILiquidityPool public immutable liquidityPool; IEtherFiNodesManager public immutable etherFiNodesManager; IRoleRegistry public immutable roleRegistry; @@ -25,7 +26,7 @@ contract EtherFiNode is IEtherFiNode { // eigenlayer core contracts IEigenPodManager public immutable eigenPodManager; IDelegationManager public immutable delegationManager; - uint32 public constant EIGENLAYER_WITHDRAWAL_DELAY_BLOCKS = 100800; + uint32 public constant EIGENLAYER_WITHDRAWAL_DELAY_BLOCKS = 100_800; address public constant BEACON_ETH_STRATEGY_ADDRESS = address(0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0); //--------------------------------------------------------------------------- @@ -83,7 +84,6 @@ contract EtherFiNode is IEtherFiNode { /// @dev convenience function to queue a beaconETH withdrawal from eigenlayer. You must wait EIGENLAYER_WITHDRAWAL_DELAY_BLOCKS before claiming. /// It is fine to queue a withdrawal before validators have finished exiting on the beacon chain. function queueETHWithdrawal(uint256 amount) external onlyEtherFiNodesManager returns (bytes32 withdrawalRoot) { - // beacon eth is always 1 to 1 with deposit shares uint256[] memory depositShares = new uint256[](1); depositShares[0] = amount; @@ -100,20 +100,17 @@ contract EtherFiNode is IEtherFiNode { return delegationManager.queueWithdrawals(paramsArray)[0]; } - /// @dev completes all queued beaconETH withdrawals that are currently claimable. /// Note that since the node is usually delegated to an operator, /// most of the time this should be called with "receiveAsTokens" = true because /// receiving shares while delegated will simply redelegate the shares. function completeQueuedETHWithdrawals(bool receiveAsTokens) external onlyEtherFiNodesManager returns (uint256 balance) { - // because we are just dealing with beacon eth we don't need to populate the tokens[] array IERC20[] memory tokens = new IERC20[](1); bool anyWithdrawalsCompleted = false; - (IDelegationManager.Withdrawal[] memory queuedWithdrawals, ) = delegationManager.getQueuedWithdrawals(address(this)); + (IDelegationManager.Withdrawal[] memory queuedWithdrawals,) = delegationManager.getQueuedWithdrawals(address(this)); for (uint256 i = 0; i < queuedWithdrawals.length; i++) { - // skip this withdrawal if not enough time has passed or if it is not a simple beaconETH withdrawal uint32 slashableUntil = queuedWithdrawals[i].startBlock + EIGENLAYER_WITHDRAWAL_DELAY_BLOCKS; if (uint32(block.number) <= slashableUntil) continue; @@ -128,7 +125,7 @@ contract EtherFiNode is IEtherFiNode { // if there are available rewards, forward them to the liquidityPool uint256 balance = address(this).balance; if (balance > 0) { - (bool sent, ) = payable(address(liquidityPool)).call{value: balance, gas: 20000}(""); + (bool sent,) = payable(address(liquidityPool)).call{value: balance, gas: 20_000}(""); if (!sent) revert TransferFailed(); emit FundsTransferred(address(liquidityPool), balance); } @@ -143,11 +140,7 @@ contract EtherFiNode is IEtherFiNode { /// @dev complete an arbitrary withdrawal from eigenlayer. /// For the general case of claiming beaconETH withdrawals you can use completeQueuedETHWithdrawals instead. - function completeQueuedWithdrawals( - IDelegationManager.Withdrawal[] calldata withdrawals, - IERC20[][] calldata tokens, - bool[] calldata receiveAsTokens - ) external onlyEtherFiNodesManager { + function completeQueuedWithdrawals(IDelegationManager.Withdrawal[] calldata withdrawals, IERC20[][] calldata tokens, bool[] calldata receiveAsTokens) external onlyEtherFiNodesManager { delegationManager.completeQueuedWithdrawals(withdrawals, tokens, receiveAsTokens); } @@ -157,7 +150,7 @@ contract EtherFiNode is IEtherFiNode { function sweepFunds() external onlyEtherFiNodesManager returns (uint256 balance) { uint256 balance = address(this).balance; if (balance > 0) { - (bool sent, ) = payable(address(liquidityPool)).call{value: balance, gas: 20000}(""); + (bool sent,) = payable(address(liquidityPool)).call{value: balance, gas: 20_000}(""); if (!sent) revert TransferFailed(); emit FundsTransferred(address(liquidityPool), balance); } @@ -199,5 +192,4 @@ contract EtherFiNode is IEtherFiNode { if (msg.sender != address(etherFiNodesManager)) revert InvalidCaller(); _; } - } diff --git a/src/EtherFiNodesManager.sol b/src/EtherFiNodesManager.sol index bf1a04e78..3b6c8841c 100644 --- a/src/EtherFiNodesManager.sol +++ b/src/EtherFiNodesManager.sol @@ -1,31 +1,25 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import "@openzeppelin/contracts/utils/math/SafeCast.sol"; -import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; -import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; -import "./interfaces/IAuctionManager.sol"; import "./eigenlayer-interfaces/IEigenPod.sol"; +import "./interfaces/IAuctionManager.sol"; import "./interfaces/IEtherFiNode.sol"; import "./interfaces/IEtherFiNodesManager.sol"; + +import "./interfaces/IEtherFiRateLimiter.sol"; import "./interfaces/IProtocolRevenueManager.sol"; -import "./interfaces/IStakingManager.sol"; import "./interfaces/IRoleRegistry.sol"; -import "./interfaces/IEtherFiRateLimiter.sol"; +import "./interfaces/IStakingManager.sol"; +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -contract EtherFiNodesManager is - Initializable, - IEtherFiNodesManager, - OwnableUpgradeable, - PausableUpgradeable, - ReentrancyGuardUpgradeable, - UUPSUpgradeable -{ +import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; +import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; +import "@openzeppelin/contracts/utils/math/SafeCast.sol"; +contract EtherFiNodesManager is Initializable, IEtherFiNodesManager, OwnableUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { IStakingManager public immutable stakingManager; IRoleRegistry public immutable roleRegistry; IEtherFiRateLimiter public immutable rateLimiter; @@ -88,7 +82,7 @@ contract EtherFiNodesManager is function sweepFunds(uint256 id) external onlyAdmin whenNotPaused { address nodeAddr = etherfiNodeAddress(id); uint256 balance = IEtherFiNode(nodeAddr).sweepFunds(); - if(balance > 0) { + if (balance > 0) { emit FundsTransferred(nodeAddr, balance); } } @@ -111,7 +105,7 @@ contract EtherFiNodesManager is _validateNode(node); return address(IEtherFiNode(node).getEigenPod()); } - + function getEigenPod(uint256 id) public view returns (address) { return getEigenPod(etherfiNodeAddress(id)); } @@ -120,7 +114,7 @@ contract EtherFiNodesManager is _validateNode(node); IEtherFiNode(node).startCheckpoint(); } - + function startCheckpoint(uint256 id) external onlyPodProver whenNotPaused { startCheckpoint(etherfiNodeAddress(id)); } @@ -129,7 +123,7 @@ contract EtherFiNodesManager is _validateNode(node); IEtherFiNode(node).verifyCheckpointProofs(balanceContainerProof, proofs); } - + function verifyCheckpointProofs(uint256 id, BeaconChainProofs.BalanceContainerProof calldata balanceContainerProof, BeaconChainProofs.BalanceProof[] calldata proofs) external onlyPodProver whenNotPaused { verifyCheckpointProofs(etherfiNodeAddress(id), balanceContainerProof, proofs); } @@ -138,7 +132,7 @@ contract EtherFiNodesManager is _validateNode(node); IEtherFiNode(node).setProofSubmitter(proofSubmitter); } - + function setProofSubmitter(uint256 id, address proofSubmitter) external onlyEigenlayerAdmin whenNotPaused { setProofSubmitter(etherfiNodeAddress(id), proofSubmitter); } @@ -148,7 +142,7 @@ contract EtherFiNodesManager is rateLimiter.consume(UNRESTAKING_LIMIT_ID, SafeCast.toUint64(amount / 1 gwei)); return IEtherFiNode(node).queueETHWithdrawal(amount); } - + function queueETHWithdrawal(uint256 id, uint256 amount) external onlyEigenlayerAdmin whenNotPaused returns (bytes32 withdrawalRoot) { return queueETHWithdrawal(etherfiNodeAddress(id), amount); } @@ -156,11 +150,11 @@ contract EtherFiNodesManager is function completeQueuedETHWithdrawals(address node, bool receiveAsTokens) public onlyEigenlayerAdmin whenNotPaused { _validateNode(node); uint256 balance = IEtherFiNode(node).completeQueuedETHWithdrawals(receiveAsTokens); - if(balance > 0) { + if (balance > 0) { emit FundsTransferred(node, balance); } } - + function completeQueuedETHWithdrawals(uint256 id, bool receiveAsTokens) external onlyEigenlayerAdmin whenNotPaused { completeQueuedETHWithdrawals(etherfiNodeAddress(id), receiveAsTokens); } @@ -171,7 +165,7 @@ contract EtherFiNodesManager is rateLimiter.consume(UNRESTAKING_LIMIT_ID, SafeCast.toUint64(sumRestakingETHWithdrawals(params) / 1 gwei)); IEtherFiNode(node).queueWithdrawals(params); } - + function queueWithdrawals(uint256 id, IDelegationManager.QueuedWithdrawalParams[] calldata params) external onlyEigenlayerAdmin whenNotPaused { queueWithdrawals(etherfiNodeAddress(id), params); } @@ -180,7 +174,7 @@ contract EtherFiNodesManager is _validateNode(node); IEtherFiNode(node).completeQueuedWithdrawals(withdrawals, tokens, receiveAsTokens); } - + function completeQueuedWithdrawals(uint256 id, IDelegationManager.Withdrawal[] calldata withdrawals, IERC20[][] calldata tokens, bool[] calldata receiveAsTokens) external onlyEigenlayerAdmin whenNotPaused { completeQueuedWithdrawals(etherfiNodeAddress(id), withdrawals, tokens, receiveAsTokens); } @@ -233,19 +227,16 @@ contract EtherFiNodesManager is } } - function getTotalEthRequested (IEigenPod.WithdrawalRequest[] calldata requests) internal pure returns (uint256) { + function getTotalEthRequested(IEigenPod.WithdrawalRequest[] calldata requests) internal pure returns (uint256) { uint256 totalGwei; for (uint256 i = 0; i < requests.length; ++i) { - uint256 gweiAmount = requests[i].amountGwei == 0 - ? FULL_EXIT_GWEI - : uint256(requests[i].amountGwei); + uint256 gweiAmount = requests[i].amountGwei == 0 ? FULL_EXIT_GWEI : uint256(requests[i].amountGwei); totalGwei += gweiAmount; } return totalGwei; } - /** * @notice Triggers EIP-7251 consolidation requests for validators in the same EigenPod. * @dev Access: only admin role, pausable, nonReentrant. @@ -268,7 +259,7 @@ contract EtherFiNodesManager is if (msg.value < pod.getConsolidationRequestFee() * requests.length) revert InsufficientConsolidationFees(); node.requestConsolidation{value: msg.value}(requests); - for (uint256 i = 0; i < requests.length; ) { + for (uint256 i = 0; i < requests.length;) { bytes32 srcPkHash = calculateValidatorPubkeyHash(requests[i].srcPubkey); bytes32 targetPkHash = calculateValidatorPubkeyHash(requests[i].targetPubkey); @@ -278,7 +269,9 @@ contract EtherFiNodesManager is } else { emit ValidatorConsolidationRequested(address(pod), srcPkHash, requests[i].srcPubkey, targetPkHash, requests[i].targetPubkey); } - unchecked { ++i; } + unchecked { + ++i; + } } } @@ -350,7 +343,6 @@ contract EtherFiNodesManager is function linkLegacyValidatorIds(uint256[] calldata validatorIds, bytes[] calldata pubkeys) external onlyAdmin { if (validatorIds.length != pubkeys.length) revert LengthMismatch(); for (uint256 i = 0; i < validatorIds.length; i++) { - // lookup which node we are linking against address nodeAddress = legacyState.DEPRECATED_etherfiNodeAddress[validatorIds[i]]; if (nodeAddress == address(0)) revert UnknownNode(); @@ -364,7 +356,6 @@ contract EtherFiNodesManager is } } - //-------------------------------------------------------------------------------------- //-------------------------------- CALL FORWARDING ------------------------------------ //-------------------------------------------------------------------------------------- @@ -429,7 +420,7 @@ contract EtherFiNodesManager is //-------------------------------------------------------------------------------------- //----------------------------------- HELPERS ---------------------------------------- //-------------------------------------------------------------------------------------- - + /// @dev Internal helper to validate node exists and revert if not function _validateNode(address node) internal view { if (!stakingManager.deployedEtherFiNodes(node)) revert UnknownNode(); diff --git a/src/EtherFiOracle.sol b/src/EtherFiOracle.sol index c2402a350..df091ed5b 100644 --- a/src/EtherFiOracle.sol +++ b/src/EtherFiOracle.sol @@ -1,18 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; - +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; -import "./interfaces/IEtherFiOracle.sol"; import "./interfaces/IEtherFiAdmin.sol"; - +import "./interfaces/IEtherFiOracle.sol"; contract EtherFiOracle is Initializable, OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable, IEtherFiOracle { - mapping(address => IEtherFiOracle.CommitteeMemberState) public committeeMemberStates; // committee member wallet address to its State mapping(bytes32 => IEtherFiOracle.ConsensusState) public consensusStates; // report's hash -> Consensus State @@ -47,16 +44,12 @@ contract EtherFiOracle is Initializable, OwnableUpgradeable, PausableUpgradeable event ReportPublished(uint32 consensusVersion, uint32 refSlotFrom, uint32 refSlotTo, uint32 refBlockFrom, uint32 refBlockTo, bytes32 indexed hash); event ReportSubmitted(uint32 consensusVersion, uint32 refSlotFrom, uint32 refSlotTo, uint32 refBlockFrom, uint32 refBlockTo, bytes32 indexed hash, address indexed committeeMember); - /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } - function initialize(uint32 _quorumSize, uint32 _reportPeriodSlot, uint32 _reportStartSlot, uint32 _slotsPerEpoch, uint32 _secondsPerSlot, uint32 _genesisTime) - external - initializer - { + function initialize(uint32 _quorumSize, uint32 _reportPeriodSlot, uint32 _reportStartSlot, uint32 _slotsPerEpoch, uint32 _secondsPerSlot, uint32 _genesisTime) external initializer { __Ownable_init(); __UUPSUpgradeable_init(); @@ -75,7 +68,6 @@ contract EtherFiOracle is Initializable, OwnableUpgradeable, PausableUpgradeable require(shouldSubmitReport(msg.sender), "You don't need to submit a report"); verifyReport(_report); - // update the member state CommitteeMemberState storage memberState = committeeMemberStates[msg.sender]; memberState.lastReportRefSlot = _report.refSlotTo; @@ -84,15 +76,7 @@ contract EtherFiOracle is Initializable, OwnableUpgradeable, PausableUpgradeable // update the consensus state ConsensusState storage consenState = consensusStates[reportHash]; - emit ReportSubmitted( - _report.consensusVersion, - _report.refSlotFrom, - _report.refSlotTo, - _report.refBlockFrom, - _report.refBlockTo, - reportHash, - msg.sender - ); + emit ReportSubmitted(_report.consensusVersion, _report.refSlotFrom, _report.refSlotTo, _report.refBlockFrom, _report.refBlockTo, reportHash, msg.sender); // if the consensus reaches consenState.support++; @@ -170,14 +154,7 @@ contract EtherFiOracle is Initializable, OwnableUpgradeable, PausableUpgradeable lastPublishedReportRefBlock = _report.refBlockTo; // emit report published event - emit ReportPublished( - _report.consensusVersion, - _report.refSlotFrom, - _report.refSlotTo, - _report.refBlockFrom, - _report.refBlockTo, - _hash - ); + emit ReportPublished(_report.consensusVersion, _report.refSlotFrom, _report.refSlotTo, _report.refBlockFrom, _report.refBlockTo, _hash); } // Given the last published report AND the current slot number, @@ -196,31 +173,11 @@ contract EtherFiOracle is Initializable, OwnableUpgradeable, PausableUpgradeable } function generateReportHash(OracleReport calldata _report) public pure returns (bytes32) { - bytes32 chunk1 = keccak256( - abi.encode( - _report.consensusVersion, - _report.refSlotFrom, - _report.refSlotTo, - _report.refBlockFrom, - _report.refBlockTo, - _report.accruedRewards, - _report.protocolFees - ) - ); - - bytes32 chunk2 = keccak256( - abi.encode( - _report.validatorsToApprove - ) - ); - - bytes32 chunk3 = keccak256( - abi.encode( - _report.withdrawalRequestsToInvalidate, - _report.lastFinalizedWithdrawalRequestId, - _report.finalizedWithdrawalAmount - ) - ); + bytes32 chunk1 = keccak256(abi.encode(_report.consensusVersion, _report.refSlotFrom, _report.refSlotTo, _report.refBlockFrom, _report.refBlockTo, _report.accruedRewards, _report.protocolFees)); + + bytes32 chunk2 = keccak256(abi.encode(_report.validatorsToApprove)); + + bytes32 chunk3 = keccak256(abi.encode(_report.withdrawalRequestsToInvalidate, _report.lastFinalizedWithdrawalRequestId, _report.finalizedWithdrawalAmount)); return keccak256(abi.encode(chunk1, chunk2, chunk3)); } @@ -265,7 +222,7 @@ contract EtherFiOracle is Initializable, OwnableUpgradeable, PausableUpgradeable require(_reportStartSlot > lastPublishedReportRefSlot, "The start slot should be after the last published report"); require(_reportStartSlot % SLOTS_PER_EPOCH == 0, "The start slot should be at the beginning of the epoch"); reportStartSlot = _reportStartSlot; - + emit ReportStartSlotUpdated(_reportStartSlot); } @@ -294,7 +251,7 @@ contract EtherFiOracle is Initializable, OwnableUpgradeable, PausableUpgradeable require(etherFiAdmin == IEtherFiAdmin(address(0)), "EtherFiAdmin is already set"); etherFiAdmin = IEtherFiAdmin(_etherFiAdminAddress); } - + function unpublishReport(bytes32 _hash) external isAdmin { require(consensusStates[_hash].consensusReached, "Consensus is not reached yet"); consensusStates[_hash].support = 0; diff --git a/src/EtherFiRateLimiter.sol b/src/EtherFiRateLimiter.sol index f514dda7d..6d1564ed6 100644 --- a/src/EtherFiRateLimiter.sol +++ b/src/EtherFiRateLimiter.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; import "./interfaces/IEtherFiRateLimiter.sol"; @@ -10,7 +10,6 @@ import "./interfaces/IRoleRegistry.sol"; import "lib/BucketLimiter.sol"; contract EtherFiRateLimiter is IEtherFiRateLimiter, Initializable, UUPSUpgradeable, PausableUpgradeable { - IRoleRegistry public immutable roleRegistry; //--------------------------------------------------------------------------- @@ -181,4 +180,4 @@ contract EtherFiRateLimiter is IEtherFiRateLimiter, Initializable, UUPSUpgradeab if (!roleRegistry.hasRole(ETHERFI_RATE_LIMITER_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); _; } -} \ No newline at end of file +} diff --git a/src/EtherFiRedemptionManager.sol b/src/EtherFiRedemptionManager.sol index 821f41dfa..13bd2d232 100644 --- a/src/EtherFiRedemptionManager.sol +++ b/src/EtherFiRedemptionManager.sol @@ -1,21 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin/contracts/utils/math/SafeCast.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; -import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; + import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; +import "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import "./interfaces/ILiquidityPool.sol"; -import "./interfaces/IeETH.sol"; + import "./interfaces/IWeETH.sol"; +import "./interfaces/IeETH.sol"; import "lib/BucketLimiter.sol"; @@ -56,7 +58,7 @@ contract EtherFiRedemptionManager is Initializable, PausableUpgradeable, Reentra treasury = _treasury; liquidityPool = ILiquidityPool(payable(_liquidityPool)); eEth = IeETH(_eEth); - weEth = IWeETH(_weEth); + weEth = IWeETH(_weEth); _disableInitializers(); } @@ -112,7 +114,7 @@ contract EtherFiRedemptionManager is Initializable, PausableUpgradeable, Reentra * @param permit The permit params. */ function redeemWeEthWithPermit(uint256 weEthAmount, address receiver, IWeETH.PermitInput calldata permit) external whenNotPaused nonReentrant { - try weEth.permit(msg.sender, address(this), permit.value, permit.deadline, permit.v, permit.r, permit.s) {} catch {} + try weEth.permit(msg.sender, address(this), permit.value, permit.deadline, permit.v, permit.r, permit.s) {} catch {} _redeemWeEth(weEthAmount, receiver); } @@ -142,12 +144,12 @@ contract EtherFiRedemptionManager is Initializable, PausableUpgradeable, Reentra // To Treasury by transferring eETH IERC20(address(eEth)).safeTransfer(treasury, eEthFeeAmountToTreasury); - + // uint256 totalShares = eEth.totalShares(); require(eEth.totalShares() >= 1 gwei && eEth.totalShares() == totalEEthShare - (sharesToBurn + feeShareToStakers), "EtherFiRedemptionManager: Invalid total shares"); // To Receiver by transferring ETH, using gas 10k for additional safety - (bool success, ) = receiver.call{value: ethReceived, gas: 10_000}(""); + (bool success,) = receiver.call{value: ethReceived, gas: 10_000}(""); require(success, "EtherFiRedemptionManager: Transfer failed"); // Make sure the liquidity pool balance is correct && total shares are correct @@ -262,7 +264,6 @@ contract EtherFiRedemptionManager is Initializable, PausableUpgradeable, Reentra _redeem(eEthAmount, eEthShares, receiver, eEthAmountToReceiver, eEthFeeAmountToTreasury, sharesToBurn, feeShareToTreasury); } - function _updateRateLimit(uint256 amount) internal { uint64 bucketUnit = _convertToBucketUnit(amount, Math.Rounding.Up); require(BucketLimiter.consume(limit, bucketUnit), "BucketRateLimiter: rate limit exceeded"); @@ -277,7 +278,6 @@ contract EtherFiRedemptionManager is Initializable, PausableUpgradeable, Reentra return bucketUnit * BUCKET_UNIT_SCALE; } - function _calcRedemption(uint256 ethAmount) internal view returns (uint256 eEthShares, uint256 eEthAmountToReceiver, uint256 eEthFeeAmountToTreasury, uint256 sharesToBurn, uint256 feeShareToTreasury) { eEthShares = liquidityPool.sharesForAmount(ethAmount); eEthAmountToReceiver = liquidityPool.amountForShare(eEthShares.mulDiv(BASIS_POINT_SCALE - exitFeeInBps, BASIS_POINT_SCALE)); // ethShareToReceiver @@ -317,5 +317,4 @@ contract EtherFiRedemptionManager is Initializable, PausableUpgradeable, Reentra _hasRole(role, msg.sender); _; } - } diff --git a/src/EtherFiRestaker.sol b/src/EtherFiRestaker.sol index 71cb06ebc..de7d2520f 100644 --- a/src/EtherFiRestaker.sol +++ b/src/EtherFiRestaker.sol @@ -1,21 +1,21 @@ /// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import "./Liquifier.sol"; import "./LiquidityPool.sol"; +import "./Liquifier.sol"; -import "./eigenlayer-interfaces/IStrategyManager.sol"; import "./eigenlayer-interfaces/IDelegationManager.sol"; import "./eigenlayer-interfaces/IRewardsCoordinator.sol"; +import "./eigenlayer-interfaces/IStrategyManager.sol"; contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, PausableUpgradeable { using SafeERC20 for IERC20; @@ -40,11 +40,10 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, mapping(address => bool) public admins; mapping(address => TokenInfo) public tokenInfos; - + EnumerableSet.Bytes32Set private withdrawalRootsSet; mapping(bytes32 => IDelegationManager.Withdrawal) public DEPRECATED_withdrawalRootToWithdrawal; - event QueuedStEthWithdrawals(uint256[] _reqIds); event CompletedStEthQueuedWithdrawals(uint256[] _reqIds); event CompletedQueuedWithdrawal(bytes32 _withdrawalRoot); @@ -58,14 +57,14 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, error WrongOutput(); error IncorrectCaller(); - /// @custom:oz-upgrades-unsafe-allow constructor + /// @custom:oz-upgrades-unsafe-allow constructor constructor(address _rewardsCoordinator) { rewardsCoordinator = IRewardsCoordinator(_rewardsCoordinator); _disableInitializers(); } /// @notice initialize to set variables on deployment - function initialize(address _liquidityPool, address _liquifier) initializer external { + function initialize(address _liquidityPool, address _liquifier) external initializer { __Ownable_init(); __Pausable_init(); __UUPSUpgradeable_init(); @@ -80,10 +79,7 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, eigenLayerDelegationManager = liquifier.eigenLayerDelegationManager(); (,, IStrategy strategy,,,,,,,,) = liquifier.tokenInfos(address(lido)); - tokenInfos[address(lido)] = TokenInfo({ - elStrategy: strategy, - elSharesInPendingForWithdrawals: 0 - }); + tokenInfos[address(lido)] = TokenInfo({elStrategy: strategy, elSharesInPendingForWithdrawals: 0}); } receive() external payable {} @@ -92,7 +88,7 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, // | Handling Lido's stETH | // |--------------------------------------------------------------------------------------------| - /// Initiate the redemption of stETH for ETH + /// Initiate the redemption of stETH for ETH /// @notice Request for all stETH holdings function stEthRequestWithdrawal() external onlyAdmin returns (uint256[] memory) { uint256 amount = lido.balanceOf(address(this)); @@ -134,7 +130,7 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, // Send the ETH back to the liquidity pool function withdrawEther() public onlyAdmin { uint256 amountToLiquidityPool = address(this).balance; - (bool sent, ) = payable(address(liquidityPool)).call{value: amountToLiquidityPool, gas: 20000}(""); + (bool sent,) = payable(address(liquidityPool)).call{value: amountToLiquidityPool, gas: 20_000}(""); require(sent, "ETH_SEND_TO_LIQUIDITY_POOL_FAILED"); } @@ -146,7 +142,7 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, function setRewardsClaimer(address _claimer) external onlyAdmin { rewardsCoordinator.setClaimerFor(_claimer); } - + // delegate to an AVS operator function delegateTo(address operator, IDelegationManager.SignatureWithExpiry memory approverSignatureAndExpiry, bytes32 approverSalt) external onlyAdmin { eigenLayerDelegationManager.delegateTo(operator, approverSignatureAndExpiry, approverSalt); @@ -233,7 +229,7 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, (uint256 restaked, uint256 unrestaking, uint256 holding, uint256 pendingForWithdrawals) = getTotalPooledEtherSplits(_token); return restaked + unrestaking + holding + pendingForWithdrawals; } - + function getRestakedAmount(address _token) public view returns (uint256) { TokenInfo memory info = tokenInfos[_token]; IStrategy[] memory strategies = new IStrategy[](1); @@ -241,7 +237,7 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, // get the shares locked in the EigenPod // - `withdrawableShares` reflects the slashing on 'depositShares' - (uint256[] memory withdrawableShares, ) = eigenLayerDelegationManager.getWithdrawableShares(address(this), strategies); + (uint256[] memory withdrawableShares,) = eigenLayerDelegationManager.getWithdrawableShares(address(this), strategies); // convert the share amount to the token's balance amount uint256 restaked = info.elStrategy.sharesToUnderlyingView(withdrawableShares[0]); @@ -265,7 +261,8 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, restaked = liquifier.quoteByFairValue(_token, restakedTokenAmount); // restaked & pending for withdrawals unrestaking = liquifier.quoteByFairValue(_token, unrestakingTokenAmount); // restaked & pending for withdrawals } - holding = liquifier.quoteByFairValue(_token, IERC20(_token).balanceOf(address(this))); /// eth value for erc20 holdings + holding = liquifier.quoteByFairValue(_token, IERC20(_token).balanceOf(address(this))); + /// eth value for erc20 holdings pendingForWithdrawals = liquifier.quoteByFairValue(_token, getAmountPendingForRedemption(_token)); } @@ -318,11 +315,7 @@ contract EtherFiRestaker is Initializable, UUPSUpgradeable, OwnableUpgradeable, strategies[0] = tokenInfos[_token].elStrategy; shares[0] = _shares; - params[0] = IDelegationManagerTypes.QueuedWithdrawalParams({ - strategies: strategies, - depositShares: shares, - __deprecated_withdrawer: address(this) - }); + params[0] = IDelegationManagerTypes.QueuedWithdrawalParams({strategies: strategies, depositShares: shares, __deprecated_withdrawer: address(this)}); return queueWithdrawalsWithParams(params); } diff --git a/src/EtherFiRewardsRouter.sol b/src/EtherFiRewardsRouter.sol index 31ac83bbf..8b2b60175 100644 --- a/src/EtherFiRewardsRouter.sol +++ b/src/EtherFiRewardsRouter.sol @@ -3,12 +3,13 @@ pragma solidity ^0.8.24; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; + import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "./RoleRegistry.sol"; -contract EtherFiRewardsRouter is OwnableUpgradeable, UUPSUpgradeable { +contract EtherFiRewardsRouter is OwnableUpgradeable, UUPSUpgradeable { using SafeERC20 for IERC20; address public immutable treasury; @@ -42,12 +43,11 @@ contract EtherFiRewardsRouter is OwnableUpgradeable, UUPSUpgradeable { } function withdrawToLiquidityPool() external { - uint256 balance = address(this).balance; require(balance > 0, "Contract balance is zero"); - (bool success, ) = liquidityPool.call{value: balance}(""); + (bool success,) = liquidityPool.call{value: balance}(""); require(success, "TRANSFER_FAILED"); - + emit EthSent(address(this), liquidityPool, balance); } @@ -69,5 +69,7 @@ contract EtherFiRewardsRouter is OwnableUpgradeable, UUPSUpgradeable { function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} - function getImplementation() external view returns (address) {return _getImplementation();} + function getImplementation() external view returns (address) { + return _getImplementation(); + } } diff --git a/src/EtherFiTimelock.sol b/src/EtherFiTimelock.sol index 451b26e26..18f8694c3 100644 --- a/src/EtherFiTimelock.sol +++ b/src/EtherFiTimelock.sol @@ -4,12 +4,5 @@ pragma solidity ^0.8.13; import "@openzeppelin/contracts/governance/TimelockController.sol"; contract EtherFiTimelock is TimelockController { - - constructor( - uint256 minDelay, - address[] memory proposers, - address[] memory executors, - address admin - ) TimelockController(minDelay, proposers, executors, admin) {} - + constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) TimelockController(minDelay, proposers, executors, admin) {} } diff --git a/src/LiquidityPool.sol b/src/LiquidityPool.sol index 85c01df37..1be96e5a4 100644 --- a/src/LiquidityPool.sol +++ b/src/LiquidityPool.sol @@ -3,19 +3,20 @@ pragma solidity ^0.8.13; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "./EtherFiRedemptionManager.sol"; -import "./interfaces/IeETH.sol"; -import "./interfaces/IStakingManager.sol"; -import "./interfaces/IWithdrawRequestNFT.sol"; -import "./interfaces/ILiquidityPool.sol"; -import "./interfaces/ILiquifier.sol"; + import "./interfaces/IEtherFiNode.sol"; import "./interfaces/IEtherFiNodesManager.sol"; +import "./interfaces/ILiquidityPool.sol"; +import "./interfaces/ILiquifier.sol"; import "./interfaces/IRoleRegistry.sol"; +import "./interfaces/IStakingManager.sol"; +import "./interfaces/IWithdrawRequestNFT.sol"; +import "./interfaces/IeETH.sol"; contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, ILiquidityPool { using SafeERC20 for IERC20; @@ -28,7 +29,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL address public DEPRECATED_regulationsManager; address public membershipManager; address public DEPRECATED_TNFT; - IeETH public eETH; + IeETH public eETH; bool public DEPRECATED_eEthliquidStakingOpened; @@ -85,7 +86,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL event Deposit(address indexed sender, uint256 amount, SourceOfFunds source, address referral); event Withdraw(address indexed sender, address recipient, uint256 amount, SourceOfFunds source); event UpdatedWhitelist(address userAddress, bool value); - event UpdatedTreasury(address newTreasury); + event UpdatedTreasury(address newTreasury); event UpdatedFeeRecipient(address newFeeRecipient); event BnftHolderDeregistered(address user, uint256 index); event BnftHolderRegistered(address user, uint256 index); @@ -125,7 +126,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL function initialize(address _eEthAddress, address _stakingManagerAddress, address _nodesManagerAddress, address _membershipManagerAddress, address _tNftAddress, address _etherFiAdminContract, address _withdrawRequestNFT) external initializer { if (_eEthAddress == address(0) || _stakingManagerAddress == address(0) || _nodesManagerAddress == address(0) || _membershipManagerAddress == address(0) || _tNftAddress == address(0)) revert DataNotSet(); - + __Ownable_init(); __UUPSUpgradeable_init(); eETH = IeETH(_eEthAddress); @@ -141,7 +142,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL DEPRECATED_isLpBnftHolder = false; } - function initializeOnUpgrade(address _auctionManager, address _liquifier) external onlyOwner { + function initializeOnUpgrade(address _auctionManager, address _liquifier) external onlyOwner { require(_auctionManager != address(0) && _liquifier != address(0) && address(DEPRECATED_auctionManager) == address(0) && address(liquifier) == address(0), "Invalid"); DEPRECATED_auctionManager = _auctionManager; @@ -153,7 +154,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL require(address(etherFiRedemptionManager) == address(0) && _etherFiRedemptionManager != address(0), "Invalid"); require(address(roleRegistry) == address(0x00), "already initialized"); - etherFiRedemptionManager = EtherFiRedemptionManager(payable(_etherFiRedemptionManager)); + etherFiRedemptionManager = EtherFiRedemptionManager(payable(_etherFiRedemptionManager)); roleRegistry = IRoleRegistry(_roleRegistry); //correct splits @@ -161,7 +162,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL totalValueInLp = uint128(address(this).balance); totalValueOutOfLp = tvl - totalValueInLp; - if(tvl != getTotalPooledEther()) revert(); + if (tvl != getTotalPooledEther()) revert(); } // Used by eETH staking flow @@ -230,7 +231,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL IERC20(address(eETH)).safeTransferFrom(msg.sender, address(withdrawRequestNFT), amount); uint256 requestId = withdrawRequestNFT.requestWithdraw(uint96(amount), uint96(share), recipient, 0); - + emit Withdraw(msg.sender, recipient, amount, SourceOfFunds.EETH); return requestId; @@ -242,11 +243,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL /// @param _amount requested amount to withdraw from contract /// @param _permit signed permit data to approve transfer of eETH /// @return uint256 requestId of the WithdrawRequestNFT - function requestWithdrawWithPermit(address _owner, uint256 _amount, PermitInput calldata _permit) - external - whenNotPaused - returns (uint256) - { + function requestWithdrawWithPermit(address _owner, uint256 _amount, PermitInput calldata _permit) external whenNotPaused returns (uint256) { try eETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s) {} catch {} return requestWithdraw(_owner, _amount); } @@ -272,7 +269,6 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL return requestId; } - //--------------------------------------------------------------------------- //---------------------- Staking/Deposit Flow ------------------------------- //--------------------------------------------------------------------------- @@ -284,11 +280,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL /// @notice claim bids and send 1 eth deposits to deposit contract to create the provided validators. /// @dev step 2 of staking flow - function batchRegister( - IStakingManager.DepositData[] calldata _depositData, - uint256[] calldata _bidIds, - address _etherFiNode - ) external whenNotPaused { + function batchRegister(IStakingManager.DepositData[] calldata _depositData, uint256[] calldata _bidIds, address _etherFiNode) external whenNotPaused { require(validatorSpawner[msg.sender].registered, "Incorrect Caller"); // liquidity pool supplies 1 eth per validator @@ -301,11 +293,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL /// @notice send remaining eth to deposit contract to activate the provided validators /// @dev step 3 of staking flow. This version exists to remain compatible with existing callers. /// future services should use confirmAndFundBeaconValidators() - function batchApproveRegistration( - uint256[] memory _validatorIds, - bytes[] calldata _pubkeys, - bytes[] calldata _signatures - ) external whenNotPaused { + function batchApproveRegistration(uint256[] memory _validatorIds, bytes[] calldata _pubkeys, bytes[] calldata _signatures) external whenNotPaused { if (!roleRegistry.hasRole(LIQUIDITY_POOL_VALIDATOR_APPROVER_ROLE, msg.sender)) revert IncorrectRole(); if (validatorSizeWei < 32 ether || validatorSizeWei > 2048 ether) revert InvalidValidatorSize(); @@ -324,18 +312,8 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL // enforce that all validators are part of same node if (address(etherFiNode) != address(nodesManager.etherfiNodeAddress(_validatorIds[i]))) revert InvalidEtherFiNode(); - bytes32 confirmDepositDataRoot = stakingManager.generateDepositDataRoot( - _pubkeys[i], - _signatures[i], - withdrawalCredentials, - remainingEthPerValidator - ); - IStakingManager.DepositData memory confirmDepositData = IStakingManager.DepositData({ - publicKey: _pubkeys[i], - signature: _signatures[i], - depositDataRoot: confirmDepositDataRoot, - ipfsHashForEncryptedValidatorKey: "" - }); + bytes32 confirmDepositDataRoot = stakingManager.generateDepositDataRoot(_pubkeys[i], _signatures[i], withdrawalCredentials, remainingEthPerValidator); + IStakingManager.DepositData memory confirmDepositData = IStakingManager.DepositData({publicKey: _pubkeys[i], signature: _signatures[i], depositDataRoot: confirmDepositDataRoot, ipfsHashForEncryptedValidatorKey: ""}); depositData[i] = confirmDepositData; } @@ -347,10 +325,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL /// @notice send remaining eth to deposit contract to activate the provided validators /// @dev step 3 of staking flow - function confirmAndFundBeaconValidators( - IStakingManager.DepositData[] calldata _depositData, - uint256 _validatorSizeWei - ) external whenNotPaused { + function confirmAndFundBeaconValidators(IStakingManager.DepositData[] calldata _depositData, uint256 _validatorSizeWei) external whenNotPaused { if (!roleRegistry.hasRole(LIQUIDITY_POOL_VALIDATOR_APPROVER_ROLE, msg.sender)) revert IncorrectRole(); if (_validatorSizeWei < 32 ether || _validatorSizeWei > 2048 ether) revert InvalidValidatorSize(); @@ -376,7 +351,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL /// @param _user The address of the Validator Spawner to register function registerValidatorSpawner(address _user) public { if (!roleRegistry.hasRole(LIQUIDITY_POOL_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); - require(!validatorSpawner[_user].registered, "Already registered"); + require(!validatorSpawner[_user].registered, "Already registered"); validatorSpawner[_user] = ValidatorSpawner({registered: true}); @@ -414,7 +389,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL /// @notice pay protocol fees including 5% to treaury, 5% to node operator and ethfund bnft holders /// @param _protocolFees The amount of protocol fees to pay in ether function payProtocolFees(uint128 _protocolFees) external { - if (msg.sender != address(etherFiAdminContract)) revert IncorrectCaller(); + if (msg.sender != address(etherFiAdminContract)) revert IncorrectCaller(); emit ProtocolFeePaid(_protocolFees); depositToRecipient(feeRecipient, _protocolFees, address(0)); } @@ -453,8 +428,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL } // Deprecated, just existing not to touch EtherFiAdmin contract - function setStakingTargetWeights(uint32 _eEthWeight, uint32 _etherFanWeight) external { - } + function setStakingTargetWeights(uint32 _eEthWeight, uint32 _etherFanWeight) external {} function addEthAmountLockedForWithdrawal(uint128 _amount) external { if (!(msg.sender == address(etherFiAdminContract))) revert IncorrectCaller(); @@ -493,7 +467,7 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL function _sendFund(address _recipient, uint256 _amount) internal { uint256 balance = address(this).balance; - (bool sent, ) = _recipient.call{value: _amount}(""); + (bool sent,) = _recipient.call{value: _amount}(""); require(sent && address(this).balance >= balance - _amount, "SendFail"); } @@ -551,7 +525,9 @@ contract LiquidityPool is Initializable, OwnableUpgradeable, UUPSUpgradeable, IL return (_share * getTotalPooledEther()) / totalShares; } - function getImplementation() external view returns (address) {return _getImplementation();} + function getImplementation() external view returns (address) { + return _getImplementation(); + } function _requireNotPaused() internal view virtual { require(!paused, "Pausable: paused"); diff --git a/src/Liquifier.sol b/src/Liquifier.sol index fa8a99434..99f4f0efe 100644 --- a/src/Liquifier.sol +++ b/src/Liquifier.sol @@ -1,20 +1,19 @@ /// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "./interfaces/ILiquifier.sol"; import "./interfaces/ILiquidityPool.sol"; +import "./interfaces/ILiquifier.sol"; -import "./eigenlayer-interfaces/IStrategyManager.sol"; import "./eigenlayer-interfaces/IDelegationManager.sol"; - +import "./eigenlayer-interfaces/IStrategyManager.sol"; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via PancakeSwap V3 @@ -79,7 +78,7 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab IPancackeV3SwapRouter pancakeRouter; mapping(string => bool) flags; - + // To support L2 native minting of weETH IERC20[] public dummies; address public l1SyncPool; @@ -112,9 +111,7 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab } /// @notice initialize to set variables on deployment - function initialize(address _treasury, address _liquidityPool, address _eigenLayerStrategyManager, address _lidoWithdrawalQueue, - address _stEth, address _cbEth, address _wbEth, address _cbEth_Eth_Pool, address _wbEth_Eth_Pool, address _stEth_Eth_Pool, - uint32 _timeBoundCapRefreshInterval) initializer external { + function initialize(address _treasury, address _liquidityPool, address _eigenLayerStrategyManager, address _lidoWithdrawalQueue, address _stEth, address _cbEth, address _wbEth, address _cbEth_Eth_Pool, address _wbEth_Eth_Pool, address _stEth_Eth_Pool, uint32 _timeBoundCapRefreshInterval) external initializer { __Pausable_init(); __Ownable_init(); __UUPSUpgradeable_init(); @@ -131,7 +128,7 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab cbEth_Eth_Pool = ICurvePool(_cbEth_Eth_Pool); wbEth_Eth_Pool = ICurvePool(_wbEth_Eth_Pool); stEth_Eth_Pool = ICurvePool(_stEth_Eth_Pool); - + timeBoundCapRefreshInterval = _timeBoundCapRefreshInterval; DEPRECATED_eigenLayerWithdrawalClaimGasCost = 150_000; } @@ -148,18 +145,18 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab /// @param _referral The referral address /// @return mintedAmount the amount of eETH minted to the caller (= msg.sender) /// If the token is l2Eth, only the l2SyncPool can call this function - function depositWithERC20(address _token, uint256 _amount, address _referral) public whenNotPaused nonReentrant returns (uint256) { + function depositWithERC20(address _token, uint256 _amount, address _referral) public whenNotPaused nonReentrant returns (uint256) { require(isTokenWhitelisted(_token) && (!tokenInfos[_token].isL2Eth || msg.sender == l1SyncPool), "NOT_ALLOWED"); if (tokenInfos[_token].isL2Eth) { - IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); + IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); } else { IERC20(_token).safeTransferFrom(msg.sender, address(etherfiRestaker), _amount); } // The L1SyncPool's `_anticipatedDeposit` should be the only place to mint the `token` and always send its entirety to the Liquifier contract - if(tokenInfos[_token].isL2Eth) _L2SanityChecks(_token); - + if (tokenInfos[_token].isL2Eth) _L2SanityChecks(_token); + uint256 dx = quoteByDiscountedValue(_token, _amount); require(!isDepositCapReached(_token, dx), "CAPPED"); @@ -179,7 +176,7 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab // Send the redeemed ETH back to the liquidity pool & Send the fee to Treasury function withdrawEther() external onlyAdmin { uint256 amountToLiquidityPool = address(this).balance; - (bool sent, ) = payable(address(liquidityPool)).call{value: amountToLiquidityPool, gas: 20000}(""); + (bool sent,) = payable(address(liquidityPool)).call{value: amountToLiquidityPool, gas: 20_000}(""); if (!sent) revert EthTransferFailed(); } @@ -195,7 +192,7 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab tokenInfos[_token].timeBoundCapInEther = _timeBoundCapInEther; tokenInfos[_token].totalCapInEther = _totalCapInEther; } - + function registerToken(address _token, address _target, bool _isWhitelisted, uint16 _discountInBasisPoints, uint32 _timeBoundCapInEther, uint32 _totalCapInEther, bool _isL2Eth) external onlyOwner { if (tokenInfos[_token].timeBoundCapClockStartTime != 0) revert AlreadyRegistered(); if (_isL2Eth) { @@ -255,14 +252,16 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab /* VIEW FUNCTIONS */ - // Given the `_amount` of `_token` token, returns the equivalent amount of ETH + // Given the `_amount` of `_token` token, returns the equivalent amount of ETH function quoteByFairValue(address _token, uint256 _amount) public view returns (uint256) { if (!isTokenWhitelisted(_token)) revert NotSupportedToken(); - if (_token == address(lido)) return _amount * 1; /// 1:1 from stETH to eETH + if (_token == address(lido)) return _amount * 1; + /// 1:1 from stETH to eETH else if (_token == address(cbEth)) return _amount * cbEth.exchangeRate() / 1e18; else if (_token == address(wbEth)) return _amount * wbEth.exchangeRate() / 1e18; - else if (tokenInfos[_token].isL2Eth) return _amount * 1; /// 1:1 from l2Eth to eETH + else if (tokenInfos[_token].isL2Eth) return _amount * 1; + /// 1:1 from l2Eth to eETH revert NotSupportedToken(); } @@ -279,7 +278,8 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab if (quoteStEthWithCurve) { return _min(_amount, ICurvePoolQuoter1(address(stEth_Eth_Pool)).get_dy(1, 0, _amount)); } else { - return _amount; /// 1:1 from stETH to eETH + return _amount; + /// 1:1 from stETH to eETH } } else if (_token == address(cbEth)) { return _min(_amount * cbEth.exchangeRate() / 1e18, ICurvePoolQuoter2(address(cbEth_Eth_Pool)).get_dy(1, 0, _amount)); @@ -297,7 +297,7 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab function quoteByDiscountedValue(address _token, uint256 _amount) public view returns (uint256) { uint256 marketValue = quoteByMarketValue(_token, _amount); - return (10000 - tokenInfos[_token].discountInBasisPoints) * marketValue / 10000; + return (10_000 - tokenInfos[_token].discountInBasisPoints) * marketValue / 10_000; } function isTokenWhitelisted(address _token) public view returns (bool) { @@ -324,10 +324,13 @@ contract Liquifier is Initializable, UUPSUpgradeable, OwnableUpgradeable, Pausab if (!isTokenWhitelisted(_token)) return (0, 0, 0); if (info.strategy != IStrategy(address(0))) { - restaked = quoteByFairValue(_token, info.strategy.sharesToUnderlyingView(info.strategyShare)); /// restaked & pending for withdrawals + restaked = quoteByFairValue(_token, info.strategy.sharesToUnderlyingView(info.strategyShare)); + /// restaked & pending for withdrawals } - holding = quoteByFairValue(_token, IERC20(_token).balanceOf(address(this))); /// eth value for erc20 holdings - pendingForWithdrawals = info.ethAmountPendingForWithdrawals; /// eth pending for withdrawals + holding = quoteByFairValue(_token, IERC20(_token).balanceOf(address(this))); + /// eth value for erc20 holdings + pendingForWithdrawals = info.ethAmountPendingForWithdrawals; + /// eth pending for withdrawals } function getTotalPooledEther(address _token) public view returns (uint256) { diff --git a/src/MembershipManager.sol b/src/MembershipManager.sol index b0fc741e0..cfd090c2d 100644 --- a/src/MembershipManager.sol +++ b/src/MembershipManager.sol @@ -6,18 +6,17 @@ import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; -import "./interfaces/IeETH.sol"; +import "./interfaces/IEtherFiAdmin.sol"; +import "./interfaces/ILiquidityPool.sol"; import "./interfaces/IMembershipManager.sol"; import "./interfaces/IMembershipNFT.sol"; -import "./interfaces/ILiquidityPool.sol"; -import "./interfaces/IEtherFiAdmin.sol"; +import "./interfaces/IeETH.sol"; import "./libraries/GlobalIndexLibrary.sol"; import "forge-std/console.sol"; contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable, IMembershipManager { - //-------------------------------------------------------------------------------------- //--------------------------------- STATE-VARIABLES ---------------------------------- //-------------------------------------------------------------------------------------- @@ -28,9 +27,9 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade address public treasury; address public DEPRECATED_protocolRevenueManager; - mapping (uint256 => uint256) public allTimeHighDepositAmount; - mapping (uint256 => TokenDeposit) public tokenDeposits; - mapping (uint256 => TokenData) public tokenData; + mapping(uint256 => uint256) public allTimeHighDepositAmount; + mapping(uint256 => TokenDeposit) public tokenDeposits; + mapping(uint256 => TokenData) public tokenData; TierDeposit[] public tierDeposits; TierData[] public tierData; @@ -39,7 +38,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade uint16 public pointsBoostFactor; // + (X / 10000) more points, if staking rewards are sacrificed uint16 public pointsGrowthRate; // + (X / 10000) kwei points are earned per ETH per day uint56 public minDepositGwei; - uint8 public maxDepositTopUpPercent; + uint8 public maxDepositTopUpPercent; uint16 private mintFee; // fee = 0.001 ETH * 'mintFee' uint16 private burnFee; // fee = 0.001 ETH * 'burnFee' @@ -109,14 +108,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade /// @param _snapshotEthAmount exact balance that the user has in the merkle snapshot /// @param _points EAP points that the user has in the merkle snapshot /// @param _merkleProof array of hashes forming the merkle proof for the user - function wrapEthForEap( - uint256 _amount, - uint256 _amountForPoints, - uint32 _eapDepositBlockNumber, - uint256 _snapshotEthAmount, - uint256 _points, - bytes32[] calldata _merkleProof - ) external payable whenNotPaused returns (uint256) { + function wrapEthForEap(uint256 _amount, uint256 _amountForPoints, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external payable whenNotPaused returns (uint256) { if (_points == 0 || msg.value < _snapshotEthAmount || msg.value > _snapshotEthAmount * 2 || msg.value != _amount + _amountForPoints) revert InvalidEAPRollover(); membershipNFT.processDepositFromEapUser(msg.sender, _eapDepositBlockNumber, _snapshotEthAmount, _points, _merkleProof); @@ -237,7 +229,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade eETH.approve(address(liquidityPool), totalBalance); uint256 withdrawTokenId = liquidityPool.requestMembershipNFTWithdraw(msg.sender, totalBalance, feeAmount); - + return withdrawTokenId; } @@ -258,6 +250,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade } error InvalidCaller(); + function rebase(int128 _accruedRewards) external { if (msg.sender != address(etherFiAdmin)) revert InvalidCaller(); uint256 ethRewardsPerEEthShareBeforeRebase = liquidityPool.amountForShare(1 ether); @@ -301,6 +294,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade } error TierLimitExceeded(); + function addNewTier(uint40 _requiredTierPoints, uint24 _weight) external { _requireAdmin(); if (tierData.length >= type(uint8).max) revert TierLimitExceeded(); @@ -309,6 +303,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade } error OutOfBound(); + function updateTier(uint8 _tier, uint40 _requiredTierPoints, uint24 _weight) external { _requireAdmin(); if (_tier >= tierData.length) revert OutOfBound(); @@ -398,14 +393,14 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade error WrongTokenMinted(); /** - * @dev Internal function to mint a new membership NFT. - * @param _to The address of the recipient of the NFT. - * @param _amount The amount of ETH to earn the staking rewards. - * @param _amountForPoints The amount of ETH to boost the points earnings. - * @param _loyaltyPoints The initial loyalty points for the NFT. - * @param _tierPoints The initial tier points for the NFT. - * @return tokenId The unique ID of the newly minted NFT. - */ + * @dev Internal function to mint a new membership NFT. + * @param _to The address of the recipient of the NFT. + * @param _amount The amount of ETH to earn the staking rewards. + * @param _amountForPoints The amount of ETH to boost the points earnings. + * @param _loyaltyPoints The initial loyalty points for the NFT. + * @param _tierPoints The initial tier points for the NFT. + * @return tokenId The unique ID of the newly minted NFT. + */ function _mintMembershipNFT(address _to, uint256 _amount, uint256 _amountForPoints, uint40 _loyaltyPoints, uint40 _tierPoints) internal returns (uint256) { uint256 tokenId = membershipNFT.nextMintTokenId(); uint8 tier = tierForPoints(_tierPoints); @@ -491,7 +486,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade uint256 eEthShare = liquidityPool.sharesForAmount(_amount); _decrementTierVaultV1(tier, eEthShare, vaultShare); - _decrementTokenVaultShareV1(_tokenId, vaultShare); + _decrementTokenVaultShareV1(_tokenId, vaultShare); } // V0 @@ -499,40 +494,28 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade TokenDeposit memory deposit = tokenDeposits[_tokenId]; uint128 newAmount = deposit.amounts + uint128(_amount); uint128 newShare = uint128(liquidityPool.sharesForAmount(newAmount)); - tokenDeposits[_tokenId] = TokenDeposit( - newAmount, - newShare - ); + tokenDeposits[_tokenId] = TokenDeposit(newAmount, newShare); } function _decrementTokenDeposit(uint256 _tokenId, uint256 _amount) internal { TokenDeposit memory deposit = tokenDeposits[_tokenId]; uint128 newAmount = deposit.amounts - uint128(_amount); uint128 newShare = uint128(liquidityPool.sharesForAmount(newAmount)); - tokenDeposits[_tokenId] = TokenDeposit( - newAmount, - newShare - ); + tokenDeposits[_tokenId] = TokenDeposit(newAmount, newShare); } function _incrementTierDeposit(uint256 _tier, uint256 _amount) internal { TierDeposit memory deposit = tierDeposits[_tier]; uint128 newAmount = deposit.amounts + uint128(_amount); uint128 newShare = uint128(liquidityPool.sharesForAmount(newAmount)); - tierDeposits[_tier] = TierDeposit( - newAmount, - newShare - ); + tierDeposits[_tier] = TierDeposit(newAmount, newShare); } function _decrementTierDeposit(uint256 _tier, uint256 _amount) internal { TierDeposit memory deposit = tierDeposits[_tier]; uint128 newAmount = deposit.amounts - uint128(_amount); uint128 newShare = uint128(liquidityPool.sharesForAmount(newAmount)); - tierDeposits[_tier] = TierDeposit( - newAmount, - newShare - ); + tierDeposits[_tier] = TierDeposit(newAmount, newShare); } // V1 @@ -567,7 +550,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade if (_curTier == _newTier) { return; } - + uint256 prevVaultShare = tokenData[_tokenId].vaultShare; uint256 eEthShare = eEthShareForVaultShare(_curTier, prevVaultShare); uint256 newVaultShare = vaultShareForEEthShare(_newTier, eEthShare); @@ -600,12 +583,12 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade uint256 amount = membershipNFT.accruedStakingRewardsOf(_tokenId); _incrementTokenDeposit(_tokenId, amount); _incrementTierDeposit(tier, amount); - + token.vaultShare = tierData[tier].rewardsGlobalIndex; } - error NotInV0(); + function migrateFromV0ToV1(uint256 _tokenId) public { claim(_tokenId); _migrateFromV0ToV1(_tokenId); @@ -675,11 +658,13 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade } error OnlyTokenOwner(); + function _requireTokenOwner(uint256 _tokenId) internal view { if (membershipNFT.balanceOfUser(msg.sender, _tokenId) != 1) revert OnlyTokenOwner(); } error OnlyAdmin(); + function _requireAdmin() internal view { if (!admins[msg.sender]) revert OnlyAdmin(); } @@ -712,8 +697,8 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade uint40 degradeTierPenalty = curTierPoints - tierData[prevTier].requiredTierPoints; // point deduction if scaled proportional to withdrawal amount - uint256 ratio = (10000 * _withdrawalAmount) / _prevAmount; - uint40 scaledTierPointsPenalty = uint40((ratio * curTierPoints) / 10000); + uint256 ratio = (10_000 * _withdrawalAmount) / _prevAmount; + uint40 scaledTierPointsPenalty = uint40((ratio * curTierPoints) / 10_000); uint40 penalty = uint40(_max(degradeTierPenalty, scaledTierPointsPenalty)); @@ -731,9 +716,7 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade function _emitNftUpdateEvent(uint256 _tokenId) internal { uint128 amount = uint128(membershipNFT.valueOf(_tokenId)); TokenData memory token = tokenData[_tokenId]; - emit NftUpdated(_tokenId, amount, 0, - token.baseLoyaltyPoints, token.baseTierPoints, token.tier, - token.prevTopUpTimestamp, token.vaultShare); + emit NftUpdated(_tokenId, amount, 0, token.baseLoyaltyPoints, token.baseTierPoints, token.tier, token.prevTopUpTimestamp, token.vaultShare); } // Finds the corresponding for the tier points @@ -784,5 +767,4 @@ contract MembershipManager is Initializable, OwnableUpgradeable, PausableUpgrade //-------------------------------------------------------------------------------------- //------------------------------------ MODIFIER -------------------------------------- //-------------------------------------------------------------------------------------- - } diff --git a/src/MembershipNFT.sol b/src/MembershipNFT.sol index a7293188b..d23cdc997 100644 --- a/src/MembershipNFT.sol +++ b/src/MembershipNFT.sol @@ -8,14 +8,13 @@ import "@openzeppelin-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; +import "./interfaces/ILiquidityPool.sol"; import "./interfaces/IMembershipManager.sol"; import "./interfaces/IMembershipNFT.sol"; -import "./interfaces/ILiquidityPool.sol"; import "forge-std/console.sol"; contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ERC1155Upgradeable, IMembershipNFT { - IMembershipManager membershipManager; uint32 public nextMintTokenId; uint32 public maxTokenId; @@ -23,11 +22,13 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER uint24 __gap0; mapping(uint256 => NftData) public nftData; - mapping (address => bool) public eapDepositProcessed; + mapping(address => bool) public eapDepositProcessed; bytes32 public eapMerkleRoot; uint64[] public requiredEapPointsPerEapDeposit; - string private contractMetadataURI; /// @dev opensea contract-level metadata + string private contractMetadataURI; + + /// @dev opensea contract-level metadata address public DEPRECATED_admin; @@ -38,7 +39,7 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER event MerkleUpdated(bytes32, bytes32); event MintingPaused(bool isPaused); event TokenLocked(uint256 indexed _tokenId, uint256 until); - + error DisallowZeroAddress(); error MintingIsPaused(); error InvalidEAPRollover(); @@ -74,12 +75,12 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER return tokenId; } - function burn(address _from, uint256 _tokenId, uint256 _amount) onlyMembershipManagerContract external { + function burn(address _from, uint256 _tokenId, uint256 _amount) external onlyMembershipManagerContract { _burn(_from, _tokenId, _amount); } /// @dev locks a token from being transferred for a number of blocks - function incrementLock(uint256 _tokenId, uint32 _blocks) onlyMembershipManagerContract external { + function incrementLock(uint256 _tokenId, uint32 _blocks) external onlyMembershipManagerContract { uint32 target = uint32(block.number) + _blocks; // don't accidentally shorten an existing lock @@ -89,10 +90,10 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER } } - function processDepositFromEapUser(address _user, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) onlyMembershipManagerContract external { + function processDepositFromEapUser(address _user, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external onlyMembershipManagerContract { if (eapDepositProcessed[_user] == true) revert InvalidEAPRollover(); - bytes32 leaf = keccak256(abi.encodePacked(_user,_snapshotEthAmount, _points, _eapDepositBlockNumber)); - if (!MerkleProof.verify(_merkleProof, eapMerkleRoot, leaf)) revert InvalidEAPRollover(); + bytes32 leaf = keccak256(abi.encodePacked(_user, _snapshotEthAmount, _points, _eapDepositBlockNumber)); + if (!MerkleProof.verify(_merkleProof, eapMerkleRoot, leaf)) revert InvalidEAPRollover(); eapDepositProcessed[_user] = true; } @@ -101,7 +102,7 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER //-------------------------------------- SETTER -------------------------------------- //-------------------------------------------------------------------------------------- - function setMaxTokenId(uint32 _maxTokenId) external onlyAdmin() { + function setMaxTokenId(uint32 _maxTokenId) external onlyAdmin { maxTokenId = _maxTokenId; } @@ -121,7 +122,7 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER require(_address != address(0), "Cannot be address zero"); admins[_address] = _isAdmin; } - + function setMintingPaused(bool _paused) external onlyAdmin { mintingPaused = _paused; emit MintingPaused(_paused); @@ -133,16 +134,7 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} - - function _beforeTokenTransfer( - address _operator, - address _from, - address _to, - uint256[] memory _ids, - uint256[] memory _amounts, - bytes memory _data - ) internal view override { - + function _beforeTokenTransfer(address _operator, address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data) internal view override { // empty mints and burns from checks if (_from == address(0x00) || _to == address(0x00)) { return; @@ -163,6 +155,7 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER } error InvalidVersion(); + function valueOf(uint256 _tokenId) public view returns (uint256) { (uint96 rewardsLocalIndex,,,,, uint8 tier, uint8 version) = membershipManager.tokenData(_tokenId); if (version == 0) { @@ -188,7 +181,7 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER function _V0_valueOf(uint256 _tokenId) internal view returns (uint256) { (uint96 rewardsLocalIndex,,,,, uint8 tier, uint8 version) = membershipManager.tokenData(_tokenId); (uint128 amounts,) = membershipManager.tokenDeposits(_tokenId); - (uint96 rewardsGlobalIndex,,, ) = membershipManager.tierData(tier); + (uint96 rewardsGlobalIndex,,,) = membershipManager.tierData(tier); uint256 rewards = accruedStakingRewardsOf(_tokenId); return amounts + rewards; } @@ -196,9 +189,9 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER function _V0_accruedStakingRewardsOf(uint256 _tokenId) internal view returns (uint256) { (uint96 rewardsLocalIndex,,,,, uint8 tier, uint8 version) = membershipManager.tokenData(_tokenId); (uint128 amounts, uint128 shares) = membershipManager.tokenDeposits(_tokenId); - (uint96 rewardsGlobalIndex,,, ) = membershipManager.tierData(tier); + (uint96 rewardsGlobalIndex,,,) = membershipManager.tierData(tier); uint256 rewards = 0; - if (rewardsGlobalIndex > rewardsLocalIndex) { + if (rewardsGlobalIndex > rewardsLocalIndex) { rewards = uint256(rewardsGlobalIndex - rewardsLocalIndex) * shares / 1 ether; } return rewards; @@ -262,14 +255,14 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER function allTimeHighDepositOf(uint256 _tokenId) public view returns (uint256) { uint256 totalDeposit = valueOf(_tokenId); - return _max(totalDeposit, membershipManager.allTimeHighDepositAmount(_tokenId)); + return _max(totalDeposit, membershipManager.allTimeHighDepositAmount(_tokenId)); } function transferLockedUntil(uint256 _tokenId) external view returns (uint32) { return nftData[_tokenId].transferLockedUntil; } - // Compute the points earnings of a user between [since, until) + // Compute the points earnings of a user between [since, until) // Assuming the user's balance didn't change in between [since, until) function membershipPointsEarning(uint256 _tokenId, uint256 _since, uint256 _until) public view returns (uint40) { uint256 amounts = valueOf(_tokenId); @@ -277,12 +270,12 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER if (amounts == 0 || shares == 0) { return 0; } - + uint16 pointsGrowthRate = membershipManager.pointsGrowthRate(); uint256 elapsed = _until - _since; uint256 effectiveBalanceForEarningPoints = shares; - uint256 earning = effectiveBalanceForEarningPoints * elapsed * pointsGrowthRate / 10000; + uint256 earning = effectiveBalanceForEarningPoints * elapsed * pointsGrowthRate / 10_000; // 0.001 ether earns 1 wei points per day // == 1 ether earns 1 kwei points per day @@ -296,13 +289,13 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER function computeTierPointsForEap(uint32 _eapDepositBlockNumber) public view returns (uint40) { uint8 numTiers = membershipManager.numberOfTiers(); uint32[] memory lastBlockNumbers = new uint32[](numTiers); - uint32 eapCloseBlockNumber = 17664247; // https://etherscan.io/tx/0x1ff2ade678bea8b4e5633841ff21390283e57bc50fced4dea54b11ebc929b10c - + uint32 eapCloseBlockNumber = 17_664_247; // https://etherscan.io/tx/0x1ff2ade678bea8b4e5633841ff21390283e57bc50fced4dea54b11ebc929b10c + lastBlockNumbers[0] = 0; lastBlockNumbers[1] = eapCloseBlockNumber; - lastBlockNumbers[2] = 16970393; // https://etherscan.io/tx/0x65bc8e0e5c038fc1569c3b7d9663438696a1e261451a6a57d44373266eda5a19 - lastBlockNumbers[3] = 16755015; // https://etherscan.io/tx/0xe579a56c6c1b1878b368836b682b8fa7c39fe54d6f07750158b570844597e5b4 - + lastBlockNumbers[2] = 16_970_393; // https://etherscan.io/tx/0x65bc8e0e5c038fc1569c3b7d9663438696a1e261451a6a57d44373266eda5a19 + lastBlockNumbers[3] = 16_755_015; // https://etherscan.io/tx/0xe579a56c6c1b1878b368836b682b8fa7c39fe54d6f07750158b570844597e5b4 + uint8 tierId; if (_eapDepositBlockNumber <= lastBlockNumbers[3]) { tierId = 3; // PLATINUM @@ -315,8 +308,8 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER } uint8 nextTierId = (tierId < numTiers - 1) ? tierId + 1 : tierId; - (,uint40 current,, ) = membershipManager.tierData(tierId); - (,uint40 next,, ) = membershipManager.tierData(nextTierId); + (, uint40 current,,) = membershipManager.tierData(tierId); + (, uint40 next,,) = membershipManager.tierData(nextTierId); // Minimum tierPoints for the current tier uint40 tierPoints = current; @@ -359,7 +352,7 @@ contract MembershipNFT is Initializable, OwnableUpgradeable, UUPSUpgradeable, ER /// @dev ERC-4906 This event emits when the metadata of a range of tokens is changed. /// So that the third-party platforms such as NFT market could - /// timely update the images and related attributes of the NFTs. + /// timely update the images and related attributes of the NFTs. event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); /// @notice OpenSea contract-level metadata diff --git a/src/NodeOperatorManager.sol b/src/NodeOperatorManager.sol index b91162bb5..791220de8 100644 --- a/src/NodeOperatorManager.sol +++ b/src/NodeOperatorManager.sol @@ -1,17 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "../src/interfaces/INodeOperatorManager.sol"; -import "../src/interfaces/IAuctionManager.sol"; import "../src/LiquidityPool.sol"; +import "../src/interfaces/IAuctionManager.sol"; +import "../src/interfaces/INodeOperatorManager.sol"; + import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; + import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; /// Contract which helps us control our node operators and their permissions in different aspects of the protocol contract NodeOperatorManager is INodeOperatorManager, Initializable, UUPSUpgradeable, PausableUpgradeable, OwnableUpgradeable { - //-------------------------------------------------------------------------------------- //------------------------------------- EVENTS --------------------------------------- //-------------------------------------------------------------------------------------- @@ -54,72 +55,41 @@ contract NodeOperatorManager is INodeOperatorManager, Initializable, UUPSUpgrade /// @notice Migrates operator details from previous contract /// @dev Our previous node operator contract was non upgradeable. We will be moving to an upgradeable version but need this /// function to migrate the data - function initializeOnUpgrade( - address[] memory _operator, - bytes[] memory _ipfsHash, - uint64[] memory _totalKeys, - uint64[] memory _keysUsed - ) external onlyOwner { + function initializeOnUpgrade(address[] memory _operator, bytes[] memory _ipfsHash, uint64[] memory _totalKeys, uint64[] memory _keysUsed) external onlyOwner { require((_operator.length == _ipfsHash.length) && (_operator.length == _totalKeys.length) && (_operator.length == _keysUsed.length), "Invalid lengths"); - for(uint256 x = 0; x < _operator.length; x++) { + for (uint256 x = 0; x < _operator.length; x++) { require(!registered[_operator[x]], "Already registered"); - KeyData memory keyData = KeyData({ - totalKeys: _totalKeys[x], - keysUsed: _keysUsed[x], - ipfsHash: abi.encodePacked(_ipfsHash[x]) - }); + KeyData memory keyData = KeyData({totalKeys: _totalKeys[x], keysUsed: _keysUsed[x], ipfsHash: abi.encodePacked(_ipfsHash[x])}); addressToOperatorData[_operator[x]] = keyData; registered[_operator[x]] = true; - emit OperatorRegistered( - _operator[x], - keyData.totalKeys, - keyData.keysUsed, - _ipfsHash[x] - ); + emit OperatorRegistered(_operator[x], keyData.totalKeys, keyData.keysUsed, _ipfsHash[x]); } } /// @notice Registers a user as a operator to allow them to bid /// @param _ipfsHash location of all IPFS data stored for operator /// @param _totalKeys The number of keys they have available, relates to how many validators they can run - function registerNodeOperator( - bytes memory _ipfsHash, - uint64 _totalKeys - ) public whenNotPaused { + function registerNodeOperator(bytes memory _ipfsHash, uint64 _totalKeys) public whenNotPaused { require(!registered[msg.sender], "Already registered"); - KeyData memory keyData = KeyData({ - totalKeys: _totalKeys, - keysUsed: 0, - ipfsHash: abi.encodePacked(_ipfsHash) - }); + KeyData memory keyData = KeyData({totalKeys: _totalKeys, keysUsed: 0, ipfsHash: abi.encodePacked(_ipfsHash)}); addressToOperatorData[msg.sender] = keyData; registered[msg.sender] = true; - emit OperatorRegistered( - msg.sender, - keyData.totalKeys, - keyData.keysUsed, - _ipfsHash - ); + emit OperatorRegistered(msg.sender, keyData.totalKeys, keyData.keysUsed, _ipfsHash); } /// @notice Fetches the next key they have available to use /// @param _user the user to fetch the key for /// @return The ipfs index available for the validator - function fetchNextKeyIndex( - address _user - ) external onlyAuctionManagerContract returns (uint64) { + function fetchNextKeyIndex(address _user) external onlyAuctionManagerContract returns (uint64) { KeyData storage keyData = addressToOperatorData[_user]; uint64 totalKeys = keyData.totalKeys; - require( - keyData.keysUsed < totalKeys, - "Insufficient public keys" - ); + require(keyData.keysUsed < totalKeys, "Insufficient public keys"); uint64 ipfsIndex = keyData.keysUsed; keyData.keysUsed++; @@ -134,14 +104,10 @@ contract NodeOperatorManager is INodeOperatorManager, Initializable, UUPSUpgrade /// @param _users the operator addresses to perform an approval or denial on /// @param _approvedTags the source of funds we will be updating operator permissions for /// @param _approvals whether we are approving or un approving the operator - function batchUpdateOperatorsApprovedTags( - address[] memory _users, - LiquidityPool.SourceOfFunds[] memory _approvedTags, - bool[] memory _approvals - ) external onlyAdmin { + function batchUpdateOperatorsApprovedTags(address[] memory _users, LiquidityPool.SourceOfFunds[] memory _approvedTags, bool[] memory _approvals) external onlyAdmin { require(_users.length == _approvedTags.length && _users.length == _approvals.length, "Invalid array lengths"); - for(uint256 x; x < _approvedTags.length; x++) { + for (uint256 x; x < _approvedTags.length; x++) { operatorApprovedTags[_users[x]][_approvedTags[x]] = _approvals[x]; emit UpdatedOperatorApprovals(_users[x], _approvedTags[x], _approvals[x]); } @@ -188,31 +154,24 @@ contract NodeOperatorManager is INodeOperatorManager, Initializable, UUPSUpgrade /// @notice Fetches the number of keys the user has, used or un-used /// @param _user the user to fetch the data for /// @return totalKeys The number of keys the user has - function getUserTotalKeys( - address _user - ) external view returns (uint64 totalKeys) { + function getUserTotalKeys(address _user) external view returns (uint64 totalKeys) { totalKeys = addressToOperatorData[_user].totalKeys; } /// @notice Fetches the number of keys the user has left to use /// @param _user the user to fetch the data for /// @return numKeysRemaining the number of keys the user has remaining - function getNumKeysRemaining( - address _user - ) external view returns (uint64 numKeysRemaining) { + function getNumKeysRemaining(address _user) external view returns (uint64 numKeysRemaining) { KeyData storage keyData = addressToOperatorData[_user]; - numKeysRemaining = - keyData.totalKeys - keyData.keysUsed; + numKeysRemaining = keyData.totalKeys - keyData.keysUsed; } /// @notice Fetches if the user is whitelisted /// @dev Used in the auction contract to verify when a user bids that they are indeed whitelisted /// @param _user the user to fetch the data for /// @return whitelisted Bool value if they are whitelisted or not - function isWhitelisted( - address _user - ) public view returns (bool whitelisted) { + function isWhitelisted(address _user) public view returns (bool whitelisted) { whitelisted = whitelistedAddresses[_user]; } @@ -227,9 +186,7 @@ contract NodeOperatorManager is INodeOperatorManager, Initializable, UUPSUpgrade /// @notice Sets the auction contract address for verification purposes /// @dev Set manually due to circular dependencies /// @param _auctionContractAddress address of the deployed auction contract address - function setAuctionContractAddress( - address _auctionContractAddress - ) public onlyOwner { + function setAuctionContractAddress(address _auctionContractAddress) public onlyOwner { require(auctionManagerContractAddress == address(0), "Address already set"); require(_auctionContractAddress != address(0), "No zero addresses"); auctionManagerContractAddress = _auctionContractAddress; @@ -246,19 +203,14 @@ contract NodeOperatorManager is INodeOperatorManager, Initializable, UUPSUpgrade //------------------------------- INTERNAL FUNCTIONS -------------------------------- //-------------------------------------------------------------------------------------- - function _authorizeUpgrade( - address newImplementation - ) internal override onlyOwner {} + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} //-------------------------------------------------------------------------------------- //----------------------------------- MODIFIERS -------------------------------------- //-------------------------------------------------------------------------------------- modifier onlyAuctionManagerContract() { - require( - msg.sender == auctionManagerContractAddress, - "Only auction manager contract function" - ); + require(msg.sender == auctionManagerContractAddress, "Only auction manager contract function"); _; } diff --git a/src/RoleRegistry.sol b/src/RoleRegistry.sol index 112c8a3a1..e082094ba 100644 --- a/src/RoleRegistry.sol +++ b/src/RoleRegistry.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.24; import {Ownable2StepUpgradeable} from "@openzeppelin-upgradeable/contracts/access/Ownable2StepUpgradeable.sol"; -import {UUPSUpgradeable, Initializable} from "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import {Initializable, UUPSUpgradeable} from "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import {EnumerableRoles} from "solady/auth/EnumerableRoles.sol"; /// @title RoleRegistry - An upgradeable role-based access control system @@ -54,15 +54,15 @@ contract RoleRegistry is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable /// @param role The role to grant (as bytes32) /// @param account The address to grant the role to function grantRole(bytes32 role, address account) public { - setRole(account, uint256(role), true); - } + setRole(account, uint256(role), true); + } /// @notice Revokes a role from an account /// @dev Only callable by the contract owner (handled in setRole function) /// @param role The role to revoke (as bytes32) /// @param account The address to revoke the role from function revokeRole(bytes32 role, address account) public { - setRole(account, uint256(role), false); + setRole(account, uint256(role), false); } /// @notice Gets all addresses that have a specific role @@ -86,4 +86,4 @@ contract RoleRegistry is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable } function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} -} \ No newline at end of file +} diff --git a/src/StakingManager.sol b/src/StakingManager.sol index 58f962027..ed321d20f 100644 --- a/src/StakingManager.sol +++ b/src/StakingManager.sol @@ -1,33 +1,26 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "./interfaces/IRoleRegistry.sol"; import "./interfaces/IAuctionManager.sol"; -import "./interfaces/IStakingManager.sol"; + import "./interfaces/IDepositContract.sol"; import "./interfaces/IEtherFiNode.sol"; import "./interfaces/IEtherFiNodesManager.sol"; +import "./interfaces/IRoleRegistry.sol"; +import "./interfaces/IStakingManager.sol"; import "./libraries/DepositDataRootGenerator.sol"; -import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; -import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -import "@openzeppelin-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol"; + import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; +import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; +import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -contract StakingManager is - Initializable, - IStakingManager, - IBeaconUpgradeable, - OwnableUpgradeable, - PausableUpgradeable, - ReentrancyGuardUpgradeable, - UUPSUpgradeable -{ - +contract StakingManager is Initializable, IStakingManager, IBeaconUpgradeable, OwnableUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { address public immutable liquidityPool; uint256 public constant initialDepositAmount = 1 ether; IEtherFiNodesManager public immutable etherFiNodesManager; @@ -54,14 +47,7 @@ contract StakingManager is //----------------------------- Admin ----------------------------------- //------------------------------------------------------------------------- - constructor( - address _liquidityPool, - address _etherFiNodesManager, - address _ethDepositContract, - address _auctionManager, - address _etherFiNodeBeacon, - address _roleRegistry - ) { + constructor(address _liquidityPool, address _etherFiNodesManager, address _ethDepositContract, address _auctionManager, address _etherFiNodeBeacon, address _roleRegistry) { liquidityPool = _liquidityPool; etherFiNodesManager = IEtherFiNodesManager(_etherFiNodesManager); depositContractEth2 = IDepositContract(_ethDepositContract); @@ -80,6 +66,7 @@ contract StakingManager is if (!roleRegistry.hasRole(roleRegistry.PROTOCOL_PAUSER(), msg.sender)) revert IncorrectRole(); _pause(); } + function unPauseContract() external { if (!roleRegistry.hasRole(roleRegistry.PROTOCOL_UNPAUSER(), msg.sender)) revert IncorrectRole(); _unpause(); @@ -99,7 +86,6 @@ contract StakingManager is // process each 1 eth deposit to create validators for later verification from oracle for (uint256 i = 0; i < depositData.length; i++) { - // claim the bid if (!auctionManager.isBidActive(bidIds[i])) revert InactiveBid(); auctionManager.updateSelectedBidInformation(bidIds[i]); @@ -138,7 +124,6 @@ contract StakingManager is uint256 remainingDeposit = validatorSizeWei - initialDepositAmount; for (uint256 i = 0; i < depositData.length; i++) { - // check that withdrawal credentials for pubkey match what we originally intended // It is expected that the oracle will not call the function for any key that was front-run by a malicious operator bytes32 pubkeyHash = calculateValidatorPubkeyHash(depositData[i].publicKey); @@ -233,5 +218,4 @@ contract StakingManager is if (!roleRegistry.hasRole(STAKING_MANAGER_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); _; } - } diff --git a/src/TNFT.sol b/src/TNFT.sol index e5214e768..b1b39701a 100644 --- a/src/TNFT.sol +++ b/src/TNFT.sol @@ -1,13 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/token/ERC721/ERC721Upgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/token/ERC721/ERC721Upgradeable.sol"; import "./interfaces/IEtherFiNodesManager.sol"; - contract TNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { //-------------------------------------------------------------------------------------- //--------------------------------- STATE-VARIABLES ---------------------------------- @@ -25,9 +24,9 @@ contract TNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { } /// @notice initialize to set variables on deployment - function initialize(address _stakingManagerAddress) initializer external { + function initialize(address _stakingManagerAddress) external initializer { require(_stakingManagerAddress != address(0), "No zero addresses"); - + __ERC721_init("Transferrable NFT", "TNFT"); __Ownable_init(); __UUPSUpgradeable_init(); @@ -36,7 +35,7 @@ contract TNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { } /// @notice initialization function that should be called after phase 2.0 contract upgrade - function initializeOnUpgrade(address _etherFiNodesManagerAddress) onlyOwner external { + function initializeOnUpgrade(address _etherFiNodesManagerAddress) external onlyOwner { require(_etherFiNodesManagerAddress != address(0), "Cannot initialize to zero address"); etherFiNodesManagerAddress = _etherFiNodesManagerAddress; @@ -55,19 +54,16 @@ contract TNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable { _burn(_validatorId); } - /// @notice burn the associated one + /// @notice burn the associated one function burnFromCancelBNftFlow(uint256 _validatorId) external onlyStakingManager { _burn(_validatorId); } - //-------------------------------------------------------------------------------------- //------------------------------- INTERNAL FUNCTIONS -------------------------------- //-------------------------------------------------------------------------------------- - function _authorizeUpgrade( - address newImplementation - ) internal override onlyOwner {} + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} //-------------------------------------------------------------------------------------- //-------------------------------------- GETTER -------------------------------------- diff --git a/src/TVLOracle.sol b/src/TVLOracle.sol index 0c6d4291e..cd8f6bbc3 100644 --- a/src/TVLOracle.sol +++ b/src/TVLOracle.sol @@ -17,10 +17,7 @@ contract TVLOracle is Ownable { /// @notice Sets TVL by aggregator /// @param _newTvl New TVL calculated by aggregator function setTvl(uint256 _newTvl) public { - require( - msg.sender == tvlAggregator, - "Only TVL Aggregator can call this message" - ); + require(msg.sender == tvlAggregator, "Only TVL Aggregator can call this message"); require(_newTvl > 0, "TVL shouldn't be 0"); _currentTvl = _newTvl; diff --git a/src/UUPSProxy.sol b/src/UUPSProxy.sol index 310c3cbd5..34b860197 100644 --- a/src/UUPSProxy.sol +++ b/src/UUPSProxy.sol @@ -4,8 +4,5 @@ pragma solidity ^0.8.13; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract UUPSProxy is ERC1967Proxy { - constructor( - address _implementation, - bytes memory _data - ) ERC1967Proxy(_implementation, _data) {} + constructor(address _implementation, bytes memory _data) ERC1967Proxy(_implementation, _data) {} } diff --git a/src/WeETH.sol b/src/WeETH.sol index db41c9f6d..064ae4037 100644 --- a/src/WeETH.sol +++ b/src/WeETH.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol"; -import "./interfaces/IeETH.sol"; import "./interfaces/ILiquidityPool.sol"; import "./interfaces/IRateProvider.sol"; +import "./interfaces/IeETH.sol"; +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol"; + +import "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol"; import "./AssetRecovery.sol"; import "./interfaces/IRoleRegistry.sol"; contract WeETH is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC20PermitUpgradeable, IRateProvider, AssetRecovery { - IRoleRegistry public immutable roleRegistry; error IncorrectRole(); @@ -74,10 +74,7 @@ contract WeETH is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC20Pe /// @notice Wraps eEth with PermitInput struct so user does not have to call approve on eeth contract /// @param _eETHAmount the amount of eEth to wrap /// @return returns the amount of weEth the user receives - function wrapWithPermit(uint256 _eETHAmount, ILiquidityPool.PermitInput calldata _permit) - external - returns (uint256) - { + function wrapWithPermit(uint256 _eETHAmount, ILiquidityPool.PermitInput calldata _permit) external returns (uint256) { try eETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s) {} catch {} return wrap(_eETHAmount); } @@ -94,18 +91,18 @@ contract WeETH is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC20Pe } function recoverETH(address payable to, uint256 amount) external { - if(!roleRegistry.hasRole(WEETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(WEETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); _recoverETH(to, amount); } function recoverERC20(address token, address to, uint256 amount) external { - if(!roleRegistry.hasRole(WEETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(WEETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); if (token == address(eETH)) revert CannotRecoverEETH(); _recoverERC20(token, to, amount); } function recoverERC721(address token, address to, uint256 tokenId) external { - if(!roleRegistry.hasRole(WEETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); + if (!roleRegistry.hasRole(WEETH_OPERATING_ADMIN_ROLE, msg.sender)) revert IncorrectRole(); _recoverERC721(token, to, tokenId); } @@ -113,13 +110,10 @@ contract WeETH is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC20Pe //------------------------------- INTERNAL FUNCTIONS --------------------------------- //-------------------------------------------------------------------------------------- - function _authorizeUpgrade( - address /* newImplementation */ - ) internal view override { + function _authorizeUpgrade(address /* newImplementation */ ) internal view override { roleRegistry.onlyProtocolUpgrader(msg.sender); } - //-------------------------------------------------------------------------------------- //------------------------------------ GETTERS --------------------------------------- //-------------------------------------------------------------------------------------- diff --git a/src/WithdrawRequestNFT.sol b/src/WithdrawRequestNFT.sol index b0f3dd310..bb7397446 100644 --- a/src/WithdrawRequestNFT.sol +++ b/src/WithdrawRequestNFT.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/token/ERC721/ERC721Upgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; + import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/token/ERC721/ERC721Upgradeable.sol"; -import "./interfaces/IeETH.sol"; import "./interfaces/ILiquidityPool.sol"; -import "./interfaces/IWithdrawRequestNFT.sol"; + import "./interfaces/IMembershipManager.sol"; +import "./interfaces/IWithdrawRequestNFT.sol"; +import "./interfaces/IeETH.sol"; -import "@openzeppelin/contracts/utils/math/Math.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./RoleRegistry.sol"; - - +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/utils/math/Math.sol"; contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IWithdrawRequestNFT { using Math for uint256; @@ -22,9 +22,9 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad uint256 private constant BASIS_POINT_SCALE = 1e4; // this treasury address is set to ethfi buyback wallet address address public immutable treasury; - + ILiquidityPool public liquidityPool; - IeETH public eETH; + IeETH public eETH; IMembershipManager public membershipManager; mapping(uint256 => IWithdrawRequestNFT.WithdrawRequest) private _requests; @@ -45,7 +45,6 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad bool public paused; RoleRegistry public roleRegistry; - bytes32 public constant WITHDRAW_REQUEST_NFT_ADMIN_ROLE = keccak256("WITHDRAW_REQUEST_NFT_ADMIN_ROLE"); bytes32 public constant IMPLICIT_FEE_CLAIMER_ROLE = keccak256("IMPLICIT_FEE_CLAIMER_ROLE"); @@ -64,11 +63,11 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad /// @custom:oz-upgrades-unsafe-allow constructor constructor(address _treasury) { treasury = _treasury; - + _disableInitializers(); } - function initialize(address _liquidityPoolAddress, address _eEthAddress, address _membershipManagerAddress) initializer external { + function initialize(address _liquidityPoolAddress, address _eEthAddress, address _membershipManagerAddress) external initializer { require(_liquidityPoolAddress != address(0), "No zero addresses"); require(_eEthAddress != address(0), "No zero addresses"); __ERC721_init("Withdraw Request NFT", "WithdrawRequestNFT"); @@ -89,7 +88,7 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad roleRegistry = RoleRegistry(_roleRegistry); _unused_gap = 0; - + shareRemainderSplitToTreasuryInBps = _shareRemainderSplitToTreasuryInBps; currentRequestIdToScanFromForShareRemainder = 1; @@ -138,7 +137,7 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad function claimWithdraw(uint256 tokenId) external whenNotPaused { return _claimWithdraw(tokenId, ownerOf(tokenId)); } - + function _claimWithdraw(uint256 tokenId, address recipient) internal { require(ownerOf(tokenId) == msg.sender, "Not the owner of the NFT"); IWithdrawRequestNFT.WithdrawRequest memory request = _requests[tokenId]; @@ -151,11 +150,11 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad _burn(tokenId); delete _requests[tokenId]; - // update accounting + // update accounting totalRemainderEEthShares += request.shareOfEEth - shareAmountToBurnForWithdrawal; uint256 amountBurnedShare = liquidityPool.withdraw(recipient, amountToWithdraw); - assert (amountBurnedShare == shareAmountToBurnForWithdrawal); + assert(amountBurnedShare == shareAmountToBurnForWithdrawal); emit WithdrawRequestClaimed(uint32(tokenId), amountToWithdraw, amountBurnedShare, recipient, 0); } @@ -181,7 +180,7 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad } currentRequestIdToScanFromForShareRemainder = uint32(scanUntil + 1); - + // When the scan is completed, update the `totalRemainderEEthShares` and reset the `aggregateSumOfEEthShare` if (isScanOfShareRemainderCompleted()) { totalRemainderEEthShares = eETH.shares(address(this)) - aggregateSumOfEEthShare; @@ -250,7 +249,6 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad if (!roleRegistry.hasRole(roleRegistry.PROTOCOL_UNPAUSER(), msg.sender)) revert IncorrectRole(); if (!paused) revert("Pausable: not paused"); - paused = false; emit Unpaused(msg.sender); } @@ -262,8 +260,8 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad /// - Burn: the rest of the remainder is burned /// @param _eEthAmount: the remainder of the eEth amount function handleRemainder(uint256 _eEthAmount) external { - if(!roleRegistry.hasRole(IMPLICIT_FEE_CLAIMER_ROLE, msg.sender)) revert IncorrectRole(); - require(_eEthAmount != 0, "EETH amount cannot be 0"); + if (!roleRegistry.hasRole(IMPLICIT_FEE_CLAIMER_ROLE, msg.sender)) revert IncorrectRole(); + require(_eEthAmount != 0, "EETH amount cannot be 0"); require(isScanOfShareRemainderCompleted(), "Not all prev requests have been scanned"); require(getEEthRemainderAmount() >= _eEthAmount, "Not enough eETH remainder"); @@ -279,7 +277,7 @@ contract WithdrawRequestNFT is ERC721Upgradeable, UUPSUpgradeable, OwnableUpgrad if (eEthAmountToTreasury > 0) IERC20(address(eETH)).safeTransfer(treasury, eEthAmountToTreasury); if (eEthSharesToBurn > 0) liquidityPool.burnEEthShares(eEthSharesToBurn); - require (beforeEEthShares - eEthSharesToMoved == eETH.shares(address(this)), "Invalid eETH shares after remainder handling"); + require(beforeEEthShares - eEthSharesToMoved == eETH.shares(address(this)), "Invalid eETH shares after remainder handling"); emit HandledRemainderOfClaimedWithdrawRequests(eEthAmountToTreasury, liquidityPool.amountForShare(eEthSharesToBurn)); } diff --git a/src/archive/LoyaltyPointsMarketSafe.sol b/src/archive/LoyaltyPointsMarketSafe.sol index 2dda188e0..b04fee0aa 100644 --- a/src/archive/LoyaltyPointsMarketSafe.sol +++ b/src/archive/LoyaltyPointsMarketSafe.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.13; import "@openzeppelin/contracts/access/Ownable.sol"; contract LoyaltyPointsMarketSafe is Ownable { - event PointsPurchased(address indexed buyer, uint256 indexed tokenId, uint256 amountWei, uint256 weiPerPoint); event BoostToTop(address indexed buyer, uint256 indexed tokenId, uint256 amountWei); diff --git a/src/archive/MembershipManagerV0.sol b/src/archive/MembershipManagerV0.sol index 3e5f823d8..5c76d08b4 100644 --- a/src/archive/MembershipManagerV0.sol +++ b/src/archive/MembershipManagerV0.sol @@ -6,16 +6,14 @@ import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; -import "../interfaces/IeETH.sol"; +import "../interfaces/ILiquidityPool.sol"; import "../interfaces/IMembershipManagerV0.sol"; import "../interfaces/IMembershipNFT.sol"; -import "../interfaces/ILiquidityPool.sol"; +import "../interfaces/IeETH.sol"; import "../libraries/GlobalIndexLibrary.sol"; - contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable, IMembershipManagerV0 { - //-------------------------------------------------------------------------------------- //--------------------------------- STATE-VARIABLES ---------------------------------- //-------------------------------------------------------------------------------------- @@ -26,9 +24,9 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra address public treasury; address public protocolRevenueManager; - mapping (uint256 => uint256) public allTimeHighDepositAmount; - mapping (uint256 => TokenDeposit) public tokenDeposits; - mapping (uint256 => TokenData) public tokenData; + mapping(uint256 => uint256) public allTimeHighDepositAmount; + mapping(uint256 => TokenDeposit) public tokenDeposits; + mapping(uint256 => TokenData) public tokenData; TierDeposit[] public tierDeposits; TierData[] public tierData; @@ -37,7 +35,7 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra uint16 public pointsBoostFactor; // + (X / 10000) more points, if staking rewards are sacrificed uint16 public pointsGrowthRate; // + (X / 10000) kwei points are earned per ETH per day uint56 public minDepositGwei; - uint8 public maxDepositTopUpPercent; + uint8 public maxDepositTopUpPercent; uint16 private mintFee; // fee = 0.001 ETH * 'mintFee' uint16 private burnFee; // fee = 0.001 ETH * 'burnFee' @@ -56,7 +54,7 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra address public DEPRECATED_admin; mapping(address => bool) public admins; - + //-------------------------------------------------------------------------------------- //------------------------------------- EVENTS --------------------------------------- //-------------------------------------------------------------------------------------- @@ -90,8 +88,8 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra treasury = _treasury; protocolRevenueManager = _protocolRevenueManager; - pointsBoostFactor = 10000; - pointsGrowthRate = 10000; + pointsBoostFactor = 10_000; + pointsGrowthRate = 10_000; minDepositGwei = (0.1 ether / 1 gwei); maxDepositTopUpPercent = 20; withdrawalLockBlocks = 3600; @@ -110,14 +108,7 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra /// @param _snapshotEthAmount exact balance that the user has in the merkle snapshot /// @param _points EAP points that the user has in the merkle snapshot /// @param _merkleProof array of hashes forming the merkle proof for the user - function wrapEthForEap( - uint256 _amount, - uint256 _amountForPoints, - uint32 _eapDepositBlockNumber, - uint256 _snapshotEthAmount, - uint256 _points, - bytes32[] calldata _merkleProof - ) external payable whenNotPaused returns (uint256) { + function wrapEthForEap(uint256 _amount, uint256 _amountForPoints, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external payable whenNotPaused returns (uint256) { if (_points == 0 || msg.value < _snapshotEthAmount || msg.value > _snapshotEthAmount * 2 || msg.value != _amount + _amountForPoints) revert InvalidEAPRollover(); membershipNFT.processDepositFromEapUser(msg.sender, _eapDepositBlockNumber, _snapshotEthAmount, _points, _merkleProof); @@ -288,6 +279,7 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra } error TierLimitExceeded(); + function addNewTier(uint40 _requiredTierPoints, uint24 _weight) external returns (uint256) { _requireAdmin(); if (tierDeposits.length >= type(uint8).max) revert TierLimitExceeded(); @@ -297,6 +289,7 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra } error OutOfBound(); + function updateTier(uint8 _tier, uint40 _requiredTierPoints, uint24 _weight) external { _requireAdmin(); if (_tier >= tierData.length) revert OutOfBound(); @@ -311,7 +304,7 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra /// @param _tierPoints The number of tier points to set for the specified NFT. function setPointsBatch(uint256[] calldata _tokenIds, uint40[] calldata _loyaltyPoints, uint40[] calldata _tierPoints) external { for (uint256 i = 0; i < _tokenIds.length; i++) { - setPoints(_tokenIds[i], _loyaltyPoints[i], _tierPoints[i]); + setPoints(_tokenIds[i], _loyaltyPoints[i], _tierPoints[i]); } } @@ -340,7 +333,7 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra /// @notice Recover the tier points for a given NFT. /// @param _tokenId The ID of the membership NFT. /// @param _eapDepositBlockNumber the block number at which the user deposited into the EAP - function recoverTierPointsForEap(uint256 _tokenId, uint32 _eapDepositBlockNumber) public { + function recoverTierPointsForEap(uint256 _tokenId, uint32 _eapDepositBlockNumber) public { _requireAdmin(); _claimPoints(_tokenId); @@ -354,11 +347,12 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra } error InvalidWithdraw(); + function withdrawFees(uint256 _amount, address _recipient) external { _requireAdmin(); if (_recipient == address(0)) revert InvalidWithdraw(); if (address(this).balance < _amount) revert InvalidWithdraw(); - (bool sent, ) = address(_recipient).call{value: _amount}(""); + (bool sent,) = address(_recipient).call{value: _amount}(""); if (!sent) revert InvalidWithdraw(); } @@ -430,14 +424,14 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra error WrongTokenMinted(); /** - * @dev Internal function to mint a new membership NFT. - * @param _to The address of the recipient of the NFT. - * @param _amount The amount of ETH to earn the staking rewards. - * @param _amountForPoints The amount of ETH to boost the points earnings. - * @param _loyaltyPoints The initial loyalty points for the NFT. - * @param _tierPoints The initial tier points for the NFT. - * @return tokenId The unique ID of the newly minted NFT. - */ + * @dev Internal function to mint a new membership NFT. + * @param _to The address of the recipient of the NFT. + * @param _amount The amount of ETH to earn the staking rewards. + * @param _amountForPoints The amount of ETH to boost the points earnings. + * @param _loyaltyPoints The initial loyalty points for the NFT. + * @param _tierPoints The initial tier points for the NFT. + * @return tokenId The unique ID of the newly minted NFT. + */ function _mintMembershipNFT(address _to, uint256 _amount, uint256 _amountForPoints, uint40 _loyaltyPoints, uint40 _tierPoints) internal returns (uint256) { uint256 tokenId = membershipNFT.nextMintTokenId(); uint8 tier = tierForPoints(_tierPoints); @@ -512,40 +506,28 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra TokenDeposit memory deposit = tokenDeposits[_tokenId]; uint128 newAmount = deposit.amounts + uint128(_amount); uint128 newShare = uint128(liquidityPool.sharesForAmount(newAmount)); - tokenDeposits[_tokenId] = TokenDeposit( - newAmount, - newShare - ); + tokenDeposits[_tokenId] = TokenDeposit(newAmount, newShare); } function _decrementTokenDeposit(uint256 _tokenId, uint256 _amount) internal { TokenDeposit memory deposit = tokenDeposits[_tokenId]; uint128 newAmount = deposit.amounts - uint128(_amount); uint128 newShare = uint128(liquidityPool.sharesForAmount(newAmount)); - tokenDeposits[_tokenId] = TokenDeposit( - newAmount, - newShare - ); + tokenDeposits[_tokenId] = TokenDeposit(newAmount, newShare); } function _incrementTierDeposit(uint256 _tier, uint256 _amount) internal { TierDeposit memory deposit = tierDeposits[_tier]; uint128 newAmount = deposit.amounts + uint128(_amount); uint128 newShare = uint128(liquidityPool.sharesForAmount(newAmount)); - tierDeposits[_tier] = TierDeposit( - newAmount, - newShare - ); + tierDeposits[_tier] = TierDeposit(newAmount, newShare); } function _decrementTierDeposit(uint256 _tier, uint256 _amount) internal { TierDeposit memory deposit = tierDeposits[_tier]; uint128 newAmount = deposit.amounts - uint128(_amount); uint128 newShare = uint128(liquidityPool.sharesForAmount(newAmount)); - tierDeposits[_tier] = TierDeposit( - newAmount, - newShare - ); + tierDeposits[_tier] = TierDeposit(newAmount, newShare); } function _claimTier(uint256 _tokenId) internal { @@ -605,11 +587,13 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra } error OnlyTokenOwner(); + function _requireTokenOwner(uint256 _tokenId) internal { if (membershipNFT.balanceOfUser(msg.sender, _tokenId) != 1) revert OnlyTokenOwner(); } error OnlyAdmin(); + function _requireAdmin() internal { if (!admins[msg.sender]) revert OnlyAdmin(); } @@ -642,8 +626,8 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra uint40 degradeTierPenalty = curTierPoints - tierData[prevTier].requiredTierPoints; // point deduction if scaled proportional to withdrawal amount - uint256 ratio = (10000 * _withdrawalAmount) / _prevAmount; - uint40 scaledTierPointsPenalty = uint40((ratio * curTierPoints) / 10000); + uint256 ratio = (10_000 * _withdrawalAmount) / _prevAmount; + uint40 scaledTierPointsPenalty = uint40((ratio * curTierPoints) / 10_000); uint40 penalty = uint40(_max(degradeTierPenalty, scaledTierPointsPenalty)); @@ -661,9 +645,7 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra function _emitNftUpdateEvent(uint256 _tokenId) internal { TokenDeposit memory deposit = tokenDeposits[_tokenId]; TokenData memory token = tokenData[_tokenId]; - emit NftUpdated(_tokenId, deposit.amounts, 0, - token.baseLoyaltyPoints, token.baseTierPoints, token.tier, - token.prevTopUpTimestamp, token.rewardsLocalIndex); + emit NftUpdated(_tokenId, deposit.amounts, 0, token.baseLoyaltyPoints, token.baseTierPoints, token.tier, token.prevTopUpTimestamp, token.rewardsLocalIndex); } // Finds the corresponding for the tier points @@ -714,5 +696,4 @@ contract MembershipManagerV0 is Initializable, OwnableUpgradeable, PausableUpgra //-------------------------------------------------------------------------------------- //------------------------------------ MODIFIER -------------------------------------- //-------------------------------------------------------------------------------------- - } diff --git a/src/archive/NFTExchange.sol b/src/archive/NFTExchange.sol index e89d08e1c..bff80e660 100644 --- a/src/archive/NFTExchange.sol +++ b/src/archive/NFTExchange.sol @@ -1,23 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import "../interfaces/IMembershipNFT.sol"; -import "../interfaces/IEtherFiNodesManager.sol"; import "../interfaces/IEtherFiNode.sol"; +import "../interfaces/IEtherFiNodesManager.sol"; +import "../interfaces/IMembershipNFT.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; - /** * @title Escrow * @dev A contract for escrowing NFT trades between a multi-sig wallet and a staker. */ contract NFTExchange is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { - //-------------------------------------------------------------------------------------- //--------------------------------- STATE-VARIABLES ---------------------------------- //-------------------------------------------------------------------------------------- @@ -26,8 +24,8 @@ contract NFTExchange is Initializable, OwnableUpgradeable, ReentrancyGuardUpgrad IMembershipNFT public membershipNft; IEtherFiNodesManager nodesMgr; - mapping (uint256 => address) public reservedBuyers; - mapping (uint256 => uint256) public targetTNftTokenIds; + mapping(uint256 => address) public reservedBuyers; + mapping(uint256 => uint256) public targetTNftTokenIds; address public admin; //-------------------------------------------------------------------------------------- @@ -87,7 +85,7 @@ contract NFTExchange is Initializable, OwnableUpgradeable, ReentrancyGuardUpgrad require(tnftTokenId == targetTNftTokenIds[mNftTokenId], "The T-NFT is not the target"); // TODO(dave): I think we can delete this entire contract? - // require(nodesMgr.phase(tnftTokenId) == IEtherFiNode.VALIDATOR_PHASE.LIVE, "The validator is not LIVE"); + // require(nodesMgr.phase(tnftTokenId) == IEtherFiNode.VALIDATOR_PHASE.LIVE, "The validator is not LIVE"); reservedBuyers[mNftTokenId] = address(0); targetTNftTokenIds[mNftTokenId] = 0; @@ -115,7 +113,7 @@ contract NFTExchange is Initializable, OwnableUpgradeable, ReentrancyGuardUpgrad function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} - function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns(bytes4) { + function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) { return this.onERC1155Received.selector; } @@ -138,5 +136,4 @@ contract NFTExchange is Initializable, OwnableUpgradeable, ReentrancyGuardUpgrad require(msg.sender == admin, "Caller is not the admin"); _; } - } diff --git a/src/archive/ProtocolRevenueManager.sol b/src/archive/ProtocolRevenueManager.sol index 0aaca65c8..672a7c356 100644 --- a/src/archive/ProtocolRevenueManager.sol +++ b/src/archive/ProtocolRevenueManager.sol @@ -1,28 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; -import "../interfaces/IProtocolRevenueManager.sol"; -import "../interfaces/IEtherFiNodesManager.sol"; import "../interfaces/IAuctionManager.sol"; +import "../interfaces/IEtherFiNodesManager.sol"; +import "../interfaces/IProtocolRevenueManager.sol"; -contract ProtocolRevenueManager is - Initializable, - IProtocolRevenueManager, - PausableUpgradeable, - OwnableUpgradeable, - ReentrancyGuardUpgradeable, - UUPSUpgradeable -{ +contract ProtocolRevenueManager is Initializable, IProtocolRevenueManager, PausableUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { //-------------------------------------------------------------------------------------- //--------------------------------- STATE-VARIABLES ---------------------------------- //-------------------------------------------------------------------------------------- - + IEtherFiNodesManager public etherFiNodesManager; IAuctionManager public auctionManager; @@ -35,7 +28,7 @@ contract ProtocolRevenueManager is //-------------------------------------------------------------------------------------- //---------------------------- STATE-CHANGING FUNCTIONS ------------------------------ //-------------------------------------------------------------------------------------- - + /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); @@ -52,7 +45,6 @@ contract ProtocolRevenueManager is DEPRECATED_auctionFeeVestingPeriodForStakersInDays = 6 * 7 * 4; // 6 months } - //-------------------------------------------------------------------------------------- //----------------------------------- SETTERS --------------------------------------- //-------------------------------------------------------------------------------------- @@ -75,8 +67,13 @@ contract ProtocolRevenueManager is auctionManager = IAuctionManager(_auctionManager); } - function pauseContract() external onlyAdmin { _pause(); } - function unPauseContract() external onlyAdmin { _unpause(); } + function pauseContract() external onlyAdmin { + _pause(); + } + + function unPauseContract() external onlyAdmin { + _unpause(); + } /// @notice Updates the address of the admin /// @param _newAdmin the new address to set as admin diff --git a/src/archive/RegulationsManager.sol b/src/archive/RegulationsManager.sol index 5717c33e1..defa5daf8 100644 --- a/src/archive/RegulationsManager.sol +++ b/src/archive/RegulationsManager.sol @@ -1,19 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; +import "../interfaces/IRegulationsManager.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "../interfaces/IRegulationsManager.sol"; +import "@openzeppelin-upgradeable/contracts/security/PausableUpgradeable.sol"; -contract RegulationsManager is - IRegulationsManager, - Initializable, - OwnableUpgradeable, - PausableUpgradeable, - UUPSUpgradeable -{ +contract RegulationsManager is IRegulationsManager, Initializable, OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable { mapping(uint32 => mapping(address => bool)) public isEligible; mapping(address => bytes32) public declarationHashes; mapping(uint256 => bytes32) public correctVersionHash; @@ -39,7 +33,7 @@ contract RegulationsManager is constructor() { _disableInitializers(); } - + /// @notice initializes contract function initialize() external initializer { __Pausable_init(); @@ -60,14 +54,8 @@ contract RegulationsManager is /// @dev can be called by the owner or the user them self /// @param _user the user to remove from the whitelist function removeFromWhitelist(address _user) external whenNotPaused { - require( - msg.sender == _user || msg.sender == owner(), - "Incorrect Caller" - ); - require( - isEligible[whitelistVersion][_user] == true, - "User may be in a regulated country" - ); + require(msg.sender == _user || msg.sender == owner(), "Incorrect Caller"); + require(isEligible[whitelistVersion][_user] == true, "User may be in a regulated country"); isEligible[whitelistVersion][_user] = false; @@ -104,9 +92,7 @@ contract RegulationsManager is //------------------------------- INTERNAL FUNCTIONS -------------------------------- //-------------------------------------------------------------------------------------- - function _authorizeUpgrade( - address newImplementation - ) internal override onlyOwner {} + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} //-------------------------------------------------------------------------------------- //------------------------------------ GETTERS --------------------------------------- diff --git a/src/archive/RegulationsManagerV2.sol b/src/archive/RegulationsManagerV2.sol index 3571b29cf..5ff0f5c0c 100644 --- a/src/archive/RegulationsManagerV2.sol +++ b/src/archive/RegulationsManagerV2.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.13; import "@openzeppelin/contracts/access/Ownable.sol"; contract RegulationsManagerV2 is Ownable { - bytes32 constant TYPEHASH = keccak256("TermsOfService(string message,bytes32 hashOfTerms)"); bytes32 constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version)"); string public DOMAIN_NAME = "Ether.fi Terms of Service"; @@ -14,6 +13,7 @@ contract RegulationsManagerV2 is Ownable { string message; bytes32 hashOfTerms; } + TermsOfService public currentTerms; error InvalidTermsAndConditionsSignature(); @@ -23,7 +23,6 @@ contract RegulationsManagerV2 is Ownable { } function generateTermsDigest() public view returns (bytes32) { - // Notice: EIP-712 spec has an exception for string types. If a field is type "string" or "bytes" // you hash it instead of using the default encoding. bytes2 prefix = "\x19\x01"; @@ -39,7 +38,7 @@ contract RegulationsManagerV2 is Ownable { //-------------------------------------------------------------------------------------- function updateTermsOfService(string memory _message, bytes32 _hashOfTerms, string memory _domainVersion) external onlyOwner { - currentTerms = TermsOfService({ message: _message, hashOfTerms: _hashOfTerms }); + currentTerms = TermsOfService({message: _message, hashOfTerms: _hashOfTerms}); DOMAIN_VERSION = _domainVersion; } @@ -47,11 +46,7 @@ contract RegulationsManagerV2 is Ownable { //--------------------------- Signature Recovery ------------------------------------ //-------------------------------------------------------------------------------------- - function splitSignature(bytes memory sig) - internal - pure - returns (uint8 v, bytes32 r, bytes32 s) - { + function splitSignature(bytes memory sig) internal pure returns (uint8 v, bytes32 r, bytes32 s) { require(sig.length == 65); assembly { @@ -66,14 +61,9 @@ contract RegulationsManagerV2 is Ownable { return (v, r, s); } - function recoverSigner(bytes32 message, bytes memory sig) - internal - pure - returns (address) - { + function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); return ecrecover(message, v, r, s); } - } diff --git a/src/archive/Treasury.sol b/src/archive/Treasury.sol index 97c32d574..580139ab2 100644 --- a/src/archive/Treasury.sol +++ b/src/archive/Treasury.sol @@ -6,19 +6,15 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import "../interfaces/ITreasury.sol"; contract Treasury is ITreasury, Ownable { - //-------------------------------------------------------------------------------------- //---------------------------- STATE-CHANGING FUNCTIONS ------------------------------ //-------------------------------------------------------------------------------------- /// @notice Function allows only the owner to withdraw all the funds in the contract function withdraw(uint256 _amount, address _to) external onlyOwner { - require( - _amount <= address(this).balance, - "the balance is lower than the requested amount" - ); + require(_amount <= address(this).balance, "the balance is lower than the requested amount"); require(_to != address(0), "null address is not allowed"); - (bool sent, ) = payable(_to).call{value: _amount}(""); + (bool sent,) = payable(_to).call{value: _amount}(""); require(sent, "Failed to send Ether"); } diff --git a/src/eigenlayer-interfaces/IAVSDirectory.sol b/src/eigenlayer-interfaces/IAVSDirectory.sol index 643f601e5..aee646b68 100644 --- a/src/eigenlayer-interfaces/IAVSDirectory.sol +++ b/src/eigenlayer-interfaces/IAVSDirectory.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "./ISignatureUtilsMixin.sol"; import "./IPauserRegistry.sol"; +import "./ISignatureUtilsMixin.sol"; import "./IStrategy.sol"; interface IAVSDirectoryErrors { @@ -44,9 +44,7 @@ interface IAVSDirectoryEvents is IAVSDirectoryTypes { * @notice Emitted when an operator's registration status with an AVS id updated * @notice Only used by legacy M2 AVSs that have not integrated with operatorSets. */ - event OperatorAVSRegistrationStatusUpdated( - address indexed operator, address indexed avs, OperatorAVSRegistrationStatus status - ); + event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, OperatorAVSRegistrationStatus status); /// @notice Emitted when an AVS updates their metadata URI (Uniform Resource Identifier). /// @dev The URI is never stored; it is simply emitted through an event for off-chain indexing. @@ -72,18 +70,14 @@ interface IAVSDirectory is IAVSDirectoryEvents, IAVSDirectoryErrors, ISignatureU * * @dev Note that the `metadataURI` is *never stored* and is only emitted in the `AVSMetadataURIUpdated` event. */ - function updateAVSMetadataURI( - string calldata metadataURI - ) external; + function updateAVSMetadataURI(string calldata metadataURI) external; /** * @notice Called by an operator to cancel a salt that has been used to register with an AVS. * * @param salt A unique and single use value associated with the approver signature. */ - function cancelSalt( - bytes32 salt - ) external; + function cancelSalt(bytes32 salt) external; /** * @notice Legacy function called by the AVS's service manager contract @@ -96,10 +90,7 @@ interface IAVSDirectory is IAVSDirectoryEvents, IAVSDirectoryErrors, ISignatureU * @dev msg.sender must be the AVS. * @dev Only used by legacy M2 AVSs that have not integrated with operator sets. */ - function registerOperatorToAVS( - address operator, - ISignatureUtilsMixinTypes.SignatureWithSaltAndExpiry memory operatorSignature - ) external; + function registerOperatorToAVS(address operator, ISignatureUtilsMixinTypes.SignatureWithSaltAndExpiry memory operatorSignature) external; /** * @notice Legacy function called by an AVS to deregister an operator from the AVS. @@ -110,9 +101,7 @@ interface IAVSDirectory is IAVSDirectoryEvents, IAVSDirectoryErrors, ISignatureU * * @dev Only used by legacy M2 AVSs that have not integrated with operator sets. */ - function deregisterOperatorFromAVS( - address operator - ) external; + function deregisterOperatorFromAVS(address operator) external; /** * @@ -129,12 +118,7 @@ interface IAVSDirectory is IAVSDirectoryEvents, IAVSDirectoryErrors, ISignatureU * @param salt A unique and single-use value associated with the approver's signature. * @param expiry The time after which the approver's signature becomes invalid. */ - function calculateOperatorAVSRegistrationDigestHash( - address operator, - address avs, - bytes32 salt, - uint256 expiry - ) external view returns (bytes32); + function calculateOperatorAVSRegistrationDigestHash(address operator, address avs, bytes32 salt, uint256 expiry) external view returns (bytes32); /// @notice The EIP-712 typehash for the Registration struct used by the contract. function OPERATOR_AVS_REGISTRATION_TYPEHASH() external view returns (bytes32); diff --git a/src/eigenlayer-interfaces/IAVSRegistrar.sol b/src/eigenlayer-interfaces/IAVSRegistrar.sol index 054de2e16..effa66d0a 100644 --- a/src/eigenlayer-interfaces/IAVSRegistrar.sol +++ b/src/eigenlayer-interfaces/IAVSRegistrar.sol @@ -11,12 +11,7 @@ interface IAVSRegistrar { * @param operatorSetIds the list of operator set ids being registered for * @param data arbitrary data the operator can provide as part of registration */ - function registerOperator( - address operator, - address avs, - uint32[] calldata operatorSetIds, - bytes calldata data - ) external; + function registerOperator(address operator, address avs, uint32[] calldata operatorSetIds, bytes calldata data) external; /** * @notice Called by the AllocationManager when an operator is deregistered from @@ -32,7 +27,5 @@ interface IAVSRegistrar { * @param avs the AVS to check * @return true if the AVS is supported, false otherwise */ - function supportsAVS( - address avs - ) external view returns (bool); + function supportsAVS(address avs) external view returns (bool); } diff --git a/src/eigenlayer-interfaces/IAllocationManager.sol b/src/eigenlayer-interfaces/IAllocationManager.sol index b58e90643..85d359414 100644 --- a/src/eigenlayer-interfaces/IAllocationManager.sol +++ b/src/eigenlayer-interfaces/IAllocationManager.sol @@ -2,10 +2,11 @@ pragma solidity >=0.5.0; import {OperatorSet} from "../eigenlayer-libraries/OperatorSetLib.sol"; -import "./IPauserRegistry.sol"; -import "./IStrategy.sol"; + import "./IAVSRegistrar.sol"; +import "./IPauserRegistry.sol"; import "./ISemVerMixin.sol"; +import "./IStrategy.sol"; interface IAllocationManagerErrors { /// Input Validation @@ -177,9 +178,7 @@ interface IAllocationManagerEvents is IAllocationManagerTypes { event AllocationDelaySet(address operator, uint32 delay, uint32 effectBlock); /// @notice Emitted when an operator's magnitude is updated for a given operatorSet and strategy - event AllocationUpdated( - address operator, OperatorSet operatorSet, IStrategy strategy, uint64 magnitude, uint32 effectBlock - ); + event AllocationUpdated(address operator, OperatorSet operatorSet, IStrategy strategy, uint64 magnitude, uint32 effectBlock); /// @notice Emitted when operator's encumbered magnitude is updated for a given strategy event EncumberedMagnitudeUpdated(address operator, IStrategy strategy, uint64 encumberedMagnitude); @@ -189,9 +188,7 @@ interface IAllocationManagerEvents is IAllocationManagerTypes { /// @notice Emitted when an operator is slashed by an operator set for a strategy /// `wadSlashed` is the proportion of the operator's total delegated stake that was slashed - event OperatorSlashed( - address operator, OperatorSet operatorSet, IStrategy[] strategies, uint256[] wadSlashed, string description - ); + event OperatorSlashed(address operator, OperatorSet operatorSet, IStrategy[] strategies, uint256[] wadSlashed, string description); /// @notice Emitted when an AVS configures the address that will handle registration/deregistration event AVSRegistrarSet(address avs, IAVSRegistrar registrar); @@ -267,11 +264,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * * @dev can be called permissionlessly by anyone */ - function clearDeallocationQueue( - address operator, - IStrategy[] calldata strategies, - uint16[] calldata numToClear - ) external; + function clearDeallocationQueue(address operator, IStrategy[] calldata strategies, uint16[] calldata numToClear) external; /** * @notice Allows an operator to register for one or more operator sets for an AVS. If the operator @@ -290,9 +283,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * deregisterOperator` method to complete deregistration. This call MUST succeed in order for * deregistration to be successful. */ - function deregisterFromOperatorSets( - DeregisterParams calldata params - ) external; + function deregisterFromOperatorSets(DeregisterParams calldata params) external; /** * @notice Called by the delegation manager OR an operator to set an operator's allocation delay. @@ -341,11 +332,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param operatorSetId the operator set to remove strategies from * @param strategies the strategies to remove */ - function removeStrategiesFromOperatorSet( - address avs, - uint32 operatorSetId, - IStrategy[] calldata strategies - ) external; + function removeStrategiesFromOperatorSet(address avs, uint32 operatorSetId, IStrategy[] calldata strategies) external; /** * @@ -357,18 +344,14 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @notice Returns the number of operator sets for the AVS * @param avs the AVS to query */ - function getOperatorSetCount( - address avs - ) external view returns (uint256); + function getOperatorSetCount(address avs) external view returns (uint256); /** * @notice Returns the list of operator sets the operator has current or pending allocations/deallocations in * @param operator the operator to query * @return the list of operator sets the operator has current or pending allocations/deallocations in */ - function getAllocatedSets( - address operator - ) external view returns (OperatorSet[] memory); + function getAllocatedSets(address operator) external view returns (OperatorSet[] memory); /** * @notice Returns the list of strategies an operator has current or pending allocations/deallocations from @@ -377,10 +360,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param operatorSet the operator set to query * @return the list of strategies */ - function getAllocatedStrategies( - address operator, - OperatorSet memory operatorSet - ) external view returns (IStrategy[] memory); + function getAllocatedStrategies(address operator, OperatorSet memory operatorSet) external view returns (IStrategy[] memory); /** * @notice Returns the current/pending stake allocation an operator has from a strategy to an operator set @@ -389,11 +369,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param strategy the strategy to query * @return the current/pending stake allocation */ - function getAllocation( - address operator, - OperatorSet memory operatorSet, - IStrategy strategy - ) external view returns (Allocation memory); + function getAllocation(address operator, OperatorSet memory operatorSet, IStrategy strategy) external view returns (Allocation memory); /** * @notice Returns the current/pending stake allocations for multiple operators from a strategy to an operator set @@ -402,11 +378,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param strategy the strategy to query * @return each operator's allocation */ - function getAllocations( - address[] memory operators, - OperatorSet memory operatorSet, - IStrategy strategy - ) external view returns (Allocation[] memory); + function getAllocations(address[] memory operators, OperatorSet memory operatorSet, IStrategy strategy) external view returns (Allocation[] memory); /** * @notice Given a strategy, returns a list of operator sets and corresponding stake allocations. @@ -417,10 +389,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @return the list of all operator sets the operator has allocations for * @return the corresponding list of allocations from the specific `strategy` */ - function getStrategyAllocations( - address operator, - IStrategy strategy - ) external view returns (OperatorSet[] memory, Allocation[] memory); + function getStrategyAllocations(address operator, IStrategy strategy) external view returns (OperatorSet[] memory, Allocation[] memory); /** * @notice For a strategy, get the amount of magnitude that is allocated across one or more operator sets @@ -456,10 +425,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param strategies the strategies to get the max magnitudes for * @return the max magnitudes for each strategy */ - function getMaxMagnitudes( - address operator, - IStrategy[] calldata strategies - ) external view returns (uint64[] memory); + function getMaxMagnitudes(address operator, IStrategy[] calldata strategies) external view returns (uint64[] memory); /** * @notice Returns the maximum magnitudes each operator can allocate for the given strategy @@ -469,10 +435,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param strategy the strategy to get the max magnitudes for * @return the max magnitudes for each operator */ - function getMaxMagnitudes( - address[] calldata operators, - IStrategy strategy - ) external view returns (uint64[] memory); + function getMaxMagnitudes(address[] calldata operators, IStrategy strategy) external view returns (uint64[] memory); /** * @notice Returns the maximum magnitude an operator can allocate for the given strategies @@ -484,11 +447,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param blockNumber the blockNumber at which to check the max magnitudes * @return the max magnitudes for each strategy */ - function getMaxMagnitudesAtBlock( - address operator, - IStrategy[] calldata strategies, - uint32 blockNumber - ) external view returns (uint64[] memory); + function getMaxMagnitudesAtBlock(address operator, IStrategy[] calldata strategies, uint32 blockNumber) external view returns (uint64[] memory); /** * @notice Returns the time in blocks between an operator allocating slashable magnitude @@ -498,17 +457,13 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @return isSet Whether the operator has configured a delay * @return delay The time in blocks between allocating magnitude and magnitude becoming slashable */ - function getAllocationDelay( - address operator - ) external view returns (bool isSet, uint32 delay); + function getAllocationDelay(address operator) external view returns (bool isSet, uint32 delay); /** * @notice Returns a list of all operator sets the operator is registered for * @param operator The operator address to query. */ - function getRegisteredSets( - address operator - ) external view returns (OperatorSet[] memory operatorSets); + function getRegisteredSets(address operator) external view returns (OperatorSet[] memory operatorSets); /** * @notice Returns whether the operator is registered for the operator set @@ -520,41 +475,31 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven /** * @notice Returns whether the operator set exists */ - function isOperatorSet( - OperatorSet memory operatorSet - ) external view returns (bool); + function isOperatorSet(OperatorSet memory operatorSet) external view returns (bool); /** * @notice Returns all the operators registered to an operator set * @param operatorSet The operatorSet to query. */ - function getMembers( - OperatorSet memory operatorSet - ) external view returns (address[] memory operators); + function getMembers(OperatorSet memory operatorSet) external view returns (address[] memory operators); /** * @notice Returns the number of operators registered to an operatorSet. * @param operatorSet The operatorSet to get the member count for */ - function getMemberCount( - OperatorSet memory operatorSet - ) external view returns (uint256); + function getMemberCount(OperatorSet memory operatorSet) external view returns (uint256); /** * @notice Returns the address that handles registration/deregistration for the AVS * If not set, defaults to the input address (`avs`) */ - function getAVSRegistrar( - address avs - ) external view returns (IAVSRegistrar); + function getAVSRegistrar(address avs) external view returns (IAVSRegistrar); /** * @notice Returns an array of strategies in the operatorSet. * @param operatorSet The operatorSet to query. */ - function getStrategiesInOperatorSet( - OperatorSet memory operatorSet - ) external view returns (IStrategy[] memory strategies); + function getStrategiesInOperatorSet(OperatorSet memory operatorSet) external view returns (IStrategy[] memory strategies); /** * @notice Returns the minimum amount of stake that will be slashable as of some future block, @@ -574,12 +519,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param strategies the strategies that each slashable stake corresponds to * @param futureBlock the block at which to get allocation information. Should be a future block. */ - function getMinimumSlashableStake( - OperatorSet memory operatorSet, - address[] memory operators, - IStrategy[] memory strategies, - uint32 futureBlock - ) external view returns (uint256[][] memory slashableStake); + function getMinimumSlashableStake(OperatorSet memory operatorSet, address[] memory operators, IStrategy[] memory strategies, uint32 futureBlock) external view returns (uint256[][] memory slashableStake); /** * @notice Returns the current allocated stake, irrespective of the operator's slashable status for the operatorSet. @@ -587,11 +527,7 @@ interface IAllocationManager is IAllocationManagerErrors, IAllocationManagerEven * @param operators the operators to query * @param strategies the strategies to query */ - function getAllocatedStake( - OperatorSet memory operatorSet, - address[] memory operators, - IStrategy[] memory strategies - ) external view returns (uint256[][] memory slashableStake); + function getAllocatedStake(OperatorSet memory operatorSet, address[] memory operators, IStrategy[] memory strategies) external view returns (uint256[][] memory slashableStake); /** * @notice Returns whether an operator is slashable by an operator set. diff --git a/src/eigenlayer-interfaces/IBackingEigen.sol b/src/eigenlayer-interfaces/IBackingEigen.sol index c8e031bd6..2542d734a 100644 --- a/src/eigenlayer-interfaces/IBackingEigen.sol +++ b/src/eigenlayer-interfaces/IBackingEigen.sol @@ -26,9 +26,7 @@ interface IBackingEigen is IERC20 { /** * @notice An initializer function that sets initial values for the contract's state variables. */ - function initialize( - address initialOwner - ) external; + function initialize(address initialOwner) external; // @notice Allows the contract owner to modify an entry in the `isMinter` mapping. function setIsMinter(address minterAddress, bool newStatus) external; @@ -44,9 +42,7 @@ interface IBackingEigen is IERC20 { * * See {ERC20-_burn}. */ - function burn( - uint256 amount - ) external; + function burn(uint256 amount) external; /// @notice the address of the wrapped Eigen token EIGEN function EIGEN() external view returns (IERC20); diff --git a/src/eigenlayer-interfaces/IDelayedWithdrawalRouter.sol b/src/eigenlayer-interfaces/IDelayedWithdrawalRouter.sol index 797ac0487..06abf96be 100644 --- a/src/eigenlayer-interfaces/IDelayedWithdrawalRouter.sol +++ b/src/eigenlayer-interfaces/IDelayedWithdrawalRouter.sol @@ -14,7 +14,7 @@ interface IDelayedWithdrawalRouter { DelayedWithdrawal[] delayedWithdrawals; } - /// @notice event for delayedWithdrawal creation + /// @notice event for delayedWithdrawal creation event DelayedWithdrawalCreated(address podOwner, address recipient, uint256 amount, uint256 index); /// @notice event for the claiming of delayedWithdrawals diff --git a/src/eigenlayer-interfaces/IDelegationFaucet.sol b/src/eigenlayer-interfaces/IDelegationFaucet.sol index a08d60f8d..96ade4325 100644 --- a/src/eigenlayer-interfaces/IDelegationFaucet.sol +++ b/src/eigenlayer-interfaces/IDelegationFaucet.sol @@ -1,40 +1,21 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "src/eigenlayer-interfaces/IStrategyManager.sol"; import "src/eigenlayer-interfaces/IDelegationManager.sol"; +import "src/eigenlayer-interfaces/IStrategyManager.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IDelegationFaucet { - function mintDepositAndDelegate( - address _operator, - IDelegationManager.SignatureWithExpiry memory approverSignatureAndExpiry, - bytes32 approverSalt, - uint256 _depositAmount - ) external; + function mintDepositAndDelegate(address _operator, IDelegationManager.SignatureWithExpiry memory approverSignatureAndExpiry, bytes32 approverSalt, uint256 _depositAmount) external; function getStaker(address operator) external returns (address); - function depositIntoStrategy( - address staker, - IStrategy strategy, - IERC20 token, - uint256 amount - ) external returns (bytes memory); - - function queueWithdrawal( - address staker, - IDelegationManager.QueuedWithdrawalParams[] calldata queuedWithdrawalParams - ) external returns (bytes memory); - - function completeQueuedWithdrawal( - address staker, - IDelegationManager.Withdrawal calldata queuedWithdrawal, - IERC20[] calldata tokens, - uint256 middlewareTimesIndex, - bool receiveAsTokens - ) external returns (bytes memory); + function depositIntoStrategy(address staker, IStrategy strategy, IERC20 token, uint256 amount) external returns (bytes memory); + + function queueWithdrawal(address staker, IDelegationManager.QueuedWithdrawalParams[] calldata queuedWithdrawalParams) external returns (bytes memory); + + function completeQueuedWithdrawal(address staker, IDelegationManager.Withdrawal calldata queuedWithdrawal, IERC20[] calldata tokens, uint256 middlewareTimesIndex, bool receiveAsTokens) external returns (bytes memory); function transfer(address staker, address token, address to, uint256 amount) external returns (bytes memory); diff --git a/src/eigenlayer-interfaces/IDelegationManager.sol b/src/eigenlayer-interfaces/IDelegationManager.sol index 2069a2dfa..d39d8ffa7 100644 --- a/src/eigenlayer-interfaces/IDelegationManager.sol +++ b/src/eigenlayer-interfaces/IDelegationManager.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "./IStrategy.sol"; +import "../eigenlayer-libraries/SlashingLib.sol"; import "./IPauserRegistry.sol"; import "./ISignatureUtilsMixin.sol"; -import "../eigenlayer-libraries/SlashingLib.sol"; +import "./IStrategy.sol"; interface IDelegationManagerErrors { /// @dev Thrown when caller is neither the StrategyManager or EigenPodManager contract. @@ -202,11 +202,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @dev This function will revert if the caller is already delegated to an operator. * @dev Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event */ - function registerAsOperator( - address initDelegationApprover, - uint32 allocationDelay, - string calldata metadataURI - ) external; + function registerAsOperator(address initDelegationApprover, uint32 allocationDelay, string calldata metadataURI) external; /** * @notice Updates an operator's stored `delegationApprover`. @@ -233,11 +229,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @dev The signature/salt are used ONLY if the operator has configured a delegationApprover. * If they have not, these params can be left empty. */ - function delegateTo( - address operator, - SignatureWithExpiry memory approverSignatureAndExpiry, - bytes32 approverSalt - ) external; + function delegateTo(address operator, SignatureWithExpiry memory approverSignatureAndExpiry, bytes32 approverSalt) external; /** * @notice Undelegates the staker from their operator and queues a withdrawal for all of their shares @@ -249,9 +241,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @dev Reverts if the caller is not the staker, nor the operator who the staker is delegated to, nor the operator's specified "delegationApprover" * @dev Reverts if the `staker` is not delegated to an operator */ - function undelegate( - address staker - ) external returns (bytes32[] memory withdrawalRoots); + function undelegate(address staker) external returns (bytes32[] memory withdrawalRoots); /** * @notice Undelegates the staker from their current operator, and redelegates to `newOperator` @@ -264,11 +254,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @param newOperatorApproverSig A signature from the operator's `delegationApprover` * @param approverSalt A unique single use value tied to the approver's signature */ - function redelegate( - address newOperator, - SignatureWithExpiry memory newOperatorApproverSig, - bytes32 approverSalt - ) external returns (bytes32[] memory withdrawalRoots); + function redelegate(address newOperator, SignatureWithExpiry memory newOperatorApproverSig, bytes32 approverSalt) external returns (bytes32[] memory withdrawalRoots); /** * @notice Allows a staker to queue a withdrawal of their deposit shares. The withdrawal can be @@ -281,9 +267,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @dev To view all the staker's strategies/deposit shares that can be queued for withdrawal, see `getDepositedShares` * @dev To view the current conversion between a staker's deposit shares and withdrawable shares, see `getWithdrawableShares` */ - function queueWithdrawals( - QueuedWithdrawalParams[] calldata params - ) external returns (bytes32[] memory); + function queueWithdrawals(QueuedWithdrawalParams[] calldata params) external returns (bytes32[] memory); /** * @notice Used to complete a queued withdrawal @@ -296,11 +280,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * NOTE: if the caller receives shares and is currently delegated to an operator, the received shares are * automatically delegated to the caller's current operator. */ - function completeQueuedWithdrawal( - Withdrawal calldata withdrawal, - IERC20[] calldata tokens, - bool receiveAsTokens - ) external; + function completeQueuedWithdrawal(Withdrawal calldata withdrawal, IERC20[] calldata tokens, bool receiveAsTokens) external; /** * @notice Used to complete multiple queued withdrawals @@ -309,11 +289,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @param receiveAsTokens Whether or not to complete each withdrawal as tokens. See `completeQueuedWithdrawal` for the usage of a single boolean. * @dev See `completeQueuedWithdrawal` for relevant dev tags */ - function completeQueuedWithdrawals( - Withdrawal[] calldata withdrawals, - IERC20[][] calldata tokens, - bool[] calldata receiveAsTokens - ) external; + function completeQueuedWithdrawals(Withdrawal[] calldata withdrawals, IERC20[][] calldata tokens, bool[] calldata receiveAsTokens) external; /** * @notice Called by a share manager when a staker's deposit share balance in a strategy increases. @@ -328,12 +304,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * staker has been slashed 100% on the beacon chain such that the calculated slashing factor is 0, this * method WILL REVERT. */ - function increaseDelegatedShares( - address staker, - IStrategy strategy, - uint256 prevDepositShares, - uint256 addedShares - ) external; + function increaseDelegatedShares(address staker, IStrategy strategy, uint256 prevDepositShares, uint256 addedShares) external; /** * @notice If the staker is delegated, decreases its operator's shares in response to @@ -344,11 +315,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @dev Note: `beaconChainSlashingFactorDecrease` are assumed to ALWAYS be < 1 WAD. * These invariants are maintained in the EigenPodManager. */ - function decreaseDelegatedShares( - address staker, - uint256 curDepositShares, - uint64 beaconChainSlashingFactorDecrease - ) external; + function decreaseDelegatedShares(address staker, uint256 curDepositShares, uint64 beaconChainSlashingFactorDecrease) external; /** * @notice Decreases the operators shares in storage after a slash and increases the burnable shares by calling @@ -361,12 +328,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @dev Note: Assumes `prevMaxMagnitude <= newMaxMagnitude`. This invariant is maintained in * the AllocationManager. */ - function slashOperatorShares( - address operator, - IStrategy strategy, - uint64 prevMaxMagnitude, - uint64 newMaxMagnitude - ) external; + function slashOperatorShares(address operator, IStrategy strategy, uint64 prevMaxMagnitude, uint64 newMaxMagnitude) external; /** * @@ -379,9 +341,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @notice Mapping: staker => operator whom the staker is currently delegated to. * @dev Note that returning address(0) indicates that the staker is not actively delegated to any operator. */ - function delegatedTo( - address staker - ) external view returns (address); + function delegatedTo(address staker) external view returns (address); /** * @notice Mapping: delegationApprover => 32-byte salt => whether or not the salt has already been used by the delegationApprover. @@ -392,50 +352,36 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, /// @notice Mapping: staker => cumulative number of queued withdrawals they have ever initiated. /// @dev This only increments (doesn't decrement), and is used to help ensure that otherwise identical withdrawals have unique hashes. - function cumulativeWithdrawalsQueued( - address staker - ) external view returns (uint256); + function cumulativeWithdrawalsQueued(address staker) external view returns (uint256); /** * @notice Returns 'true' if `staker` *is* actively delegated, and 'false' otherwise. */ - function isDelegated( - address staker - ) external view returns (bool); + function isDelegated(address staker) external view returns (bool); /** * @notice Returns true is an operator has previously registered for delegation. */ - function isOperator( - address operator - ) external view returns (bool); + function isOperator(address operator) external view returns (bool); /** * @notice Returns the delegationApprover account for an operator */ - function delegationApprover( - address operator - ) external view returns (address); + function delegationApprover(address operator) external view returns (address); /** * @notice Returns the shares that an operator has delegated to them in a set of strategies * @param operator the operator to get shares for * @param strategies the strategies to get shares for */ - function getOperatorShares( - address operator, - IStrategy[] memory strategies - ) external view returns (uint256[] memory); + function getOperatorShares(address operator, IStrategy[] memory strategies) external view returns (uint256[] memory); /** * @notice Returns the shares that a set of operators have delegated to them in a set of strategies * @param operators the operators to get shares for * @param strategies the strategies to get shares for */ - function getOperatorsShares( - address[] memory operators, - IStrategy[] memory strategies - ) external view returns (uint256[][] memory); + function getOperatorsShares(address[] memory operators, IStrategy[] memory strategies) external view returns (uint256[][] memory); /** * @notice Returns amount of withdrawable shares from an operator for a strategy that is still in the queue @@ -454,17 +400,12 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * The shares amount returned is the actual amount of Strategy shares the staker would receive (subject * to each strategy's underlying shares to token ratio). */ - function getWithdrawableShares( - address staker, - IStrategy[] memory strategies - ) external view returns (uint256[] memory withdrawableShares, uint256[] memory depositShares); + function getWithdrawableShares(address staker, IStrategy[] memory strategies) external view returns (uint256[] memory withdrawableShares, uint256[] memory depositShares); /** * @notice Returns the number of shares in storage for a staker and all their strategies */ - function getDepositedShares( - address staker - ) external view returns (IStrategy[] memory, uint256[] memory); + function getDepositedShares(address staker) external view returns (IStrategy[] memory, uint256[] memory); /** * @notice Returns the scaling factor applied to a staker's deposits for a given strategy @@ -476,9 +417,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @param withdrawalRoot The hash identifying the queued withdrawal. * @return withdrawal The withdrawal details. */ - function queuedWithdrawals( - bytes32 withdrawalRoot - ) external view returns (Withdrawal memory withdrawal); + function queuedWithdrawals(bytes32 withdrawalRoot) external view returns (Withdrawal memory withdrawal); /** * @notice Returns the Withdrawal and corresponding shares associated with a `withdrawalRoot` @@ -488,9 +427,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @dev The shares are what a user would receive from completing a queued withdrawal, assuming all slashings are applied * @dev Withdrawals queued before the slashing release cannot be queried with this method */ - function getQueuedWithdrawal( - bytes32 withdrawalRoot - ) external view returns (Withdrawal memory withdrawal, uint256[] memory shares); + function getQueuedWithdrawal(bytes32 withdrawalRoot) external view returns (Withdrawal memory withdrawal, uint256[] memory shares); /** * @notice Returns all queued withdrawals and their corresponding shares for a staker. @@ -499,15 +436,11 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @return shares 2D array of shares, where each inner array corresponds to the strategies in the withdrawal. * @dev The shares are what a user would receive from completing a queued withdrawal, assuming all slashings are applied. */ - function getQueuedWithdrawals( - address staker - ) external view returns (Withdrawal[] memory withdrawals, uint256[][] memory shares); + function getQueuedWithdrawals(address staker) external view returns (Withdrawal[] memory withdrawals, uint256[][] memory shares); /// @notice Returns a list of queued withdrawal roots for the `staker`. /// NOTE that this only returns withdrawals queued AFTER the slashing release. - function getQueuedWithdrawalRoots( - address staker - ) external view returns (bytes32[] memory); + function getQueuedWithdrawalRoots(address staker) external view returns (bytes32[] memory); /** * @notice Converts shares for a set of strategies to deposit shares, likely in order to input into `queueWithdrawals`. @@ -518,16 +451,10 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @return the deposit shares * @dev will be a few wei off due to rounding errors */ - function convertToDepositShares( - address staker, - IStrategy[] memory strategies, - uint256[] memory withdrawableShares - ) external view returns (uint256[] memory); + function convertToDepositShares(address staker, IStrategy[] memory strategies, uint256[] memory withdrawableShares) external view returns (uint256[] memory); /// @notice Returns the keccak256 hash of `withdrawal`. - function calculateWithdrawalRoot( - Withdrawal memory withdrawal - ) external pure returns (bytes32); + function calculateWithdrawalRoot(Withdrawal memory withdrawal) external pure returns (bytes32); /** * @notice Calculates the digest hash to be signed by the operator's delegationApprove and used in the `delegateTo` function. @@ -537,13 +464,7 @@ interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, * @param approverSalt A unique and single use value associated with the approver signature. * @param expiry Time after which the approver's signature becomes invalid */ - function calculateDelegationApprovalDigestHash( - address staker, - address operator, - address _delegationApprover, - bytes32 approverSalt, - uint256 expiry - ) external view returns (bytes32); + function calculateDelegationApprovalDigestHash(address staker, address operator, address _delegationApprover, bytes32 approverSalt, uint256 expiry) external view returns (bytes32); /// @notice return address of the beaconChainETHStrategy function beaconChainETHStrategy() external view returns (IStrategy); diff --git a/src/eigenlayer-interfaces/IDelegationTerms.sol b/src/eigenlayer-interfaces/IDelegationTerms.sol index fc5a82fc9..0e8295b7b 100644 --- a/src/eigenlayer-interfaces/IDelegationTerms.sol +++ b/src/eigenlayer-interfaces/IDelegationTerms.sol @@ -12,15 +12,7 @@ import "./IStrategy.sol"; interface IDelegationTerms { function payForService(IERC20 token, uint256 amount) external payable; - function onDelegationWithdrawn( - address delegator, - IStrategy[] memory stakerStrategyList, - uint256[] memory stakerShares - ) external returns(bytes memory); + function onDelegationWithdrawn(address delegator, IStrategy[] memory stakerStrategyList, uint256[] memory stakerShares) external returns (bytes memory); - function onDelegationReceived( - address delegator, - IStrategy[] memory stakerStrategyList, - uint256[] memory stakerShares - ) external returns(bytes memory); -} \ No newline at end of file + function onDelegationReceived(address delegator, IStrategy[] memory stakerStrategyList, uint256[] memory stakerShares) external returns (bytes memory); +} diff --git a/src/eigenlayer-interfaces/IETHPOSDeposit.sol b/src/eigenlayer-interfaces/IETHPOSDeposit.sol index 5fc09a5cc..9e7bab4d0 100644 --- a/src/eigenlayer-interfaces/IETHPOSDeposit.sol +++ b/src/eigenlayer-interfaces/IETHPOSDeposit.sol @@ -24,12 +24,7 @@ interface IETHPOSDeposit { /// @param signature A BLS12-381 signature. /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object. /// Used as a protection against malformed input. - function deposit( - bytes calldata pubkey, - bytes calldata withdrawal_credentials, - bytes calldata signature, - bytes32 deposit_data_root - ) external payable; + function deposit(bytes calldata pubkey, bytes calldata withdrawal_credentials, bytes calldata signature, bytes32 deposit_data_root) external payable; /// @notice Query the current deposit root hash. /// @return The deposit root hash. diff --git a/src/eigenlayer-interfaces/IEigen.sol b/src/eigenlayer-interfaces/IEigen.sol index 0de79374b..cd9279e55 100644 --- a/src/eigenlayer-interfaces/IEigen.sol +++ b/src/eigenlayer-interfaces/IEigen.sol @@ -31,16 +31,12 @@ interface IEigen is IERC20 { /** * @notice This function allows bEIGEN holders to wrap their tokens into Eigen */ - function wrap( - uint256 amount - ) external; + function wrap(uint256 amount) external; /** * @notice This function allows Eigen holders to unwrap their tokens into bEIGEN */ - function unwrap( - uint256 amount - ) external; + function unwrap(uint256 amount) external; /** * @dev Clock used for flagging checkpoints. Has been overridden to implement timestamp based diff --git a/src/eigenlayer-interfaces/IEigenPod.sol b/src/eigenlayer-interfaces/IEigenPod.sol index 19fcf3287..555acc5af 100644 --- a/src/eigenlayer-interfaces/IEigenPod.sol +++ b/src/eigenlayer-interfaces/IEigenPod.sol @@ -4,8 +4,9 @@ pragma solidity >=0.5.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../eigenlayer-libraries/BeaconChainProofs.sol"; -import "./ISemVerMixin.sol"; + import "./IEigenPodManager.sol"; +import "./ISemVerMixin.sol"; interface IEigenPodErrors { /// @dev Thrown when msg.sender is not the EPM. @@ -144,9 +145,7 @@ interface IEigenPodEvents is IEigenPodTypes { event NonBeaconChainETHReceived(uint256 amountReceived); /// @notice Emitted when a checkpoint is created - event CheckpointCreated( - uint64 indexed checkpointTimestamp, bytes32 indexed beaconBlockRoot, uint256 validatorCount - ); + event CheckpointCreated(uint64 indexed checkpointTimestamp, bytes32 indexed beaconBlockRoot, uint256 validatorCount); /// @notice Emitted when a checkpoint is finalized event CheckpointFinalized(uint64 indexed checkpointTimestamp, int256 totalShareDeltaWei); @@ -168,7 +167,6 @@ interface IEigenPodEvents is IEigenPodTypes { /// @notice Emitted when a standard consolidation request is initiated event ConsolidationRequested(bytes32 indexed sourcePubkeyHash, bytes32 indexed targetPubkeyHash); - } /** @@ -180,9 +178,7 @@ interface IEigenPodEvents is IEigenPodTypes { */ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { /// @notice Used to initialize the pointers to contracts crucial to the pod's functionality, in beacon proxy construction from EigenPodManager - function initialize( - address owner - ) external; + function initialize(address owner) external; /// @notice Called by EigenPodManager when the owner wants to create another ETH validator. /// @dev This function only supports staking to a 0x01 validator. For compounding validators, please interact directly with the deposit contract. @@ -209,9 +205,7 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { * @param revertIfNoBalance Forces a revert if the pod ETH balance is 0. This allows the pod owner * to prevent accidentally starting a checkpoint that will not increase their shares */ - function startCheckpoint( - bool revertIfNoBalance - ) external; + function startCheckpoint(bool revertIfNoBalance) external; /** * @dev Progress the current checkpoint towards completion by submitting one or more validator @@ -223,10 +217,7 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { * @param balanceContainerProof proves the beacon's current balance container root against a checkpoint's `beaconBlockRoot` * @param proofs Proofs for one or more validator current balances against the `balanceContainerRoot` */ - function verifyCheckpointProofs( - BeaconChainProofs.BalanceContainerProof calldata balanceContainerProof, - BeaconChainProofs.BalanceProof[] calldata proofs - ) external; + function verifyCheckpointProofs(BeaconChainProofs.BalanceContainerProof calldata balanceContainerProof, BeaconChainProofs.BalanceProof[] calldata proofs) external; /** * @dev Verify one or more validators have their withdrawal credentials pointed at this EigenPod, and award @@ -242,13 +233,7 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { * @param validatorFields the fields of the beacon chain "Validator" container. See consensus specs for * details: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator */ - function verifyWithdrawalCredentials( - uint64 beaconTimestamp, - BeaconChainProofs.StateRootProof calldata stateRootProof, - uint40[] calldata validatorIndices, - bytes[] calldata validatorFieldsProofs, - bytes32[][] calldata validatorFields - ) external; + function verifyWithdrawalCredentials(uint64 beaconTimestamp, BeaconChainProofs.StateRootProof calldata stateRootProof, uint40[] calldata validatorIndices, bytes[] calldata validatorFieldsProofs, bytes32[][] calldata validatorFields) external; /// @notice Allows the owner or proof submitter to initiate one or more requests to /// withdraw funds from validators on the beacon chain. @@ -290,9 +275,7 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { /// - The validator MUST be active and MUST NOT have initiated exit /// /// For further reference: https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/beacon-chain.md#new-process_withdrawal_request - function requestWithdrawal( - WithdrawalRequest[] calldata requests - ) external payable; + function requestWithdrawal(WithdrawalRequest[] calldata requests) external payable; /// @notice Allows the owner or proof submitter to initiate one or more consolidation requests. /// @param requests Array of consolidation requests consisting of source and target validator pubkeys @@ -327,9 +310,7 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { /// - The source validator MUST NOT have pending partial withdrawal requests /// /// For further reference: https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/beacon-chain.md#new-process_consolidation_request - function requestConsolidation( - ConsolidationRequest[] calldata requests - ) external payable; + function requestConsolidation(ConsolidationRequest[] calldata requests) external payable; /** * @dev Prove that one of this pod's active validators was slashed on the beacon chain. A successful @@ -361,11 +342,7 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { * - Validator MUST be in `ACTIVE` status in the pod * - Validator MUST be slashed on the beacon chain */ - function verifyStaleBalance( - uint64 beaconTimestamp, - BeaconChainProofs.StateRootProof calldata stateRootProof, - BeaconChainProofs.ValidatorProof calldata proof - ) external; + function verifyStaleBalance(uint64 beaconTimestamp, BeaconChainProofs.StateRootProof calldata stateRootProof, BeaconChainProofs.ValidatorProof calldata proof) external; /// @notice called by owner of a pod to remove any ERC20s deposited in the pod function recoverTokens(IERC20[] memory tokenList, uint256[] memory amountsToWithdraw, address recipient) external; @@ -377,9 +354,7 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { /// only address that can call these methods. /// @param newProofSubmitter The new proof submitter address. If set to 0, only the /// pod owner will be able to call `startCheckpoint` and `verifyWithdrawalCredentials` - function setProofSubmitter( - address newProofSubmitter - ) external; + function setProofSubmitter(address newProofSubmitter) external; /** * @@ -403,24 +378,16 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { function podOwner() external view returns (address); /// @notice Returns the validatorInfo struct for the provided pubkeyHash - function validatorPubkeyHashToInfo( - bytes32 validatorPubkeyHash - ) external view returns (ValidatorInfo memory); + function validatorPubkeyHashToInfo(bytes32 validatorPubkeyHash) external view returns (ValidatorInfo memory); /// @notice Returns the validatorInfo struct for the provided pubkey - function validatorPubkeyToInfo( - bytes calldata validatorPubkey - ) external view returns (ValidatorInfo memory); + function validatorPubkeyToInfo(bytes calldata validatorPubkey) external view returns (ValidatorInfo memory); /// @notice Returns the validator status for a given validator pubkey hash - function validatorStatus( - bytes32 pubkeyHash - ) external view returns (VALIDATOR_STATUS); + function validatorStatus(bytes32 pubkeyHash) external view returns (VALIDATOR_STATUS); /// @notice Returns the validator status for a given validator pubkey - function validatorStatus( - bytes calldata validatorPubkey - ) external view returns (VALIDATOR_STATUS); + function validatorStatus(bytes calldata validatorPubkey) external view returns (VALIDATOR_STATUS); /// @notice Number of validators with proven withdrawal credentials, who do not have proven full withdrawals function activeValidatorCount() external view returns (uint256); @@ -472,15 +439,11 @@ interface IEigenPod is IEigenPodErrors, IEigenPodEvents, ISemVerMixin { /// - The final partial withdrawal for an exited validator will be likely be included in this mapping. /// i.e. if a validator was last checkpointed at 32.1 ETH before exiting, the next checkpoint will calculate their /// "exited" amount to be 32.1 ETH rather than 32 ETH. - function checkpointBalanceExitedGwei( - uint64 - ) external view returns (uint64); + function checkpointBalanceExitedGwei(uint64) external view returns (uint64); /// @notice Query the 4788 oracle to get the parent block root of the slot with the given `timestamp` /// @param timestamp of the block for which the parent block root will be returned. MUST correspond /// to an existing slot within the last 24 hours. If the slot at `timestamp` was skipped, this method /// will revert. - function getParentBlockRoot( - uint64 timestamp - ) external view returns (bytes32); + function getParentBlockRoot(uint64 timestamp) external view returns (bytes32); } diff --git a/src/eigenlayer-interfaces/IEigenPodManager.sol b/src/eigenlayer-interfaces/IEigenPodManager.sol index b7814e988..d5d459d30 100644 --- a/src/eigenlayer-interfaces/IEigenPodManager.sol +++ b/src/eigenlayer-interfaces/IEigenPodManager.sol @@ -1,14 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; import "./IETHPOSDeposit.sol"; -import "./IStrategyManager.sol"; + import "./IEigenPod.sol"; -import "./IShareManager.sol"; + import "./IPausable.sol"; -import "./IStrategy.sol"; + import "./ISemVerMixin.sol"; +import "./IShareManager.sol"; +import "./IStrategy.sol"; +import "./IStrategyManager.sol"; +import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; interface IEigenPodManagerErrors { /// @dev Thrown when caller is not a EigenPod. @@ -44,19 +47,10 @@ interface IEigenPodManagerEvents { event NewTotalShares(address indexed podOwner, int256 newTotalShares); /// @notice Emitted when a withdrawal of beacon chain ETH is completed - event BeaconChainETHWithdrawalCompleted( - address indexed podOwner, - uint256 shares, - uint96 nonce, - address delegatedAddress, - address withdrawer, - bytes32 withdrawalRoot - ); + event BeaconChainETHWithdrawalCompleted(address indexed podOwner, uint256 shares, uint96 nonce, address delegatedAddress, address withdrawer, bytes32 withdrawalRoot); /// @notice Emitted when a staker's beaconChainSlashingFactor is updated - event BeaconChainSlashingFactorDecreased( - address staker, uint64 prevBeaconChainSlashingFactor, uint64 newBeaconChainSlashingFactor - ); + event BeaconChainSlashingFactorDecreased(address staker, uint64 prevBeaconChainSlashingFactor, uint64 newBeaconChainSlashingFactor); /// @notice Emitted when an operator is slashed and shares to be burned are increased event BurnableETHSharesIncreased(uint256 shares); @@ -89,14 +83,7 @@ interface IEigenPodManagerTypes { * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service */ -interface IEigenPodManager is - IEigenPodManagerErrors, - IEigenPodManagerEvents, - IEigenPodManagerTypes, - IShareManager, - IPausable, - ISemVerMixin -{ +interface IEigenPodManager is IEigenPodManagerErrors, IEigenPodManagerEvents, IEigenPodManagerTypes, IShareManager, IPausable, ISemVerMixin { /** * @notice Creates an EigenPod for the sender. * @dev Function will revert if the `msg.sender` already has an EigenPod. @@ -124,31 +111,19 @@ interface IEigenPodManager is * @dev Callable only by the podOwner's EigenPod contract. * @dev Reverts if `sharesDelta` is not a whole Gwei amount */ - function recordBeaconChainETHBalanceUpdate( - address podOwner, - uint256 prevRestakedBalanceWei, - int256 balanceDeltaWei - ) external; + function recordBeaconChainETHBalanceUpdate(address podOwner, uint256 prevRestakedBalanceWei, int256 balanceDeltaWei) external; /// @notice Sets the address that can set proof timestamps - function setProofTimestampSetter( - address newProofTimestampSetter - ) external; + function setProofTimestampSetter(address newProofTimestampSetter) external; /// @notice Sets the Pectra fork timestamp, only callable by `proofTimestampSetter` - function setPectraForkTimestamp( - uint64 timestamp - ) external; + function setPectraForkTimestamp(uint64 timestamp) external; /// @notice Returns the address of the `podOwner`'s EigenPod if it has been deployed. - function ownerToPod( - address podOwner - ) external view returns (IEigenPod); + function ownerToPod(address podOwner) external view returns (IEigenPod); /// @notice Returns the address of the `podOwner`'s EigenPod (whether it is deployed yet or not). - function getPod( - address podOwner - ) external view returns (IEigenPod); + function getPod(address podOwner) external view returns (IEigenPod); /// @notice The ETH2 Deposit Contract function ethPOS() external view returns (IETHPOSDeposit); @@ -157,9 +132,7 @@ interface IEigenPodManager is function eigenPodBeacon() external view returns (IBeacon); /// @notice Returns 'true' if the `podOwner` has created an EigenPod, and 'false' otherwise. - function hasPod( - address podOwner - ) external view returns (bool); + function hasPod(address podOwner) external view returns (bool); /// @notice Returns the number of EigenPods that have been created function numPods() external view returns (uint256); @@ -172,9 +145,7 @@ interface IEigenPodManager is * Likewise, when a withdrawal is completed, this "deficit" is decreased and the withdrawal amount is decreased; We can think of this * as the withdrawal "paying off the deficit". */ - function podOwnerDepositShares( - address podOwner - ) external view returns (int256); + function podOwnerDepositShares(address podOwner) external view returns (int256); /// @notice returns canonical, virtual beaconChainETH strategy function beaconChainETHStrategy() external view returns (IStrategy); @@ -183,9 +154,7 @@ interface IEigenPodManager is * @notice Returns the historical sum of proportional balance decreases a pod owner has experienced when * updating their pod's balance. */ - function beaconChainSlashingFactor( - address staker - ) external view returns (uint64); + function beaconChainSlashingFactor(address staker) external view returns (uint64); /// @notice Returns the accumulated amount of beacon chain ETH Strategy shares function burnableETHShares() external view returns (uint256); diff --git a/src/eigenlayer-interfaces/IPausable.sol b/src/eigenlayer-interfaces/IPausable.sol index 720081c01..b694fb132 100644 --- a/src/eigenlayer-interfaces/IPausable.sol +++ b/src/eigenlayer-interfaces/IPausable.sol @@ -46,9 +46,7 @@ interface IPausable { * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only pause functionality, and thus cannot 'unflip' any bit in `_paused` from 1 to 0. */ - function pause( - uint256 newPausedStatus - ) external; + function pause(uint256 newPausedStatus) external; /** * @notice Alias for `pause(type(uint256).max)`. @@ -61,15 +59,11 @@ interface IPausable { * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only unpause functionality, and thus cannot 'flip' any bit in `_paused` from 0 to 1. */ - function unpause( - uint256 newPausedStatus - ) external; + function unpause(uint256 newPausedStatus) external; /// @notice Returns the current paused status as a uint256. function paused() external view returns (uint256); /// @notice Returns 'true' if the `indexed`th bit of `_paused` is 1, and 'false' otherwise - function paused( - uint8 index - ) external view returns (bool); + function paused(uint8 index) external view returns (bool); } diff --git a/src/eigenlayer-interfaces/IPauserRegistry.sol b/src/eigenlayer-interfaces/IPauserRegistry.sol index e20fd77a7..9a058bcd8 100644 --- a/src/eigenlayer-interfaces/IPauserRegistry.sol +++ b/src/eigenlayer-interfaces/IPauserRegistry.sol @@ -15,9 +15,7 @@ interface IPauserRegistry { event UnpauserChanged(address previousUnpauser, address newUnpauser); /// @notice Mapping of addresses to whether they hold the pauser role. - function isPauser( - address pauser - ) external view returns (bool); + function isPauser(address pauser) external view returns (bool); /// @notice Unique address that holds the unpauser role. Capable of changing *both* the pauser and unpauser addresses. function unpauser() external view returns (address); diff --git a/src/eigenlayer-interfaces/IPermissionController.sol b/src/eigenlayer-interfaces/IPermissionController.sol index b8e215373..08fcad47c 100644 --- a/src/eigenlayer-interfaces/IPermissionController.sol +++ b/src/eigenlayer-interfaces/IPermissionController.sol @@ -65,9 +65,7 @@ interface IPermissionController is IPermissionControllerErrors, IPermissionContr * @param account The account to accept the admin role for. * @dev Only addresses that were previously set as pending admins can accept the role. */ - function acceptAdmin( - address account - ) external; + function acceptAdmin(address account) external; /** * @notice Removes an active admin from an account. @@ -121,18 +119,14 @@ interface IPermissionController is IPermissionControllerErrors, IPermissionContr * @dev If the account has no admins, returns an array containing only the account address. * @return An array of admin addresses. */ - function getAdmins( - address account - ) external view returns (address[] memory); + function getAdmins(address account) external view returns (address[] memory); /** * @notice Retrieves all pending admins for an account. * @param account The account to get the pending admins for. * @return An array of pending admin addresses. */ - function getPendingAdmins( - address account - ) external view returns (address[] memory); + function getPendingAdmins(address account) external view returns (address[] memory); /** * @notice Checks if a caller has permission to call a specific function. @@ -153,10 +147,7 @@ interface IPermissionController is IPermissionControllerErrors, IPermissionContr * @param appointee The appointee address to check. * @return Two arrays: target contract addresses and their corresponding function selectors. */ - function getAppointeePermissions( - address account, - address appointee - ) external returns (address[] memory, bytes4[] memory); + function getAppointeePermissions(address account, address appointee) external returns (address[] memory, bytes4[] memory); /** * @notice Retrieves all appointees that can call a specific function for an account. diff --git a/src/eigenlayer-interfaces/IRewardsCoordinator.sol b/src/eigenlayer-interfaces/IRewardsCoordinator.sol index b1ba3f636..cf1a7954b 100644 --- a/src/eigenlayer-interfaces/IRewardsCoordinator.sol +++ b/src/eigenlayer-interfaces/IRewardsCoordinator.sol @@ -1,16 +1,18 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.27; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../eigenlayer-libraries/OperatorSetLib.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./IAllocationManager.sol"; import "./IDelegationManager.sol"; -import "./IStrategyManager.sol"; + import "./IPauserRegistry.sol"; import "./IPermissionController.sol"; -import "./IStrategy.sol"; + import "./ISemVerMixin.sol"; +import "./IStrategy.sol"; +import "./IStrategyManager.sol"; interface IRewardsCoordinatorErrors { /// @dev Thrown when msg.sender is not allowed to call a function @@ -278,28 +280,13 @@ interface IRewardsCoordinatorTypes { interface IRewardsCoordinatorEvents is IRewardsCoordinatorTypes { /// @notice emitted when an AVS creates a valid RewardsSubmission - event AVSRewardsSubmissionCreated( - address indexed avs, - uint256 indexed submissionNonce, - bytes32 indexed rewardsSubmissionHash, - RewardsSubmission rewardsSubmission - ); + event AVSRewardsSubmissionCreated(address indexed avs, uint256 indexed submissionNonce, bytes32 indexed rewardsSubmissionHash, RewardsSubmission rewardsSubmission); /// @notice emitted when a valid RewardsSubmission is created for all stakers by a valid submitter - event RewardsSubmissionForAllCreated( - address indexed submitter, - uint256 indexed submissionNonce, - bytes32 indexed rewardsSubmissionHash, - RewardsSubmission rewardsSubmission - ); + event RewardsSubmissionForAllCreated(address indexed submitter, uint256 indexed submissionNonce, bytes32 indexed rewardsSubmissionHash, RewardsSubmission rewardsSubmission); /// @notice emitted when a valid RewardsSubmission is created when rewardAllStakersAndOperators is called - event RewardsSubmissionForAllEarnersCreated( - address indexed tokenHopper, - uint256 indexed submissionNonce, - bytes32 indexed rewardsSubmissionHash, - RewardsSubmission rewardsSubmission - ); + event RewardsSubmissionForAllEarnersCreated(address indexed tokenHopper, uint256 indexed submissionNonce, bytes32 indexed rewardsSubmissionHash, RewardsSubmission rewardsSubmission); /** * @notice Emitted when an AVS creates a valid `OperatorDirectedRewardsSubmission` @@ -309,13 +296,7 @@ interface IRewardsCoordinatorEvents is IRewardsCoordinatorTypes { * @param submissionNonce Current nonce of the avs. Used to generate a unique submission hash. * @param operatorDirectedRewardsSubmission The Operator-Directed Rewards Submission. Contains the token, start timestamp, duration, operator rewards, description and, strategy and multipliers. */ - event OperatorDirectedAVSRewardsSubmissionCreated( - address indexed caller, - address indexed avs, - bytes32 indexed operatorDirectedRewardsSubmissionHash, - uint256 submissionNonce, - OperatorDirectedRewardsSubmission operatorDirectedRewardsSubmission - ); + event OperatorDirectedAVSRewardsSubmissionCreated(address indexed caller, address indexed avs, bytes32 indexed operatorDirectedRewardsSubmissionHash, uint256 submissionNonce, OperatorDirectedRewardsSubmission operatorDirectedRewardsSubmission); /** * @notice Emitted when an AVS creates a valid `OperatorDirectedRewardsSubmission` for an operator set. @@ -325,20 +306,12 @@ interface IRewardsCoordinatorEvents is IRewardsCoordinatorTypes { * @param submissionNonce Current nonce of the avs. Used to generate a unique submission hash. * @param operatorDirectedRewardsSubmission The Operator-Directed Rewards Submission. Contains the token, start timestamp, duration, operator rewards, description and, strategy and multipliers. */ - event OperatorDirectedOperatorSetRewardsSubmissionCreated( - address indexed caller, - bytes32 indexed operatorDirectedRewardsSubmissionHash, - OperatorSet operatorSet, - uint256 submissionNonce, - OperatorDirectedRewardsSubmission operatorDirectedRewardsSubmission - ); + event OperatorDirectedOperatorSetRewardsSubmissionCreated(address indexed caller, bytes32 indexed operatorDirectedRewardsSubmissionHash, OperatorSet operatorSet, uint256 submissionNonce, OperatorDirectedRewardsSubmission operatorDirectedRewardsSubmission); /// @notice rewardsUpdater is responsible for submitting DistributionRoots, only owner can set rewardsUpdater event RewardsUpdaterSet(address indexed oldRewardsUpdater, address indexed newRewardsUpdater); - event RewardsForAllSubmitterSet( - address indexed rewardsForAllSubmitter, bool indexed oldValue, bool indexed newValue - ); + event RewardsForAllSubmitterSet(address indexed rewardsForAllSubmitter, bool indexed oldValue, bool indexed newValue); event ActivationDelaySet(uint32 oldActivationDelay, uint32 newActivationDelay); event DefaultOperatorSplitBipsSet(uint16 oldDefaultOperatorSplitBips, uint16 newDefaultOperatorSplitBips); @@ -352,14 +325,7 @@ interface IRewardsCoordinatorEvents is IRewardsCoordinatorTypes { * @param oldOperatorAVSSplitBips The old split for the operator for the AVS. * @param newOperatorAVSSplitBips The new split for the operator for the AVS. */ - event OperatorAVSSplitBipsSet( - address indexed caller, - address indexed operator, - address indexed avs, - uint32 activatedAt, - uint16 oldOperatorAVSSplitBips, - uint16 newOperatorAVSSplitBips - ); + event OperatorAVSSplitBipsSet(address indexed caller, address indexed operator, address indexed avs, uint32 activatedAt, uint16 oldOperatorAVSSplitBips, uint16 newOperatorAVSSplitBips); /** * @notice Emitted when the operator split for Programmatic Incentives is set. @@ -369,13 +335,7 @@ interface IRewardsCoordinatorEvents is IRewardsCoordinatorTypes { * @param oldOperatorPISplitBips The old split for the operator for Programmatic Incentives. * @param newOperatorPISplitBips The new split for the operator for Programmatic Incentives. */ - event OperatorPISplitBipsSet( - address indexed caller, - address indexed operator, - uint32 activatedAt, - uint16 oldOperatorPISplitBips, - uint16 newOperatorPISplitBips - ); + event OperatorPISplitBipsSet(address indexed caller, address indexed operator, uint32 activatedAt, uint16 oldOperatorPISplitBips, uint16 newOperatorPISplitBips); /** * @notice Emitted when the operator split for a given operatorSet is set. @@ -386,36 +346,17 @@ interface IRewardsCoordinatorEvents is IRewardsCoordinatorTypes { * @param oldOperatorSetSplitBips The old split for the operator for the operatorSet. * @param newOperatorSetSplitBips The new split for the operator for the operatorSet. */ - event OperatorSetSplitBipsSet( - address indexed caller, - address indexed operator, - OperatorSet operatorSet, - uint32 activatedAt, - uint16 oldOperatorSetSplitBips, - uint16 newOperatorSetSplitBips - ); + event OperatorSetSplitBipsSet(address indexed caller, address indexed operator, OperatorSet operatorSet, uint32 activatedAt, uint16 oldOperatorSetSplitBips, uint16 newOperatorSetSplitBips); event ClaimerForSet(address indexed earner, address indexed oldClaimer, address indexed claimer); /// @notice rootIndex is the specific array index of the newly created root in the storage array - event DistributionRootSubmitted( - uint32 indexed rootIndex, - bytes32 indexed root, - uint32 indexed rewardsCalculationEndTimestamp, - uint32 activatedAt - ); + event DistributionRootSubmitted(uint32 indexed rootIndex, bytes32 indexed root, uint32 indexed rewardsCalculationEndTimestamp, uint32 activatedAt); event DistributionRootDisabled(uint32 indexed rootIndex); /// @notice root is one of the submitted distribution roots that was claimed against - event RewardsClaimed( - bytes32 root, - address indexed earner, - address indexed claimer, - address indexed recipient, - IERC20 token, - uint256 claimedAmount - ); + event RewardsClaimed(bytes32 root, address indexed earner, address indexed claimer, address indexed recipient, IERC20 token, uint256 claimedAmount); } /** @@ -432,13 +373,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * @dev Initializes the addresses of the initial owner, pauser registry, rewardsUpdater and * configures the initial paused status, activationDelay, and defaultOperatorSplitBips. */ - function initialize( - address initialOwner, - uint256 initialPausedStatus, - address _rewardsUpdater, - uint32 _activationDelay, - uint16 _defaultSplitBips - ) external; + function initialize(address initialOwner, uint256 initialPausedStatus, address _rewardsUpdater, uint32 _activationDelay, uint16 _defaultSplitBips) external; /** * @notice Creates a new rewards submission on behalf of an AVS, to be split amongst the @@ -452,9 +387,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * @dev This function will revert if the `rewardsSubmission` is malformed, * e.g. if the `strategies` and `weights` arrays are of non-equal lengths */ - function createAVSRewardsSubmission( - RewardsSubmission[] calldata rewardsSubmissions - ) external; + function createAVSRewardsSubmission(RewardsSubmission[] calldata rewardsSubmissions) external; /** * @notice similar to `createAVSRewardsSubmission` except the rewards are split amongst *all* stakers @@ -462,9 +395,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * a permissioned call based on isRewardsForAllSubmitter mapping. * @param rewardsSubmissions The rewards submissions being created */ - function createRewardsForAllSubmission( - RewardsSubmission[] calldata rewardsSubmissions - ) external; + function createRewardsForAllSubmission(RewardsSubmission[] calldata rewardsSubmissions) external; /** * @notice Creates a new rewards submission for all earners across all AVSs. @@ -473,9 +404,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * by the token hopper contract from the Eigen Foundation * @param rewardsSubmissions The rewards submissions being created */ - function createRewardsForAllEarners( - RewardsSubmission[] calldata rewardsSubmissions - ) external; + function createRewardsForAllEarners(RewardsSubmission[] calldata rewardsSubmissions) external; /** * @notice Creates a new operator-directed rewards submission on behalf of an AVS, to be split amongst the operators and @@ -491,10 +420,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * @dev Operators must be in ascending order of addresses to check for duplicates. * @dev This function will revert if the `operatorDirectedRewardsSubmissions` is malformed. */ - function createOperatorDirectedAVSRewardsSubmission( - address avs, - OperatorDirectedRewardsSubmission[] calldata operatorDirectedRewardsSubmissions - ) external; + function createOperatorDirectedAVSRewardsSubmission(address avs, OperatorDirectedRewardsSubmission[] calldata operatorDirectedRewardsSubmissions) external; /** * @notice Creates a new operator-directed rewards submission for an operator set, to be split amongst the operators and @@ -510,10 +436,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * @dev Operators must be in ascending order of addresses to check for duplicates * @dev This function will revert if the `operatorDirectedRewardsSubmissions` is malformed */ - function createOperatorDirectedOperatorSetRewardsSubmission( - OperatorSet calldata operatorSet, - OperatorDirectedRewardsSubmission[] calldata operatorDirectedRewardsSubmissions - ) external; + function createOperatorDirectedOperatorSetRewardsSubmission(OperatorSet calldata operatorSet, OperatorDirectedRewardsSubmission[] calldata operatorDirectedRewardsSubmissions) external; /** * @notice Claim rewards against a given root (read from _distributionRoots[claim.rootIndex]). @@ -556,18 +479,14 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * @notice allow the rewardsUpdater to disable/cancel a pending root submission in case of an error * @param rootIndex The index of the root to be disabled */ - function disableRoot( - uint32 rootIndex - ) external; + function disableRoot(uint32 rootIndex) external; /** * @notice Sets the address of the entity that can call `processClaim` on ehalf of an earner * @param claimer The address of the entity that can call `processClaim` on behalf of the earner * @dev Assumes msg.sender is the earner */ - function setClaimerFor( - address claimer - ) external; + function setClaimerFor(address claimer) external; /** * @notice Sets the address of the entity that can call `processClaim` on behalf of an earner @@ -583,18 +502,14 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * @dev Only callable by the contract owner * @param _activationDelay The new value for activationDelay */ - function setActivationDelay( - uint32 _activationDelay - ) external; + function setActivationDelay(uint32 _activationDelay) external; /** * @notice Sets the default split for all operators across all avss. * @param split The default split for all operators across all avss in bips. * @dev Only callable by the contract owner. */ - function setDefaultOperatorSplit( - uint16 split - ) external; + function setDefaultOperatorSplit(uint16 split) external; /** * @notice Sets the split for a specific operator for a specific avs @@ -633,9 +548,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE * @dev Only callable by the contract owner * @param _rewardsUpdater The address of the new rewardsUpdater */ - function setRewardsUpdater( - address _rewardsUpdater - ) external; + function setRewardsUpdater(address _rewardsUpdater) external; /** * @notice Sets the permissioned `rewardsForAllSubmitter` address which can submit createRewardsForAllSubmission @@ -658,9 +571,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE function currRewardsCalculationEndTimestamp() external view returns (uint32); /// @notice Mapping: earner => the address of the entity who can call `processClaim` on behalf of the earner - function claimerFor( - address earner - ) external view returns (address); + function claimerFor(address earner) external view returns (address); /// @notice Mapping: claimer => token => total amount claimed function cumulativeClaimed(address claimer, IERC20 token) external view returns (uint256); @@ -672,36 +583,26 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE function getOperatorAVSSplit(address operator, address avs) external view returns (uint16); /// @notice the split for a specific `operator` for Programmatic Incentives - function getOperatorPISplit( - address operator - ) external view returns (uint16); + function getOperatorPISplit(address operator) external view returns (uint16); /// @notice Returns the split for a specific `operator` for a given `operatorSet` function getOperatorSetSplit(address operator, OperatorSet calldata operatorSet) external view returns (uint16); /// @notice return the hash of the earner's leaf - function calculateEarnerLeafHash( - EarnerTreeMerkleLeaf calldata leaf - ) external pure returns (bytes32); + function calculateEarnerLeafHash(EarnerTreeMerkleLeaf calldata leaf) external pure returns (bytes32); /// @notice returns the hash of the earner's token leaf - function calculateTokenLeafHash( - TokenTreeMerkleLeaf calldata leaf - ) external pure returns (bytes32); + function calculateTokenLeafHash(TokenTreeMerkleLeaf calldata leaf) external pure returns (bytes32); /// @notice returns 'true' if the claim would currently pass the check in `processClaims` /// but will revert if not valid - function checkClaim( - RewardsMerkleClaim calldata claim - ) external view returns (bool); + function checkClaim(RewardsMerkleClaim calldata claim) external view returns (bool); /// @notice returns the number of distribution roots posted function getDistributionRootsLength() external view returns (uint256); /// @notice returns the distributionRoot at the specified index - function getDistributionRootAtIndex( - uint256 index - ) external view returns (DistributionRoot memory); + function getDistributionRootAtIndex(uint256 index) external view returns (DistributionRoot memory); /// @notice returns the current distributionRoot function getCurrentDistributionRoot() external view returns (DistributionRoot memory); @@ -711,9 +612,7 @@ interface IRewardsCoordinator is IRewardsCoordinatorErrors, IRewardsCoordinatorE function getCurrentClaimableDistributionRoot() external view returns (DistributionRoot memory); /// @notice loop through distribution roots from reverse and return index from hash - function getRootIndexFromHash( - bytes32 rootHash - ) external view returns (uint32); + function getRootIndexFromHash(bytes32 rootHash) external view returns (uint32); /// @notice The address of the entity that can update the contract with new merkle roots function rewardsUpdater() external view returns (address); diff --git a/src/eigenlayer-interfaces/IShareManager.sol b/src/eigenlayer-interfaces/IShareManager.sol index f2719c07c..09692ec9d 100644 --- a/src/eigenlayer-interfaces/IShareManager.sol +++ b/src/eigenlayer-interfaces/IShareManager.sol @@ -15,11 +15,7 @@ interface IShareManager { /// @notice Used by the DelegationManager to remove a Staker's shares from a particular strategy when entering the withdrawal queue /// @dev strategy must be beaconChainETH when talking to the EigenPodManager /// @return updatedShares the staker's deposit shares after decrement - function removeDepositShares( - address staker, - IStrategy strategy, - uint256 depositSharesToRemove - ) external returns (uint256); + function removeDepositShares(address staker, IStrategy strategy, uint256 depositSharesToRemove) external returns (uint256); /// @notice Used by the DelegationManager to award a Staker some shares that have passed through the withdrawal queue /// @dev strategy must be beaconChainETH when talking to the EigenPodManager diff --git a/src/eigenlayer-interfaces/ISignatureUtils.sol b/src/eigenlayer-interfaces/ISignatureUtils.sol index e1f488779..158b325d1 100644 --- a/src/eigenlayer-interfaces/ISignatureUtils.sol +++ b/src/eigenlayer-interfaces/ISignatureUtils.sol @@ -24,4 +24,4 @@ interface ISignatureUtils { // the expiration timestamp (UTC) of the signature uint256 expiry; } -} \ No newline at end of file +} diff --git a/src/eigenlayer-interfaces/ISlasher.sol b/src/eigenlayer-interfaces/ISlasher.sol index a79e4ae83..40efeea41 100644 --- a/src/eigenlayer-interfaces/ISlasher.sol +++ b/src/eigenlayer-interfaces/ISlasher.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "./IStrategyManager.sol"; import "./IDelegationManager.sol"; +import "./IStrategyManager.sol"; /** * @title Interface for the primary 'slashing' contract for EigenLayer. @@ -30,22 +30,13 @@ interface ISlasher { } /// @notice Emitted when a middleware times is added to `operator`'s array. - event MiddlewareTimesAdded( - address operator, - uint256 index, - uint32 stalestUpdateBlock, - uint32 latestServeUntilBlock - ); + event MiddlewareTimesAdded(address operator, uint256 index, uint32 stalestUpdateBlock, uint32 latestServeUntilBlock); /// @notice Emitted when `operator` begins to allow `contractAddress` to slash them. event OptedIntoSlashing(address indexed operator, address indexed contractAddress); /// @notice Emitted when `contractAddress` signals that it will no longer be able to slash `operator` after the `contractCanSlashOperatorUntilBlock`. - event SlashingAbilityRevoked( - address indexed operator, - address indexed contractAddress, - uint32 contractCanSlashOperatorUntilBlock - ); + event SlashingAbilityRevoked(address indexed operator, address indexed contractAddress, uint32 contractCanSlashOperatorUntilBlock); /** * @notice Emitted when `slashingContract` 'freezes' the `slashedOperator`. @@ -95,12 +86,7 @@ interface ISlasher { * @dev insertAfter should be calculated offchain before making the transaction that calls this. this is subject to race conditions, * but it is anticipated to be rare and not detrimental. */ - function recordStakeUpdate( - address operator, - uint32 updateBlock, - uint32 serveUntilBlock, - uint256 insertAfter - ) external; + function recordStakeUpdate(address operator, uint32 updateBlock, uint32 serveUntilBlock, uint256 insertAfter) external; /** * @notice this function is a called by middlewares during an operator's deregistration to make sure the operator's stake at deregistration @@ -132,10 +118,7 @@ interface ISlasher { function canSlash(address toBeSlashed, address slashingContract) external view returns (bool); /// @notice Returns the block until which `serviceContract` is allowed to slash the `operator`. - function contractCanSlashOperatorUntilBlock( - address operator, - address serviceContract - ) external view returns (uint32); + function contractCanSlashOperatorUntilBlock(address operator, address serviceContract) external view returns (uint32); /// @notice Returns the block at which the `serviceContract` last updated its view of the `operator`'s stake function latestUpdateBlock(address operator, address serviceContract) external view returns (uint32); @@ -155,11 +138,7 @@ interface ISlasher { * @param middlewareTimesIndex Indicates an index in `operatorToMiddlewareTimes[operator]` to consult as proof of the `operator`'s ability to withdraw * @dev The correct `middlewareTimesIndex` input should be computable off-chain. */ - function canWithdraw( - address operator, - uint32 withdrawalStartBlock, - uint256 middlewareTimesIndex - ) external returns (bool); + function canWithdraw(address operator, uint32 withdrawalStartBlock, uint256 middlewareTimesIndex) external returns (bool); /** * operator => @@ -170,10 +149,7 @@ interface ISlasher { * ) * ] */ - function operatorToMiddlewareTimes( - address operator, - uint256 arrayIndex - ) external view returns (MiddlewareTimes memory); + function operatorToMiddlewareTimes(address operator, uint256 arrayIndex) external view returns (MiddlewareTimes memory); /// @notice Getter function for fetching `operatorToMiddlewareTimes[operator].length` function middlewareTimesLength(address operator) external view returns (uint256); @@ -188,8 +164,5 @@ interface ISlasher { function operatorWhitelistedContractsLinkedListSize(address operator) external view returns (uint256); /// @notice Getter function for fetching a single node in the operator's linked list (`_operatorToWhitelistedContractsByUpdate[operator]`). - function operatorWhitelistedContractsLinkedListEntry( - address operator, - address node - ) external view returns (bool, uint256, uint256); + function operatorWhitelistedContractsLinkedListEntry(address operator, address node) external view returns (bool, uint256, uint256); } diff --git a/src/eigenlayer-interfaces/ISocketUpdater.sol b/src/eigenlayer-interfaces/ISocketUpdater.sol index 8f28465e1..df95d4ab0 100644 --- a/src/eigenlayer-interfaces/ISocketUpdater.sol +++ b/src/eigenlayer-interfaces/ISocketUpdater.sol @@ -18,4 +18,3 @@ interface ISocketUpdater { */ function updateSocket(string memory socket) external; } - diff --git a/src/eigenlayer-interfaces/IStrategy.sol b/src/eigenlayer-interfaces/IStrategy.sol index ba25ea3e6..b1a8f26b7 100644 --- a/src/eigenlayer-interfaces/IStrategy.sol +++ b/src/eigenlayer-interfaces/IStrategy.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../eigenlayer-libraries/SlashingLib.sol"; import "./ISemVerMixin.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IStrategyErrors { /// @dev Thrown when called by an account that is not strategy manager. @@ -78,9 +78,7 @@ interface IStrategy is IStrategyErrors, IStrategyEvents, ISemVerMixin { * @return The amount of underlying tokens corresponding to the input `amountShares` * @dev Implementation for these functions in particular may vary significantly for different strategies */ - function sharesToUnderlying( - uint256 amountShares - ) external returns (uint256); + function sharesToUnderlying(uint256 amountShares) external returns (uint256); /** * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy. @@ -90,25 +88,19 @@ interface IStrategy is IStrategyErrors, IStrategyEvents, ISemVerMixin { * in the `StrategyManager` contract. * @dev Implementation for these functions in particular may vary significantly for different strategies */ - function underlyingToShares( - uint256 amountUnderlying - ) external returns (uint256); + function underlyingToShares(uint256 amountUnderlying) external returns (uint256); /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlyingView`, this function **may** make state modifications */ - function userUnderlying( - address user - ) external returns (uint256); + function userUnderlying(address user) external returns (uint256); /** * @notice convenience function for fetching the current total shares of `user` in this strategy, by * querying the `strategyManager` contract */ - function shares( - address user - ) external view returns (uint256); + function shares(address user) external view returns (uint256); /** * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy. @@ -119,9 +111,7 @@ interface IStrategy is IStrategyErrors, IStrategyEvents, ISemVerMixin { * @return The amount of underlying tokens corresponding to the input `amountShares` * @dev Implementation for these functions in particular may vary significantly for different strategies */ - function sharesToUnderlyingView( - uint256 amountShares - ) external view returns (uint256); + function sharesToUnderlyingView(uint256 amountShares) external view returns (uint256); /** * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy. @@ -131,17 +121,13 @@ interface IStrategy is IStrategyErrors, IStrategyEvents, ISemVerMixin { * in the `StrategyManager` contract. * @dev Implementation for these functions in particular may vary significantly for different strategies */ - function underlyingToSharesView( - uint256 amountUnderlying - ) external view returns (uint256); + function underlyingToSharesView(uint256 amountUnderlying) external view returns (uint256); /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlying`, this function guarantees no state modifications */ - function userUnderlyingView( - address user - ) external view returns (uint256); + function userUnderlyingView(address user) external view returns (uint256); /// @notice The underlying token for shares in this Strategy function underlyingToken() external view returns (IERC20); diff --git a/src/eigenlayer-interfaces/IStrategyFactory.sol b/src/eigenlayer-interfaces/IStrategyFactory.sol index c019695b4..e5df80884 100644 --- a/src/eigenlayer-interfaces/IStrategyFactory.sol +++ b/src/eigenlayer-interfaces/IStrategyFactory.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.27; +import "./ISemVerMixin.sol"; +import "./IStrategy.sol"; import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "./IStrategy.sol"; -import "./ISemVerMixin.sol"; /** * @title Interface for the `StrategyFactory` contract. @@ -32,9 +32,7 @@ interface IStrategyFactory is ISemVerMixin { /// though deployNewStrategy does whitelist by default. /// These strategies MIGHT not be the only strategy for the underlying token /// as additional strategies can be whitelisted by the owner of the factory. - function deployedStrategies( - IERC20 token - ) external view returns (IStrategy); + function deployedStrategies(IERC20 token) external view returns (IStrategy); /** * @notice Deploy a new strategyBeacon contract for the ERC20 token. @@ -43,23 +41,17 @@ interface IStrategyFactory is ISemVerMixin { * $dev Immense caution is warranted for non-standard ERC20 tokens, particularly "reentrant" tokens * like those that conform to ERC777. */ - function deployNewStrategy( - IERC20 token - ) external returns (IStrategy newStrategy); + function deployNewStrategy(IERC20 token) external returns (IStrategy newStrategy); /** * @notice Owner-only function to pass through a call to `StrategyManager.addStrategiesToDepositWhitelist` */ - function whitelistStrategies( - IStrategy[] calldata strategiesToWhitelist - ) external; + function whitelistStrategies(IStrategy[] calldata strategiesToWhitelist) external; /** * @notice Owner-only function to pass through a call to `StrategyManager.removeStrategiesFromDepositWhitelist` */ - function removeStrategiesFromWhitelist( - IStrategy[] calldata strategiesToRemoveFromWhitelist - ) external; + function removeStrategiesFromWhitelist(IStrategy[] calldata strategiesToRemoveFromWhitelist) external; /// @notice Emitted when the `strategyBeacon` is changed event StrategyBeaconModified(IBeacon previousBeacon, IBeacon newBeacon); diff --git a/src/eigenlayer-interfaces/IStrategyManager.sol b/src/eigenlayer-interfaces/IStrategyManager.sol index 2af48d438..fdf4d8640 100644 --- a/src/eigenlayer-interfaces/IStrategyManager.sol +++ b/src/eigenlayer-interfaces/IStrategyManager.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "./IStrategy.sol"; -import "./IShareManager.sol"; import "./IDelegationManager.sol"; import "./IEigenPodManager.sol"; import "./ISemVerMixin.sol"; +import "./IShareManager.sol"; +import "./IStrategy.sol"; interface IStrategyManagerErrors { /// @dev Thrown when total strategies deployed exceeds max. @@ -65,11 +65,7 @@ interface IStrategyManager is IStrategyManagerErrors, IStrategyManagerEvents, IS * @param initialStrategyWhitelister The initial value of `strategyWhitelister` to set. * @param initialPausedStatus The initial value of `_paused` to set. */ - function initialize( - address initialOwner, - address initialStrategyWhitelister, - uint256 initialPausedStatus - ) external; + function initialize(address initialOwner, address initialStrategyWhitelister, uint256 initialPausedStatus) external; /** * @notice Deposits `amount` of `token` into the specified `strategy` and credits shares to the caller @@ -83,11 +79,7 @@ interface IStrategyManager is IStrategyManagerErrors, IStrategyManagerEvents, IS * Tokens that diverge significantly from ERC20 norms can cause unexpected behavior in token balances for * that strategy, e.g. ERC-777 tokens allowing cross-contract reentrancy. */ - function depositIntoStrategy( - IStrategy strategy, - IERC20 token, - uint256 amount - ) external returns (uint256 depositShares); + function depositIntoStrategy(IStrategy strategy, IERC20 token, uint256 amount) external returns (uint256 depositShares); /** * @notice Deposits `amount` of `token` into the specified `strategy` and credits shares to the `staker` @@ -106,69 +98,46 @@ interface IStrategyManager is IStrategyManagerErrors, IStrategyManagerEvents, IS * Tokens that diverge significantly from ERC20 norms can cause unexpected behavior in token balances for * that strategy, e.g. ERC-777 tokens allowing cross-contract reentrancy. */ - function depositIntoStrategyWithSignature( - IStrategy strategy, - IERC20 token, - uint256 amount, - address staker, - uint256 expiry, - bytes memory signature - ) external returns (uint256 depositShares); + function depositIntoStrategyWithSignature(IStrategy strategy, IERC20 token, uint256 amount, address staker, uint256 expiry, bytes memory signature) external returns (uint256 depositShares); /** * @notice Burns Strategy shares for the given strategy by calling into the strategy to transfer * to the default burn address. * @param strategy The strategy to burn shares in. */ - function burnShares( - IStrategy strategy - ) external; + function burnShares(IStrategy strategy) external; /** * @notice Owner-only function to change the `strategyWhitelister` address. * @param newStrategyWhitelister new address for the `strategyWhitelister`. */ - function setStrategyWhitelister( - address newStrategyWhitelister - ) external; + function setStrategyWhitelister(address newStrategyWhitelister) external; /** * @notice Owner-only function that adds the provided Strategies to the 'whitelist' of strategies that stakers can deposit into * @param strategiesToWhitelist Strategies that will be added to the `strategyIsWhitelistedForDeposit` mapping (if they aren't in it already) */ - function addStrategiesToDepositWhitelist( - IStrategy[] calldata strategiesToWhitelist - ) external; + function addStrategiesToDepositWhitelist(IStrategy[] calldata strategiesToWhitelist) external; /** * @notice Owner-only function that removes the provided Strategies from the 'whitelist' of strategies that stakers can deposit into * @param strategiesToRemoveFromWhitelist Strategies that will be removed to the `strategyIsWhitelistedForDeposit` mapping (if they are in it) */ - function removeStrategiesFromDepositWhitelist( - IStrategy[] calldata strategiesToRemoveFromWhitelist - ) external; + function removeStrategiesFromDepositWhitelist(IStrategy[] calldata strategiesToRemoveFromWhitelist) external; /// @notice Returns bool for whether or not `strategy` is whitelisted for deposit - function strategyIsWhitelistedForDeposit( - IStrategy strategy - ) external view returns (bool); + function strategyIsWhitelistedForDeposit(IStrategy strategy) external view returns (bool); /** * @notice Get all details on the staker's deposits and corresponding shares * @return (staker's strategies, shares in these strategies) */ - function getDeposits( - address staker - ) external view returns (IStrategy[] memory, uint256[] memory); + function getDeposits(address staker) external view returns (IStrategy[] memory, uint256[] memory); - function getStakerStrategyList( - address staker - ) external view returns (IStrategy[] memory); + function getStakerStrategyList(address staker) external view returns (IStrategy[] memory); /// @notice Simple getter function that returns `stakerStrategyList[staker].length`. - function stakerStrategyListLength( - address staker - ) external view returns (uint256); + function stakerStrategyListLength(address staker) external view returns (uint256); /// @notice Returns the current shares of `user` in `strategy` function stakerDepositShares(address user, IStrategy strategy) external view returns (uint256 shares); @@ -180,9 +149,7 @@ interface IStrategyManager is IStrategyManagerErrors, IStrategyManagerEvents, IS function strategyWhitelister() external view returns (address); /// @notice Returns the burnable shares of a strategy - function getBurnableShares( - IStrategy strategy - ) external view returns (uint256); + function getBurnableShares(IStrategy strategy) external view returns (uint256); /** * @notice Gets every strategy with burnable shares and the amount of burnable shares in each said strategy @@ -203,12 +170,5 @@ interface IStrategyManager is IStrategyManagerErrors, IStrategyManagerEvents, IS * @param expiry The expiry of the signature. * @return The EIP-712 signable digest hash. */ - function calculateStrategyDepositDigestHash( - address staker, - IStrategy strategy, - IERC20 token, - uint256 amount, - uint256 nonce, - uint256 expiry - ) external view returns (bytes32); + function calculateStrategyDepositDigestHash(address staker, IStrategy strategy, IERC20 token, uint256 amount, uint256 nonce, uint256 expiry) external view returns (bytes32); } diff --git a/src/eigenlayer-interfaces/ITimelock.sol b/src/eigenlayer-interfaces/ITimelock.sol index 93db83b52..7c4771927 100644 --- a/src/eigenlayer-interfaces/ITimelock.sol +++ b/src/eigenlayer-interfaces/ITimelock.sol @@ -1,13 +1,12 @@ // SPDX-License-Identifier: BSD-3-Clause pragma solidity ^0.8.10; - interface ITimelock { - function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external returns (bytes32); + function queueTransaction(address target, uint256 value, string memory signature, bytes memory data, uint256 eta) external returns (bytes32); - function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external ; + function cancelTransaction(address target, uint256 value, string memory signature, bytes memory data, uint256 eta) external; - function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external payable returns (bytes memory); + function executeTransaction(address target, uint256 value, string memory signature, bytes memory data, uint256 eta) external payable returns (bytes memory); function admin() external view returns (address); } diff --git a/src/eigenlayer-interfaces/IWhitelister.sol b/src/eigenlayer-interfaces/IWhitelister.sol index ebae0873a..42d8b2365 100644 --- a/src/eigenlayer-interfaces/IWhitelister.sol +++ b/src/eigenlayer-interfaces/IWhitelister.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "./IStrategyManager.sol"; -import "./IStrategy.sol"; import "./IDelegationManager.sol"; +import "./IStrategy.sol"; +import "./IStrategyManager.sol"; // import "../../../script/whitelist/Staker.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/Create2.sol"; interface IWhitelister { @@ -15,25 +15,11 @@ interface IWhitelister { function getStaker(address operator) external returns (address); - function depositIntoStrategy( - address staker, - IStrategy strategy, - IERC20 token, - uint256 amount - ) external returns (bytes memory); - - function queueWithdrawal( - address staker, - IDelegationManager.QueuedWithdrawalParams[] calldata queuedWithdrawalParams - ) external returns (bytes memory); - - function completeQueuedWithdrawal( - address staker, - IDelegationManager.Withdrawal calldata queuedWithdrawal, - IERC20[] calldata tokens, - uint256 middlewareTimesIndex, - bool receiveAsTokens - ) external returns (bytes memory); + function depositIntoStrategy(address staker, IStrategy strategy, IERC20 token, uint256 amount) external returns (bytes memory); + + function queueWithdrawal(address staker, IDelegationManager.QueuedWithdrawalParams[] calldata queuedWithdrawalParams) external returns (bytes memory); + + function completeQueuedWithdrawal(address staker, IDelegationManager.Withdrawal calldata queuedWithdrawal, IERC20[] calldata tokens, uint256 middlewareTimesIndex, bool receiveAsTokens) external returns (bytes memory); function transfer(address staker, address token, address to, uint256 amount) external returns (bytes memory); diff --git a/src/eigenlayer-libraries/BeaconChainProofs.sol b/src/eigenlayer-libraries/BeaconChainProofs.sol index 05d94689e..d57e648db 100644 --- a/src/eigenlayer-libraries/BeaconChainProofs.sol +++ b/src/eigenlayer-libraries/BeaconChainProofs.sol @@ -10,7 +10,6 @@ import "./Endian.sol"; //BeaconBlockHeader Spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblockheader //BeaconState Spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconstate library BeaconChainProofs { - /// @notice Heights of various merkle trees in the beacon chain /// - beaconBlockRoot /// | HEIGHT: BEACON_BLOCK_HEADER_TREE_HEIGHT @@ -25,7 +24,7 @@ library BeaconChainProofs { uint256 internal constant BEACON_STATE_TREE_HEIGHT = 5; uint256 internal constant BALANCE_TREE_HEIGHT = 38; uint256 internal constant VALIDATOR_TREE_HEIGHT = 40; - + /// @notice Index of the beaconStateRoot in the `BeaconBlockHeader` container /// /// BeaconBlockHeader = [..., state_root, ...] @@ -89,35 +88,23 @@ library BeaconChainProofs { bytes proof; } - /******************************************************************************* - VALIDATOR FIELDS -> BEACON STATE ROOT -> BEACON BLOCK ROOT - *******************************************************************************/ + /** + * + * VALIDATOR FIELDS -> BEACON STATE ROOT -> BEACON BLOCK ROOT + * + */ /// @notice Verify a merkle proof of the beacon state root against a beacon block root /// @param beaconBlockRoot merkle root of the beacon block /// @param proof the beacon state root and merkle proof of its inclusion under `beaconBlockRoot` - function verifyStateRoot( - bytes32 beaconBlockRoot, - StateRootProof calldata proof - ) internal view { - require( - proof.proof.length == 32 * (BEACON_BLOCK_HEADER_TREE_HEIGHT), - "BeaconChainProofs.verifyStateRoot: Proof has incorrect length" - ); + function verifyStateRoot(bytes32 beaconBlockRoot, StateRootProof calldata proof) internal view { + require(proof.proof.length == 32 * (BEACON_BLOCK_HEADER_TREE_HEIGHT), "BeaconChainProofs.verifyStateRoot: Proof has incorrect length"); /// This merkle proof verifies the `beaconStateRoot` under the `beaconBlockRoot` /// - beaconBlockRoot /// | HEIGHT: BEACON_BLOCK_HEADER_TREE_HEIGHT /// -- beaconStateRoot - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: proof.proof, - root: beaconBlockRoot, - leaf: proof.beaconStateRoot, - index: STATE_ROOT_INDEX - }), - "BeaconChainProofs.verifyStateRoot: Invalid state root merkle proof" - ); + require(EigenlayerMerkle.verifyInclusionSha256({proof: proof.proof, root: beaconBlockRoot, leaf: proof.beaconStateRoot, index: STATE_ROOT_INDEX}), "BeaconChainProofs.verifyStateRoot: Invalid state root merkle proof"); } /// @notice Verify a merkle proof of a validator container against a `beaconStateRoot` @@ -130,23 +117,12 @@ library BeaconChainProofs { /// which is used as the leaf to prove against `beaconStateRoot` /// @param validatorFieldsProof a merkle proof of inclusion of `validatorFields` under `beaconStateRoot` /// @param validatorIndex the validator's unique index - function verifyValidatorFields( - bytes32 beaconStateRoot, - bytes32[] calldata validatorFields, - bytes calldata validatorFieldsProof, - uint40 validatorIndex - ) internal view { - require( - validatorFields.length == VALIDATOR_FIELDS_LENGTH, - "BeaconChainProofs.verifyValidatorFields: Validator fields has incorrect length" - ); + function verifyValidatorFields(bytes32 beaconStateRoot, bytes32[] calldata validatorFields, bytes calldata validatorFieldsProof, uint40 validatorIndex) internal view { + require(validatorFields.length == VALIDATOR_FIELDS_LENGTH, "BeaconChainProofs.verifyValidatorFields: Validator fields has incorrect length"); /// Note: the reason we use `VALIDATOR_TREE_HEIGHT + 1` here is because the merklization process for /// this container includes hashing the root of the validator tree with the length of the validator list - require( - validatorFieldsProof.length == 32 * ((VALIDATOR_TREE_HEIGHT + 1) + BEACON_STATE_TREE_HEIGHT), - "BeaconChainProofs.verifyValidatorFields: Proof has incorrect length" - ); + require(validatorFieldsProof.length == 32 * ((VALIDATOR_TREE_HEIGHT + 1) + BEACON_STATE_TREE_HEIGHT), "BeaconChainProofs.verifyValidatorFields: Proof has incorrect length"); // Merkleize `validatorFields` to get the leaf to prove bytes32 validatorRoot = EigenlayerMerkle.merkleizeSha256(validatorFields); @@ -159,20 +135,14 @@ library BeaconChainProofs { /// ---- validatorRoot uint256 index = (VALIDATOR_CONTAINER_INDEX << (VALIDATOR_TREE_HEIGHT + 1)) | uint256(validatorIndex); - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: validatorFieldsProof, - root: beaconStateRoot, - leaf: validatorRoot, - index: index - }), - "BeaconChainProofs.verifyValidatorFields: Invalid merkle proof" - ); + require(EigenlayerMerkle.verifyInclusionSha256({proof: validatorFieldsProof, root: beaconStateRoot, leaf: validatorRoot, index: index}), "BeaconChainProofs.verifyValidatorFields: Invalid merkle proof"); } - /******************************************************************************* - VALIDATOR BALANCE -> BALANCE CONTAINER ROOT -> BEACON BLOCK ROOT - *******************************************************************************/ + /** + * + * VALIDATOR BALANCE -> BALANCE CONTAINER ROOT -> BEACON BLOCK ROOT + * + */ /// @notice Verify a merkle proof of the beacon state's balances container against the beacon block root /// @dev This proof starts at the balance container root, proves through the beacon state root, and @@ -183,14 +153,8 @@ library BeaconChainProofs { /// against the same balance container root. /// @param beaconBlockRoot merkle root of the beacon block /// @param proof a beacon balance container root and merkle proof of its inclusion under `beaconBlockRoot` - function verifyBalanceContainer( - bytes32 beaconBlockRoot, - BalanceContainerProof calldata proof - ) internal view { - require( - proof.proof.length == 32 * (BEACON_BLOCK_HEADER_TREE_HEIGHT + BEACON_STATE_TREE_HEIGHT), - "BeaconChainProofs.verifyBalanceContainer: Proof has incorrect length" - ); + function verifyBalanceContainer(bytes32 beaconBlockRoot, BalanceContainerProof calldata proof) internal view { + require(proof.proof.length == 32 * (BEACON_BLOCK_HEADER_TREE_HEIGHT + BEACON_STATE_TREE_HEIGHT), "BeaconChainProofs.verifyBalanceContainer: Proof has incorrect length"); /// This proof combines two proofs, so its index accounts for the relative position of leaves in two trees: /// - beaconBlockRoot @@ -199,16 +163,8 @@ library BeaconChainProofs { /// | HEIGHT: BEACON_STATE_TREE_HEIGHT /// ---- balancesContainerRoot uint256 index = (STATE_ROOT_INDEX << (BEACON_STATE_TREE_HEIGHT)) | BALANCE_CONTAINER_INDEX; - - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: proof.proof, - root: beaconBlockRoot, - leaf: proof.balanceContainerRoot, - index: index - }), - "BeaconChainProofs.verifyBalanceContainer: invalid balance container proof" - ); + + require(EigenlayerMerkle.verifyInclusionSha256({proof: proof.proof, root: beaconBlockRoot, leaf: proof.balanceContainerRoot, index: index}), "BeaconChainProofs.verifyBalanceContainer: invalid balance container proof"); } /// @notice Verify a merkle proof of a validator's balance against the beacon state's `balanceContainerRoot` @@ -216,17 +172,10 @@ library BeaconChainProofs { /// @param validatorIndex the index of the validator whose balance we are proving /// @param proof the validator's associated balance root and a merkle proof of inclusion under `balanceContainerRoot` /// @return validatorBalanceGwei the validator's current balance (in gwei) - function verifyValidatorBalance( - bytes32 balanceContainerRoot, - uint40 validatorIndex, - BalanceProof calldata proof - ) internal view returns (uint64 validatorBalanceGwei) { + function verifyValidatorBalance(bytes32 balanceContainerRoot, uint40 validatorIndex, BalanceProof calldata proof) internal view returns (uint64 validatorBalanceGwei) { /// Note: the reason we use `BALANCE_TREE_HEIGHT + 1` here is because the merklization process for /// this container includes hashing the root of the balances tree with the length of the balances list - require( - proof.proof.length == 32 * (BALANCE_TREE_HEIGHT + 1), - "BeaconChainProofs.verifyValidatorBalance: Proof has incorrect length" - ); + require(proof.proof.length == 32 * (BALANCE_TREE_HEIGHT + 1), "BeaconChainProofs.verifyValidatorBalance: Proof has incorrect length"); /// When merkleized, beacon chain balances are combined into groups of 4 called a `balanceRoot`. The merkle /// proof here verifies that this validator's `balanceRoot` is included in the `balanceContainerRoot` @@ -234,25 +183,17 @@ library BeaconChainProofs { /// | HEIGHT: BALANCE_TREE_HEIGHT /// -- balanceRoot uint256 balanceIndex = uint256(validatorIndex / 4); - - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: proof.proof, - root: balanceContainerRoot, - leaf: proof.balanceRoot, - index: balanceIndex - }), - "BeaconChainProofs.verifyValidatorBalance: Invalid merkle proof" - ); + + require(EigenlayerMerkle.verifyInclusionSha256({proof: proof.proof, root: balanceContainerRoot, leaf: proof.balanceRoot, index: balanceIndex}), "BeaconChainProofs.verifyValidatorBalance: Invalid merkle proof"); /// Extract the individual validator's balance from the `balanceRoot` return getBalanceAtIndex(proof.balanceRoot, validatorIndex); } /** - * @notice Parses a balanceRoot to get the uint64 balance of a validator. - * @dev During merkleization of the beacon state balance tree, four uint64 values are treated as a single - * leaf in the merkle tree. We use validatorIndex % 4 to determine which of the four uint64 values to + * @notice Parses a balanceRoot to get the uint64 balance of a validator. + * @dev During merkleization of the beacon state balance tree, four uint64 values are treated as a single + * leaf in the merkle tree. We use validatorIndex % 4 to determine which of the four uint64 values to * extract from the balanceRoot. * @param balanceRoot is the combination of 4 validator balances being proven for * @param validatorIndex is the index of the validator being proven for @@ -260,8 +201,7 @@ library BeaconChainProofs { */ function getBalanceAtIndex(bytes32 balanceRoot, uint40 validatorIndex) internal pure returns (uint64) { uint256 bitShiftAmount = (validatorIndex % 4) * 64; - return - Endian.fromLittleEndianUint64(bytes32((uint256(balanceRoot) << bitShiftAmount))); + return Endian.fromLittleEndianUint64(bytes32((uint256(balanceRoot) << bitShiftAmount))); } /// @notice Indices for fields in the `Validator` container: @@ -278,20 +218,17 @@ library BeaconChainProofs { /// @dev Retrieves a validator's pubkey hash function getPubkeyHash(bytes32[] memory validatorFields) internal pure returns (bytes32) { - return - validatorFields[VALIDATOR_PUBKEY_INDEX]; + return validatorFields[VALIDATOR_PUBKEY_INDEX]; } /// @dev Retrieves a validator's withdrawal credentials function getWithdrawalCredentials(bytes32[] memory validatorFields) internal pure returns (bytes32) { - return - validatorFields[VALIDATOR_WITHDRAWAL_CREDENTIALS_INDEX]; + return validatorFields[VALIDATOR_WITHDRAWAL_CREDENTIALS_INDEX]; } /// @dev Retrieves a validator's effective balance (in gwei) function getEffectiveBalanceGwei(bytes32[] memory validatorFields) internal pure returns (uint64) { - return - Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_BALANCE_INDEX]); + return Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_BALANCE_INDEX]); } /// @dev Retrieves true IFF a validator is marked slashed @@ -301,7 +238,6 @@ library BeaconChainProofs { /// @dev Retrieves a validator's exit epoch function getExitEpoch(bytes32[] memory validatorFields) internal pure returns (uint64) { - return - Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_EXIT_EPOCH_INDEX]); + return Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_EXIT_EPOCH_INDEX]); } } diff --git a/src/eigenlayer-libraries/BytesLib.sol b/src/eigenlayer-libraries/BytesLib.sol index 961d239ff..cc382053d 100644 --- a/src/eigenlayer-libraries/BytesLib.sol +++ b/src/eigenlayer-libraries/BytesLib.sol @@ -57,14 +57,10 @@ library BytesLib { // length of the arrays. end := add(mc, length) - for { - let cc := add(_postBytes, 0x20) - } lt(mc, end) { + for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) - } { - mstore(mc, mload(cc)) - } + } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the @@ -158,13 +154,7 @@ library BytesLib { let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) - sstore( - sc, - add( - and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00), - and(mload(mc), mask) - ) - ) + sstore(sc, add(and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00), and(mload(mc), mask))) for { mc := add(mc, 0x20) @@ -172,9 +162,7 @@ library BytesLib { } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) - } { - sstore(sc, mload(mc)) - } + } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) @@ -207,9 +195,7 @@ library BytesLib { } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) - } { - sstore(sc, mload(mc)) - } + } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) @@ -255,9 +241,7 @@ library BytesLib { } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) - } { - mstore(mc, mload(cc)) - } + } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) @@ -396,9 +380,7 @@ library BytesLib { let mc := add(_preBytes, 0x20) let end := add(mc, length) - for { - let cc := add(_postBytes, 0x20) - } // while(uint256(mc < end) + cb == 2) // the next line is the loop condition: + for { let cc := add(_postBytes, 0x20) } // while(uint256(mc < end) + cb == 2) // the next line is the loop condition: eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) @@ -464,9 +446,7 @@ library BytesLib { // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) // solhint-disable-next-line no-empty-blocks - for { - - } eq(add(lt(mc, end), cb), 2) { + for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { diff --git a/src/eigenlayer-libraries/EIP1271SignatureUtils.sol b/src/eigenlayer-libraries/EIP1271SignatureUtils.sol index a4452f91e..64ce4589f 100644 --- a/src/eigenlayer-libraries/EIP1271SignatureUtils.sol +++ b/src/eigenlayer-libraries/EIP1271SignatureUtils.sol @@ -27,15 +27,9 @@ library EIP1271SignatureUtils { * 2) if `signer` is a contract, then `signature` must will be checked according to EIP-1271 */ if (Address.isContract(signer)) { - require( - IERC1271(signer).isValidSignature(digestHash, signature) == EIP1271_MAGICVALUE, - "EIP1271SignatureUtils.checkSignature_EIP1271: ERC1271 signature verification failed" - ); + require(IERC1271(signer).isValidSignature(digestHash, signature) == EIP1271_MAGICVALUE, "EIP1271SignatureUtils.checkSignature_EIP1271: ERC1271 signature verification failed"); } else { - require( - ECDSA.recover(digestHash, signature) == signer, - "EIP1271SignatureUtils.checkSignature_EIP1271: signature not from signer" - ); + require(ECDSA.recover(digestHash, signature) == signer, "EIP1271SignatureUtils.checkSignature_EIP1271: signature not from signer"); } } } diff --git a/src/eigenlayer-libraries/EigenlayerMerkle.sol b/src/eigenlayer-libraries/EigenlayerMerkle.sol index 1d54b9ceb..b8827aa63 100644 --- a/src/eigenlayer-libraries/EigenlayerMerkle.sol +++ b/src/eigenlayer-libraries/EigenlayerMerkle.sol @@ -26,12 +26,7 @@ library EigenlayerMerkle { * * Note this is for a Merkle tree using the keccak/sha3 hash function */ - function verifyInclusionKeccak( - bytes memory proof, - bytes32 root, - bytes32 leaf, - uint256 index - ) internal pure returns (bool) { + function verifyInclusionKeccak(bytes memory proof, bytes32 root, bytes32 leaf, uint256 index) internal pure returns (bool) { return processInclusionProofKeccak(proof, leaf, index) == root; } @@ -45,15 +40,8 @@ library EigenlayerMerkle { * * Note this is for a Merkle tree using the keccak/sha3 hash function */ - function processInclusionProofKeccak( - bytes memory proof, - bytes32 leaf, - uint256 index - ) internal pure returns (bytes32) { - require( - proof.length != 0 && proof.length % 32 == 0, - "Merkle.processInclusionProofKeccak: proof length should be a non-zero multiple of 32" - ); + function processInclusionProofKeccak(bytes memory proof, bytes32 leaf, uint256 index) internal pure returns (bytes32) { + require(proof.length != 0 && proof.length % 32 == 0, "Merkle.processInclusionProofKeccak: proof length should be a non-zero multiple of 32"); bytes32 computedHash = leaf; for (uint256 i = 32; i <= proof.length; i += 32) { if (index % 2 == 0) { @@ -85,12 +73,7 @@ library EigenlayerMerkle { * * Note this is for a Merkle tree using the sha256 hash function */ - function verifyInclusionSha256( - bytes memory proof, - bytes32 root, - bytes32 leaf, - uint256 index - ) internal view returns (bool) { + function verifyInclusionSha256(bytes memory proof, bytes32 root, bytes32 leaf, uint256 index) internal view returns (bool) { return processInclusionProofSha256(proof, leaf, index) == root; } @@ -104,15 +87,8 @@ library EigenlayerMerkle { * * Note this is for a Merkle tree using the sha256 hash function */ - function processInclusionProofSha256( - bytes memory proof, - bytes32 leaf, - uint256 index - ) internal view returns (bytes32) { - require( - proof.length != 0 && proof.length % 32 == 0, - "Merkle.processInclusionProofSha256: proof length should be a non-zero multiple of 32" - ); + function processInclusionProofSha256(bytes memory proof, bytes32 leaf, uint256 index) internal view returns (bytes32) { + require(proof.length != 0 && proof.length % 32 == 0, "Merkle.processInclusionProofSha256: proof length should be a non-zero multiple of 32"); bytes32[1] memory computedHash = [leaf]; for (uint256 i = 32; i <= proof.length; i += 32) { if (index % 2 == 0) { @@ -120,9 +96,7 @@ library EigenlayerMerkle { assembly { mstore(0x00, mload(computedHash)) mstore(0x20, mload(add(proof, i))) - if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { - revert(0, 0) - } + if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { revert(0, 0) } index := div(index, 2) } } else { @@ -130,9 +104,7 @@ library EigenlayerMerkle { assembly { mstore(0x00, mload(add(proof, i))) mstore(0x20, mload(computedHash)) - if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { - revert(0, 0) - } + if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { revert(0, 0) } index := div(index, 2) } } @@ -141,10 +113,10 @@ library EigenlayerMerkle { } /** - @notice this function returns the merkle root of a tree created from a set of leaves using sha256 as its hash function - @param leaves the leaves of the merkle tree - @return The computed Merkle root of the tree. - @dev A pre-condition to this function is that leaves.length is a power of two. If not, the function will merkleize the inputs incorrectly. + * @notice this function returns the merkle root of a tree created from a set of leaves using sha256 as its hash function + * @param leaves the leaves of the merkle tree + * @return The computed Merkle root of the tree. + * @dev A pre-condition to this function is that leaves.length is a power of two. If not, the function will merkleize the inputs incorrectly. */ function merkleizeSha256(bytes32[] memory leaves) internal pure returns (bytes32) { //there are half as many nodes in the layer above the leaves diff --git a/src/eigenlayer-libraries/Endian.sol b/src/eigenlayer-libraries/Endian.sol index ac996ce38..1ea226dda 100644 --- a/src/eigenlayer-libraries/Endian.sol +++ b/src/eigenlayer-libraries/Endian.sol @@ -12,14 +12,6 @@ library Endian { function fromLittleEndianUint64(bytes32 lenum) internal pure returns (uint64 n) { // the number needs to be stored in little-endian encoding (ie in bytes 0-8) n = uint64(uint256(lenum >> 192)); - return - (n >> 56) | - ((0x00FF000000000000 & n) >> 40) | - ((0x0000FF0000000000 & n) >> 24) | - ((0x000000FF00000000 & n) >> 8) | - ((0x00000000FF000000 & n) << 8) | - ((0x0000000000FF0000 & n) << 24) | - ((0x000000000000FF00 & n) << 40) | - ((0x00000000000000FF & n) << 56); + return (n >> 56) | ((0x00FF000000000000 & n) >> 40) | ((0x0000FF0000000000 & n) >> 24) | ((0x000000FF00000000 & n) >> 8) | ((0x00000000FF000000 & n) << 8) | ((0x0000000000FF0000 & n) << 24) | ((0x000000000000FF00 & n) << 40) | ((0x00000000000000FF & n) << 56); } } diff --git a/src/eigenlayer-libraries/LegacyBeaconChainProofs.sol b/src/eigenlayer-libraries/LegacyBeaconChainProofs.sol index 01e80d613..e62329c91 100644 --- a/src/eigenlayer-libraries/LegacyBeaconChainProofs.sol +++ b/src/eigenlayer-libraries/LegacyBeaconChainProofs.sol @@ -106,7 +106,7 @@ library LegacyBeaconChainProofs { /// @notice The number of seconds in a slot in the beacon chain uint64 internal constant SECONDS_PER_SLOT = 12; - /// @notice Number of seconds per epoch: 384 == 32 slots/epoch * 12 seconds/slot + /// @notice Number of seconds per epoch: 384 == 32 slots/epoch * 12 seconds/slot uint64 internal constant SECONDS_PER_EPOCH = SLOTS_PER_EPOCH * SECONDS_PER_SLOT; bytes8 internal constant UINT64_MASK = 0xffffffffffffffff; @@ -140,39 +140,20 @@ library LegacyBeaconChainProofs { * @param validatorFieldsProof is the data used in proving the validator's fields * @param validatorFields the claimed fields of the validator */ - function verifyValidatorFields( - bytes32 beaconStateRoot, - bytes32[] calldata validatorFields, - bytes calldata validatorFieldsProof, - uint40 validatorIndex - ) internal view { - require( - validatorFields.length == 2 ** VALIDATOR_FIELD_TREE_HEIGHT, - "BeaconChainProofs.verifyValidatorFields: Validator fields has incorrect length" - ); + function verifyValidatorFields(bytes32 beaconStateRoot, bytes32[] calldata validatorFields, bytes calldata validatorFieldsProof, uint40 validatorIndex) internal view { + require(validatorFields.length == 2 ** VALIDATOR_FIELD_TREE_HEIGHT, "BeaconChainProofs.verifyValidatorFields: Validator fields has incorrect length"); /** * Note: the length of the validator merkle proof is BeaconChainProofs.VALIDATOR_TREE_HEIGHT + 1. * There is an additional layer added by hashing the root with the length of the validator list */ - require( - validatorFieldsProof.length == 32 * ((VALIDATOR_TREE_HEIGHT + 1) + BEACON_STATE_FIELD_TREE_HEIGHT), - "BeaconChainProofs.verifyValidatorFields: Proof has incorrect length" - ); + require(validatorFieldsProof.length == 32 * ((VALIDATOR_TREE_HEIGHT + 1) + BEACON_STATE_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyValidatorFields: Proof has incorrect length"); uint256 index = (VALIDATOR_TREE_ROOT_INDEX << (VALIDATOR_TREE_HEIGHT + 1)) | uint256(validatorIndex); // merkleize the validatorFields to get the leaf to prove bytes32 validatorRoot = EigenlayerMerkle.merkleizeSha256(validatorFields); // verify the proof of the validatorRoot against the beaconStateRoot - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: validatorFieldsProof, - root: beaconStateRoot, - leaf: validatorRoot, - index: index - }), - "BeaconChainProofs.verifyValidatorFields: Invalid merkle proof" - ); + require(EigenlayerMerkle.verifyInclusionSha256({proof: validatorFieldsProof, root: beaconStateRoot, leaf: validatorRoot, index: index}), "BeaconChainProofs.verifyValidatorFields: Invalid merkle proof"); } /** @@ -182,25 +163,10 @@ library LegacyBeaconChainProofs { * @param stateRootProof is the provided merkle proof * @param latestBlockRoot is hashtree root of the latest block header in the beacon state */ - function verifyStateRootAgainstLatestBlockRoot( - bytes32 latestBlockRoot, - bytes32 beaconStateRoot, - bytes calldata stateRootProof - ) internal view { - require( - stateRootProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT), - "BeaconChainProofs.verifyStateRootAgainstLatestBlockRoot: Proof has incorrect length" - ); + function verifyStateRootAgainstLatestBlockRoot(bytes32 latestBlockRoot, bytes32 beaconStateRoot, bytes calldata stateRootProof) internal view { + require(stateRootProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyStateRootAgainstLatestBlockRoot: Proof has incorrect length"); //Next we verify the slot against the blockRoot - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: stateRootProof, - root: latestBlockRoot, - leaf: beaconStateRoot, - index: STATE_ROOT_INDEX - }), - "BeaconChainProofs.verifyStateRootAgainstLatestBlockRoot: Invalid latest block header root merkle proof" - ); + require(EigenlayerMerkle.verifyInclusionSha256({proof: stateRootProof, root: latestBlockRoot, leaf: beaconStateRoot, index: STATE_ROOT_INDEX}), "BeaconChainProofs.verifyStateRootAgainstLatestBlockRoot: Invalid latest block header root merkle proof"); } /** @@ -208,115 +174,40 @@ library LegacyBeaconChainProofs { * @param withdrawalProof is the provided set of merkle proofs * @param withdrawalFields is the serialized withdrawal container to be proven */ - function verifyWithdrawal( - bytes32 beaconStateRoot, - bytes32[] calldata withdrawalFields, - WithdrawalProof calldata withdrawalProof - ) internal view { - require( - withdrawalFields.length == 2 ** WITHDRAWAL_FIELD_TREE_HEIGHT, - "BeaconChainProofs.verifyWithdrawal: withdrawalFields has incorrect length" - ); - - require( - withdrawalProof.blockRootIndex < 2 ** BLOCK_ROOTS_TREE_HEIGHT, - "BeaconChainProofs.verifyWithdrawal: blockRootIndex is too large" - ); - require( - withdrawalProof.withdrawalIndex < 2 ** WITHDRAWALS_TREE_HEIGHT, - "BeaconChainProofs.verifyWithdrawal: withdrawalIndex is too large" - ); - - require( - withdrawalProof.historicalSummaryIndex < 2 ** HISTORICAL_SUMMARIES_TREE_HEIGHT, - "BeaconChainProofs.verifyWithdrawal: historicalSummaryIndex is too large" - ); - - require( - withdrawalProof.withdrawalProof.length == - 32 * (EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT + WITHDRAWALS_TREE_HEIGHT + 1), - "BeaconChainProofs.verifyWithdrawal: withdrawalProof has incorrect length" - ); - require( - withdrawalProof.executionPayloadProof.length == - 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT + BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT), - "BeaconChainProofs.verifyWithdrawal: executionPayloadProof has incorrect length" - ); - require( - withdrawalProof.slotProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT), - "BeaconChainProofs.verifyWithdrawal: slotProof has incorrect length" - ); - require( - withdrawalProof.timestampProof.length == 32 * (EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT), - "BeaconChainProofs.verifyWithdrawal: timestampProof has incorrect length" - ); - - require( - withdrawalProof.historicalSummaryBlockRootProof.length == - 32 * - (BEACON_STATE_FIELD_TREE_HEIGHT + - (HISTORICAL_SUMMARIES_TREE_HEIGHT + 1) + - 1 + - (BLOCK_ROOTS_TREE_HEIGHT)), - "BeaconChainProofs.verifyWithdrawal: historicalSummaryBlockRootProof has incorrect length" - ); + function verifyWithdrawal(bytes32 beaconStateRoot, bytes32[] calldata withdrawalFields, WithdrawalProof calldata withdrawalProof) internal view { + require(withdrawalFields.length == 2 ** WITHDRAWAL_FIELD_TREE_HEIGHT, "BeaconChainProofs.verifyWithdrawal: withdrawalFields has incorrect length"); + + require(withdrawalProof.blockRootIndex < 2 ** BLOCK_ROOTS_TREE_HEIGHT, "BeaconChainProofs.verifyWithdrawal: blockRootIndex is too large"); + require(withdrawalProof.withdrawalIndex < 2 ** WITHDRAWALS_TREE_HEIGHT, "BeaconChainProofs.verifyWithdrawal: withdrawalIndex is too large"); + + require(withdrawalProof.historicalSummaryIndex < 2 ** HISTORICAL_SUMMARIES_TREE_HEIGHT, "BeaconChainProofs.verifyWithdrawal: historicalSummaryIndex is too large"); + + require(withdrawalProof.withdrawalProof.length == 32 * (EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT + WITHDRAWALS_TREE_HEIGHT + 1), "BeaconChainProofs.verifyWithdrawal: withdrawalProof has incorrect length"); + require(withdrawalProof.executionPayloadProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT + BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyWithdrawal: executionPayloadProof has incorrect length"); + require(withdrawalProof.slotProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyWithdrawal: slotProof has incorrect length"); + require(withdrawalProof.timestampProof.length == 32 * (EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyWithdrawal: timestampProof has incorrect length"); + + require(withdrawalProof.historicalSummaryBlockRootProof.length == 32 * (BEACON_STATE_FIELD_TREE_HEIGHT + (HISTORICAL_SUMMARIES_TREE_HEIGHT + 1) + 1 + (BLOCK_ROOTS_TREE_HEIGHT)), "BeaconChainProofs.verifyWithdrawal: historicalSummaryBlockRootProof has incorrect length"); /** * Note: Here, the "1" in "1 + (BLOCK_ROOTS_TREE_HEIGHT)" signifies that extra step of choosing the "block_root_summary" within the individual * "historical_summary". Everywhere else it signifies merkelize_with_mixin, where the length of an array is hashed with the root of the array, * but not here. */ - uint256 historicalBlockHeaderIndex = (HISTORICAL_SUMMARIES_INDEX << - ((HISTORICAL_SUMMARIES_TREE_HEIGHT + 1) + 1 + (BLOCK_ROOTS_TREE_HEIGHT))) | - (uint256(withdrawalProof.historicalSummaryIndex) << (1 + (BLOCK_ROOTS_TREE_HEIGHT))) | - (BLOCK_SUMMARY_ROOT_INDEX << (BLOCK_ROOTS_TREE_HEIGHT)) | - uint256(withdrawalProof.blockRootIndex); - - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: withdrawalProof.historicalSummaryBlockRootProof, - root: beaconStateRoot, - leaf: withdrawalProof.blockRoot, - index: historicalBlockHeaderIndex - }), - "BeaconChainProofs.verifyWithdrawal: Invalid historicalsummary merkle proof" - ); + uint256 historicalBlockHeaderIndex = (HISTORICAL_SUMMARIES_INDEX << ((HISTORICAL_SUMMARIES_TREE_HEIGHT + 1) + 1 + (BLOCK_ROOTS_TREE_HEIGHT))) | (uint256(withdrawalProof.historicalSummaryIndex) << (1 + (BLOCK_ROOTS_TREE_HEIGHT))) | (BLOCK_SUMMARY_ROOT_INDEX << (BLOCK_ROOTS_TREE_HEIGHT)) | uint256(withdrawalProof.blockRootIndex); + + require(EigenlayerMerkle.verifyInclusionSha256({proof: withdrawalProof.historicalSummaryBlockRootProof, root: beaconStateRoot, leaf: withdrawalProof.blockRoot, index: historicalBlockHeaderIndex}), "BeaconChainProofs.verifyWithdrawal: Invalid historicalsummary merkle proof"); //Next we verify the slot against the blockRoot - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: withdrawalProof.slotProof, - root: withdrawalProof.blockRoot, - leaf: withdrawalProof.slotRoot, - index: SLOT_INDEX - }), - "BeaconChainProofs.verifyWithdrawal: Invalid slot merkle proof" - ); + require(EigenlayerMerkle.verifyInclusionSha256({proof: withdrawalProof.slotProof, root: withdrawalProof.blockRoot, leaf: withdrawalProof.slotRoot, index: SLOT_INDEX}), "BeaconChainProofs.verifyWithdrawal: Invalid slot merkle proof"); { // Next we verify the executionPayloadRoot against the blockRoot - uint256 executionPayloadIndex = (BODY_ROOT_INDEX << (BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT)) | - EXECUTION_PAYLOAD_INDEX; - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: withdrawalProof.executionPayloadProof, - root: withdrawalProof.blockRoot, - leaf: withdrawalProof.executionPayloadRoot, - index: executionPayloadIndex - }), - "BeaconChainProofs.verifyWithdrawal: Invalid executionPayload merkle proof" - ); + uint256 executionPayloadIndex = (BODY_ROOT_INDEX << (BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT)) | EXECUTION_PAYLOAD_INDEX; + require(EigenlayerMerkle.verifyInclusionSha256({proof: withdrawalProof.executionPayloadProof, root: withdrawalProof.blockRoot, leaf: withdrawalProof.executionPayloadRoot, index: executionPayloadIndex}), "BeaconChainProofs.verifyWithdrawal: Invalid executionPayload merkle proof"); } // Next we verify the timestampRoot against the executionPayload root - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: withdrawalProof.timestampProof, - root: withdrawalProof.executionPayloadRoot, - leaf: withdrawalProof.timestampRoot, - index: TIMESTAMP_INDEX - }), - "BeaconChainProofs.verifyWithdrawal: Invalid blockNumber merkle proof" - ); + require(EigenlayerMerkle.verifyInclusionSha256({proof: withdrawalProof.timestampProof, root: withdrawalProof.executionPayloadRoot, leaf: withdrawalProof.timestampRoot, index: TIMESTAMP_INDEX}), "BeaconChainProofs.verifyWithdrawal: Invalid blockNumber merkle proof"); { /** @@ -330,18 +221,9 @@ library LegacyBeaconChainProofs { * Note: EigenlayerMerkleization of the withdrawals root tree uses EigenlayerMerkleizeWithMixin, i.e., the length of the array is hashed with the root of * the array. Thus we shift the WITHDRAWALS_INDEX over by WITHDRAWALS_TREE_HEIGHT + 1 and not just WITHDRAWALS_TREE_HEIGHT. */ - uint256 withdrawalIndex = (WITHDRAWALS_INDEX << (WITHDRAWALS_TREE_HEIGHT + 1)) | - uint256(withdrawalProof.withdrawalIndex); + uint256 withdrawalIndex = (WITHDRAWALS_INDEX << (WITHDRAWALS_TREE_HEIGHT + 1)) | uint256(withdrawalProof.withdrawalIndex); bytes32 withdrawalRoot = EigenlayerMerkle.merkleizeSha256(withdrawalFields); - require( - EigenlayerMerkle.verifyInclusionSha256({ - proof: withdrawalProof.withdrawalProof, - root: withdrawalProof.executionPayloadRoot, - leaf: withdrawalRoot, - index: withdrawalIndex - }), - "BeaconChainProofs.verifyWithdrawal: Invalid withdrawal merkle proof" - ); + require(EigenlayerMerkle.verifyInclusionSha256({proof: withdrawalProof.withdrawalProof, root: withdrawalProof.executionPayloadRoot, leaf: withdrawalRoot, index: withdrawalIndex}), "BeaconChainProofs.verifyWithdrawal: Invalid withdrawal merkle proof"); } } @@ -361,16 +243,14 @@ library LegacyBeaconChainProofs { * @dev Retrieve the withdrawal timestamp */ function getWithdrawalTimestamp(WithdrawalProof memory withdrawalProof) internal pure returns (uint64) { - return - Endian.fromLittleEndianUint64(withdrawalProof.timestampRoot); + return Endian.fromLittleEndianUint64(withdrawalProof.timestampRoot); } /** * @dev Converts the withdrawal's slot to an epoch */ function getWithdrawalEpoch(WithdrawalProof memory withdrawalProof) internal pure returns (uint64) { - return - Endian.fromLittleEndianUint64(withdrawalProof.slotRoot) / SLOTS_PER_EPOCH; + return Endian.fromLittleEndianUint64(withdrawalProof.slotRoot) / SLOTS_PER_EPOCH; } /** @@ -389,29 +269,25 @@ library LegacyBeaconChainProofs { * @dev Retrieves a validator's pubkey hash */ function getPubkeyHash(bytes32[] memory validatorFields) internal pure returns (bytes32) { - return - validatorFields[VALIDATOR_PUBKEY_INDEX]; + return validatorFields[VALIDATOR_PUBKEY_INDEX]; } function getWithdrawalCredentials(bytes32[] memory validatorFields) internal pure returns (bytes32) { - return - validatorFields[VALIDATOR_WITHDRAWAL_CREDENTIALS_INDEX]; + return validatorFields[VALIDATOR_WITHDRAWAL_CREDENTIALS_INDEX]; } /** * @dev Retrieves a validator's effective balance (in gwei) */ function getEffectiveBalanceGwei(bytes32[] memory validatorFields) internal pure returns (uint64) { - return - Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_BALANCE_INDEX]); + return Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_BALANCE_INDEX]); } /** * @dev Retrieves a validator's withdrawable epoch */ function getWithdrawableEpoch(bytes32[] memory validatorFields) internal pure returns (uint64) { - return - Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_WITHDRAWABLE_EPOCH_INDEX]); + return Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_WITHDRAWABLE_EPOCH_INDEX]); } /** @@ -426,15 +302,13 @@ library LegacyBeaconChainProofs { * @dev Retrieves a withdrawal's validator index */ function getValidatorIndex(bytes32[] memory withdrawalFields) internal pure returns (uint40) { - return - uint40(Endian.fromLittleEndianUint64(withdrawalFields[WITHDRAWAL_VALIDATOR_INDEX_INDEX])); + return uint40(Endian.fromLittleEndianUint64(withdrawalFields[WITHDRAWAL_VALIDATOR_INDEX_INDEX])); } /** * @dev Retrieves a withdrawal's withdrawal amount (in gwei) */ function getWithdrawalAmountGwei(bytes32[] memory withdrawalFields) internal pure returns (uint64) { - return - Endian.fromLittleEndianUint64(withdrawalFields[WITHDRAWAL_VALIDATOR_AMOUNT_INDEX]); + return Endian.fromLittleEndianUint64(withdrawalFields[WITHDRAWAL_VALIDATOR_AMOUNT_INDEX]); } } diff --git a/src/eigenlayer-libraries/Merkle.sol b/src/eigenlayer-libraries/Merkle.sol index 1d54b9ceb..b8827aa63 100644 --- a/src/eigenlayer-libraries/Merkle.sol +++ b/src/eigenlayer-libraries/Merkle.sol @@ -26,12 +26,7 @@ library EigenlayerMerkle { * * Note this is for a Merkle tree using the keccak/sha3 hash function */ - function verifyInclusionKeccak( - bytes memory proof, - bytes32 root, - bytes32 leaf, - uint256 index - ) internal pure returns (bool) { + function verifyInclusionKeccak(bytes memory proof, bytes32 root, bytes32 leaf, uint256 index) internal pure returns (bool) { return processInclusionProofKeccak(proof, leaf, index) == root; } @@ -45,15 +40,8 @@ library EigenlayerMerkle { * * Note this is for a Merkle tree using the keccak/sha3 hash function */ - function processInclusionProofKeccak( - bytes memory proof, - bytes32 leaf, - uint256 index - ) internal pure returns (bytes32) { - require( - proof.length != 0 && proof.length % 32 == 0, - "Merkle.processInclusionProofKeccak: proof length should be a non-zero multiple of 32" - ); + function processInclusionProofKeccak(bytes memory proof, bytes32 leaf, uint256 index) internal pure returns (bytes32) { + require(proof.length != 0 && proof.length % 32 == 0, "Merkle.processInclusionProofKeccak: proof length should be a non-zero multiple of 32"); bytes32 computedHash = leaf; for (uint256 i = 32; i <= proof.length; i += 32) { if (index % 2 == 0) { @@ -85,12 +73,7 @@ library EigenlayerMerkle { * * Note this is for a Merkle tree using the sha256 hash function */ - function verifyInclusionSha256( - bytes memory proof, - bytes32 root, - bytes32 leaf, - uint256 index - ) internal view returns (bool) { + function verifyInclusionSha256(bytes memory proof, bytes32 root, bytes32 leaf, uint256 index) internal view returns (bool) { return processInclusionProofSha256(proof, leaf, index) == root; } @@ -104,15 +87,8 @@ library EigenlayerMerkle { * * Note this is for a Merkle tree using the sha256 hash function */ - function processInclusionProofSha256( - bytes memory proof, - bytes32 leaf, - uint256 index - ) internal view returns (bytes32) { - require( - proof.length != 0 && proof.length % 32 == 0, - "Merkle.processInclusionProofSha256: proof length should be a non-zero multiple of 32" - ); + function processInclusionProofSha256(bytes memory proof, bytes32 leaf, uint256 index) internal view returns (bytes32) { + require(proof.length != 0 && proof.length % 32 == 0, "Merkle.processInclusionProofSha256: proof length should be a non-zero multiple of 32"); bytes32[1] memory computedHash = [leaf]; for (uint256 i = 32; i <= proof.length; i += 32) { if (index % 2 == 0) { @@ -120,9 +96,7 @@ library EigenlayerMerkle { assembly { mstore(0x00, mload(computedHash)) mstore(0x20, mload(add(proof, i))) - if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { - revert(0, 0) - } + if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { revert(0, 0) } index := div(index, 2) } } else { @@ -130,9 +104,7 @@ library EigenlayerMerkle { assembly { mstore(0x00, mload(add(proof, i))) mstore(0x20, mload(computedHash)) - if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { - revert(0, 0) - } + if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { revert(0, 0) } index := div(index, 2) } } @@ -141,10 +113,10 @@ library EigenlayerMerkle { } /** - @notice this function returns the merkle root of a tree created from a set of leaves using sha256 as its hash function - @param leaves the leaves of the merkle tree - @return The computed Merkle root of the tree. - @dev A pre-condition to this function is that leaves.length is a power of two. If not, the function will merkleize the inputs incorrectly. + * @notice this function returns the merkle root of a tree created from a set of leaves using sha256 as its hash function + * @param leaves the leaves of the merkle tree + * @return The computed Merkle root of the tree. + * @dev A pre-condition to this function is that leaves.length is a power of two. If not, the function will merkleize the inputs incorrectly. */ function merkleizeSha256(bytes32[] memory leaves) internal pure returns (bytes32) { //there are half as many nodes in the layer above the leaves diff --git a/src/eigenlayer-libraries/OperatorSetLib.sol b/src/eigenlayer-libraries/OperatorSetLib.sol index 0b1ae4808..12e984fe0 100644 --- a/src/eigenlayer-libraries/OperatorSetLib.sol +++ b/src/eigenlayer-libraries/OperatorSetLib.sol @@ -14,15 +14,11 @@ struct OperatorSet { } library OperatorSetLib { - function key( - OperatorSet memory os - ) internal pure returns (bytes32) { + function key(OperatorSet memory os) internal pure returns (bytes32) { return bytes32(abi.encodePacked(os.avs, uint96(os.id))); } - function decode( - bytes32 _key - ) internal pure returns (OperatorSet memory) { + function decode(bytes32 _key) internal pure returns (OperatorSet memory) { /// forgefmt: disable-next-item return OperatorSet({ avs: address(uint160(uint256(_key) >> 96)), diff --git a/src/eigenlayer-libraries/SlashingLib.sol b/src/eigenlayer-libraries/SlashingLib.sol index aa4846935..1e14613f5 100644 --- a/src/eigenlayer-libraries/SlashingLib.sol +++ b/src/eigenlayer-libraries/SlashingLib.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.27; -import "@openzeppelin/contracts/utils/math/Math.sol"; import "@openzeppelin-upgradeable/contracts/utils/math/SafeCastUpgradeable.sol"; +import "@openzeppelin/contracts/utils/math/Math.sol"; /// @dev All scaling factors have `1e18` as an initial/default value. This value is represented /// by the constant `WAD`, which is used to preserve precision with uint256 math. @@ -57,16 +57,11 @@ library SlashingLib { // GETTERS - function scalingFactor( - DepositScalingFactor memory dsf - ) internal pure returns (uint256) { + function scalingFactor(DepositScalingFactor memory dsf) internal pure returns (uint256) { return dsf._scalingFactor == 0 ? WAD : dsf._scalingFactor; } - function scaleForQueueWithdrawal( - DepositScalingFactor memory dsf, - uint256 depositSharesToWithdraw - ) internal pure returns (uint256) { + function scaleForQueueWithdrawal(DepositScalingFactor memory dsf, uint256 depositSharesToWithdraw) internal pure returns (uint256) { return depositSharesToWithdraw.mulWad(dsf.scalingFactor()); } @@ -80,20 +75,11 @@ library SlashingLib { * withdrawal queue. * NOTE: max magnitude is guaranteed to only ever decrease. */ - function scaleForBurning( - uint256 scaledShares, - uint64 prevMaxMagnitude, - uint64 newMaxMagnitude - ) internal pure returns (uint256) { + function scaleForBurning(uint256 scaledShares, uint64 prevMaxMagnitude, uint64 newMaxMagnitude) internal pure returns (uint256) { return scaledShares.mulWad(prevMaxMagnitude - newMaxMagnitude); } - function update( - DepositScalingFactor storage dsf, - uint256 prevDepositShares, - uint256 addedShares, - uint256 slashingFactor - ) internal { + function update(DepositScalingFactor storage dsf, uint256 prevDepositShares, uint256 addedShares, uint256 slashingFactor) internal { if (prevDepositShares == 0) { // If this is the staker's first deposit or they are delegating to an operator, // the slashing factor is inverted and applied to the existing DSF. This has the @@ -143,41 +129,27 @@ library SlashingLib { /// A DSF is reset when a staker reduces their deposit shares to 0, either by queueing /// a withdrawal, or undelegating from their operator. This ensures that subsequent /// delegations/deposits do not use a stale DSF (e.g. from a prior operator). - function reset( - DepositScalingFactor storage dsf - ) internal { + function reset(DepositScalingFactor storage dsf) internal { dsf._scalingFactor = 0; } // CONVERSION - function calcWithdrawable( - DepositScalingFactor memory dsf, - uint256 depositShares, - uint256 slashingFactor - ) internal pure returns (uint256) { + function calcWithdrawable(DepositScalingFactor memory dsf, uint256 depositShares, uint256 slashingFactor) internal pure returns (uint256) { /// forgefmt: disable-next-item return depositShares .mulWad(dsf.scalingFactor()) .mulWad(slashingFactor); } - function calcDepositShares( - DepositScalingFactor memory dsf, - uint256 withdrawableShares, - uint256 slashingFactor - ) internal pure returns (uint256) { + function calcDepositShares(DepositScalingFactor memory dsf, uint256 withdrawableShares, uint256 slashingFactor) internal pure returns (uint256) { /// forgefmt: disable-next-item return withdrawableShares .divWad(dsf.scalingFactor()) .divWad(slashingFactor); } - function calcSlashedAmount( - uint256 operatorShares, - uint256 prevMaxMagnitude, - uint256 newMaxMagnitude - ) internal pure returns (uint256) { + function calcSlashedAmount(uint256 operatorShares, uint256 prevMaxMagnitude, uint256 newMaxMagnitude) internal pure returns (uint256) { // round up mulDiv so we don't overslash return operatorShares - operatorShares.mulDiv(newMaxMagnitude, prevMaxMagnitude, Math.Rounding.Up); } diff --git a/src/helpers/AddressProvider.sol b/src/helpers/AddressProvider.sol index 853e3d063..3a6f1d2a8 100644 --- a/src/helpers/AddressProvider.sol +++ b/src/helpers/AddressProvider.sol @@ -6,7 +6,6 @@ interface EtherFiProxy { } contract AddressProvider { - //-------------------------------------------------------------------------------------- //--------------------------------- STATE-VARIABLES ---------------------------------- //-------------------------------------------------------------------------------------- @@ -38,10 +37,7 @@ contract AddressProvider { /// @param _name the name of the contract for reference function addContract(address _contractAddress, string memory _name) external onlyOwner { require(contracts[_name].contractAddress == address(0), "Contract already exists"); - contracts[_name] = ContractData({ - contractAddress: _contractAddress, - name: _name - }); + contracts[_name] = ContractData({contractAddress: _contractAddress, name: _name}); numberOfContracts++; emit ContractAdded(_contractAddress, _name); @@ -53,7 +49,7 @@ contract AddressProvider { function removeContract(string memory _name) external onlyOwner { ContractData memory contractData = contracts[_name]; require(contracts[_name].contractAddress != address(0), "Contract does not exist"); - + address contractAddress = contractData.contractAddress; delete contracts[_name]; numberOfContracts--; @@ -98,4 +94,4 @@ contract AddressProvider { require(msg.sender == owner, "Only owner function"); _; } -} \ No newline at end of file +} diff --git a/src/helpers/EtherFiOperationParameters.sol b/src/helpers/EtherFiOperationParameters.sol index dc2309d1b..8f1f179d7 100644 --- a/src/helpers/EtherFiOperationParameters.sol +++ b/src/helpers/EtherFiOperationParameters.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; contract EtherFiOperationParameters is UUPSUpgradeable, OwnableUpgradeable { mapping(string => mapping(address => bool)) public tagAdmins; @@ -23,14 +23,14 @@ contract EtherFiOperationParameters is UUPSUpgradeable, OwnableUpgradeable { function updateTagAdmin(string memory tag, address admin, bool allowed) external onlyOwner { tagAdmins[tag][admin] = allowed; - + emit UpdatedAdmin(tag, admin, allowed); } function updateTagKeyValue(string memory tag, string memory key, string memory value) external onlyAdmin(tag) { string memory old_value = tagKeyValues[tag][key]; tagKeyValues[tag][key] = value; - + emit UpdatedKeyValue(tag, key, old_value, value); } @@ -44,4 +44,4 @@ contract EtherFiOperationParameters is UUPSUpgradeable, OwnableUpgradeable { require(tagAdmins[tag][msg.sender], "Only admin can call"); _; } -} \ No newline at end of file +} diff --git a/src/helpers/EtherFiViewer.sol b/src/helpers/EtherFiViewer.sol index f85419267..a3e94d609 100644 --- a/src/helpers/EtherFiViewer.sol +++ b/src/helpers/EtherFiViewer.sol @@ -1,20 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; +import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; -import "src/interfaces/IEtherFiNodesManager.sol"; +import "src/eigenlayer-interfaces/IDelegationManager.sol"; import "src/eigenlayer-interfaces/IEigenPod.sol"; import "src/eigenlayer-interfaces/IEigenPodManager.sol"; -import "src/eigenlayer-interfaces/IDelegationManager.sol"; +import "src/interfaces/IEtherFiNodesManager.sol"; import "src/helpers/AddressProvider.sol"; contract EtherFiViewer is Initializable, OwnableUpgradeable, UUPSUpgradeable { - - AddressProvider addressProvider; IEtherFiNodesManager nodesManager; diff --git a/src/helpers/WeETHWithdrawAdapter.sol b/src/helpers/WeETHWithdrawAdapter.sol index 622cdca52..4d21aaff3 100644 --- a/src/helpers/WeETHWithdrawAdapter.sol +++ b/src/helpers/WeETHWithdrawAdapter.sol @@ -1,30 +1,28 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; +import {OwnableUpgradeable} from "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import {Initializable} from "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import {UUPSUpgradeable} from "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import {OwnableUpgradeable} from "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; -import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IWeETHWithdrawAdapter} from "../interfaces/IWeETHWithdrawAdapter.sol"; -import {IWeETH} from "../interfaces/IWeETH.sol"; -import {IeETH} from "../interfaces/IeETH.sol"; import {ILiquidityPool} from "../interfaces/ILiquidityPool.sol"; -import {IWithdrawRequestNFT} from "../interfaces/IWithdrawRequestNFT.sol"; + import {IRoleRegistry} from "../interfaces/IRoleRegistry.sol"; +import {IWeETH} from "../interfaces/IWeETH.sol"; +import {IWeETHWithdrawAdapter} from "../interfaces/IWeETHWithdrawAdapter.sol"; + +import {IWithdrawRequestNFT} from "../interfaces/IWithdrawRequestNFT.sol"; +import {IeETH} from "../interfaces/IeETH.sol"; /** * @title WeETHWithdrawAdapter * @notice Adapter contract that allows users to request withdrawals using weETH directly * @dev This contract converts weETH to eETH and creates withdrawal requests in the existing system */ -contract WeETHWithdrawAdapter is - Initializable, - UUPSUpgradeable, - OwnableUpgradeable, - IWeETHWithdrawAdapter -{ +contract WeETHWithdrawAdapter is Initializable, UUPSUpgradeable, OwnableUpgradeable, IWeETHWithdrawAdapter { using SafeERC20 for IERC20; //-------------------------------------------------------------------------------------- @@ -67,18 +65,8 @@ contract WeETHWithdrawAdapter is //-------------------------------------------------------------------------------------- /// @custom:oz-upgrades-unsafe-allow constructor - constructor( - address _weETH, - address _eETH, - address _liquidityPool, - address _withdrawRequestNFT, - address _roleRegistry - ) { - if (_weETH == address(0) || - _eETH == address(0) || - _liquidityPool == address(0) || - _withdrawRequestNFT == address(0) || - _roleRegistry == address(0)) { + constructor(address _weETH, address _eETH, address _liquidityPool, address _withdrawRequestNFT, address _roleRegistry) { + if (_weETH == address(0) || _eETH == address(0) || _liquidityPool == address(0) || _withdrawRequestNFT == address(0) || _roleRegistry == address(0)) { revert ZeroAddress(); } @@ -87,7 +75,7 @@ contract WeETHWithdrawAdapter is liquidityPool = ILiquidityPool(_liquidityPool); withdrawRequestNFT = IWithdrawRequestNFT(_withdrawRequestNFT); roleRegistry = IRoleRegistry(_roleRegistry); - + _disableInitializers(); } @@ -109,26 +97,22 @@ contract WeETHWithdrawAdapter is * @param recipient Address that will receive the WithdrawRequestNFT * @return requestId The ID of the created withdrawal request */ - function requestWithdraw(uint256 weETHAmount, address recipient) - public - whenNotPaused - returns (uint256 requestId) - { + function requestWithdraw(uint256 weETHAmount, address recipient) public whenNotPaused returns (uint256 requestId) { if (weETHAmount == 0) revert ZeroAmount(); if (recipient == address(0)) revert ZeroAddress(); // Transfer weETH from user to this contract IERC20(address(weETH)).safeTransferFrom(msg.sender, address(this), weETHAmount); - + // Unwrap weETH to get eETH uint256 eETHAmount = weETH.unwrap(weETHAmount); - + // Approve eETH to be spent by LiquidityPool IERC20(address(eETH)).safeApprove(address(liquidityPool), eETHAmount); - + // Create withdrawal request through LiquidityPool requestId = liquidityPool.requestWithdraw(recipient, eETHAmount); - + return requestId; } @@ -139,28 +123,14 @@ contract WeETHWithdrawAdapter is * @param permit Permit data for weETH approval * @return requestId The ID of the created withdrawal request */ - function requestWithdrawWithPermit( - uint256 weETHAmount, - address recipient, - PermitInput calldata permit - ) external whenNotPaused returns (uint256 requestId) { + function requestWithdrawWithPermit(uint256 weETHAmount, address recipient, PermitInput calldata permit) external whenNotPaused returns (uint256 requestId) { // Use permit to approve weETH transfer - try weETH.permit( - msg.sender, - address(this), - permit.value, - permit.deadline, - permit.v, - permit.r, - permit.s - ) {} catch {} + try weETH.permit(msg.sender, address(this), permit.value, permit.deadline, permit.v, permit.r, permit.s) {} catch {} // Call the regular requestWithdraw function return requestWithdraw(weETHAmount, recipient); } - - //-------------------------------------------------------------------------------------- //---------------------------------- ADMIN FUNCTIONS -------------------------------- //-------------------------------------------------------------------------------------- @@ -215,7 +185,7 @@ contract WeETHWithdrawAdapter is /** * @notice Authorize contract upgrades */ - function _authorizeUpgrade(address /* newImplementation */) internal view override { + function _authorizeUpgrade(address /* newImplementation */ ) internal view override { roleRegistry.onlyProtocolUpgrader(msg.sender); } diff --git a/src/interfaces/IAuctionManager.sol b/src/interfaces/IAuctionManager.sol index 9be753e48..d0b761c26 100644 --- a/src/interfaces/IAuctionManager.sol +++ b/src/interfaces/IAuctionManager.sol @@ -17,10 +17,7 @@ interface IAuctionManager { function isBidActive(uint256 _bidId) external view returns (bool); - function createBid( - uint256 _bidSize, - uint256 _bidAmount - ) external payable returns (uint256[] memory); + function createBid(uint256 _bidSize, uint256 _bidAmount) external payable returns (uint256[] memory); function cancelBidBatch(uint256[] calldata _bidIds) external; @@ -32,15 +29,13 @@ interface IAuctionManager { function processAuctionFeeTransfer(uint256 _validatorId) external; - function setStakingManagerContractAddress( - address _stakingManagerContractAddress - ) external; + function setStakingManagerContractAddress(address _stakingManagerContractAddress) external; function setAccumulatedRevenueThreshold(uint128 _newThreshold) external; function updateAdmin(address _address, bool _isAdmin) external; function pauseContract() external; function unPauseContract() external; - + function transferAccumulatedRevenue() external; } diff --git a/src/interfaces/IBNFT.sol b/src/interfaces/IBNFT.sol index 496ce9085..d71d6ad86 100644 --- a/src/interfaces/IBNFT.sol +++ b/src/interfaces/IBNFT.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.13; import "@openzeppelin-upgradeable/contracts/token/ERC721/IERC721Upgradeable.sol"; interface IBNFT is IERC721Upgradeable { - function burnFromWithdrawal(uint256 _validatorId) external; function initialize() external; function initializeOnUpgrade(address _etherFiNodesManagerAddress) external; diff --git a/src/interfaces/ICumulativeMerkleRewardsDistributor.sol b/src/interfaces/ICumulativeMerkleRewardsDistributor.sol index 7d782bd1b..5546bc4d2 100644 --- a/src/interfaces/ICumulativeMerkleRewardsDistributor.sol +++ b/src/interfaces/ICumulativeMerkleRewardsDistributor.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.24; // Allows anyone to claim a token if they exist in a merkle root. interface ICumulativeMerkleRewardsDistributor { - event Claimed(address indexed token, address indexed account, uint256 amount); event PendingMerkleRootUpdated(address indexed token, bytes32 merkleRoot); event ClaimableMerkleRootUpdated(address indexed token, bytes32 oldMerkleRoot, bytes32 newMerkleRoot, uint256 rewardsCalculatedToBlock); @@ -29,11 +28,5 @@ interface ICumulativeMerkleRewardsDistributor { function pause() external; function unpause() external; // Claim the given amount of the token to the given address. Reverts if the inputs are invalid. - function claim( - address token, - address account, - uint256 cumulativeAmount, - bytes32 expectedMerkleRoot, - bytes32[] calldata merkleProof - ) external; -} \ No newline at end of file + function claim(address token, address account, uint256 cumulativeAmount, bytes32 expectedMerkleRoot, bytes32[] calldata merkleProof) external; +} diff --git a/src/interfaces/IDepositContract.sol b/src/interfaces/IDepositContract.sol index d26186649..a8599717e 100644 --- a/src/interfaces/IDepositContract.sol +++ b/src/interfaces/IDepositContract.sol @@ -8,13 +8,7 @@ pragma solidity ^0.8.13; /// https://github.com/ethereum/eth2.0-specs/blob/dev/solidity_deposit_contract/deposit_contract.sol interface IDepositContract { /// @notice A processed deposit event. - event DepositEvent( - bytes pubkey, - bytes withdrawal_credentials, - bytes amount, - bytes signature, - bytes index - ); + event DepositEvent(bytes pubkey, bytes withdrawal_credentials, bytes amount, bytes signature, bytes index); /// @notice Submit a Phase 0 DepositData object. /// @param pubkey A BLS12-381 public key. @@ -22,12 +16,7 @@ interface IDepositContract { /// @param signature A BLS12-381 signature. /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object. /// Used as a protection against malformed input. - function deposit( - bytes calldata pubkey, - bytes calldata withdrawal_credentials, - bytes calldata signature, - bytes32 deposit_data_root - ) external payable; + function deposit(bytes calldata pubkey, bytes calldata withdrawal_credentials, bytes calldata signature, bytes32 deposit_data_root) external payable; /// @notice Query the current deposit root hash. /// @return The deposit root hash. @@ -36,4 +25,4 @@ interface IDepositContract { /// @notice Query the current deposit count. /// @return The deposit count encoded as a little endian 64-bit number. function get_deposit_count() external view returns (bytes memory); -} \ No newline at end of file +} diff --git a/src/interfaces/IEtherFiNode.sol b/src/interfaces/IEtherFiNode.sol index 466bb1aac..fe4f454dc 100644 --- a/src/interfaces/IEtherFiNode.sol +++ b/src/interfaces/IEtherFiNode.sol @@ -7,7 +7,6 @@ import "../eigenlayer-interfaces/IDelegationManager.sol"; import "../eigenlayer-interfaces/IEigenPod.sol"; interface IEtherFiNode { - // eigenlayer function createEigenPod() external returns (address); function getEigenPod() external view returns (IEigenPod); @@ -22,14 +21,14 @@ interface IEtherFiNode { function requestExecutionLayerTriggeredWithdrawal(IEigenPod.WithdrawalRequest[] calldata requests) external payable; function requestConsolidation(IEigenPod.ConsolidationRequest[] calldata requests) external payable; - // call forwarding function forwardEigenPodCall(bytes memory data) external returns (bytes memory); function forwardExternalCall(address to, bytes memory data) external returns (bytes memory); struct LegacyNodeState { uint256[10] legacyPadding; - /* + } + /* ╭---------------------------------------------------+-----------------------------------+------+--------+-------+---------------------------------╮ | Name | Type | Slot | Offset | Bytes | Contract | +=================================================================================================================================================+ @@ -74,7 +73,6 @@ interface IEtherFiNode { | DEPRECATED_restakingObservedExitBlocks | mapping(uint256 => uint32) | 9 | 0 | 32 | src/EtherFiNode.sol:EtherFiNode | ╰---------------------------------------------------+-----------------------------------+------+--------+-------+---------------------------------╯ */ - } //--------------------------------------------------------------------------- //----------------------------- Events ----------------------------------- @@ -95,5 +93,4 @@ interface IEtherFiNode { error InvalidForwardedCall(); error InvalidCaller(); error NoCompleteableWithdrawals(); - } diff --git a/src/interfaces/IEtherFiNodesManager.sol b/src/interfaces/IEtherFiNodesManager.sol index 1ac85bf19..69ad94dab 100644 --- a/src/interfaces/IEtherFiNodesManager.sol +++ b/src/interfaces/IEtherFiNodesManager.sol @@ -1,17 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "../interfaces/IEtherFiNode.sol"; -import "../interfaces/IStakingManager.sol"; import "../eigenlayer-interfaces/IDelegationManager.sol"; import "../eigenlayer-interfaces/IEigenPod.sol"; import {BeaconChainProofs} from "../eigenlayer-libraries/BeaconChainProofs.sol"; +import "../interfaces/IEtherFiNode.sol"; +import "../interfaces/IStakingManager.sol"; interface IEtherFiNodesManager { - function addressToWithdrawalCredentials(address addr) external pure returns (bytes memory); function addressToCompoundingWithdrawalCredentials(address addr) external pure returns (bytes memory); - function etherfiNodeAddress(uint256 id) external view returns(address); + function etherfiNodeAddress(uint256 id) external view returns (address); function etherFiNodeFromPubkeyHash(bytes32 pubkeyHash) external view returns (IEtherFiNode); function linkPubkeyToNode(bytes calldata pubkey, address nodeAddress, uint256 legacyId) external; function calculateValidatorPubkeyHash(bytes memory pubkey) external pure returns (bytes32); @@ -41,7 +40,6 @@ interface IEtherFiNodesManager { function requestExecutionLayerTriggeredWithdrawal(IEigenPod.WithdrawalRequest[] calldata requests) external payable; function requestConsolidation(IEigenPod.ConsolidationRequest[] calldata requests) external payable; - // rate limiting constants function UNRESTAKING_LIMIT_ID() external view returns (bytes32); function EXIT_REQUEST_LIMIT_ID() external view returns (bytes32); @@ -63,7 +61,8 @@ interface IEtherFiNodesManager { // we are continuing to use this field in the short term before we fully transition to using pubkeyhash mapping(uint256 => address) DEPRECATED_etherfiNodeAddress; uint256[15] legacyPadding2; - /* + } + /* |-------------------------------------------+---------------------------------------------------------------+------+--------+-------+-------------------------------------------------| | numberOfValidators | uint64 | 301 | 0 | 8 | src/EtherFiNodesManager.sol:EtherFiNodesManager | |-------------------------------------------+---------------------------------------------------------------+------+--------+-------+-------------------------------------------------| @@ -114,7 +113,6 @@ interface IEtherFiNodesManager { | operatingAdmin | mapping(address => bool) | 320 | 0 | 32 | src/EtherFiNodesManager.sol:EtherFiNodesManager | |-------------------------------------------+---------------------------------------------------------------+------+--------+-------+-------------------------------------------------| */ - } //--------------------------------------------------------------------------- //----------------------------- Events ----------------------------------- diff --git a/src/interfaces/IEtherFiOracle.sol b/src/interfaces/IEtherFiOracle.sol index fd68b65f6..2ea41c086 100644 --- a/src/interfaces/IEtherFiOracle.sol +++ b/src/interfaces/IEtherFiOracle.sol @@ -56,4 +56,4 @@ interface IEtherFiOracle { function pauseContract() external; function unPauseContract() external; -} \ No newline at end of file +} diff --git a/src/interfaces/IEtherFiRateLimiter.sol b/src/interfaces/IEtherFiRateLimiter.sol index 9fc49e644..23f57fd44 100644 --- a/src/interfaces/IEtherFiRateLimiter.sol +++ b/src/interfaces/IEtherFiRateLimiter.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.27; interface IEtherFiRateLimiter { - // admin function updateConsumers(bytes32 id, address consumer, bool allowed) external; function createNewLimiter(bytes32 id, uint64 capacity, uint64 refillRate) external; @@ -24,7 +23,6 @@ interface IEtherFiRateLimiter { function isConsumerAllowed(bytes32 id, address consumer) external view returns (bool); function limitExists(bytes32 id) external view returns (bool); - //--------------------------------------------------------------------------- //----------------------------- Events ----------------------------------- //--------------------------------------------------------------------------- @@ -42,4 +40,4 @@ interface IEtherFiRateLimiter { error LimitAlreadyExists(); error LimitExceeded(); error UnknownLimit(); -} \ No newline at end of file +} diff --git a/src/interfaces/ILiquidityPool.sol b/src/interfaces/ILiquidityPool.sol index 2400d7fbd..260a217b6 100644 --- a/src/interfaces/ILiquidityPool.sol +++ b/src/interfaces/ILiquidityPool.sol @@ -5,14 +5,13 @@ import "./IStakingManager.sol"; import "./IeETH.sol"; interface ILiquidityPool { - struct PermitInput { uint256 value; uint256 deadline; uint8 v; bytes32 r; bytes32 s; - } + } enum SourceOfFunds { UNDEFINED, @@ -75,8 +74,8 @@ interface ILiquidityPool { function pauseContract() external; function burnEEthShares(uint256 shares) external; - function unPauseContract() external; + function unPauseContract() external; - function setStakingTargetWeights(uint32 _eEthWeight, uint32 _etherFanWeight) external; + function setStakingTargetWeights(uint32 _eEthWeight, uint32 _etherFanWeight) external; function setValidatorSizeWei(uint256 _size) external; } diff --git a/src/interfaces/ILiquifier.sol b/src/interfaces/ILiquifier.sol index 7fc22f97f..f2aeefef2 100644 --- a/src/interfaces/ILiquifier.sol +++ b/src/interfaces/ILiquifier.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "../eigenlayer-interfaces/IStrategyManager.sol"; -import "../eigenlayer-interfaces/IStrategy.sol"; import "../eigenlayer-interfaces/IPauserRegistry.sol"; +import "../eigenlayer-interfaces/IStrategy.sol"; +import "../eigenlayer-interfaces/IStrategyManager.sol"; // cbETH-ETH mainnet: 0x5FAE7E604FC3e24fd43A72867ceBaC94c65b404A // wBETH-ETH mainnet: 0xBfAb6FA95E0091ed66058ad493189D2cB29385E6 @@ -31,7 +31,7 @@ interface IcbETH is IERC20 { // mainnet: 0xa2E3356610840701BDf5611a53974510Ae27E2e1 interface IwBETH is IERC20 { - function deposit(address referral) payable external; + function deposit(address referral) external payable; function mint(address _to, uint256 _amount) external; function exchangeRate() external view returns (uint256 _exchangeRate); } @@ -55,7 +55,7 @@ interface IEigenLayerStrategyManager is IStrategyManager { function unpause(uint256 newPausedStatus) external; // For testing - function queueWithdrawal( uint256[] calldata strategyIndexes, IStrategy[] calldata strategies, uint256[] calldata shares, address withdrawer, bool undelegateIfPossible ) external returns(bytes32); + function queueWithdrawal(uint256[] calldata strategyIndexes, IStrategy[] calldata strategies, uint256[] calldata shares, address withdrawer, bool undelegateIfPossible) external returns (bytes32); } interface IEigenLayerStrategyTVLLimits is IStrategy { @@ -101,14 +101,13 @@ interface ILidoWithdrawalQueue { } interface ILiquifier { - struct PermitInput { uint256 value; uint256 deadline; uint8 v; bytes32 r; bytes32 s; - } + } struct TokenInfo { uint128 strategyShare; diff --git a/src/interfaces/IMembershipManager.sol b/src/interfaces/IMembershipManager.sol index 6d037d84e..0fa713572 100644 --- a/src/interfaces/IMembershipManager.sol +++ b/src/interfaces/IMembershipManager.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.13; interface IMembershipManager { - struct TokenDeposit { uint128 amounts; uint128 shares; @@ -14,8 +13,8 @@ interface IMembershipManager { uint40 baseTierPoints; uint32 prevPointsAccrualTimestamp; uint32 prevTopUpTimestamp; - uint8 tier; - uint8 version; + uint8 tier; + uint8 version; } // Used for V1 @@ -34,11 +33,11 @@ interface IMembershipManager { uint96 rewardsGlobalIndex; uint40 requiredTierPoints; uint24 weight; - uint96 __gap; + uint96 __gap; } // State-changing functions - function wrapEthForEap(uint256 _amount, uint256 _amountForPoint, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external payable returns (uint256); + function wrapEthForEap(uint256 _amount, uint256 _amountForPoint, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external payable returns (uint256); function wrapEth(uint256 _amount, uint256 _amountForPoint) external payable returns (uint256); function wrapEth(uint256 _amount, uint256 _amountForPoint, address _referral) external payable returns (uint256); diff --git a/src/interfaces/IMembershipManagerV0.sol b/src/interfaces/IMembershipManagerV0.sol index 325abe4b8..c427c2c4e 100644 --- a/src/interfaces/IMembershipManagerV0.sol +++ b/src/interfaces/IMembershipManagerV0.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.13; interface IMembershipManagerV0 { - struct TokenDeposit { uint128 amounts; uint128 shares; @@ -14,8 +13,8 @@ interface IMembershipManagerV0 { uint40 baseTierPoints; uint32 prevPointsAccrualTimestamp; uint32 prevTopUpTimestamp; - uint8 tier; - uint8 __gap; + uint8 tier; + uint8 __gap; } struct TierDeposit { @@ -27,13 +26,13 @@ interface IMembershipManagerV0 { uint96 rewardsGlobalIndex; uint40 requiredTierPoints; uint24 weight; - uint96 __gap; + uint96 __gap; } // State-changing functions function initialize(address _eEthAddress, address _liquidityPoolAddress, address _membershipNft, address _treasury, address _protocolRevenueManager) external; - function wrapEthForEap(uint256 _amount, uint256 _amountForPoint, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external payable returns (uint256); + function wrapEthForEap(uint256 _amount, uint256 _amountForPoint, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external payable returns (uint256); function wrapEth(uint256 _amount, uint256 _amountForPoint) external payable returns (uint256); function topUpDepositWithEth(uint256 _tokenId, uint128 _amount, uint128 _amountForPoints) external payable; @@ -69,7 +68,7 @@ interface IMembershipManagerV0 { function updateTier(uint8 _tier, uint40 _requiredTierPoints, uint24 _weight) external; function setPoints(uint256 _tokenId, uint40 _loyaltyPoints, uint40 _tierPoints) external; function setPointsBatch(uint256[] calldata _tokenIds, uint40[] calldata _loyaltyPoints, uint40[] calldata _tierPoints) external; - function recoverTierPointsForEap(uint256 _tokenId, uint32 _eapDepositBlockNumber) external; + function recoverTierPointsForEap(uint256 _tokenId, uint32 _eapDepositBlockNumber) external; function recoverTierPointsForEapBatch(uint256[] calldata _tokenIds, uint32[] calldata _eapDepositBlockNumbers) external; function setMinDepositWei(uint56 _value) external; function setMaxDepositTopUpPercent(uint8 _percent) external; diff --git a/src/interfaces/IMembershipNFT.sol b/src/interfaces/IMembershipNFT.sol index 13e9432f0..d4740875b 100644 --- a/src/interfaces/IMembershipNFT.sol +++ b/src/interfaces/IMembershipNFT.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.13; import "@openzeppelin-upgradeable/contracts/token/ERC1155/IERC1155Upgradeable.sol"; interface IMembershipNFT is IERC1155Upgradeable { - struct NftData { uint32 transferLockedUntil; // in terms of blocck number uint8[28] __gap; @@ -14,8 +13,8 @@ interface IMembershipNFT is IERC1155Upgradeable { function initializeOnUpgrade(address _liquidityPoolAddress) external; function computeTierPointsForEap(uint32 _eapDepositBlockNumber) external view returns (uint40); function setUpForEap(bytes32 _newMerkleRoot, uint64[] calldata _requiredEapPointsPerEapDeposit) external; - function processDepositFromEapUser(address _user, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external; - + function processDepositFromEapUser(address _user, uint32 _eapDepositBlockNumber, uint256 _snapshotEthAmount, uint256 _points, bytes32[] calldata _merkleProof) external; + function incrementLock(uint256 _tokenId, uint32 _blocks) external; function mint(address _to, uint256 _amount) external returns (uint256); function burn(address _from, uint256 _tokenId, uint256 _amount) external; @@ -28,7 +27,7 @@ interface IMembershipNFT is IERC1155Upgradeable { function claimableTier(uint256 _tokenId) external view returns (uint8); function accruedLoyaltyPointsOf(uint256 _tokenId) external view returns (uint40); function accruedTierPointsOf(uint256 _tokenId) external view returns (uint40); - function accruedStakingRewardsOf(uint256 _tokenId) external view returns (uint); + function accruedStakingRewardsOf(uint256 _tokenId) external view returns (uint256); function canTopUp(uint256 _tokenId, uint256 _totalAmount, uint128 _amount, uint128 _amountForPoints) external view returns (bool); function isWithdrawable(uint256 _tokenId, uint256 _withdrawalAmount) external view returns (bool); function allTimeHighDepositOf(uint256 _tokenId) external view returns (uint256); diff --git a/src/interfaces/INodeOperatorManager.sol b/src/interfaces/INodeOperatorManager.sol index b669e9bfc..d94161be6 100644 --- a/src/interfaces/INodeOperatorManager.sol +++ b/src/interfaces/INodeOperatorManager.sol @@ -10,38 +10,19 @@ interface INodeOperatorManager { bytes ipfsHash; } - function getUserTotalKeys( - address _user - ) external view returns (uint64 totalKeys); - - function getNumKeysRemaining( - address _user - ) external view returns (uint64 numKeysRemaining); - - function isWhitelisted( - address _user - ) external view returns (bool whitelisted); - - function registerNodeOperator( - bytes memory ipfsHash, - uint64 totalKeys - ) external; - - function initializeOnUpgrade( - address[] memory _operator, - bytes[] memory _ipfsHash, - uint64[] memory _totalKeys, - uint64[] memory _keysUsed - ) external; - - function batchUpdateOperatorsApprovedTags( - address[] memory _users, - LiquidityPool.SourceOfFunds[] memory _approvedTags, - bool[] memory _approvals - ) external; + function getUserTotalKeys(address _user) external view returns (uint64 totalKeys); + + function getNumKeysRemaining(address _user) external view returns (uint64 numKeysRemaining); + + function isWhitelisted(address _user) external view returns (bool whitelisted); + + function registerNodeOperator(bytes memory ipfsHash, uint64 totalKeys) external; + + function initializeOnUpgrade(address[] memory _operator, bytes[] memory _ipfsHash, uint64[] memory _totalKeys, uint64[] memory _keysUsed) external; + + function batchUpdateOperatorsApprovedTags(address[] memory _users, LiquidityPool.SourceOfFunds[] memory _approvedTags, bool[] memory _approvals) external; function fetchNextKeyIndex(address _user) external returns (uint64); function isEligibleToRunValidatorsForSourceOfFund(address _operator, LiquidityPool.SourceOfFunds _source) external view returns (bool approved); - } diff --git a/src/interfaces/IPausableEF.sol b/src/interfaces/IPausableEF.sol index 4baffa978..bfb5c64b4 100644 --- a/src/interfaces/IPausableEF.sol +++ b/src/interfaces/IPausableEF.sol @@ -4,4 +4,4 @@ pragma solidity ^0.8.21; interface IPausableEF { function pauseContract() external; function unPauseContract() external; -} \ No newline at end of file +} diff --git a/src/interfaces/IRateLimiter.sol b/src/interfaces/IRateLimiter.sol index 7f854be0b..be3acd6b1 100644 --- a/src/interfaces/IRateLimiter.sol +++ b/src/interfaces/IRateLimiter.sol @@ -4,4 +4,4 @@ pragma solidity ^0.8.20; // Used by {L1,L2}SyncPool interface IRateLimiter { function updateRateLimit(address sender, address tokenIn, uint256 amountIn, uint256 amountOut) external; -} \ No newline at end of file +} diff --git a/src/interfaces/IRateProvider.sol b/src/interfaces/IRateProvider.sol index 0f1ad000e..ac16581e2 100644 --- a/src/interfaces/IRateProvider.sol +++ b/src/interfaces/IRateProvider.sol @@ -16,4 +16,4 @@ pragma solidity ^0.8.0; interface IRateProvider { function getRate() external view returns (uint256); -} \ No newline at end of file +} diff --git a/src/interfaces/IRegulationsManager.sol b/src/interfaces/IRegulationsManager.sol index 3e9c3a5db..58ae6b17c 100644 --- a/src/interfaces/IRegulationsManager.sol +++ b/src/interfaces/IRegulationsManager.sol @@ -13,5 +13,4 @@ interface IRegulationsManager { function isEligible(uint32 _whitelistVersion, address _user) external view returns (bool); function whitelistVersion() external view returns (uint32); - } diff --git a/src/interfaces/IStakingManager.sol b/src/interfaces/IStakingManager.sol index 8989618b3..662a944ab 100644 --- a/src/interfaces/IStakingManager.sol +++ b/src/interfaces/IStakingManager.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.13; import "./ILiquidityPool.sol"; interface IStakingManager { - struct DepositData { bytes publicKey; bytes signature; @@ -31,7 +30,8 @@ interface IStakingManager { // prevent storage shift on upgrade struct LegacyStakingManagerState { uint256[14] legacyState; - /* + } + /* |------------------------+-------------------------------------------------------+------+--------+-------+---------------------------------------| | stakeAmount | uint128 | 301 | 16 | 16 | src/StakingManager.sol:StakingManager | |------------------------+-------------------------------------------------------+------+--------+-------+---------------------------------------| @@ -64,7 +64,6 @@ interface IStakingManager { | admins | mapping(address => bool) | 314 | 0 | 32 | src/StakingManager.sol:StakingManager | ╰------------------------+-------------------------------------------------------+------+--------+-------+---------------------------------------╯ */ - } //--------------------------------------------------------------------------- //----------------------------- Events ----------------------------------- @@ -92,5 +91,4 @@ interface IStakingManager { error InvalidValidatorSize(); error IncorrectRole(); error InvalidUpgrade(); - } diff --git a/src/interfaces/ITNFT.sol b/src/interfaces/ITNFT.sol index 8fd057fad..b85d142fa 100644 --- a/src/interfaces/ITNFT.sol +++ b/src/interfaces/ITNFT.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.13; import "@openzeppelin-upgradeable/contracts/token/ERC721/IERC721Upgradeable.sol"; interface ITNFT is IERC721Upgradeable { - function burnFromWithdrawal(uint256 _validatorId) external; function initialize() external; function initializeOnUpgrade(address _etherFiNodesManagerAddress) external; diff --git a/src/interfaces/ITVLOracle.sol b/src/interfaces/ITVLOracle.sol index a65cb80c9..010e483ba 100644 --- a/src/interfaces/ITVLOracle.sol +++ b/src/interfaces/ITVLOracle.sol @@ -2,9 +2,7 @@ pragma solidity ^0.8.13; interface ITVLOracle { - function setTvl(uint256 _newTvl) external; function getTvl() external view returns (uint256 _currentTvl); function setTVLAggregator(address _tvlAggregator) external; - -} \ No newline at end of file +} diff --git a/src/interfaces/IWETH.sol b/src/interfaces/IWETH.sol index c88ece160..81e1c177a 100644 --- a/src/interfaces/IWETH.sol +++ b/src/interfaces/IWETH.sol @@ -1,15 +1,15 @@ pragma solidity ^0.8.13; interface IWETH { - function balanceOf(address owner) external view returns (uint); - function allowance(address owner, address spender) external view returns (uint); - + function balanceOf(address owner) external view returns (uint256); + function allowance(address owner, address spender) external view returns (uint256); + function deposit() external payable; - function withdraw(uint wad) external; + function withdraw(uint256 wad) external; + + function totalSupply() external view returns (uint256); - function totalSupply() external view returns (uint); - - function approve(address guy, uint wad) external returns (bool); - function transfer(address dst, uint wad) external returns (bool); - function transferFrom(address src, address dst, uint wad) external returns (bool); + function approve(address guy, uint256 wad) external returns (bool); + function transfer(address dst, uint256 wad) external returns (bool); + function transferFrom(address src, address dst, uint256 wad) external returns (bool); } diff --git a/src/interfaces/IWeETH.sol b/src/interfaces/IWeETH.sol index 425a99ffc..90cb3816c 100644 --- a/src/interfaces/IWeETH.sol +++ b/src/interfaces/IWeETH.sol @@ -1,20 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; import "./ILiquidityPool.sol"; import "./IeETH.sol"; +import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; interface IWeETH is IERC20Upgradeable { - struct PermitInput { uint256 value; uint256 deadline; uint8 v; bytes32 r; bytes32 s; - } - + } + // STATE VARIABLES function eETH() external view returns (IeETH); function liquidityPool() external view returns (ILiquidityPool); @@ -26,15 +25,7 @@ interface IWeETH is IERC20Upgradeable { function wrap(uint256 _eETHAmount) external returns (uint256); function wrapWithPermit(uint256 _eETHAmount, ILiquidityPool.PermitInput calldata _permit) external returns (uint256); function unwrap(uint256 _weETHAmount) external returns (uint256); - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; + function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; function setWhitelistedSpender(address[] calldata _spenders, bool _isWhitelisted) external; function setBlacklistedRecipient(address[] calldata _recipients, bool _isBlacklisted) external; @@ -44,5 +35,4 @@ interface IWeETH is IERC20Upgradeable { function getEETHByWeETH(uint256 _weETHAmount) external view returns (uint256); function getRate() external view returns (uint256); function getImplementation() external view returns (address); - } diff --git a/src/interfaces/IWeETHWithdrawAdapter.sol b/src/interfaces/IWeETHWithdrawAdapter.sol index 612800d3b..7c3c356c1 100644 --- a/src/interfaces/IWeETHWithdrawAdapter.sol +++ b/src/interfaces/IWeETHWithdrawAdapter.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.13; import "./ILiquidityPool.sol"; interface IWeETHWithdrawAdapter { - struct PermitInput { uint256 value; uint256 deadline; @@ -28,13 +27,7 @@ interface IWeETHWithdrawAdapter { * @param permit Permit data for weETH approval * @return requestId The ID of the created withdrawal request */ - function requestWithdrawWithPermit( - uint256 weETHAmount, - address recipient, - PermitInput calldata permit - ) external returns (uint256 requestId); - - + function requestWithdrawWithPermit(uint256 weETHAmount, address recipient, PermitInput calldata permit) external returns (uint256 requestId); /** * @notice Get the equivalent eETH amount for a given weETH amount diff --git a/src/interfaces/IWithdrawRequestNFT.sol b/src/interfaces/IWithdrawRequestNFT.sol index 9911a22b3..b8349605f 100644 --- a/src/interfaces/IWithdrawRequestNFT.sol +++ b/src/interfaces/IWithdrawRequestNFT.sol @@ -3,10 +3,10 @@ pragma solidity ^0.8.13; interface IWithdrawRequestNFT { struct WithdrawRequest { - uint96 amountOfEEth; - uint96 shareOfEEth; - bool isValid; - uint32 feeGwei; + uint96 amountOfEEth; + uint96 shareOfEEth; + bool isValid; + uint32 feeGwei; } function initialize(address _liquidityPoolAddress, address _eEthAddress, address _membershipManager) external; diff --git a/src/interfaces/IeETH.sol b/src/interfaces/IeETH.sol index f8ee974b9..205af2648 100644 --- a/src/interfaces/IeETH.sol +++ b/src/interfaces/IeETH.sol @@ -2,15 +2,14 @@ pragma solidity ^0.8.13; interface IeETH { - struct PermitInput { uint256 value; uint256 deadline; uint8 v; bytes32 r; bytes32 s; - } - + } + function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); diff --git a/src/interfaces/IwstETH.sol b/src/interfaces/IwstETH.sol index c28750681..a1d3c7c1b 100644 --- a/src/interfaces/IwstETH.sol +++ b/src/interfaces/IwstETH.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol"; import "@openzeppelin-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; +import "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol"; interface IwstETH is IERC20PermitUpgradeable, IERC20Upgradeable { - function wrap(uint256 _stETHAmount) external returns (uint256); function unwrap(uint256 _wstETHAmount) external returns (uint256); - } diff --git a/src/libraries/DepositDataRootGenerator.sol b/src/libraries/DepositDataRootGenerator.sol index 9b21191e8..dba4bdfcd 100644 --- a/src/libraries/DepositDataRootGenerator.sol +++ b/src/libraries/DepositDataRootGenerator.sol @@ -2,39 +2,18 @@ pragma solidity ^0.8.13; library depositDataRootGenerator { - uint constant GWEI = 1e9; + uint256 constant GWEI = 1e9; - function generateDepositDataRoot( - bytes calldata pubkey, - bytes calldata signature, - bytes calldata withdrawal_credentials, - uint256 _amountIn - ) public pure returns (bytes32) { - - uint deposit_amount = _amountIn / GWEI; + function generateDepositDataRoot(bytes calldata pubkey, bytes calldata signature, bytes calldata withdrawal_credentials, uint256 _amountIn) public pure returns (bytes32) { + uint256 deposit_amount = _amountIn / GWEI; bytes memory amount = to_little_endian_64(uint64(deposit_amount)); bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0))); - bytes32 signature_root = sha256( - abi.encodePacked( - sha256(abi.encodePacked(signature[:64])), - sha256(abi.encodePacked(signature[64:], bytes32(0))) - ) - ); - return - sha256( - abi.encodePacked( - sha256( - abi.encodePacked(pubkey_root, withdrawal_credentials) - ), - sha256(abi.encodePacked(amount, bytes24(0), signature_root)) - ) - ); + bytes32 signature_root = sha256(abi.encodePacked(sha256(abi.encodePacked(signature[:64])), sha256(abi.encodePacked(signature[64:], bytes32(0))))); + return sha256(abi.encodePacked(sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)), sha256(abi.encodePacked(amount, bytes24(0), signature_root)))); } - function to_little_endian_64( - uint64 value - ) internal pure returns (bytes memory ret) { + function to_little_endian_64(uint64 value) internal pure returns (bytes memory ret) { ret = new bytes(8); bytes8 bytesValue = bytes8(value); // Byteswapping during copying to bytes. diff --git a/src/libraries/GlobalIndexLibrary.sol b/src/libraries/GlobalIndexLibrary.sol index 4c90e24c7..88a39ccb8 100644 --- a/src/libraries/GlobalIndexLibrary.sol +++ b/src/libraries/GlobalIndexLibrary.sol @@ -1,32 +1,31 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "../MembershipManager.sol"; import "../LiquidityPool.sol"; +import "../MembershipManager.sol"; import "forge-std/console.sol"; library globalIndexLibrary { - error IntegerOverflow(); /** - * @dev This function calculates the global index and adjusted shares for each tier used for reward distribution. - * - * The function performs the following steps: - * 1. Iterates over each tier, computing rebased amounts, tier rewards, weighted tier rewards. - * 2. Sums all the tier rewards and the weighted tier rewards. - * 3. If there are any weighted tier rewards, it iterates over each tier to perform the following actions: - * a. Computes the amounts eligible for rewards. - * b. If there are amounts eligible for rewards, - * it calculates rescaled tier rewards and updates the global index and adjusted shares for the tier. - * - * The rescaling of tier rewards is done based on the weight of each tier. - * - * @notice This function essentially pools all the staking rewards across tiers and redistributes them proportional to the tier weights - * @param _membershipManager the address of the membership manager - * @param _liquidityPool the address of the liquidity pool - * @return globalIndex A uint96 array containing the updated global index for each tier. - */ + * @dev This function calculates the global index and adjusted shares for each tier used for reward distribution. + * + * The function performs the following steps: + * 1. Iterates over each tier, computing rebased amounts, tier rewards, weighted tier rewards. + * 2. Sums all the tier rewards and the weighted tier rewards. + * 3. If there are any weighted tier rewards, it iterates over each tier to perform the following actions: + * a. Computes the amounts eligible for rewards. + * b. If there are amounts eligible for rewards, + * it calculates rescaled tier rewards and updates the global index and adjusted shares for the tier. + * + * The rescaling of tier rewards is done based on the weight of each tier. + * + * @notice This function essentially pools all the staking rewards across tiers and redistributes them proportional to the tier weights + * @param _membershipManager the address of the membership manager + * @param _liquidityPool the address of the liquidity pool + * @return globalIndex A uint96 array containing the updated global index for each tier. + */ function calculateGlobalIndex(address _membershipManager, address _liquidityPool, uint256 _ethRewardsPerEEthShareBeforeRebase, uint256 _ethRewardsPerEEthShareAfterRebase) public view returns (uint96[] memory) { MembershipManager membershipManager = MembershipManager(payable(_membershipManager)); LiquidityPool liquidityPool = LiquidityPool(payable(_liquidityPool)); @@ -46,7 +45,7 @@ library globalIndexLibrary { if (shares > 0) { uint256 delta = 1 ether * rescaledTierRewards[i] / shares; if (uint256(rewardsGlobalIndex) + uint256(delta) > type(uint96).max) revert IntegerOverflow(); - + if (isLoss) { globalIndex[i] -= uint96(delta); } else { @@ -76,7 +75,7 @@ library globalIndexLibrary { return (tierRewards, tierWeights); } - + // Compute `rescaledTierRewards` for each tier from `tierRewards` and `weight` function calculateRescaledTierRewards(uint256[] memory tierRewards, uint24[] memory tierWeights) public pure returns (uint256[] memory) { uint256[] memory weightedTierRewards = new uint256[](tierRewards.length); @@ -131,12 +130,12 @@ library globalIndexLibrary { uint128[] memory vaultTotalPooledEEthShares = new uint128[](membershipManager.numberOfTiers()); for (uint256 i = 0; i < vaultTotalPooledEEthShares.length; i++) { - (uint128 totalPooledEEthShares, ) = membershipManager.tierVaults(i); + (uint128 totalPooledEEthShares,) = membershipManager.tierVaults(i); uint256 prevEthAmount = _ethRewardsPerEEthShareBeforeRebase * totalPooledEEthShares / 1 ether; uint256 newEthAmount = prevEthAmount; if (isLoss) { newEthAmount -= rescaledTierRewards[i]; - } else { + } else { newEthAmount += rescaledTierRewards[i]; } vaultTotalPooledEEthShares[i] = uint128(liquidityPool.sharesForAmount(newEthAmount)); diff --git a/test/AddressProvider.t.sol b/test/AddressProvider.t.sol index 2feb9fff1..6df317862 100644 --- a/test/AddressProvider.t.sol +++ b/test/AddressProvider.t.sol @@ -4,13 +4,12 @@ pragma solidity ^0.8.13; import "./TestSetup.sol"; contract AuctionManagerV2Test is AuctionManager { - function isUpgraded() public pure returns(bool){ + function isUpgraded() public pure returns (bool) { return true; } } contract AddressProviderTest is TestSetup { - AuctionManagerV2Test public auctionManagerV2Instance; function setUp() public { @@ -25,23 +24,14 @@ contract AddressProviderTest is TestSetup { function test_AddNewContract() public { vm.expectRevert("Only owner function"); vm.prank(alice); - addressProviderInstance.addContract( - address(auctionManagerProxy), - "AuctionManager" - ); + addressProviderInstance.addContract(address(auctionManagerProxy), "AuctionManager"); vm.startPrank(owner); - vm.warp(20000); - addressProviderInstance.addContract( - address(auctionManagerProxy), - "AuctionManager" - ); - - ( - address contractAddress, - string memory name - ) = addressProviderInstance.contracts("AuctionManager"); - + vm.warp(20_000); + addressProviderInstance.addContract(address(auctionManagerProxy), "AuctionManager"); + + (address contractAddress, string memory name) = addressProviderInstance.contracts("AuctionManager"); + assertEq(contractAddress, address(auctionManagerProxy)); assertEq(name, "AuctionManager"); assertEq(addressProviderInstance.numberOfContracts(), 1); @@ -49,51 +39,32 @@ contract AddressProviderTest is TestSetup { function test_RemoveContract() public { vm.startPrank(owner); - vm.warp(20000); - addressProviderInstance.addContract( - address(auctionManagerProxy), - "AuctionManager" - ); - - addressProviderInstance.addContract( - address(liquidityPoolProxy), - "LiquidityPool" - ); + vm.warp(20_000); + addressProviderInstance.addContract(address(auctionManagerProxy), "AuctionManager"); + + addressProviderInstance.addContract(address(liquidityPoolProxy), "LiquidityPool"); vm.stopPrank(); vm.expectRevert("Only owner function"); vm.prank(alice); - addressProviderInstance.removeContract( - "AuctionManager" - ); + addressProviderInstance.removeContract("AuctionManager"); vm.startPrank(owner); vm.expectRevert("Contract does not exist"); - addressProviderInstance.removeContract( - "AuctionManage" - ); - - ( - address contractAddress, - string memory name - ) = addressProviderInstance.contracts("AuctionManager"); - + addressProviderInstance.removeContract("AuctionManage"); + + (address contractAddress, string memory name) = addressProviderInstance.contracts("AuctionManager"); + assertEq(contractAddress, address(auctionManagerProxy)); assertEq(name, "AuctionManager"); assertEq(addressProviderInstance.numberOfContracts(), 2); - addressProviderInstance.removeContract( - "AuctionManager" - ); + addressProviderInstance.removeContract("AuctionManager"); - ( - contractAddress, - name - ) = addressProviderInstance.contracts("AuctionManager"); + (contractAddress, name) = addressProviderInstance.contracts("AuctionManager"); assertEq(contractAddress, address(0)); assertEq(addressProviderInstance.numberOfContracts(), 1); - } function test_SetOwner() public { @@ -113,18 +84,9 @@ contract AddressProviderTest is TestSetup { function test_GetImplementationAddress() public { vm.startPrank(owner); - addressProviderInstance.addContract( - address(auctionManagerProxy), - "AuctionManager" - ); - addressProviderInstance.addContract( - address(liquidityPoolProxy), - "LiquidityPool" - ); - addressProviderInstance.addContract( - address(regulationsManagerProxy), - "RegulationsManager" - ); + addressProviderInstance.addContract(address(auctionManagerProxy), "AuctionManager"); + addressProviderInstance.addContract(address(liquidityPoolProxy), "LiquidityPool"); + addressProviderInstance.addContract(address(regulationsManagerProxy), "RegulationsManager"); assertEq(addressProviderInstance.getImplementationAddress("LiquidityPool"), address(liquidityPoolImplementation)); assertEq(addressProviderInstance.getImplementationAddress("RegulationsManager"), address(regulationsManagerImplementation)); @@ -134,6 +96,5 @@ contract AddressProviderTest is TestSetup { auctionInstance.upgradeTo(address(auctionManagerV2Implementation)); assertEq(addressProviderInstance.getImplementationAddress("AuctionManager"), address(auctionManagerV2Implementation)); - } } diff --git a/test/AuctionManager.t.sol b/test/AuctionManager.t.sol index 34a8ff350..3707c594d 100644 --- a/test/AuctionManager.t.sol +++ b/test/AuctionManager.t.sol @@ -4,16 +4,11 @@ pragma solidity ^0.8.13; import "./TestSetup.sol"; contract AuctionManagerTest is TestSetup { - event BidCreated( - address indexed bidder, - uint256 amountPerBid, - uint256[] bidId, - uint64[] ipfsIndexArray - ); + event BidCreated(address indexed bidder, uint256 amountPerBid, uint256[] bidId, uint64[] ipfsIndexArray); event BidCancelled(uint256 indexed bidId); event BidReEnteredAuction(uint256 indexed bidId); event Received(address indexed sender, uint256 value); - + function setUp() public { setUpTests(); } @@ -23,14 +18,10 @@ contract AuctionManagerTest is TestSetup { vm.prank(owner); auctionImplementation.initialize(address(nodeOperatorManagerInstance)); } - function test_AuctionManagerContractInstantiatedCorrectly() public { assertEq(auctionInstance.numberOfBids(), 1); - assertEq( - auctionInstance.stakingManagerContractAddress(), - address(stakingManagerInstance) - ); + assertEq(auctionInstance.stakingManagerContractAddress(), address(stakingManagerInstance)); assertEq(auctionInstance.whitelistBidAmount(), 0.001 ether); assertEq(auctionInstance.minBidAmount(), 0.01 ether); assertEq(auctionInstance.whitelistBidAmount(), 0.001 ether); @@ -181,40 +172,23 @@ contract AuctionManagerTest is TestSetup { function test_createBidWorks() public { vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 5); vm.prank(bob); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 5); vm.prank(henry); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 5); assertFalse(nodeOperatorManagerInstance.isWhitelisted(jess)); assertTrue(nodeOperatorManagerInstance.isWhitelisted(alice)); hoax(alice); - uint256[] memory bid1Id = auctionInstance.createBid{value: 0.001 ether}( - 1, - 0.001 ether - ); + uint256[] memory bid1Id = auctionInstance.createBid{value: 0.001 ether}(1, 0.001 ether); assertEq(auctionInstance.numberOfActiveBids(), 1); - ( - uint256 amount, - uint64 ipfsIndex, - address bidderAddress, - bool isActive - ) = auctionInstance.bids(bid1Id[0]); + (uint256 amount, uint64 ipfsIndex, address bidderAddress, bool isActive) = auctionInstance.bids(bid1Id[0]); assertEq(amount, 0.001 ether); assertEq(ipfsIndex, 0); @@ -247,13 +221,9 @@ contract AuctionManagerTest is TestSetup { // Bob can still bid below min bid amount because he was whitelisted hoax(bob); - uint256[] memory bobBidIds = auctionInstance.createBid{ - value: 0.001 ether - }(1, 0.001 ether); + uint256[] memory bobBidIds = auctionInstance.createBid{value: 0.001 ether}(1, 0.001 ether); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - bobBidIds[0] - ); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(bobBidIds[0]); assertEq(amount, 0.001 ether); assertEq(ipfsIndex, 0); assertEq(bidderAddress, bob); @@ -264,18 +234,11 @@ contract AuctionManagerTest is TestSetup { // jess cannot bid below the min bid amount because he was not whitelisted vm.expectRevert("Incorrect bid value"); hoax(jess); - uint256[] memory henryBidIds = auctionInstance.createBid{ - value: 0.001 ether - }(1, 0.001 ether); + uint256[] memory henryBidIds = auctionInstance.createBid{value: 0.001 ether}(1, 0.001 ether); hoax(henry); - henryBidIds = auctionInstance.createBid{value: 0.01 ether}( - 1, - 0.01 ether - ); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - henryBidIds[0] - ); + henryBidIds = auctionInstance.createBid{value: 0.01 ether}(1, 0.01 ether); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(henryBidIds[0]); assertEq(amount, 0.01 ether); assertEq(ipfsIndex, 0); assertEq(bidderAddress, henry); @@ -290,14 +253,9 @@ contract AuctionManagerTest is TestSetup { auctionInstance.createBid{value: 0.01 ether}(1, 0.01 ether); hoax(bob); - bobBidIds = auctionInstance.createBid{value: 0.001 ether}( - 1, - 0.001 ether - ); + bobBidIds = auctionInstance.createBid{value: 0.001 ether}(1, 0.001 ether); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - bobBidIds[0] - ); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(bobBidIds[0]); assertEq(amount, 0.001 ether); assertEq(ipfsIndex, 1); assertEq(bidderAddress, bob); @@ -306,16 +264,10 @@ contract AuctionManagerTest is TestSetup { function test_CreateBidMinMaxAmounts() public { vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 5); vm.prank(henry); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 5); vm.expectRevert("Incorrect bid value"); hoax(alice); @@ -347,16 +299,10 @@ contract AuctionManagerTest is TestSetup { function test_createBidFailsIfBidSizeIsLargerThanKeysRemaining() public { vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 3 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 3); hoax(alice); - uint256[] memory bidIds = auctionInstance.createBid{value: 0.2 ether}( - 2, - 0.1 ether - ); + uint256[] memory bidIds = auctionInstance.createBid{value: 0.2 ether}(2, 0.1 ether); (uint256 amount, uint64 ipfsIndex, address bidderAddress, bool isActive) = auctionInstance.bids(bidIds[0]); assertEq(amount, 0.1 ether); @@ -374,16 +320,10 @@ contract AuctionManagerTest is TestSetup { function test_createBidFailsIfIPFSIndexMoreThanTotalKeys() public { vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 1 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 1); hoax(alice); - auctionInstance.createBid{value: 0.1 ether}( - 1, - 0.1 ether - ); + auctionInstance.createBid{value: 0.1 ether}(1, 0.1 ether); vm.expectRevert("Insufficient public keys"); hoax(alice); @@ -396,60 +336,41 @@ contract AuctionManagerTest is TestSetup { function test_createBidBatch() public { startHoax(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 10 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 10); - uint256[] memory bidIds = auctionInstance.createBid{value: 0.5 ether}( - 5, - 0.1 ether - ); + uint256[] memory bidIds = auctionInstance.createBid{value: 0.5 ether}(5, 0.1 ether); vm.stopPrank(); - ( - uint256 amount, - uint64 ipfsIndex, - address bidderAddress, - bool isActive - ) = auctionInstance.bids(bidIds[0]); + (uint256 amount, uint64 ipfsIndex, address bidderAddress, bool isActive) = auctionInstance.bids(bidIds[0]); assertEq(amount, 0.1 ether); assertEq(ipfsIndex, 0); assertEq(bidderAddress, alice); assertTrue(isActive); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - bidIds[1] - ); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(bidIds[1]); assertEq(amount, 0.1 ether); assertEq(ipfsIndex, 1); assertEq(bidderAddress, alice); assertTrue(isActive); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - bidIds[2] - ); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(bidIds[2]); assertEq(amount, 0.1 ether); assertEq(ipfsIndex, 2); assertEq(bidderAddress, alice); assertTrue(isActive); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - bidIds[3] - ); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(bidIds[3]); assertEq(amount, 0.1 ether); assertEq(ipfsIndex, 3); assertEq(bidderAddress, alice); assertTrue(isActive); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - bidIds[4] - ); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(bidIds[4]); assertEq(amount, 0.1 ether); assertEq(ipfsIndex, 4); @@ -459,32 +380,22 @@ contract AuctionManagerTest is TestSetup { assertEq(bidIds.length, 5); startHoax(bob); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 10 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 10); - uint256[] memory bobBidIds = auctionInstance.createBid{value: 1 ether}( - 10, - 0.1 ether - ); + uint256[] memory bobBidIds = auctionInstance.createBid{value: 1 ether}(10, 0.1 ether); vm.stopPrank(); assertEq(bobBidIds.length, 10); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - bobBidIds[0] - ); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(bobBidIds[0]); assertEq(amount, 0.1 ether); assertEq(ipfsIndex, 0); assertEq(bidderAddress, bob); assertTrue(isActive); - (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids( - bobBidIds[9] - ); + (amount, ipfsIndex, bidderAddress, isActive) = auctionInstance.bids(bobBidIds[9]); assertEq(amount, 0.1 ether); assertEq(ipfsIndex, 9); @@ -494,25 +405,16 @@ contract AuctionManagerTest is TestSetup { function test_createBidBatchFailsWithIncorrectValue() public { hoax(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 10 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 10); vm.expectRevert("Incorrect bid value"); hoax(alice); - auctionInstance.createBid{value: 0.4 ether}( - 5, - 0.1 ether - ); + auctionInstance.createBid{value: 0.4 ether}(5, 0.1 ether); } function test_CreateBidPauseable() public { vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 5); assertFalse(auctionInstance.paused()); vm.prank(alice); @@ -536,16 +438,10 @@ contract AuctionManagerTest is TestSetup { function test_CancelBidFailsWhenBidAlreadyInactive() public { vm.prank(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 5); hoax(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); - uint256[] memory bid1Id = auctionInstance.createBid{value: 0.1 ether}( - 1, - 0.1 ether - ); + uint256[] memory bid1Id = auctionInstance.createBid{value: 0.1 ether}(1, 0.1 ether); hoax(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); auctionInstance.cancelBidBatch(bid1Id); @@ -557,10 +453,7 @@ contract AuctionManagerTest is TestSetup { function test_CancelBidFailsWhenNotBidOwnerCalling() public { vm.prank(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 5); hoax(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); auctionInstance.createBid{value: 0.1 ether}(1, 0.1 ether); @@ -578,91 +471,54 @@ contract AuctionManagerTest is TestSetup { function test_CancelBidWorksIfBidIsNotCurrentHighest() public { vm.prank(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 5); vm.prank(0x9154a74AAfF2F586FB0a884AeAb7A64521c64bCf); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 5); vm.prank(0xCDca97f61d8EE53878cf602FF6BC2f260f10240B); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 5); hoax(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); - auctionInstance.createBid{value: 0.1 ether}( - 1, - 0.1 ether - ); + auctionInstance.createBid{value: 0.1 ether}(1, 0.1 ether); assertEq(auctionInstance.numberOfActiveBids(), 1); hoax(0x9154a74AAfF2F586FB0a884AeAb7A64521c64bCf); - auctionInstance.createBid{value: 0.3 ether}( - 1, - 0.3 ether - ); + auctionInstance.createBid{value: 0.3 ether}(1, 0.3 ether); assertEq(auctionInstance.numberOfActiveBids(), 2); startHoax(0xCDca97f61d8EE53878cf602FF6BC2f260f10240B); - uint256[] memory bid3Id = auctionInstance.createBid{value: 0.2 ether}( - 1, - 0.2 ether - ); + uint256[] memory bid3Id = auctionInstance.createBid{value: 0.2 ether}(1, 0.2 ether); assertEq(address(auctionInstance).balance, 0.6 ether); assertEq(auctionInstance.numberOfActiveBids(), 3); - uint256 balanceBeforeCancellation = 0xCDca97f61d8EE53878cf602FF6BC2f260f10240B - .balance; + uint256 balanceBeforeCancellation = 0xCDca97f61d8EE53878cf602FF6BC2f260f10240B.balance; auctionInstance.cancelBid(bid3Id[0]); assertEq(auctionInstance.numberOfActiveBids(), 2); - (, , , bool isActive) = auctionInstance.bids(bid3Id[0]); + (,,, bool isActive) = auctionInstance.bids(bid3Id[0]); assertEq(isActive, false); assertEq(address(auctionInstance).balance, 0.4 ether); - assertEq( - 0xCDca97f61d8EE53878cf602FF6BC2f260f10240B.balance, - balanceBeforeCancellation += 0.2 ether - ); + assertEq(0xCDca97f61d8EE53878cf602FF6BC2f260f10240B.balance, balanceBeforeCancellation += 0.2 ether); } function test_PausableCancelBid() public { vm.prank(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 5); vm.prank(0x9154a74AAfF2F586FB0a884AeAb7A64521c64bCf); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 5); vm.prank(0xCDca97f61d8EE53878cf602FF6BC2f260f10240B); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 5); hoax(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); - auctionInstance.createBid{value: 0.1 ether}( - 1, - 0.1 ether - ); + auctionInstance.createBid{value: 0.1 ether}(1, 0.1 ether); assertEq(auctionInstance.numberOfActiveBids(), 1); hoax(0x9154a74AAfF2F586FB0a884AeAb7A64521c64bCf); - uint256[] memory bid2Id = auctionInstance.createBid{value: 0.3 ether}( - 1, - 0.3 ether - ); + uint256[] memory bid2Id = auctionInstance.createBid{value: 0.3 ether}(1, 0.3 ether); assertEq(auctionInstance.numberOfActiveBids(), 2); vm.prank(alice); @@ -782,12 +638,8 @@ contract AuctionManagerTest is TestSetup { } function test_EventBidPlaced() public { - vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 5); uint256[] memory bidIdArray = new uint256[](1); uint64[] memory ipfsIndexArray = new uint64[](1); @@ -822,19 +674,15 @@ contract AuctionManagerTest is TestSetup { */ function test_EventBidCancelled() public { - vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFSHash, - 5 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFSHash, 5); startHoax(alice); uint256[] memory bidIds = auctionInstance.createBid{value: 0.2 ether}(1, 0.2 ether); vm.expectEmit(true, false, false, true); emit BidCancelled(bidIds[0]); - auctionInstance.cancelBid(bidIds[0]); + auctionInstance.cancelBid(bidIds[0]); } function test_CanOnlySetAddressesOnce() public { @@ -955,7 +803,7 @@ contract AuctionManagerTest is TestSetup { assertEq(address(membershipManagerInstance).balance, 1.2 ether); } */ - + /* function test_transferAccumulatedRevenue() public { vm.startPrank(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); diff --git a/test/BNFT.t.sol b/test/BNFT.t.sol index 80b51fa83..a2cc55449 100644 --- a/test/BNFT.t.sol +++ b/test/BNFT.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.13; import "./TestSetup.sol"; contract BNFTTest is TestSetup { - function setUp() public { + function setUp() public { setUpTests(); } diff --git a/test/BucketRaterLimiter.t.sol b/test/BucketRaterLimiter.t.sol index 3876abf95..630e2f962 100644 --- a/test/BucketRaterLimiter.t.sol +++ b/test/BucketRaterLimiter.t.sol @@ -11,7 +11,7 @@ contract BucketRateLimiterTest is Test { BucketRateLimiter limiter; function setUp() public { - address owner = address(10000); + address owner = address(10_000); vm.startPrank(owner); BucketRateLimiter impl = new BucketRateLimiter(); UUPSProxy proxy = new UUPSProxy(address(impl), ""); @@ -90,7 +90,7 @@ contract BucketRateLimiterTest is Test { vm.stopPrank(); } - + function test_access_control() public { vm.expectRevert("Ownable: caller is not the owner"); limiter.updateAdmin(address(0), true); @@ -107,7 +107,7 @@ contract BucketRateLimiterTest is Test { vm.expectRevert("Ownable: caller is not the owner"); limiter.updateConsumer(address(0)); } - + function test_pauser() public { address alice = address(1); address bob = address(2); @@ -145,5 +145,4 @@ contract BucketRateLimiterTest is Test { vm.prank(bob); limiter.unPauseContract(); } - -} \ No newline at end of file +} diff --git a/test/ContractCodeChecker.t.sol b/test/ContractCodeChecker.t.sol index 4ec9611dc..6245ba7bb 100644 --- a/test/ContractCodeChecker.t.sol +++ b/test/ContractCodeChecker.t.sol @@ -1,17 +1,16 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import "./TestSetup.sol"; import "../src/EtherFiNode.sol"; import "../src/EtherFiNodesManager.sol"; import "../src/EtherFiRestaker.sol"; +import "./TestSetup.sol"; /** * @title TestByteCodeMatch * @dev Test contract to verify bytecode matches between deployed contracts and their implementations */ contract ContractCodeCheckerTest is TestSetup { - function setUp() public { initializeRealisticFork(MAINNET_FORK); } @@ -37,11 +36,10 @@ contract ContractCodeCheckerTest is TestSetup { // This test can be used for future deployments // It follows the same pattern as the test_deployment_bytecode function // but with different contract addresses - + // Example (replace with actual addresses when needed): // address newNodesManagerImplAddress = address(0x...); // EtherFiNodesManager newNodesManagerImplementation = new EtherFiNodesManager(); // verifyContractByteCodeMatch(newNodesManagerImplAddress, address(newNodesManagerImplementation)); } } - diff --git a/test/CumulativeMerkleRewardsDistributor.t.sol b/test/CumulativeMerkleRewardsDistributor.t.sol index b05ae3959..fc3c26ebd 100644 --- a/test/CumulativeMerkleRewardsDistributor.t.sol +++ b/test/CumulativeMerkleRewardsDistributor.t.sol @@ -1,7 +1,7 @@ import "./TestSetup.sol"; import "forge-std/console2.sol"; -contract CumulativeMerkleRewardsDistributorTest is TestSetup { +contract CumulativeMerkleRewardsDistributorTest is TestSetup { address[] public accounts = new address[](4); uint256[] public amounts = new uint256[](4); bytes32[] public leaves = new bytes32[](4); @@ -10,18 +10,15 @@ contract CumulativeMerkleRewardsDistributorTest is TestSetup { bytes32 public merkleRoot; bytes32[][] public proofs = new bytes32[][](4); - function hashPair(bytes32 a, bytes32 b) internal pure returns (bytes32) { - return a < b - ? keccak256(abi.encodePacked(a, b)) - : keccak256(abi.encodePacked(b, a)); + return a < b ? keccak256(abi.encodePacked(a, b)) : keccak256(abi.encodePacked(b, a)); } function generateMerkleTree(uint256 multipler) internal { // Create leaves for each account/amount pair - for(uint256 i = 0; i < 4; i++) { - accounts[i] = address(uint160(i+1)); - amounts[i] = (i+1) * multipler * 1 ether; + for (uint256 i = 0; i < 4; i++) { + accounts[i] = address(uint160(i + 1)); + amounts[i] = (i + 1) * multipler * 1 ether; leaves[i] = keccak256(abi.encodePacked(accounts[i], amounts[i])); proofs[i] = new bytes32[](2); vm.prank(admin); @@ -34,151 +31,152 @@ contract CumulativeMerkleRewardsDistributorTest is TestSetup { proofs[0][0] = leaves[1]; proofs[0][1] = node2; - + proofs[1][0] = leaves[0]; - proofs[1][1] = node2; - - proofs[2][0] = leaves[3]; - proofs[2][1] = node1; + proofs[1][1] = node2; + + proofs[2][0] = leaves[3]; + proofs[2][1] = node1; proofs[3][0] = leaves[2]; - proofs[3][1] = node1; + proofs[3][1] = node1; } function setMerkleRoot(address token) internal { - vm.startPrank(admin); - cumulativeMerkleRewardsDistributorInstance.setPendingMerkleRoot(token, merkleRoot); - vm.roll(block.number + 15000); - vm.warp(block.timestamp + 15000 * 12); - cumulativeMerkleRewardsDistributorInstance.finalizeMerkleRoot(token, block.number - 15000); - vm.stopPrank(); + vm.startPrank(admin); + cumulativeMerkleRewardsDistributorInstance.setPendingMerkleRoot(token, merkleRoot); + vm.roll(block.number + 15_000); + vm.warp(block.timestamp + 15_000 * 12); + cumulativeMerkleRewardsDistributorInstance.finalizeMerkleRoot(token, block.number - 15_000); + vm.stopPrank(); + } + + //write setup method + function setUp() public { + setUpTests(); + generateMerkleTree(100); + rETH.mint(address(cumulativeMerkleRewardsDistributorInstance), 1000 ether); + vm.deal(address(cumulativeMerkleRewardsDistributorInstance), 1000 ether); + vm.prank(address(cumulativeMerkleRewardsDistributorInstance)); + liquidityPoolInstance.deposit{value: 1000 ether}(); + } + + function test_claiming() public { + setMerkleRoot(address(eETHInstance)); + vm.prank(accounts[0]); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[1], 200 ether, merkleRoot, proofs[1]); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[2], 300 ether, merkleRoot, proofs[2]); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[3], 400 ether, merkleRoot, proofs[3]); + assertEq(eETHInstance.balanceOf(accounts[0]), 100 ether); + assertEq(eETHInstance.balanceOf(accounts[1]), 200 ether); + assertEq(eETHInstance.balanceOf(accounts[2]), 300 ether); + assertEq(eETHInstance.balanceOf(accounts[3]), 400 ether); + } + + function test_verification() public { + vm.expectRevert(ICumulativeMerkleRewardsDistributor.MerkleRootWasUpdated.selector); + //need to pass correct merkle root + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, bytes32(uint256(1)), proofs[0]); + setMerkleRoot(address(eETHInstance)); + vm.startPrank(admin); + cumulativeMerkleRewardsDistributorInstance.updateWhitelistedRecipient(accounts[0], false); + //claimer must be whitelisted + vm.expectRevert(ICumulativeMerkleRewardsDistributor.NonWhitelistedUser.selector); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); + cumulativeMerkleRewardsDistributorInstance.updateWhitelistedRecipient(accounts[0], true); + vm.stopPrank(); + + //must provide correct balance + vm.expectRevert(ICumulativeMerkleRewardsDistributor.InvalidProof.selector); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 200 ether, merkleRoot, proofs[0]); + + //must provide correct user + vm.expectRevert(ICumulativeMerkleRewardsDistributor.InvalidProof.selector); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 200 ether, merkleRoot, proofs[1]); + + //must provide correct user + bytes32[] memory incorrectProofs = new bytes32[](2); + incorrectProofs[0] = proofs[0][0]; + incorrectProofs[1] = proofs[0][0]; + vm.expectRevert(ICumulativeMerkleRewardsDistributor.InvalidProof.selector); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, incorrectProofs); } - //write setup method - function setUp() public { - setUpTests(); - generateMerkleTree(100); - rETH.mint(address(cumulativeMerkleRewardsDistributorInstance), 1000 ether); - vm.deal(address(cumulativeMerkleRewardsDistributorInstance), 1000 ether); - vm.prank(address(cumulativeMerkleRewardsDistributorInstance)); - liquidityPoolInstance.deposit{value: 1000 ether}(); - } - - function test_claiming() public { - setMerkleRoot(address(eETHInstance)); - vm.prank(accounts[0]); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[1], 200 ether, merkleRoot, proofs[1]); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[2], 300 ether, merkleRoot, proofs[2]); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[3], 400 ether, merkleRoot, proofs[3]); - assertEq(eETHInstance.balanceOf(accounts[0]), 100 ether); - assertEq(eETHInstance.balanceOf(accounts[1]), 200 ether); - assertEq(eETHInstance.balanceOf(accounts[2]), 300 ether); - assertEq(eETHInstance.balanceOf(accounts[3]), 400 ether); - } - - function test_verification() public { - vm.expectRevert(ICumulativeMerkleRewardsDistributor.MerkleRootWasUpdated.selector); - //need to pass correct merkle root - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, bytes32(uint256(1)), proofs[0]); - setMerkleRoot(address(eETHInstance)); - vm.startPrank(admin); - cumulativeMerkleRewardsDistributorInstance.updateWhitelistedRecipient(accounts[0], false); - //claimer must be whitelisted - vm.expectRevert(ICumulativeMerkleRewardsDistributor.NonWhitelistedUser.selector); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); - cumulativeMerkleRewardsDistributorInstance.updateWhitelistedRecipient(accounts[0], true); - vm.stopPrank(); - - //must provide correct balance - vm.expectRevert(ICumulativeMerkleRewardsDistributor.InvalidProof.selector); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 200 ether, merkleRoot, proofs[0]); - - //must provide correct user - vm.expectRevert(ICumulativeMerkleRewardsDistributor.InvalidProof.selector); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 200 ether, merkleRoot, proofs[1]); - - //must provide correct user - bytes32[] memory incorrectProofs = new bytes32[](2); - incorrectProofs[0] = proofs[0][0]; - incorrectProofs[1] = proofs[0][0]; - vm.expectRevert(ICumulativeMerkleRewardsDistributor.InvalidProof.selector); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, incorrectProofs); - } - - function test_whitelisting() public { - vm.expectRevert(ICumulativeMerkleRewardsDistributor.IncorrectRole.selector); - cumulativeMerkleRewardsDistributorInstance.updateWhitelistedRecipient(accounts[0], false); - } - - function test_claiming_delay() public { - vm.startPrank(admin); - cumulativeMerkleRewardsDistributorInstance.setPendingMerkleRoot(address(eETHInstance), merkleRoot); - vm.roll(block.number + 14399); - vm.warp(block.timestamp + 14399 * 12); - vm.expectRevert(ICumulativeMerkleRewardsDistributor.InsufficentDelay.selector); - cumulativeMerkleRewardsDistributorInstance.finalizeMerkleRoot(address(eETHInstance), block.number - 12000); - vm.roll(block.number + 1); - vm.warp(block.timestamp + 12); - cumulativeMerkleRewardsDistributorInstance.finalizeMerkleRoot(address(eETHInstance), block.number - 12000); - vm.assertEq(cumulativeMerkleRewardsDistributorInstance.claimableMerkleRoots(address(eETHInstance)), merkleRoot); - vm.stopPrank(); - } - - function test_multiple_token() public { - setMerkleRoot(address(eETHInstance)); - setMerkleRoot(address(rETH)); - console.logBytes32(merkleRoot); - - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); - cumulativeMerkleRewardsDistributorInstance.claim(address(rETH), accounts[0], 100 ether, merkleRoot, proofs[0]); - assertEq(eETHInstance.balanceOf(accounts[0]), 100 ether); - assertEq(rETH.balanceOf(accounts[0]), 100 ether); - } - - function test_cummulative_claim() public { - setMerkleRoot(address(eETHInstance)); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); - generateMerkleTree(200); - setMerkleRoot(address(eETHInstance)); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 200 ether, merkleRoot, proofs[0]); - } - - function test_pausing() public { - vm.prank(chad); - vm.expectRevert(ICumulativeMerkleRewardsDistributor.IncorrectRole.selector); - cumulativeMerkleRewardsDistributorInstance.pause(); - vm.startPrank(admin); - cumulativeMerkleRewardsDistributorInstance.pause(); - vm.expectRevert(ICumulativeMerkleRewardsDistributor.ContractPaused.selector); - cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); - vm.expectRevert(ICumulativeMerkleRewardsDistributor.ContractPaused.selector); - cumulativeMerkleRewardsDistributorInstance.setPendingMerkleRoot(address(eETHInstance), merkleRoot); - vm.expectRevert(ICumulativeMerkleRewardsDistributor.ContractPaused.selector); - vm.roll(block.number + 15000); - vm.warp(block.timestamp + 15000 * 12); - cumulativeMerkleRewardsDistributorInstance.finalizeMerkleRoot(address(eETHInstance), block.number - 12000); - cumulativeMerkleRewardsDistributorInstance.unpause(); - test_claiming(); - vm.stopPrank(); - } - function test_upgrading() public { - vm.prank(chad); - vm.expectRevert(RoleRegistry.OnlyProtocolUpgrader.selector); - cumulativeMerkleRewardsDistributorInstance.upgradeTo(address(0x555)); - CumulativeMerkleRewardsDistributor newImpl = new CumulativeMerkleRewardsDistributor(address(roleRegistryInstance)); - vm.prank(roleRegistryInstance.owner()); - cumulativeMerkleRewardsDistributorInstance.upgradeTo(address(newImpl)); - vm.assertEq(cumulativeMerkleRewardsDistributorInstance.getImplementation(), address(newImpl)); - } - - function test_verify_bytes() public { - initializeRealisticFork(MAINNET_FORK); - CumulativeMerkleRewardsDistributor cumulativeMerkleRewardsDistributorImplementation = new CumulativeMerkleRewardsDistributor(address(roleRegistryInstance)); - CumulativeMerkleRewardsDistributor cumulativeMerkleRewardsDistributorInstance = CumulativeMerkleRewardsDistributor(payable(0x9A8c5046a290664Bf42D065d33512fe403484534)); - address deployedProxy = address(0x9A8c5046a290664Bf42D065d33512fe403484534); - address deployedImpl = address(0xD3F3480511FB25a3D86568B6e1eFBa09d0aDEebF); - verifyContractByteCodeMatch(deployedImpl, address(cumulativeMerkleRewardsDistributorImplementation)); - verifyContractByteCodeMatch(deployedProxy, address(cumulativeMerkleRewardsDistributorInstance)); - } -} \ No newline at end of file + function test_whitelisting() public { + vm.expectRevert(ICumulativeMerkleRewardsDistributor.IncorrectRole.selector); + cumulativeMerkleRewardsDistributorInstance.updateWhitelistedRecipient(accounts[0], false); + } + + function test_claiming_delay() public { + vm.startPrank(admin); + cumulativeMerkleRewardsDistributorInstance.setPendingMerkleRoot(address(eETHInstance), merkleRoot); + vm.roll(block.number + 14_399); + vm.warp(block.timestamp + 14_399 * 12); + vm.expectRevert(ICumulativeMerkleRewardsDistributor.InsufficentDelay.selector); + cumulativeMerkleRewardsDistributorInstance.finalizeMerkleRoot(address(eETHInstance), block.number - 12_000); + vm.roll(block.number + 1); + vm.warp(block.timestamp + 12); + cumulativeMerkleRewardsDistributorInstance.finalizeMerkleRoot(address(eETHInstance), block.number - 12_000); + vm.assertEq(cumulativeMerkleRewardsDistributorInstance.claimableMerkleRoots(address(eETHInstance)), merkleRoot); + vm.stopPrank(); + } + + function test_multiple_token() public { + setMerkleRoot(address(eETHInstance)); + setMerkleRoot(address(rETH)); + console.logBytes32(merkleRoot); + + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); + cumulativeMerkleRewardsDistributorInstance.claim(address(rETH), accounts[0], 100 ether, merkleRoot, proofs[0]); + assertEq(eETHInstance.balanceOf(accounts[0]), 100 ether); + assertEq(rETH.balanceOf(accounts[0]), 100 ether); + } + + function test_cummulative_claim() public { + setMerkleRoot(address(eETHInstance)); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); + generateMerkleTree(200); + setMerkleRoot(address(eETHInstance)); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 200 ether, merkleRoot, proofs[0]); + } + + function test_pausing() public { + vm.prank(chad); + vm.expectRevert(ICumulativeMerkleRewardsDistributor.IncorrectRole.selector); + cumulativeMerkleRewardsDistributorInstance.pause(); + vm.startPrank(admin); + cumulativeMerkleRewardsDistributorInstance.pause(); + vm.expectRevert(ICumulativeMerkleRewardsDistributor.ContractPaused.selector); + cumulativeMerkleRewardsDistributorInstance.claim(address(eETHInstance), accounts[0], 100 ether, merkleRoot, proofs[0]); + vm.expectRevert(ICumulativeMerkleRewardsDistributor.ContractPaused.selector); + cumulativeMerkleRewardsDistributorInstance.setPendingMerkleRoot(address(eETHInstance), merkleRoot); + vm.expectRevert(ICumulativeMerkleRewardsDistributor.ContractPaused.selector); + vm.roll(block.number + 15_000); + vm.warp(block.timestamp + 15_000 * 12); + cumulativeMerkleRewardsDistributorInstance.finalizeMerkleRoot(address(eETHInstance), block.number - 12_000); + cumulativeMerkleRewardsDistributorInstance.unpause(); + test_claiming(); + vm.stopPrank(); + } + + function test_upgrading() public { + vm.prank(chad); + vm.expectRevert(RoleRegistry.OnlyProtocolUpgrader.selector); + cumulativeMerkleRewardsDistributorInstance.upgradeTo(address(0x555)); + CumulativeMerkleRewardsDistributor newImpl = new CumulativeMerkleRewardsDistributor(address(roleRegistryInstance)); + vm.prank(roleRegistryInstance.owner()); + cumulativeMerkleRewardsDistributorInstance.upgradeTo(address(newImpl)); + vm.assertEq(cumulativeMerkleRewardsDistributorInstance.getImplementation(), address(newImpl)); + } + + function test_verify_bytes() public { + initializeRealisticFork(MAINNET_FORK); + CumulativeMerkleRewardsDistributor cumulativeMerkleRewardsDistributorImplementation = new CumulativeMerkleRewardsDistributor(address(roleRegistryInstance)); + CumulativeMerkleRewardsDistributor cumulativeMerkleRewardsDistributorInstance = CumulativeMerkleRewardsDistributor(payable(0x9A8c5046a290664Bf42D065d33512fe403484534)); + address deployedProxy = address(0x9A8c5046a290664Bf42D065d33512fe403484534); + address deployedImpl = address(0xD3F3480511FB25a3D86568B6e1eFBa09d0aDEebF); + verifyContractByteCodeMatch(deployedImpl, address(cumulativeMerkleRewardsDistributorImplementation)); + verifyContractByteCodeMatch(deployedProxy, address(cumulativeMerkleRewardsDistributorInstance)); + } +} diff --git a/test/DepositAdapter.t.sol b/test/DepositAdapter.t.sol index 9a6baa314..47ca44c4e 100644 --- a/test/DepositAdapter.t.sol +++ b/test/DepositAdapter.t.sol @@ -1,12 +1,10 @@ - // SPDX-License-Identifier: MIT + // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "../src/DepositAdapter.sol"; import "./TestSetup.sol"; - contract DepositAdapterTest is TestSetup { - event Deposit(address indexed sender, uint256 amount, uint8 source, address referral); DepositAdapter depositAdapterInstance; @@ -22,18 +20,8 @@ contract DepositAdapterTest is TestSetup { stETHmainnet = IERC20Upgradeable(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84); wstETHmainnet = IwstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0); - // deploying+initializing the deposit adapter - address depositAdapterImpl = address( - new DepositAdapter( - address(liquidityPoolInstance), - address(liquifierInstance), - address(weEthInstance), - address(eETHInstance), - address(wETH), - address(stETHmainnet), - address(wstETHmainnet) - ) - ); + // deploying+initializing the deposit adapter + address depositAdapterImpl = address(new DepositAdapter(address(liquidityPoolInstance), address(liquifierInstance), address(weEthInstance), address(eETHInstance), address(wETH), address(stETHmainnet), address(wstETHmainnet))); address depositAdapterProxy = address(new UUPSProxy(depositAdapterImpl, "")); depositAdapterInstance = DepositAdapter(payable(depositAdapterProxy)); depositAdapterInstance.initialize(); @@ -41,19 +29,19 @@ contract DepositAdapterTest is TestSetup { vm.startPrank(owner); // Caps are hit on mainnet - liquifierInstance.updateDepositCap(address(stEth), 6000, 400000); + liquifierInstance.updateDepositCap(address(stEth), 6000, 400_000); - startHoax(alice); + startHoax(alice); } function test_DepositWeETH() public { vm.expectRevert(LiquidityPool.InvalidAmount.selector); depositAdapterInstance.depositETHForWeETH{value: 0 ether}(address(0)); - + uint256 weEthAmount = depositAdapterInstance.depositETHForWeETH{value: 1 ether}(address(0)); assertApproxEqAbs(weEthInstance.balanceOf(address(alice)), weEthInstance.getWeETHByeETH(1 ether), 3); assertApproxEqAbs(weEthAmount, weEthInstance.getWeETHByeETH(1 ether), 3); - + uint256 balanceBeforeDeposit = weEthInstance.balanceOf(address(alice)); depositAdapterInstance.depositETHForWeETH{value: 1000 ether}(address(0)); assertApproxEqAbs(weEthInstance.balanceOf(address(alice)), weEthInstance.getWeETHByeETH(1000 ether) + balanceBeforeDeposit, 3); @@ -82,13 +70,13 @@ contract DepositAdapterTest is TestSetup { stEth.submit{value: 2 ether}(address(0)); // valid permit for not enough amount - ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(depositAdapterInstance), 1 ether - 1, stEth.nonces(alice), 2**256 - 1, stEth.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(depositAdapterInstance), 1 ether - 1, stEth.nonces(alice), 2 ** 256 - 1, stEth.DOMAIN_SEPARATOR()); ILiquifier.PermitInput memory liquifierPermitInput = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); vm.expectRevert("ALLOWANCE_EXCEEDED"); depositAdapterInstance.depositStETHForWeETHWithPermit(1 ether, address(0), liquifierPermitInput); // empty request - permitInput = createPermitInput(2, address(depositAdapterInstance), 0, stEth.nonces(alice), 2**256 - 1, stEth.DOMAIN_SEPARATOR()); + permitInput = createPermitInput(2, address(depositAdapterInstance), 0, stEth.nonces(alice), 2 ** 256 - 1, stEth.DOMAIN_SEPARATOR()); liquifierPermitInput = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); vm.expectRevert(LiquidityPool.InvalidAmount.selector); depositAdapterInstance.depositStETHForWeETHWithPermit(0, address(0), liquifierPermitInput); @@ -96,7 +84,7 @@ contract DepositAdapterTest is TestSetup { // valid input uint256 protocolStETHBeforeDeposit = stEth.balanceOf(address(liquifierInstance)); uint256 stEthBalanceBeforeDeposit = stEth.balanceOf(address(alice)); - permitInput = createPermitInput(2, address(depositAdapterInstance), 1 ether, stEth.nonces(alice), 2**256 - 1, stEth.DOMAIN_SEPARATOR()); + permitInput = createPermitInput(2, address(depositAdapterInstance), 1 ether, stEth.nonces(alice), 2 ** 256 - 1, stEth.DOMAIN_SEPARATOR()); liquifierPermitInput = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); depositAdapterInstance.depositStETHForWeETHWithPermit(1 ether, bob, liquifierPermitInput); @@ -108,12 +96,11 @@ contract DepositAdapterTest is TestSetup { vm.expectRevert("ALLOWANCE_EXCEEDED"); depositAdapterInstance.depositStETHForWeETHWithPermit(1 ether, bob, liquifierPermitInput); - // much larger deposit stEth.submit{value: 5000 ether}(address(0)); protocolStETHBeforeDeposit = stEth.balanceOf(address(liquifierInstance)); - permitInput = createPermitInput(2, address(depositAdapterInstance), 5000 ether, stEth.nonces(alice), 2**256 - 1, stEth.DOMAIN_SEPARATOR()); + permitInput = createPermitInput(2, address(depositAdapterInstance), 5000 ether, stEth.nonces(alice), 2 ** 256 - 1, stEth.DOMAIN_SEPARATOR()); liquifierPermitInput = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); depositAdapterInstance.depositStETHForWeETHWithPermit(5000 ether, bob, liquifierPermitInput); @@ -127,7 +114,7 @@ contract DepositAdapterTest is TestSetup { // valid wstETH deposit uint256 protocolSeETHBeforeDeposit = stEth.balanceOf(address(liquifierInstance)); - ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(depositAdapterInstance), wstETHAmount, wstETHmainnet.nonces(alice), 2**256 - 1, wstETHmainnet.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(depositAdapterInstance), wstETHAmount, wstETHmainnet.nonces(alice), 2 ** 256 - 1, wstETHmainnet.DOMAIN_SEPARATOR()); ILiquifier.PermitInput memory liquifierPermitInput = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); depositAdapterInstance.depositWstETHForWeETHWithPermit(wstETHAmount, bob, liquifierPermitInput); @@ -137,7 +124,7 @@ contract DepositAdapterTest is TestSetup { assertApproxEqAbs(stEth.balanceOf(address(liquifierInstance)), protocolSeETHBeforeDeposit + 5 ether, 3); // deposit with insufficient balance - permitInput = createPermitInput(2, address(depositAdapterInstance), 1 ether, wstETHmainnet.nonces(alice), 2**256 - 1, wstETHmainnet.DOMAIN_SEPARATOR()); + permitInput = createPermitInput(2, address(depositAdapterInstance), 1 ether, wstETHmainnet.nonces(alice), 2 ** 256 - 1, wstETHmainnet.DOMAIN_SEPARATOR()); liquifierPermitInput = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); vm.expectRevert("ERC20: transfer amount exceeds balance"); depositAdapterInstance.depositWstETHForWeETHWithPermit(1 ether, bob, liquifierPermitInput); @@ -149,27 +136,14 @@ contract DepositAdapterTest is TestSetup { // valid input uint256 protocolStETHBeforeDeposit = stEth.balanceOf(address(liquifierInstance)); uint256 stEthBalanceBeforeDeposit = stEth.balanceOf(address(alice)); - - ILiquidityPool.PermitInput memory permitInput = createPermitInput( - 2, - address(depositAdapterInstance), - 2 ether, - stEth.nonces(alice), - 2 ** 32 - 1, - stEth.DOMAIN_SEPARATOR() - ); - - ILiquifier.PermitInput memory liquifierPermitInput = ILiquifier.PermitInput({ - value: permitInput.value, - deadline: permitInput.deadline, - v: permitInput.v, - r: permitInput.r, - s: permitInput.s - }); - + + ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(depositAdapterInstance), 2 ether, stEth.nonces(alice), 2 ** 32 - 1, stEth.DOMAIN_SEPARATOR()); + + ILiquifier.PermitInput memory liquifierPermitInput = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); + //record timestamp and deadline before warp - uint blockTimestampBefore = block.timestamp; - uint permitDeadline = permitInput.deadline; + uint256 blockTimestampBefore = block.timestamp; + uint256 permitDeadline = permitInput.deadline; console.log("Block Timestamp Before:", blockTimestampBefore); console.log("Permit Deadline:", permitDeadline); depositAdapterInstance.depositStETHForWeETHWithPermit(1 ether, bob, liquifierPermitInput); @@ -179,21 +153,21 @@ contract DepositAdapterTest is TestSetup { assertApproxEqAbs(stEth.balanceOf(address(liquifierInstance)), protocolStETHBeforeDeposit + 1 ether, 3); vm.warp(block.timestamp + permitDeadline + 1 days); - + //record timestamp and deadline after warp - uint blockTimestampAfter = block.timestamp; + uint256 blockTimestampAfter = block.timestamp; console.log("Block Timestamp After:", blockTimestampAfter); console.log("Permit Deadline:", permitDeadline); vm.expectRevert("PERMIT_EXPIRED"); depositAdapterInstance.depositStETHForWeETHWithPermit(1 ether, bob, liquifierPermitInput); } - + function test_Receive() public { vm.expectRevert("ETH_TRANSFERS_NOT_ACCEPTED"); address(depositAdapterInstance).call{value: 1 ether}(""); address payable depositAdapterPayable = payable(address(depositAdapterInstance)); - + vm.expectRevert("ETH_TRANSFERS_NOT_ACCEPTED"); bool success = depositAdapterPayable.send(1 ether); } diff --git a/test/EETH.t.sol b/test/EETH.t.sol index 8163de8fa..fe37191f5 100644 --- a/test/EETH.t.sol +++ b/test/EETH.t.sol @@ -1,8 +1,8 @@ pragma solidity ^0.8.13; -import "./TestSetup.sol"; import "./TestERC20.sol"; import "./TestERC721.sol"; +import "./TestSetup.sol"; // Helper contract to force ETH into a contract using selfdestruct contract ForceETHSender { @@ -12,12 +12,10 @@ contract ForceETHSender { } contract EETHTest is TestSetup { - event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function setUp() public { - setUpTests(); } @@ -130,7 +128,7 @@ contract EETHTest is TestSetup { // Staking Rewards sent to liquidity pool /// vm.deal sets the balance of whoever its called on - /// In this case 10 ether is added as reward + /// In this case 10 ether is added as reward vm.prank(address(membershipManagerInstance)); liquidityPoolInstance.rebase(10 ether); _transferTo(address(liquidityPoolInstance), 10 ether); @@ -308,53 +306,55 @@ contract EETHTest is TestSetup { assertEq(eETHInstance.allowance(alice, bob), 0.5 ether); } + function test_RecoverETH() public { uint256 amountToSend = 2 ether; // We cannot send ETH directly to eETH contract because it has no fallback/retrieve method ForceETHSender sender = new ForceETHSender(); vm.deal(address(sender), amountToSend); sender.forceSend(payable(address(eETHInstance))); - + // Check that eETH contract now has ETH assertEq(address(eETHInstance).balance, amountToSend); - + // Try to recover ETH without proper role - should fail vm.expectRevert(); vm.prank(bob); eETHInstance.recoverETH(payable(bob), amountToSend); - + // Check alice's balance before recovery uint256 aliceBalanceBefore = alice.balance; - + // Recover ETH as admin vm.prank(admin); eETHInstance.recoverETH(payable(alice), amountToSend); - + // Verify ETH was recovered assertEq(address(eETHInstance).balance, 0); assertEq(alice.balance, aliceBalanceBefore + amountToSend); } + function test_RecoverERC20() public { // Create a mock ERC20 token TestERC20 mockToken = new TestERC20("Test Token", "TEST"); uint256 amountToSend = 1000e18; - + // Mint tokens to alice and send to eETH contract mockToken.mint(alice, amountToSend); vm.prank(alice); mockToken.transfer(address(eETHInstance), amountToSend); - + assertEq(mockToken.balanceOf(address(eETHInstance)), amountToSend); - + // Try to recover tokens without proper role - should fail vm.expectRevert(); vm.prank(bob); eETHInstance.recoverERC20(address(mockToken), alice, amountToSend); - + // Recover tokens as admin (who has the role) vm.prank(admin); eETHInstance.recoverERC20(address(mockToken), alice, amountToSend); - + // Verify tokens were recovered assertEq(mockToken.balanceOf(address(eETHInstance)), 0); assertEq(mockToken.balanceOf(alice), amountToSend); @@ -363,23 +363,23 @@ contract EETHTest is TestSetup { function test_RecoverERC721() public { // Create a mock ERC721 token TestERC721 mockNFT = new TestERC721("Test NFT", "TNFT"); - + // Mint NFT to alice and send to eETH contract uint256 tokenId = mockNFT.mint(alice); vm.prank(alice); mockNFT.transferFrom(alice, address(eETHInstance), tokenId); - + assertEq(mockNFT.ownerOf(tokenId), address(eETHInstance)); - + // Try to recover NFT without proper role - should fail vm.expectRevert(); vm.prank(bob); eETHInstance.recoverERC721(address(mockNFT), alice, tokenId); - + // Recover NFT as admin vm.prank(admin); eETHInstance.recoverERC721(address(mockNFT), alice, tokenId); - + // Verify NFT was recovered assertEq(mockNFT.ownerOf(tokenId), alice); } @@ -390,17 +390,17 @@ contract EETHTest is TestSetup { ForceETHSender sender = new ForceETHSender(); vm.deal(address(sender), amountToSend); sender.forceSend(payable(address(eETHInstance))); - + // Test 1: Try to recover 0 ETH - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); eETHInstance.recoverETH(payable(alice), 0); - + // Test 2: Try to recover more ETH than exists - should revert with InsufficientBalance vm.expectRevert(AssetRecovery.InsufficientBalance.selector); vm.prank(admin); eETHInstance.recoverETH(payable(alice), amountToSend + 1); - + // Test 3: Try to send to zero address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); @@ -410,27 +410,27 @@ contract EETHTest is TestSetup { function test_RecoverERC20_ErrorConditions() public { TestERC20 mockToken = new TestERC20("Test Token", "TEST"); uint256 amountToSend = 1000e18; - + // Send tokens to eETH contract mockToken.mint(alice, amountToSend); vm.prank(alice); mockToken.transfer(address(eETHInstance), amountToSend); - + // Test 1: Try to recover 0 tokens - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); eETHInstance.recoverERC20(address(mockToken), alice, 0); - + // Test 2: Try to recover more tokens than exists - should revert with InsufficientBalance vm.expectRevert(AssetRecovery.InsufficientBalance.selector); vm.prank(admin); eETHInstance.recoverERC20(address(mockToken), alice, amountToSend + 1); - + // Test 3: Try to send to zero address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); eETHInstance.recoverERC20(address(mockToken), address(0), amountToSend); - + // Test 4: Try to recover from zero token address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); @@ -440,33 +440,31 @@ contract EETHTest is TestSetup { function test_RecoverERC721_ErrorConditions() public { TestERC721 mockNFT = new TestERC721("Test NFT", "TNFT"); uint256 tokenId = mockNFT.mint(alice); - + // Send NFT to eETH contract vm.prank(alice); mockNFT.transferFrom(alice, address(eETHInstance), tokenId); - + // Test 1: Try to recover NFT that doesn't exist - should revert uint256 nonExistentTokenId = 9999; vm.expectRevert(); // ERC721: invalid token ID or similar vm.prank(admin); eETHInstance.recoverERC721(address(mockNFT), alice, nonExistentTokenId); - + // Test 2: Try to recover NFT that contract doesn't own - should revert with ContractIsNotOwnerOfERC721Token uint256 bobsTokenId = mockNFT.mint(bob); vm.expectRevert(AssetRecovery.ContractIsNotOwnerOfERC721Token.selector); vm.prank(admin); eETHInstance.recoverERC721(address(mockNFT), alice, bobsTokenId); - + // Test 3: Try to send to zero address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); eETHInstance.recoverERC721(address(mockNFT), address(0), tokenId); - + // Test 4: Try to recover from zero token address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); eETHInstance.recoverERC721(address(0), alice, tokenId); } - - } diff --git a/test/ELExitsForkTestingDeployment.t.sol b/test/ELExitsForkTestingDeployment.t.sol index f3c3d8efb..3088e3862 100644 --- a/test/ELExitsForkTestingDeployment.t.sol +++ b/test/ELExitsForkTestingDeployment.t.sol @@ -1,20 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "forge-std/Test.sol"; -import "forge-std/console2.sol"; -import "../src/StakingManager.sol"; -import "../src/EtherFiNodesManager.sol"; +import "../src/AuctionManager.sol"; import "../src/EtherFiNode.sol"; +import "../src/EtherFiNodesManager.sol"; import "../src/EtherFiRateLimiter.sol"; +import "../src/EtherFiTimelock.sol"; import "../src/LiquidityPool.sol"; +import "../src/StakingManager.sol"; import "../src/UUPSProxy.sol"; -import "../src/AuctionManager.sol"; -import "../src/EtherFiTimelock.sol"; -import "../src/interfaces/IRoleRegistry.sol"; + +import {IEigenPod, IEigenPodTypes} from "../src/eigenlayer-interfaces/IEigenPod.sol"; import "../src/interfaces/ILiquidityPool.sol"; +import "../src/interfaces/IRoleRegistry.sol"; import "../src/interfaces/IStakingManager.sol"; -import {IEigenPod, IEigenPodTypes } from "../src/eigenlayer-interfaces/IEigenPod.sol"; +import "forge-std/Test.sol"; +import "forge-std/console2.sol"; interface IUpgradable { function upgradeTo(address newImplementation) external; @@ -26,15 +27,14 @@ interface IUpgradable { * @title ELExitsForkTestingDeployment * @notice fork test using actual mainnet addresses and roles * @dev Run with: forge test --fork-url --match-path test/ELExitsForkTestingDeployment.t.sol -vvv - * + * * This test simulates the ACTUAL upgrade process using: * - mainnet contract addresses - * - current role holders + * - current role holders * - timelock if needed * - Actual upgrade permissions */ contract ELExitsForkTestingDeploymentTest is Test { - // === MAINNET CONTRACT ADDRESSES === StakingManager constant stakingManager = StakingManager(0x25e821b7197B146F7713C3b89B6A4D83516B912d); ILiquidityPool constant liquidityPool = ILiquidityPool(0x308861A430be4cce5502d0A12724771Fc6DaF216); @@ -71,7 +71,7 @@ contract ELExitsForkTestingDeploymentTest is Test { console2.log("StakingManager Owner:", stakingManagerOwner); console2.log("EtherFiNodesManager Owner:", etherFiNodesManagerOwner); console2.log(unicode"⚠️ All contracts use timelock - upgrades need governance"); - + console2.log(""); } @@ -120,41 +120,24 @@ contract ELExitsForkTestingDeploymentTest is Test { console2.log(unicode"✓ Rate limiter deployed and initialized"); console2.log(""); } - + function _deployNewImplementations() internal { console2.log("--- Step 2: Deploying New Contract Implementations (EIP-7002 Only) ---"); // Deploy new StakingManager implementation (minor rate limiter integration) - newStakingManagerImpl = new StakingManager( - address(liquidityPool), - address(etherFiNodesManager), - address(stakingDepositContract), - address(auctionManager), - address(etherFiNodeBeacon), - address(roleRegistry) - ); + newStakingManagerImpl = new StakingManager(address(liquidityPool), address(etherFiNodesManager), address(stakingDepositContract), address(auctionManager), address(etherFiNodeBeacon), address(roleRegistry)); console2.log("New StakingManager implementation:", address(newStakingManagerImpl)); // Deploy new EtherFiNodesManager implementation (with EL exits + rate limiter) - newEtherFiNodesManagerImpl = new EtherFiNodesManager( - address(stakingManager), - address(roleRegistry), - address(rateLimiter) - ); + newEtherFiNodesManagerImpl = new EtherFiNodesManager(address(stakingManager), address(roleRegistry), address(rateLimiter)); console2.log("New EtherFiNodesManager implementation:", address(newEtherFiNodesManagerImpl)); // Deploy new EtherFiNode implementation (with EL exits + consolidation) - newEtherFiNodeImpl = new EtherFiNode( - address(liquidityPool), - address(etherFiNodesManager), - eigenPodManager, - delegationManager, - address(roleRegistry) - ); + newEtherFiNodeImpl = new EtherFiNode(address(liquidityPool), address(etherFiNodesManager), eigenPodManager, delegationManager, address(roleRegistry)); console2.log("New EtherFiNode implementation:", address(newEtherFiNodeImpl)); console2.log(""); } - + function _performRealisticUpgrades() internal { console2.log("--- Step 3: Performing Upgrades (EIP-7002 Contracts Only) ---"); @@ -163,7 +146,7 @@ contract ELExitsForkTestingDeploymentTest is Test { stakingManager.upgradeTo(address(newStakingManagerImpl)); console2.log(unicode"✓ StakingManager upgraded (rate limiter integration)"); - // Upgrade EtherFiNodesManager - prank the owner (hardcoded timelock) + // Upgrade EtherFiNodesManager - prank the owner (hardcoded timelock) vm.prank(etherFiNodesManagerOwner); etherFiNodesManager.upgradeTo(address(newEtherFiNodesManagerImpl)); console2.log(unicode"✓ EtherFiNodesManager upgraded (EL exits + rate limiter)"); @@ -175,7 +158,7 @@ contract ELExitsForkTestingDeploymentTest is Test { console2.log(""); } - + function _assignNewRoles() internal { console2.log("--- Step 4: Assigning New Roles (Following Prelude Pattern) ---"); @@ -187,7 +170,7 @@ contract ELExitsForkTestingDeploymentTest is Test { roleRegistry.grantRole(etherFiNodesManager.ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(), realElExiter); console2.log("Granted ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE to:", realElExiter); - // Assign rate limiter admin role to a realistic address + // Assign rate limiter admin role to a realistic address address realRateLimiterAdmin = 0x0EF8fa4760Db8f5Cd4d993f3e3416f30f942D705; // etherFiAdmin roleRegistry.grantRole(rateLimiter.ETHERFI_RATE_LIMITER_ADMIN_ROLE(), realRateLimiterAdmin); console2.log("Granted ETHERFI_RATE_LIMITER_ADMIN_ROLE to:", realRateLimiterAdmin); @@ -234,10 +217,7 @@ contract ELExitsForkTestingDeploymentTest is Test { // Try to call EL triggered withdrawal (will revert due to no validators, but tests access control) IEigenPodTypes.WithdrawalRequest[] memory requests = new IEigenPodTypes.WithdrawalRequest[](1); - requests[0] = IEigenPodTypes.WithdrawalRequest({ - pubkey: hex"b964a67b7272ce6b59243d65ffd7b011363dd99322c88e583f14e34e19dfa249c80c724361ceaee7a9bfbfe1f3822871", - amountGwei: 32000000000 - }); + requests[0] = IEigenPodTypes.WithdrawalRequest({pubkey: hex"b964a67b7272ce6b59243d65ffd7b011363dd99322c88e583f14e34e19dfa249c80c724361ceaee7a9bfbfe1f3822871", amountGwei: 32_000_000_000}); vm.prank(realElExiter); try etherFiNodesManager.requestExecutionLayerTriggeredWithdrawal(requests) { @@ -279,7 +259,7 @@ contract ELExitsForkTestingDeploymentTest is Test { console2.log(""); } - + function _printUpgradeSummary() internal view { console2.log("=== REALISTIC UPGRADE SUMMARY ==="); console2.log(""); @@ -326,14 +306,8 @@ contract ELExitsForkTestingDeploymentTest is Test { if (hasRole) { // Test with a more realistic scenario IEigenPodTypes.WithdrawalRequest[] memory requests = new IEigenPodTypes.WithdrawalRequest[](2); - requests[0] = IEigenPodTypes.WithdrawalRequest({ - pubkey: hex"b964a67b7272ce6b59243d65ffd7b011363dd99322c88e583f14e34e19dfa249c80c724361ceaee7a9bfbfe1f3822871", - amountGwei: 32000000000 - }); - requests[1] = IEigenPodTypes.WithdrawalRequest({ - pubkey: hex"b22c8896452c858287426b478e76c2bf366f0c139cf54bd07fa7351290e9a9f92cc4f059ea349a441e1cfb60aacd2447", - amountGwei: 32000000000 - }); + requests[0] = IEigenPodTypes.WithdrawalRequest({pubkey: hex"b964a67b7272ce6b59243d65ffd7b011363dd99322c88e583f14e34e19dfa249c80c724361ceaee7a9bfbfe1f3822871", amountGwei: 32_000_000_000}); + requests[1] = IEigenPodTypes.WithdrawalRequest({pubkey: hex"b22c8896452c858287426b478e76c2bf366f0c139cf54bd07fa7351290e9a9f92cc4f059ea349a441e1cfb60aacd2447", amountGwei: 32_000_000_000}); vm.prank(realElExiter); vm.expectRevert(); // Will revert due to validators not existing, but tests role system @@ -343,4 +317,4 @@ contract ELExitsForkTestingDeploymentTest is Test { console2.log(" (Reverts due to non-existent validators - expected behavior)"); } } -} \ No newline at end of file +} diff --git a/test/EigenLayerIntegration.t.sol b/test/EigenLayerIntegration.t.sol index 7070a042a..bc2da486f 100644 --- a/test/EigenLayerIntegration.t.sol +++ b/test/EigenLayerIntegration.t.sol @@ -1,24 +1,24 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import "./TestSetup.sol"; import "../src/EtherFiNode.sol"; -import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; -import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -import "../src/eigenlayer-interfaces/IEigenPodManager.sol"; -import "../src/eigenlayer-interfaces/IEigenPod.sol"; + import "../src/eigenlayer-interfaces/IDelayedWithdrawalRouter.sol"; +import "../src/eigenlayer-interfaces/IEigenPod.sol"; +import "../src/eigenlayer-interfaces/IEigenPodManager.sol"; + import "../src/eigenlayer-libraries/BeaconChainProofs.sol"; +import "./TestSetup.sol"; +import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; +import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -import "./eigenlayer-utils/ProofParsing.sol"; import "./eigenlayer-mocks/BeaconChainOracleMock.sol"; +import "./eigenlayer-utils/ProofParsing.sol"; -import "forge-std/console2.sol"; import "forge-std/console.sol"; - +import "forge-std/console2.sol"; contract EigenLayerIntegraitonTest is TestSetup, ProofParsing { - address p2p; address dsrv; address etherfi_avs_operator_1; @@ -80,7 +80,6 @@ contract EigenLayerIntegraitonTest is TestSetup, ProofParsing { vm.stopPrank(); */ - } /* @@ -421,7 +420,6 @@ contract EigenLayerIntegraitonTest is TestSetup, ProofParsing { verifyContractByteCodeMatch(etherFiNodesManagerImplAddress, address(etherFiNodesManagerImplementation)); verifyContractByteCodeMatch(etherFiNodeImplAddress, address(etherFiNodeImplementation)); verifyContractByteCodeMatch(etherFiRestakerImplAddress, address(etherFiRestakerImplementation)); - } - */ - + } + */ } diff --git a/test/EtherFiNode.t.sol b/test/EtherFiNode.t.sol index 1b0daac8f..9a7241e78 100644 --- a/test/EtherFiNode.t.sol +++ b/test/EtherFiNode.t.sol @@ -1,31 +1,23 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import "./TestSetup.sol"; import "../src/EtherFiNode.sol"; -import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; -import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -import "../src/eigenlayer-interfaces/IEigenPodManager.sol"; + import "../src/eigenlayer-interfaces/IDelayedWithdrawalRouter.sol"; +import "../src/eigenlayer-interfaces/IEigenPodManager.sol"; +import "./TestSetup.sol"; + import "./mocks/MockDelegationManager.sol"; import "./mocks/MockEigenPod.sol"; +import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; +import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import "forge-std/console2.sol"; interface IEigenlayerTimelock { - function execute( - address target, - uint256 value, - bytes calldata payload, - bytes32 predecessor, - bytes32 salt - ) external; + function execute(address target, uint256 value, bytes calldata payload, bytes32 predecessor, bytes32 salt) external; function grantRole(bytes32 role, address account) external; } -contract EtherFiNodeTest is TestSetup, ArrayTestHelper { - -} - - +contract EtherFiNodeTest is TestSetup, ArrayTestHelper {} diff --git a/test/EtherFiNodesManager.t.sol b/test/EtherFiNodesManager.t.sol index 108c0403c..ed780e885 100644 --- a/test/EtherFiNodesManager.t.sol +++ b/test/EtherFiNodesManager.t.sol @@ -1,15 +1,13 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import "./TestSetup.sol"; import "../src/EtherFiNode.sol"; +import "./TestSetup.sol"; import "forge-std/console2.sol"; contract EtherFiNodesManagerTest is TestSetup { - function setUp() public { setUpTests(); } - } diff --git a/test/EtherFiOperationParameters.t.sol b/test/EtherFiOperationParameters.t.sol index 20d88ac1c..58e0ab686 100644 --- a/test/EtherFiOperationParameters.t.sol +++ b/test/EtherFiOperationParameters.t.sol @@ -4,14 +4,13 @@ pragma solidity ^0.8.13; import "./TestSetup.sol"; import "forge-std/Test.sol"; -import "../src/helpers/EtherFiOperationParameters.sol"; import "../src/UUPSProxy.sol"; +import "../src/helpers/EtherFiOperationParameters.sol"; contract EtherFiOperationParametersTest is TestSetup { - EtherFiOperationParameters operationParameters; address rando1 = address(0x1); // Non-owner account for testing - address rando2 = address(0x2); // Another non-owner account + address rando2 = address(0x2); // Another non-owner account function setUp() public { EtherFiOperationParameters impl = new EtherFiOperationParameters(); @@ -21,21 +20,12 @@ contract EtherFiOperationParametersTest is TestSetup { operationParameters.initialize(); } - function testFuzz_updateTagAdmin( - string calldata tag, - address admin, - bool allowed - ) public { + function testFuzz_updateTagAdmin(string calldata tag, address admin, bool allowed) public { operationParameters.updateTagAdmin(tag, admin, allowed); assertEq(operationParameters.tagAdmins(tag, admin), allowed); } - function testFuzz_updateTagKeyValue( - string calldata tag, - string calldata key, - string calldata value1, - string calldata value2 - ) public { + function testFuzz_updateTagKeyValue(string calldata tag, string calldata key, string calldata value1, string calldata value2) public { vm.expectRevert(); operationParameters.updateTagKeyValue(tag, key, value1); @@ -52,11 +42,7 @@ contract EtherFiOperationParametersTest is TestSetup { } // Test that only the owner can call updateTagAdmin - function testFuzz_updateTagAdmin_onlyOwner( - string calldata tag, - address admin, - bool allowed - ) public { + function testFuzz_updateTagAdmin_onlyOwner(string calldata tag, address admin, bool allowed) public { vm.prank(rando1); // Attempt to call from a non-owner account vm.expectRevert("Ownable: caller is not the owner"); operationParameters.updateTagAdmin(tag, admin, allowed); @@ -68,11 +54,7 @@ contract EtherFiOperationParametersTest is TestSetup { } // Test that only an admin can call updateTagKeyValue - function testFuzz_updateTagKeyValue_onlyAdmin( - string calldata tag, - string calldata key, - string calldata value - ) public { + function testFuzz_updateTagKeyValue_onlyAdmin(string calldata tag, string calldata key, string calldata value) public { // Attempt to call without being an admin vm.prank(rando1); vm.expectRevert("Only admin can call"); @@ -89,12 +71,7 @@ contract EtherFiOperationParametersTest is TestSetup { } // Test the updateTagKeyValue function with multiple updates by an admin - function testFuzz_updateTagKeyValue_asAdmin( - string calldata tag, - string calldata key, - string calldata value1, - string calldata value2 - ) public { + function testFuzz_updateTagKeyValue_asAdmin(string calldata tag, string calldata key, string calldata value1, string calldata value2) public { // Assign admin role to rando2 for the tag operationParameters.updateTagAdmin(tag, rando2, true); @@ -128,4 +105,4 @@ contract EtherFiOperationParametersTest is TestSetup { operationParameters.upgradeTo(newImplementation); assertEq(operationParameters.getImplementation(), newImplementation); } -} \ No newline at end of file +} diff --git a/test/EtherFiOracle.t.sol b/test/EtherFiOracle.t.sol index f50adda65..84124efde 100644 --- a/test/EtherFiOracle.t.sol +++ b/test/EtherFiOracle.t.sol @@ -90,7 +90,7 @@ contract EtherFiOracleTest is TestSetup { vm.expectRevert("Report is for wrong consensusVersion"); etherFiOracleInstance.submitReport(reportAtPeriod2C); - // Update the Consensus Version to 2 + // Update the Consensus Version to 2 vm.prank(owner); etherFiOracleInstance.setConsensusVersion(2); @@ -117,8 +117,8 @@ contract EtherFiOracleTest is TestSetup { vm.expectRevert("You don't need to submit a report"); vm.prank(alice); etherFiOracleInstance.submitReport(reportAtPeriod2B); - - _moveClock(1024 ); + + _moveClock(1024); // [timestamp = 25345, period 3] // 66 epoch @@ -149,20 +149,20 @@ contract EtherFiOracleTest is TestSetup { function test_submitReport() public { _moveClock(1024 + 2 * slotsPerEpoch); - + // Now it's period 2 // alice submits the period 2 report vm.prank(alice); etherFiOracleInstance.submitReport(reportAtPeriod2A); - + // check the member state (bool registered, bool enabled, uint32 lastReportRefSlot, uint32 numReports) = etherFiOracleInstance.committeeMemberStates(alice); assertEq(registered, true); assertEq(enabled, true); assertEq(lastReportRefSlot, reportAtPeriod2A.refSlotTo); assertEq(numReports, 1); - + // check the consensus state bytes32 reportHash = etherFiOracleInstance.generateReportHash(reportAtPeriod2A); (uint32 support, bool consensusReached,) = etherFiOracleInstance.consensusStates(reportHash); @@ -197,7 +197,6 @@ contract EtherFiOracleTest is TestSetup { reportAtPeriod3.lastFinalizedWithdrawalRequestId = reportAtPeriod4.lastFinalizedWithdrawalRequestId = 0; _executeAdminTasks(reportAtPeriod3); - // Now it's period 4 _moveClock(1024); @@ -213,7 +212,7 @@ contract EtherFiOracleTest is TestSetup { bytes[] memory emptySignatures = new bytes[](1); _executeAdminTasks(reportAtPeriod2A); - //execute validator task + //execute validator task vm.prank(alice); etherFiAdminInstance.executeValidatorApprovalTask(reportHash, reportAtPeriod2A.validatorsToApprove, emptyPubKeys, emptySignatures); @@ -244,7 +243,7 @@ contract EtherFiOracleTest is TestSetup { etherFiOracleInstance.submitReport(report); } - function test_change_report_start_slot1() public { + function test_change_report_start_slot1() public { vm.prank(owner); bytes[] memory emptyBytes = new bytes[](0); etherFiOracleInstance.setQuorumSize(1); @@ -254,13 +253,13 @@ contract EtherFiOracleTest is TestSetup { (uint32 slotFrom, uint32 slotTo, uint32 blockFrom) = etherFiOracleInstance.blockStampForNextReport(); assertEq(slotFrom, 0); - assertEq(slotTo, 1024-1); + assertEq(slotTo, 1024 - 1); assertEq(blockFrom, 0); report.refSlotFrom = 0; - report.refSlotTo = 1024-1; + report.refSlotTo = 1024 - 1; report.refBlockFrom = 0; - report.refBlockTo = 1024-1; + report.refBlockTo = 1024 - 1; vm.startPrank(alice); etherFiOracleInstance.submitReport(report); @@ -298,7 +297,7 @@ contract EtherFiOracleTest is TestSetup { assertEq(blockFrom, 2 * 1024 + 512); } - function test_change_report_start_slot2() public { + function test_change_report_start_slot2() public { vm.prank(owner); _moveClock(1024 + 2 * 32); @@ -347,7 +346,7 @@ contract EtherFiOracleTest is TestSetup { // 2048 + 1024 + 64 = 3136 _moveClock(1024 + 2 * slotsPerEpoch); - + vm.prank(alice); etherFiOracleInstance.submitReport(reportAtSlot3071); @@ -357,7 +356,7 @@ contract EtherFiOracleTest is TestSetup { // slot 3236 _moveClock(100); - + vm.prank(alice); vm.expectRevert("Report Epoch is not finalized yet"); etherFiOracleInstance.submitReport(reportAtSlot4287); @@ -399,7 +398,7 @@ contract EtherFiOracleTest is TestSetup { function test_pause() public { _moveClock(1024 + 2 * slotsPerEpoch); - + vm.prank(alice); etherFiOracleInstance.pauseContract(); @@ -496,13 +495,13 @@ contract EtherFiOracleTest is TestSetup { vm.prank(owner); etherFiOracleInstance.setQuorumSize(5); - + _moveClock(1024 + 2 * slotsPerEpoch); - + // alice submits the period 2 report vm.prank(alice); etherFiOracleInstance.submitReport(reportAtPeriod2A); - + // check the consensus state bytes32 reportHash = etherFiOracleInstance.generateReportHash(reportAtPeriod2A); (uint32 support, bool consensusReached, uint32 consensusTimestamp) = etherFiOracleInstance.consensusStates(reportHash); @@ -595,13 +594,13 @@ contract EtherFiOracleTest is TestSetup { (uint32 slotFrom, uint32 slotTo, uint32 blockFrom) = etherFiOracleInstance.blockStampForNextReport(); assertEq(slotFrom, 0); - assertEq(slotTo, 1024-1); + assertEq(slotTo, 1024 - 1); assertEq(blockFrom, 0); report.refSlotFrom = 0; - report.refSlotTo = 1024-1; + report.refSlotTo = 1024 - 1; report.refBlockFrom = 0; - report.refBlockTo = 1024-1; + report.refBlockTo = 1024 - 1; vm.startPrank(alice); etherFiOracleInstance.submitReport(report); @@ -643,7 +642,7 @@ contract EtherFiOracleTest is TestSetup { // Assume that the accruedRewards must be 1 ether, all the time - // Alice submited the correct report + // Alice submited the correct report vm.prank(alice); report.accruedRewards = 1 ether; bool consensusReached = etherFiOracleInstance.submitReport(report); @@ -690,7 +689,7 @@ contract EtherFiOracleTest is TestSetup { // Assume that the accruedRewards must be 1 ether, all the time - // Alice submited the correct report + // Alice submited the correct report vm.prank(alice); report.accruedRewards = 90 ether; report.protocolFees = 10 ether; diff --git a/test/EtherFiRateLimiter.t.sol b/test/EtherFiRateLimiter.t.sol index cec10c70f..bae4fb461 100644 --- a/test/EtherFiRateLimiter.t.sol +++ b/test/EtherFiRateLimiter.t.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import "forge-std/Test.sol"; -import "forge-std/console2.sol"; +import "../lib/BucketLimiter.sol"; import "../src/EtherFiRateLimiter.sol"; import "../src/UUPSProxy.sol"; import "../src/interfaces/IEtherFiRateLimiter.sol"; import "../src/interfaces/IRoleRegistry.sol"; -import "../lib/BucketLimiter.sol"; +import "forge-std/Test.sol"; +import "forge-std/console2.sol"; contract MockRoleRegistry is IRoleRegistry { mapping(bytes32 => mapping(address => bool)) public roleAssignments; @@ -82,7 +82,7 @@ contract EtherFiRateLimiterTest is Test { EtherFiRateLimiter public rateLimiter; MockRoleRegistry public roleRegistry; UUPSProxy public proxy; - + address public admin = makeAddr("admin"); address public consumer1 = makeAddr("consumer1"); address public consumer2 = makeAddr("consumer2"); @@ -109,17 +109,17 @@ contract EtherFiRateLimiterTest is Test { function setUp() public { // Deploy mock role registry roleRegistry = new MockRoleRegistry(); - + // Deploy rate limiter implementation EtherFiRateLimiter impl = new EtherFiRateLimiter(address(roleRegistry)); - + // Deploy proxy proxy = new UUPSProxy(address(impl), ""); rateLimiter = EtherFiRateLimiter(address(proxy)); - + // Initialize rateLimiter.initialize(); - + // Setup roles roleRegistry.grantRole(roleRegistry.ETHERFI_RATE_LIMITER_ADMIN_ROLE(), admin); roleRegistry.grantRole(roleRegistry.PROTOCOL_PAUSER_ROLE(), pauser); @@ -260,10 +260,9 @@ contract EtherFiRateLimiterTest is Test { rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); assertTrue(rateLimiter.limitExists(LIMIT_ID_1)); - - (uint64 capacity, uint64 remaining, uint64 refillRate, uint256 lastRefill) = - rateLimiter.getLimit(LIMIT_ID_1); - + + (uint64 capacity, uint64 remaining, uint64 refillRate, uint256 lastRefill) = rateLimiter.getLimit(LIMIT_ID_1); + assertEq(capacity, DEFAULT_CAPACITY); assertEq(remaining, DEFAULT_CAPACITY); // Should start full assertEq(refillRate, DEFAULT_REFILL_RATE); @@ -286,7 +285,7 @@ contract EtherFiRateLimiterTest is Test { rateLimiter.createNewLimiter(LIMIT_ID_1, 0, 0); assertTrue(rateLimiter.limitExists(LIMIT_ID_1)); - + (uint64 capacity, uint64 remaining, uint64 refillRate,) = rateLimiter.getLimit(LIMIT_ID_1); assertEq(capacity, 0); assertEq(remaining, 0); @@ -295,12 +294,12 @@ contract EtherFiRateLimiterTest is Test { function test_createLimiterWithMaxValues() public { uint64 maxValue = type(uint64).max; - + vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, maxValue, maxValue); assertTrue(rateLimiter.limitExists(LIMIT_ID_1)); - + (uint64 capacity, uint64 remaining, uint64 refillRate,) = rateLimiter.getLimit(LIMIT_ID_1); assertEq(capacity, maxValue); assertEq(remaining, maxValue); @@ -322,19 +321,19 @@ contract EtherFiRateLimiterTest is Test { // Add consumer vm.expectEmit(true, true, false, true); emit ConsumerUpdated(LIMIT_ID_1, consumer1, true); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); - + assertTrue(rateLimiter.isConsumerAllowed(LIMIT_ID_1, consumer1)); // Remove consumer vm.expectEmit(true, true, false, true); emit ConsumerUpdated(LIMIT_ID_1, consumer1, false); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, false); - + assertFalse(rateLimiter.isConsumerAllowed(LIMIT_ID_1, consumer1)); } @@ -352,7 +351,7 @@ contract EtherFiRateLimiterTest is Test { // Add multiple consumers vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer2, true); @@ -369,7 +368,7 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter and add consumer vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); @@ -388,7 +387,7 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter and add consumer vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); @@ -422,7 +421,7 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter and add consumer vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); @@ -455,7 +454,7 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter and add consumer vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); @@ -480,14 +479,14 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter and add consumer vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); // Consume all capacity vm.prank(consumer1); rateLimiter.consume(LIMIT_ID_1, DEFAULT_CAPACITY); - + assertEq(rateLimiter.consumable(LIMIT_ID_1), 0); // Advance time by 10 seconds @@ -501,7 +500,7 @@ contract EtherFiRateLimiterTest is Test { function test_refillCannotExceedCapacity() public { // Setup: Create limiter with small capacity uint64 smallCapacity = 50_000_000_000; // 50 ETH - + vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, smallCapacity, DEFAULT_REFILL_RATE); @@ -516,7 +515,7 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter with zero refill rate vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, 0); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); @@ -648,12 +647,11 @@ contract EtherFiRateLimiterTest is Test { function test_getLimit() public { uint256 timestamp = block.timestamp; - + vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - (uint64 capacity, uint64 remaining, uint64 refillRate, uint256 lastRefill) = - rateLimiter.getLimit(LIMIT_ID_1); + (uint64 capacity, uint64 remaining, uint64 refillRate, uint256 lastRefill) = rateLimiter.getLimit(LIMIT_ID_1); assertEq(capacity, DEFAULT_CAPACITY); assertEq(remaining, DEFAULT_CAPACITY); @@ -757,21 +755,21 @@ contract EtherFiRateLimiterTest is Test { // Create two different limiters vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, capacity1, refillRate1); - + vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_2, capacity2, refillRate2); // Add consumers to both vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_2, consumer2, true); // Verify independent operation assertTrue(rateLimiter.limitExists(LIMIT_ID_1)); assertTrue(rateLimiter.limitExists(LIMIT_ID_2)); - + assertEq(rateLimiter.consumable(LIMIT_ID_1), capacity1); assertEq(rateLimiter.consumable(LIMIT_ID_2), capacity2); @@ -793,7 +791,7 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter and add consumer vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); @@ -829,14 +827,14 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter and add consumer vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); // Consume capacity in small increments uint64 incrementAmount = 1_000_000_000; // 1 ETH uint64 totalConsumed = 0; - + for (uint256 i = 0; i < 50; i++) { if (rateLimiter.canConsume(LIMIT_ID_1, incrementAmount)) { vm.prank(consumer1); @@ -854,14 +852,14 @@ contract EtherFiRateLimiterTest is Test { // Setup: Create limiter and add consumer vm.prank(admin); rateLimiter.createNewLimiter(LIMIT_ID_1, DEFAULT_CAPACITY, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(LIMIT_ID_1, consumer1, true); // Consume all capacity vm.prank(consumer1); rateLimiter.consume(LIMIT_ID_1, DEFAULT_CAPACITY); - + assertEq(rateLimiter.consumable(LIMIT_ID_1), 0); // Test refill accuracy over different time periods @@ -876,140 +874,122 @@ contract EtherFiRateLimiterTest is Test { // Reset state vm.prank(admin); rateLimiter.setRemaining(LIMIT_ID_1, 0); - + // Advance time vm.warp(block.timestamp + timeIntervals[i]); - + // Calculate expected refill uint64 expectedRefill = uint64(timeIntervals[i] * DEFAULT_REFILL_RATE); if (expectedRefill > DEFAULT_CAPACITY) { expectedRefill = DEFAULT_CAPACITY; } - - assertEq(rateLimiter.consumable(LIMIT_ID_1), expectedRefill, - string(abi.encodePacked("Failed at time interval: ", vm.toString(timeIntervals[i])))); + + assertEq(rateLimiter.consumable(LIMIT_ID_1), expectedRefill, string(abi.encodePacked("Failed at time interval: ", vm.toString(timeIntervals[i])))); } } //-------------------------------------------------------------------------------------- //------------------------------- Fuzz Tests ----------------------------------------- //-------------------------------------------------------------------------------------- - + /// @dev Fuzz test for creating limiters with random valid parameters - function testFuzz_createLimiterWithRandomParameters( - uint64 capacity, - uint64 refillRate, - bytes32 limitId - ) public { + function testFuzz_createLimiterWithRandomParameters(uint64 capacity, uint64 refillRate, bytes32 limitId) public { vm.assume(limitId != bytes32(0)); // Avoid zero limit ID - + vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, refillRate); - + assertTrue(rateLimiter.limitExists(limitId)); - - (uint64 actualCapacity, uint64 remaining, uint64 actualRefillRate, uint256 lastRefill) = - rateLimiter.getLimit(limitId); - + + (uint64 actualCapacity, uint64 remaining, uint64 actualRefillRate, uint256 lastRefill) = rateLimiter.getLimit(limitId); + assertEq(actualCapacity, capacity); assertEq(remaining, capacity); // Should start full assertEq(actualRefillRate, refillRate); assertEq(lastRefill, block.timestamp); } - + /// @dev Fuzz test for consumption with random valid amounts - function testFuzz_consumeRandomAmounts( - uint64 capacity, - uint64 refillRate, - uint64 consumeAmount - ) public { + function testFuzz_consumeRandomAmounts(uint64 capacity, uint64 refillRate, uint64 consumeAmount) public { vm.assume(capacity > 0); // Need some capacity to consume vm.assume(consumeAmount <= capacity); // Must be within capacity - + bytes32 limitId = keccak256("FUZZ_LIMIT"); - + // Setup vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, refillRate); - + vm.prank(admin); rateLimiter.updateConsumers(limitId, consumer1, true); - + // Consume vm.prank(consumer1); rateLimiter.consume(limitId, consumeAmount); - + // Verify remaining assertEq(rateLimiter.consumable(limitId), capacity - consumeAmount); } - + /// @dev Fuzz test for consumption exceeding capacity should always revert - function testFuzz_consumeExceedingCapacityReverts( - uint64 capacity, - uint64 excessAmount - ) public { + function testFuzz_consumeExceedingCapacityReverts(uint64 capacity, uint64 excessAmount) public { vm.assume(excessAmount > capacity); // Amount must exceed capacity - + bytes32 limitId = keccak256("FUZZ_LIMIT_EXCEED"); - + // Setup vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, 1000); - + vm.prank(admin); rateLimiter.updateConsumers(limitId, consumer1, true); - + // Should revert vm.prank(consumer1); vm.expectRevert(IEtherFiRateLimiter.LimitExceeded.selector); rateLimiter.consume(limitId, excessAmount); - + // Capacity should remain unchanged assertEq(rateLimiter.consumable(limitId), capacity); } - + /// @dev Fuzz test for time-based refill with random time advances - function testFuzz_timeBasedRefillWithRandomTime( - uint64 capacity, - uint64 refillRate, - uint64 consumeAmount, - uint256 timeAdvance - ) public { + function testFuzz_timeBasedRefillWithRandomTime(uint64 capacity, uint64 refillRate, uint64 consumeAmount, uint256 timeAdvance) public { vm.assume(capacity > 0); vm.assume(consumeAmount <= capacity); vm.assume(timeAdvance > 0 && timeAdvance < 365 days); // Reasonable time bounds - + bytes32 limitId = keccak256("FUZZ_TIME_REFILL"); - + // Setup vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, refillRate); - + vm.prank(admin); rateLimiter.updateConsumers(limitId, consumer1, true); - + // Consume some amount vm.prank(consumer1); rateLimiter.consume(limitId, consumeAmount); - + uint64 remainingAfterConsume = capacity - consumeAmount; - + // Advance time vm.warp(block.timestamp + timeAdvance); - + // Calculate expected refill (capped at original capacity) // Use checked arithmetic to prevent overflow uint256 expectedRefill; - + // Prevent multiplication overflow if (refillRate > 0 && timeAdvance > type(uint256).max / refillRate) { expectedRefill = type(uint256).max; // Overflow case } else { expectedRefill = timeAdvance * refillRate; } - + uint64 expectedRemaining; - + if (expectedRefill > type(uint64).max) { expectedRemaining = capacity; // Overflow protection } else if (remainingAfterConsume > capacity) { @@ -1022,77 +1002,69 @@ contract EtherFiRateLimiterTest is Test { expectedRemaining = uint64(totalRemaining); } } - + assertEq(rateLimiter.consumable(limitId), expectedRemaining); } - + /// @dev Fuzz test for multiple sequential consumptions - function testFuzz_multipleSequentialConsumptions( - uint64 capacity, - uint8 numConsumptions, - uint64 seed - ) public { + function testFuzz_multipleSequentialConsumptions(uint64 capacity, uint8 numConsumptions, uint64 seed) public { vm.assume(capacity > 0); vm.assume(numConsumptions > 0 && numConsumptions <= 20); // Reasonable number - + bytes32 limitId = keccak256(abi.encodePacked("FUZZ_MULTI", seed)); - + // Setup vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(limitId, consumer1, true); - + uint64 totalConsumed = 0; - + for (uint8 i = 0; i < numConsumptions; i++) { // Generate pseudo-random amount based on seed and iteration uint64 amount = uint64(uint256(keccak256(abi.encodePacked(seed, i))) % capacity); - + // Only consume if within remaining capacity if (amount <= rateLimiter.consumable(limitId)) { vm.prank(consumer1); rateLimiter.consume(limitId, amount); totalConsumed += amount; - + assertEq(rateLimiter.consumable(limitId), capacity - totalConsumed); } } } - + /// @dev Fuzz test for capacity updates with random values - function testFuzz_capacityUpdates( - uint64 initialCapacity, - uint64 newCapacity, - uint64 consumeAmount - ) public { + function testFuzz_capacityUpdates(uint64 initialCapacity, uint64 newCapacity, uint64 consumeAmount) public { vm.assume(initialCapacity > 0); vm.assume(consumeAmount <= initialCapacity); - + bytes32 limitId = keccak256("FUZZ_CAPACITY_UPDATE"); - + // Setup with initial capacity vm.prank(admin); rateLimiter.createNewLimiter(limitId, initialCapacity, DEFAULT_REFILL_RATE); - + vm.prank(admin); rateLimiter.updateConsumers(limitId, consumer1, true); - + // Consume some amount vm.prank(consumer1); rateLimiter.consume(limitId, consumeAmount); - + uint64 remainingAfterConsume = initialCapacity - consumeAmount; - + // Update capacity vm.prank(admin); rateLimiter.setCapacity(limitId, newCapacity); - + // Verify capacity update behavior (uint64 actualCapacity, uint64 remaining,,) = rateLimiter.getLimit(limitId); assertEq(actualCapacity, newCapacity); - + if (newCapacity < remainingAfterConsume) { // Remaining should be capped to new capacity assertEq(remaining, newCapacity); @@ -1101,41 +1073,36 @@ contract EtherFiRateLimiterTest is Test { assertEq(remaining, remainingAfterConsume); } } - + /// @dev Fuzz test for refill rate updates with time progression - function testFuzz_refillRateUpdates( - uint64 capacity, - uint64 initialRate, - uint64 newRate, - uint256 timeAdvance - ) public { + function testFuzz_refillRateUpdates(uint64 capacity, uint64 initialRate, uint64 newRate, uint256 timeAdvance) public { vm.assume(capacity > 0); vm.assume(timeAdvance > 0 && timeAdvance < 365 days); - + bytes32 limitId = keccak256("FUZZ_REFILL_RATE"); - + // Setup vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, initialRate); - + vm.prank(admin); rateLimiter.updateConsumers(limitId, consumer1, true); - + // Consume all capacity vm.prank(consumer1); rateLimiter.consume(limitId, capacity); - + // Update refill rate vm.prank(admin); rateLimiter.setRefillRate(limitId, newRate); - + // Advance time vm.warp(block.timestamp + timeAdvance); - + // Calculate expected refill with new rate uint256 expectedRefill = timeAdvance * newRate; uint64 expectedRemaining; - + if (expectedRefill > type(uint64).max) { expectedRemaining = capacity; } else if (uint64(expectedRefill) >= capacity) { @@ -1143,27 +1110,24 @@ contract EtherFiRateLimiterTest is Test { } else { expectedRemaining = uint64(expectedRefill); } - + assertEq(rateLimiter.consumable(limitId), expectedRemaining); } - + /// @dev Fuzz test for remaining amount updates - function testFuzz_remainingUpdates( - uint64 capacity, - uint64 newRemaining - ) public { + function testFuzz_remainingUpdates(uint64 capacity, uint64 newRemaining) public { vm.assume(capacity > 0); - + bytes32 limitId = keccak256("FUZZ_REMAINING"); - + // Setup vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, DEFAULT_REFILL_RATE); - + // Update remaining vm.prank(admin); rateLimiter.setRemaining(limitId, newRemaining); - + // Verify remaining was set correctly // Note: setRemaining caps the value to capacity if newRemaining > capacity uint64 expectedRemaining = newRemaining > capacity ? capacity : newRemaining; @@ -1171,60 +1135,52 @@ contract EtherFiRateLimiterTest is Test { assertEq(actualRemaining, expectedRemaining); assertEq(rateLimiter.consumable(limitId), expectedRemaining); } - + /// @dev Fuzz test for edge cases with very large numbers - function testFuzz_edgeCasesLargeNumbers( - uint64 capacity, - uint64 refillRate - ) public { + function testFuzz_edgeCasesLargeNumbers(uint64 capacity, uint64 refillRate) public { // Test behavior with maximum uint64 values vm.assume(capacity > 0 || refillRate > 0); // At least one must be non-zero for meaningful test - + bytes32 limitId = keccak256("FUZZ_LARGE_NUMBERS"); - + vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, refillRate); - + assertTrue(rateLimiter.limitExists(limitId)); - - (uint64 actualCapacity, uint64 remaining, uint64 actualRefillRate,) = - rateLimiter.getLimit(limitId); - + + (uint64 actualCapacity, uint64 remaining, uint64 actualRefillRate,) = rateLimiter.getLimit(limitId); + assertEq(actualCapacity, capacity); assertEq(remaining, capacity); assertEq(actualRefillRate, refillRate); } - + /// @dev Fuzz test for consumer authorization with random addresses - function testFuzz_consumerAuthorization( - address randomConsumer, - uint64 capacity, - uint64 amount - ) public { + function testFuzz_consumerAuthorization(address randomConsumer, uint64 capacity, uint64 amount) public { vm.assume(randomConsumer != address(0)); vm.assume(randomConsumer != admin); vm.assume(capacity > 0); vm.assume(amount <= capacity); - + bytes32 limitId = keccak256("FUZZ_CONSUMER_AUTH"); - + // Setup vm.prank(admin); rateLimiter.createNewLimiter(limitId, capacity, DEFAULT_REFILL_RATE); - + // Random consumer should not be able to consume vm.prank(randomConsumer); vm.expectRevert(IEtherFiRateLimiter.InvalidConsumer.selector); rateLimiter.consume(limitId, amount); - + // Authorize the consumer vm.prank(admin); rateLimiter.updateConsumers(limitId, randomConsumer, true); - + // Now they should be able to consume vm.prank(randomConsumer); rateLimiter.consume(limitId, amount); - + assertEq(rateLimiter.consumable(limitId), capacity - amount); } } diff --git a/test/EtherFiRedemptionManager.t.sol b/test/EtherFiRedemptionManager.t.sol index 6188717cb..bf40c53bf 100644 --- a/test/EtherFiRedemptionManager.t.sol +++ b/test/EtherFiRedemptionManager.t.sol @@ -1,11 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "forge-std/console2.sol"; import "./TestSetup.sol"; +import "forge-std/console2.sol"; contract EtherFiRedemptionManagerTest is TestSetup { - address user = vm.addr(999); address op_admin = vm.addr(1000); @@ -20,7 +19,6 @@ contract EtherFiRedemptionManagerTest is TestSetup { vm.startPrank(roleRegistryInstance.owner()); roleRegistryInstance.grantRole(keccak256("ETHERFI_REDEMPTION_MANAGER_ADMIN_ROLE"), op_admin); vm.stopPrank(); - } function test_upgrade_only_by_owner() public { @@ -49,58 +47,50 @@ contract EtherFiRedemptionManagerTest is TestSetup { function test_lowwatermark_guardrail() public { vm.deal(user, 100 ether); - + assertEq(etherFiRedemptionManagerInstance.lowWatermarkInETH(), 0 ether); vm.prank(user); liquidityPoolInstance.deposit{value: 100 ether}(); vm.startPrank(owner); - etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(1_00); // 1% + etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(100); // 1% assertEq(etherFiRedemptionManagerInstance.lowWatermarkInETH(), 1 ether); - etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(50_00); // 50% + etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(5000); // 50% assertEq(etherFiRedemptionManagerInstance.lowWatermarkInETH(), 50 ether); - etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(100_00); // 100% + etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(10_000); // 100% assertEq(etherFiRedemptionManagerInstance.lowWatermarkInETH(), 100 ether); vm.expectRevert("INVALID"); - etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(100_01); // 100.01% + etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(10_001); // 100.01% } function test_admin_permission() public { vm.startPrank(alice); vm.expectRevert(); - etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(1_00); // 1% + etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(100); // 1% vm.expectRevert(); - etherFiRedemptionManagerInstance.setExitFeeSplitToTreasuryInBps(1_000); // 10% + etherFiRedemptionManagerInstance.setExitFeeSplitToTreasuryInBps(1000); // 10% vm.expectRevert(); etherFiRedemptionManagerInstance.setExitFeeBasisPoints(40); // 0.4% vm.expectRevert(); - etherFiRedemptionManagerInstance.setRefillRatePerSecond(1_00); // 1% + etherFiRedemptionManagerInstance.setRefillRatePerSecond(100); // 1% vm.expectRevert(); - etherFiRedemptionManagerInstance.setCapacity(1_00); // 1% + etherFiRedemptionManagerInstance.setCapacity(100); // 1% vm.expectRevert(); - etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(1_00); // 1% + etherFiRedemptionManagerInstance.setLowWatermarkInBpsOfTvl(100); // 1% vm.stopPrank(); } - function testFuzz_redeemEEth( - uint256 depositAmount, - uint256 redeemAmount, - uint256 exitFeeSplitBps, - uint16 exitFeeBps, - uint16 lowWatermarkBps - ) public { - + function testFuzz_redeemEEth(uint256 depositAmount, uint256 redeemAmount, uint256 exitFeeSplitBps, uint16 exitFeeBps, uint16 lowWatermarkBps) public { vm.assume(depositAmount >= redeemAmount); depositAmount = bound(depositAmount, 1 ether, 1000 ether); redeemAmount = bound(redeemAmount, 0.1 ether, depositAmount); - exitFeeSplitBps = bound(exitFeeSplitBps, 0, 10000); - exitFeeBps = uint16(bound(uint256(exitFeeBps), 0, 10000)); - lowWatermarkBps = uint16(bound(uint256(lowWatermarkBps), 0, 10000)); - + exitFeeSplitBps = bound(exitFeeSplitBps, 0, 10_000); + exitFeeBps = uint16(bound(uint256(exitFeeBps), 0, 10_000)); + lowWatermarkBps = uint16(bound(uint256(lowWatermarkBps), 0, 10_000)); vm.deal(user, depositAmount); vm.startPrank(user); @@ -122,25 +112,16 @@ contract EtherFiRedemptionManagerTest is TestSetup { if (etherFiRedemptionManagerInstance.canRedeem(redeemAmount)) { uint256 userBalanceBefore = address(user).balance; uint256 treasuryBalanceBefore = eETHInstance.balanceOf(address(treasuryInstance)); - - IeETH.PermitInput memory permit = eEth_createPermitInput(999, address(etherFiRedemptionManagerInstance), redeemAmount, eETHInstance.nonces(user), 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + + IeETH.PermitInput memory permit = eEth_createPermitInput(999, address(etherFiRedemptionManagerInstance), redeemAmount, eETHInstance.nonces(user), 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); etherFiRedemptionManagerInstance.redeemEEthWithPermit(redeemAmount, user, permit); - uint256 totalFee = (redeemAmount * exitFeeBps) / 10000; - uint256 treasuryFee = (totalFee * exitFeeSplitBps) / 10000; + uint256 totalFee = (redeemAmount * exitFeeBps) / 10_000; + uint256 treasuryFee = (totalFee * exitFeeSplitBps) / 10_000; uint256 userReceives = redeemAmount - totalFee; - assertApproxEqAbs( - eETHInstance.balanceOf(address(treasuryInstance)), - treasuryBalanceBefore + treasuryFee, - 1e2 - ); - assertApproxEqAbs( - address(user).balance, - userBalanceBefore + userReceives, - 1e2 - ); - + assertApproxEqAbs(eETHInstance.balanceOf(address(treasuryInstance)), treasuryBalanceBefore + treasuryFee, 1e2); + assertApproxEqAbs(address(user).balance, userBalanceBefore + userReceives, 1e2); } else { vm.expectRevert(); etherFiRedemptionManagerInstance.redeemEEth(redeemAmount, user); @@ -148,21 +129,14 @@ contract EtherFiRedemptionManagerTest is TestSetup { vm.stopPrank(); } - function testFuzz_redeemWeEth( - uint256 depositAmount, - uint256 redeemAmount, - uint16 exitFeeSplitBps, - int256 rebase, - uint16 exitFeeBps, - uint16 lowWatermarkBps - ) public { + function testFuzz_redeemWeEth(uint256 depositAmount, uint256 redeemAmount, uint16 exitFeeSplitBps, int256 rebase, uint16 exitFeeBps, uint16 lowWatermarkBps) public { // Bound the parameters depositAmount = bound(depositAmount, 1 ether, 1000 ether); console2.log(depositAmount); redeemAmount = bound(redeemAmount, 0.1 ether, depositAmount); - exitFeeSplitBps = uint16(bound(exitFeeSplitBps, 0, 10000)); - exitFeeBps = uint16(bound(exitFeeBps, 0, 10000)); - lowWatermarkBps = uint16(bound(lowWatermarkBps, 0, 10000)); + exitFeeSplitBps = uint16(bound(exitFeeSplitBps, 0, 10_000)); + exitFeeBps = uint16(bound(exitFeeBps, 0, 10_000)); + lowWatermarkBps = uint16(bound(lowWatermarkBps, 0, 10_000)); rebase = bound(rebase, 0, int128(uint128(depositAmount) / 10)); // Deal Ether to user and perform deposit @@ -197,24 +171,15 @@ contract EtherFiRedemptionManagerTest is TestSetup { uint256 eEthAmount = liquidityPoolInstance.amountForShare(weEthAmount); - IWeETH.PermitInput memory permit = weEth_createPermitInput(999, address(etherFiRedemptionManagerInstance), weEthAmount, weEthInstance.nonces(user), 2**256 - 1, weEthInstance.DOMAIN_SEPARATOR()); + IWeETH.PermitInput memory permit = weEth_createPermitInput(999, address(etherFiRedemptionManagerInstance), weEthAmount, weEthInstance.nonces(user), 2 ** 256 - 1, weEthInstance.DOMAIN_SEPARATOR()); etherFiRedemptionManagerInstance.redeemWeEthWithPermit(weEthAmount, user, permit); - uint256 totalFee = (eEthAmount * exitFeeBps) / 10000; - uint256 treasuryFee = (totalFee * exitFeeSplitBps) / 10000; + uint256 totalFee = (eEthAmount * exitFeeBps) / 10_000; + uint256 treasuryFee = (totalFee * exitFeeSplitBps) / 10_000; uint256 userReceives = eEthAmount - totalFee; - assertApproxEqAbs( - eETHInstance.balanceOf(address(treasuryInstance)), - treasuryBalanceBefore + treasuryFee, - 1e2 - ); - assertApproxEqAbs( - address(user).balance, - userBalanceBefore + userReceives, - 1e2 - ); - + assertApproxEqAbs(eETHInstance.balanceOf(address(treasuryInstance)), treasuryBalanceBefore + treasuryFee, 1e2); + assertApproxEqAbs(address(user).balance, userBalanceBefore + userReceives, 1e2); } else { vm.expectRevert(); etherFiRedemptionManagerInstance.redeemWeEth(weEthAmount, user); @@ -296,9 +261,9 @@ contract EtherFiRedemptionManagerTest is TestSetup { function test_mainnet_redeem_eEth() public { setUp_Fork(); - vm.deal(alice, 100000 ether); + vm.deal(alice, 100_000 ether); vm.prank(alice); - liquidityPoolInstance.deposit{value: 100000 ether}(); + liquidityPoolInstance.deposit{value: 100_000 ether}(); vm.deal(user, 100 ether); vm.startPrank(user); @@ -329,9 +294,9 @@ contract EtherFiRedemptionManagerTest is TestSetup { function test_mainnet_redeem_weEth_with_rebase() public { setUp_Fork(); - vm.deal(alice, 50000 ether); + vm.deal(alice, 50_000 ether); vm.prank(alice); - liquidityPoolInstance.deposit{value: 50000 ether}(); + liquidityPoolInstance.deposit{value: 50_000 ether}(); vm.deal(user, 100 ether); @@ -353,11 +318,11 @@ contract EtherFiRedemptionManagerTest is TestSetup { uint256 treasuryBalance = eETHInstance.balanceOf(address(treasuryInstance)); weEthInstance.approve(address(etherFiRedemptionManagerInstance), 1 ether); etherFiRedemptionManagerInstance.redeemWeEth(weEthAmount, user); - + uint256 totalFee = (eEthAmount * 1e2) / 1e4; uint256 treasuryFee = (totalFee * 1e3) / 1e4; uint256 userReceives = eEthAmount - totalFee; - + assertApproxEqAbs(eETHInstance.balanceOf(address(treasuryInstance)), treasuryBalance + treasuryFee, 1e1); assertApproxEqAbs(address(user).balance, userBalance + userReceives, 1e1); diff --git a/test/EtherFiRestaker.t.sol b/test/EtherFiRestaker.t.sol index 7ddc1f2e9..2323466d2 100644 --- a/test/EtherFiRestaker.t.sol +++ b/test/EtherFiRestaker.t.sol @@ -7,12 +7,11 @@ import "forge-std/Test.sol"; import "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; import "../src/eigenlayer-interfaces/IDelegationManager.sol"; -import "../src/eigenlayer-interfaces/IStrategyManager.sol"; -import "../src/eigenlayer-interfaces/ISignatureUtils.sol"; +import "../src/eigenlayer-interfaces/ISignatureUtils.sol"; +import "../src/eigenlayer-interfaces/IStrategyManager.sol"; contract EtherFiRestakerTest is TestSetup { - address avsOperator; address avsOperator2; address etherfiOperatingAdmin; @@ -25,7 +24,6 @@ contract EtherFiRestakerTest is TestSetup { avsOperator = 0x5ACCC90436492F24E6aF278569691e2c942A676d; // EigenYields avsOperator2 = 0xfB487f216CA24162119C0C6Ae015d680D7569C2f; etherfiOperatingAdmin = alice; // - vm.prank(owner); liquifierInstance.updateQuoteStEthWithCurve(false); } @@ -38,14 +36,13 @@ contract EtherFiRestakerTest is TestSetup { uint256 aliceEEthBalance = eETHInstance.balanceOf(alice); vm.deal(alice, _amount); - vm.startPrank(alice); + vm.startPrank(alice); stEth.submit{value: _amount}(address(0)); stEth.approve(address(liquifierInstance), _amount); liquifierInstance.depositWithERC20(address(stEth), _amount, address(0)); - // Aliice has 10 ether eETH // Total eETH TVL is 10 ether assertApproxEqAbs(stEth.balanceOf(alice), aliceStEthBalance, 2 wei); @@ -69,7 +66,7 @@ contract EtherFiRestakerTest is TestSetup { uint256 stEthBalance = stEth.balanceOf(address(etherFiRestakerInstance)); uint256[] memory reqIds = etherFiRestakerInstance.stEthRequestWithdrawal(stEthBalance); vm.stopPrank(); - + assertApproxEqAbs(etherFiRestakerInstance.getAmountPendingForRedemption(address(stEth)), amount, 2 wei); assertApproxEqAbs(etherFiRestakerInstance.getTotalPooledEther(), amount, 2 wei); assertApproxEqAbs(liquidityPoolInstance.getTotalPooledEther(), lpTvl + amount, 2 wei); @@ -81,7 +78,7 @@ contract EtherFiRestakerTest is TestSetup { vm.startPrank(finalize_role); uint256 currentRate = stEth.getTotalPooledEther() * 1e27 / stEth.getTotalShares(); (uint256 ethToLock, uint256 sharesToBurn) = etherFiRestakerInstance.lidoWithdrawalQueue().prefinalize(reqIds, currentRate); - etherFiRestakerInstance.lidoWithdrawalQueue().finalize(reqIds[reqIds.length-1], currentRate); + etherFiRestakerInstance.lidoWithdrawalQueue().finalize(reqIds[reqIds.length - 1], currentRate); vm.stopPrank(); assertApproxEqAbs(etherFiRestakerInstance.getAmountPendingForRedemption(address(stEth)), amount, 2 wei); @@ -107,11 +104,10 @@ contract EtherFiRestakerTest is TestSetup { _deposit_stEth(10 ether); - vm.startPrank(alice); + vm.startPrank(alice); etherFiRestakerInstance.depositIntoStrategy(address(stEth), 5 ether); vm.stopPrank(); - assertApproxEqAbs(etherFiRestakerInstance.getRestakedAmount(address(stEth)), currentStEthRestakedAmount + 5 ether, 2 wei); } @@ -127,14 +123,10 @@ contract EtherFiRestakerTest is TestSetup { IStrategy[] memory strategies = new IStrategy[](1); strategies[0] = etherFiRestakerInstance.getEigenLayerRestakingStrategy(address(stEth)); - (uint256[] memory withdrawableShares, ) = eigenLayerDelegationManager.getWithdrawableShares(address(etherFiRestakerInstance), strategies); - + (uint256[] memory withdrawableShares,) = eigenLayerDelegationManager.getWithdrawableShares(address(etherFiRestakerInstance), strategies); + IDelegationManagerTypes.QueuedWithdrawalParams[] memory params = new IDelegationManagerTypes.QueuedWithdrawalParams[](1); - params[0] = IDelegationManagerTypes.QueuedWithdrawalParams({ - strategies: strategies, - depositShares: withdrawableShares, - __deprecated_withdrawer: address(etherFiRestakerInstance) - }); + params[0] = IDelegationManagerTypes.QueuedWithdrawalParams({strategies: strategies, depositShares: withdrawableShares, __deprecated_withdrawer: address(etherFiRestakerInstance)}); vm.prank(etherfiOperatingAdmin); return etherFiRestakerInstance.queueWithdrawalsWithParams(params); @@ -146,30 +138,30 @@ contract EtherFiRestakerTest is TestSetup { // Get the queued withdrawal details from EigenLayer (IDelegationManager.Withdrawal memory withdrawal, uint256[] memory shares) = eigenLayerDelegationManager.getQueuedWithdrawal(withdrawalRoots[0]); - + vm.startPrank(etherfiOperatingAdmin); - + // It won't complete the withdrawal because the withdrawal is still pending (not enough blocks passed) IDelegationManager.Withdrawal[] memory withdrawals = new IDelegationManager.Withdrawal[](1); withdrawals[0] = withdrawal; - + IERC20[][] memory tokens = new IERC20[][](1); tokens[0] = new IERC20[](1); tokens[0][0] = IERC20(address(stEth)); - + // This should fail because withdrawal delay hasn't passed vm.expectRevert(); etherFiRestakerInstance.completeQueuedWithdrawals(withdrawals, tokens); - + assertTrue(etherFiRestakerInstance.isPendingWithdrawal(withdrawalRoots[0])); // Fast forward past the withdrawal delay (100800 blocks + 1 since it's exclusive) - vm.roll(block.number + 100800 + 1); + vm.roll(block.number + 100_800 + 1); // Now the withdrawal should complete successfully etherFiRestakerInstance.completeQueuedWithdrawals(withdrawals, tokens); assertFalse(etherFiRestakerInstance.isPendingWithdrawal(withdrawalRoots[0])); - + vm.stopPrank(); } @@ -177,7 +169,7 @@ contract EtherFiRestakerTest is TestSetup { bytes32[] memory withdrawalRoots1 = test_queueWithdrawals_1(); // Fast forward halfway through the withdrawal delay - vm.roll(block.number + 50400); + vm.roll(block.number + 50_400); bytes32[] memory withdrawalRoots2 = test_queueWithdrawals_1(); @@ -186,54 +178,51 @@ contract EtherFiRestakerTest is TestSetup { // Fast forward so the first withdrawal is completable (total 100800 + 1 blocks from first withdrawal start) // This means 50400 + 1 more blocks from current position - vm.roll(block.number + 50400 + 1); + vm.roll(block.number + 50_400 + 1); // Get the queued withdrawal details from EigenLayer - (IDelegationManager.Withdrawal memory withdrawal1, ) = eigenLayerDelegationManager.getQueuedWithdrawal(withdrawalRoots1[0]); - (IDelegationManager.Withdrawal memory withdrawal2, ) = eigenLayerDelegationManager.getQueuedWithdrawal(withdrawalRoots2[0]); + (IDelegationManager.Withdrawal memory withdrawal1,) = eigenLayerDelegationManager.getQueuedWithdrawal(withdrawalRoots1[0]); + (IDelegationManager.Withdrawal memory withdrawal2,) = eigenLayerDelegationManager.getQueuedWithdrawal(withdrawalRoots2[0]); vm.startPrank(etherfiOperatingAdmin); - + // The first withdrawal should be completable now (100800 + 1 blocks have passed since it was queued) // But the second withdrawal is still pending (only 50400 + 1 blocks have passed) IDelegationManager.Withdrawal[] memory withdrawals1 = new IDelegationManager.Withdrawal[](1); withdrawals1[0] = withdrawal1; - + IERC20[][] memory tokens1 = new IERC20[][](1); tokens1[0] = new IERC20[](1); tokens1[0][0] = IERC20(address(stEth)); - + // Complete the first withdrawal etherFiRestakerInstance.completeQueuedWithdrawals(withdrawals1, tokens1); assertFalse(etherFiRestakerInstance.isPendingWithdrawal(withdrawalRoots1[0])); assertTrue(etherFiRestakerInstance.isPendingWithdrawal(withdrawalRoots2[0])); - // Fast forward another 50400 blocks so the second withdrawal can be completed + // Fast forward another 50400 blocks so the second withdrawal can be completed // (total 100800 + 1 blocks from its start) - vm.roll(block.number + 50400); + vm.roll(block.number + 50_400); // Now complete the second withdrawal IDelegationManager.Withdrawal[] memory withdrawals2 = new IDelegationManager.Withdrawal[](1); withdrawals2[0] = withdrawal2; - + IERC20[][] memory tokens2 = new IERC20[][](1); tokens2[0] = new IERC20[](1); tokens2[0][0] = IERC20(address(stEth)); - + etherFiRestakerInstance.completeQueuedWithdrawals(withdrawals2, tokens2); assertFalse(etherFiRestakerInstance.isPendingWithdrawal(withdrawalRoots1[0])); assertFalse(etherFiRestakerInstance.isPendingWithdrawal(withdrawalRoots2[0])); - + vm.stopPrank(); } function test_delegate_to() public { _deposit_stEth(10 ether); - ISignatureUtilsMixinTypes.SignatureWithExpiry memory signature = ISignatureUtilsMixinTypes.SignatureWithExpiry({ - signature: hex"", - expiry: 0 - }); + ISignatureUtilsMixinTypes.SignatureWithExpiry memory signature = ISignatureUtilsMixinTypes.SignatureWithExpiry({signature: hex"", expiry: 0}); vm.startPrank(etherfiOperatingAdmin); etherFiRestakerInstance.delegateTo(avsOperator, signature, 0x0); @@ -248,14 +237,11 @@ contract EtherFiRestakerTest is TestSetup { etherFiRestakerInstance.undelegate(); } - // + // function test_change_operator() public { test_delegate_to(); - ISignatureUtilsMixinTypes.SignatureWithExpiry memory signature = ISignatureUtilsMixinTypes.SignatureWithExpiry({ - signature: hex"", - expiry: 0 - }); + ISignatureUtilsMixinTypes.SignatureWithExpiry memory signature = ISignatureUtilsMixinTypes.SignatureWithExpiry({signature: hex"", expiry: 0}); vm.startPrank(etherfiOperatingAdmin); vm.expectRevert("ActivelyDelegated()"); @@ -276,5 +262,4 @@ contract EtherFiRestakerTest is TestSetup { assertEq(eigenLayerRewardsCoordinator.claimerFor(address(restaker)), _claimer); } - } diff --git a/test/EtherFiTimelock.sol b/test/EtherFiTimelock.sol index 0c13b4769..add93429e 100644 --- a/test/EtherFiTimelock.sol +++ b/test/EtherFiTimelock.sol @@ -1,12 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "./TestSetup.sol"; import "../src/EtherFiTimelock.sol"; +import "./TestSetup.sol"; import "forge-std/console2.sol"; contract TimelockTest is TestSetup { - function test_timelock() public { initializeRealisticFork(MAINNET_FORK); @@ -47,10 +46,10 @@ contract TimelockTest is TestSetup { vm.expectRevert("TimelockController: operation is not ready"); tl.execute( address(managerInstance), // target - 0, // value - data, // encoded call data - 0, // optional predecessor - 0 // optional salt + 0, // value + data, // encoded call data + 0, // optional predecessor + 0 // optional salt ); // not allowed to schedule a tx below the minimum delay @@ -58,22 +57,22 @@ contract TimelockTest is TestSetup { vm.expectRevert("TimelockController: insufficient delay"); tl.schedule( address(managerInstance), // target - 0, // value - data, // encoded call data - 0, // optional predecessor - 0, // optional salt - 1 days // time before operation can be run + 0, // value + data, // encoded call data + 0, // optional predecessor + 0, // optional salt + 1 days // time before operation can be run ); // schedule updateAdmin tx vm.prank(owner); tl.schedule( address(managerInstance), // target - 0, // value - data, // encoded call data - 0, // optional predecessor - 0, // optional salt - 2 days // time before operation can be run + 0, // value + data, // encoded call data + 0, // optional predecessor + 0, // optional salt + 2 days // time before operation can be run ); // find operation id by hashing relevant data @@ -91,21 +90,21 @@ contract TimelockTest is TestSetup { vm.expectRevert("TimelockController: operation is not ready"); tl.execute( address(managerInstance), // target - 0, // value - data, // encoded call data - 0, // optional predecessor - 0 // optional salt + 0, // value + data, // encoded call data + 0, // optional predecessor + 0 // optional salt ); // schedule again and wait vm.prank(owner); tl.schedule( address(managerInstance), // target - 0, // value - data, // encoded call data - 0, // optional predecessor - 0, // optional salt - 2 days // time before operation can be run + 0, // value + data, // encoded call data + 0, // optional predecessor + 0, // optional salt + 2 days // time before operation can be run ); vm.warp(block.timestamp + 2 days); @@ -114,23 +113,22 @@ contract TimelockTest is TestSetup { vm.expectRevert("AccessControl: account 0xcf03dd0a894ef79cb5b601a43c4b25e3ae4c67ed is missing role 0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63"); tl.execute( address(managerInstance), // target - 0, // value - data, // encoded call data - 0, // optional predecessor - 0 // optional salt + 0, // value + data, // encoded call data + 0, // optional predecessor + 0 // optional salt ); // exec account should be able to execute tx vm.prank(owner); tl.execute( address(managerInstance), // target - 0, // value - data, // encoded call data - 0, // optional predecessor - 0 // optional salt + 0, // value + data, // encoded call data + 0, // optional predecessor + 0 // optional salt ); - // TODO(dave): update test with role registry changes /* // admin account should now have admin permissions on EtherfiNodesManager @@ -216,7 +214,7 @@ contract TimelockTest is TestSetup { } function test_generate_EtherFiOracle_updateAdmin() public { - emit Schedule(address(etherFiOracleInstance), 0, abi.encodeWithSelector(bytes4(keccak256("updateAdmin(address,bool)")), 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC, true), bytes32(0), bytes32(0), 259200); + emit Schedule(address(etherFiOracleInstance), 0, abi.encodeWithSelector(bytes4(keccak256("updateAdmin(address,bool)")), 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC, true), bytes32(0), bytes32(0), 259_200); } function test_registerToken() internal { @@ -225,12 +223,12 @@ contract TimelockTest is TestSetup { { // MODE - bytes memory data = abi.encodeWithSelector(Liquifier.registerToken.selector, 0xDc400f3da3ea5Df0B7B6C127aE2e54CE55644CF3, address(0), true, 0, 2_000, 10_000, true); + bytes memory data = abi.encodeWithSelector(Liquifier.registerToken.selector, 0xDc400f3da3ea5Df0B7B6C127aE2e54CE55644CF3, address(0), true, 0, 2000, 10_000, true); _execute_timelock(target, data, false, false, true, true); } { // LINEA - bytes memory data = abi.encodeWithSelector(Liquifier.registerToken.selector, 0x61Ff310aC15a517A846DA08ac9f9abf2A0f9A2bf, address(0), true, 0, 2_000, 10_000, true); + bytes memory data = abi.encodeWithSelector(Liquifier.registerToken.selector, 0x61Ff310aC15a517A846DA08ac9f9abf2A0f9A2bf, address(0), true, 0, 2000, 10_000, true); _execute_timelock(target, data, false, false, true, true); } } @@ -239,19 +237,19 @@ contract TimelockTest is TestSetup { initializeRealisticFork(MAINNET_FORK); address target = address(liquifierInstance); { - bytes memory data = abi.encodeWithSelector(Liquifier.updateDepositCap.selector, 0x83998e169026136760bE6AF93e776C2F352D4b28, 4_000, 20_000); + bytes memory data = abi.encodeWithSelector(Liquifier.updateDepositCap.selector, 0x83998e169026136760bE6AF93e776C2F352D4b28, 4000, 20_000); _execute_timelock(target, data, false, false, true, true); } { - bytes memory data = abi.encodeWithSelector(Liquifier.updateDepositCap.selector, 0xDc400f3da3ea5Df0B7B6C127aE2e54CE55644CF3, 4_000, 20_000); + bytes memory data = abi.encodeWithSelector(Liquifier.updateDepositCap.selector, 0xDc400f3da3ea5Df0B7B6C127aE2e54CE55644CF3, 4000, 20_000); _execute_timelock(target, data, false, false, true, true); } { - bytes memory data = abi.encodeWithSelector(Liquifier.updateDepositCap.selector, 0x0295E0CE709723FB25A28b8f67C54a488BA5aE46, 1_000, 100_000); + bytes memory data = abi.encodeWithSelector(Liquifier.updateDepositCap.selector, 0x0295E0CE709723FB25A28b8f67C54a488BA5aE46, 1000, 100_000); _execute_timelock(target, data, true, true, true, false); } { - bytes memory data = abi.encodeWithSelector(Liquifier.updateDepositCap.selector, 0xDc400f3da3ea5Df0B7B6C127aE2e54CE55644CF3, 1_000, 100_000); + bytes memory data = abi.encodeWithSelector(Liquifier.updateDepositCap.selector, 0xDc400f3da3ea5Df0B7B6C127aE2e54CE55644CF3, 1000, 100_000); _execute_timelock(target, data, true, true, true, false); } } @@ -304,7 +302,7 @@ contract TimelockTest is TestSetup { bytes memory data = abi.encodeWithSelector(EtherFiNodesManager.updateAllowedForwardedExternalCalls.selector, selector, 0x7750d328b314EfFa365A0402CcfD489B80B0adda, true); _execute_timelock(target, data, true, true, true, true); } - + function test_update_treasury() public { initializeRealisticFork(MAINNET_FORK); { @@ -317,7 +315,7 @@ contract TimelockTest is TestSetup { function test_upgrade_liquifier() public { initializeRealisticFork(MAINNET_FORK); address new_impl = 0xA1A15FB15cbda9E6c480C5bca6E9ABA9C5E2ff95; - { + { assertEq(new_impl, computeAddressByCreate2(address(create2factory), type(Liquifier).creationCode, keccak256("ETHER_FI"))); address target = address(liquifierInstance); bytes memory data = abi.encodeWithSelector(UUPSUpgradeable.upgradeTo.selector, new_impl); @@ -366,7 +364,7 @@ contract TimelockTest is TestSetup { _execute_timelock(target, data, true, true, true, true); } - function test_update_committee_members() public { + function test_update_committee_members() public { initializeRealisticFork(MAINNET_FORK); address etherfi_oracle1 = address(0x6d850af8e7AB3361CfF28b31C701647414b9C92b); address etherfi_oracle2 = address(0x1a9AC2a6fC85A7234f9E21697C75D06B2b350864); @@ -375,13 +373,12 @@ contract TimelockTest is TestSetup { address target = address(etherFiOracleInstance); bytes memory data = abi.encodeWithSelector(EtherFiOracle.removeCommitteeMember.selector, etherfi_oracle1); _execute_timelock(target, data, true, true, true, true); - data = abi.encodeWithSelector(EtherFiOracle.removeCommitteeMember.selector, etherfi_oracle2); + data = abi.encodeWithSelector(EtherFiOracle.removeCommitteeMember.selector, etherfi_oracle2); _execute_timelock(target, data, true, true, true, true); data = abi.encodeWithSelector(EtherFiOracle.addCommitteeMember.selector, avs_etherfi_oracle1); _execute_timelock(target, data, true, true, true, true); data = abi.encodeWithSelector(EtherFiOracle.addCommitteeMember.selector, avs_etherfi_oracle2); _execute_timelock(target, data, true, true, true, true); - } function test_accept_ownership_role_registry() public { @@ -398,7 +395,7 @@ contract TimelockTest is TestSetup { address target = address(withdrawRequestNFTInstance); uint256 remainder = withdrawRequestNFTInstance.getEEthRemainderAmount(); - // Write remainder to a file + // Write remainder to a file string memory remainderStr = vm.toString(remainder); vm.writeFile("./release/logs/txns/remainder.txt", remainderStr); @@ -407,5 +404,4 @@ contract TimelockTest is TestSetup { } } - // {"version":"1.0","chainId":"1 diff --git a/test/EtherFiViewer.t.sol b/test/EtherFiViewer.t.sol index f8589fcd4..b96850a45 100644 --- a/test/EtherFiViewer.t.sol +++ b/test/EtherFiViewer.t.sol @@ -4,11 +4,10 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; import "forge-std/console.sol"; -import "../src/helpers/EtherFiViewer.sol"; import "../src/UUPSProxy.sol"; +import "../src/helpers/EtherFiViewer.sol"; -contract EtherFiViewerTest is Test { - +contract EtherFiViewerTest is Test { EtherFiViewer public etherFiViewer; address public eigenPodManager = address(0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338); address public delegationManager = address(0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A); @@ -38,11 +37,9 @@ contract EtherFiViewerTest is Test { function test_EigenPodManager_podOwnerDepositShares() public { uint256[] memory validatorIds = new uint256[](2); - validatorIds[0] = 25678; - validatorIds[1] = 29208; + validatorIds[0] = 25_678; + validatorIds[1] = 29_208; etherFiViewer.EigenPodManager_podOwnerDepositShares(validatorIds); } - - } diff --git a/test/LiquidityPool.t.sol b/test/LiquidityPool.t.sol index 969ecf62a..d9242f9c9 100644 --- a/test/LiquidityPool.t.sol +++ b/test/LiquidityPool.t.sol @@ -30,19 +30,13 @@ contract LiquidityPoolTest is TestSetup { nodeOperatorManagerInstance.updateAdmin(alice, true); // liquidityPoolInstance.updateAdmin(alice, true); vm.stopPrank(); - + vm.startPrank(alice); _setUpNodeOperatorWhitelist(); _approveNodeOperators(); - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 10000 - ); - bidIds = auctionInstance.createBid{value: 1 ether}( - 10, - 0.1 ether - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 10_000); + bidIds = auctionInstance.createBid{value: 1 ether}(10, 0.1 ether); vm.stopPrank(); } @@ -63,7 +57,6 @@ contract LiquidityPoolTest is TestSetup { } function test_StakingManagerLiquidityPool() public { - startHoax(alice); uint256 aliceBalBefore = alice.balance; liquidityPoolInstance.deposit{value: 1 ether}(); @@ -91,7 +84,7 @@ contract LiquidityPoolTest is TestSetup { vm.startPrank(alice); uint256 aliceNonce = eETHInstance.nonces(alice); // create permit with invalid private key (Bob) - ILiquidityPool.PermitInput memory permitInput = createPermitInput(3, address(liquidityPoolInstance), 2 ether, aliceNonce+1, 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(3, address(liquidityPoolInstance), 2 ether, aliceNonce + 1, 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); vm.expectRevert("TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); //even through the reason was invalid permit to prevent griefing attack the allowance fails liquidityPoolInstance.requestWithdrawWithPermit(alice, 2 ether, permitInput); vm.stopPrank(); @@ -108,13 +101,12 @@ contract LiquidityPoolTest is TestSetup { vm.startPrank(alice); uint256 aliceNonce = eETHInstance.nonces(alice); // permit with insufficient amount of ETH - ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(liquidityPoolInstance), 1 ether, aliceNonce, 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(liquidityPoolInstance), 1 ether, aliceNonce, 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); vm.expectRevert("TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); liquidityPoolInstance.requestWithdrawWithPermit(alice, 2 ether, permitInput); vm.stopPrank(); } - function test_WithdrawLiquidityPoolSuccess() public { vm.deal(alice, 3 ether); vm.startPrank(alice); @@ -142,12 +134,12 @@ contract LiquidityPoolTest is TestSetup { vm.startPrank(alice); uint256 aliceNonce = eETHInstance.nonces(alice); // alice priv key = 2 - ILiquidityPool.PermitInput memory permitInputAlice = createPermitInput(2, address(liquidityPoolInstance), 2 ether, aliceNonce, 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInputAlice = createPermitInput(2, address(liquidityPoolInstance), 2 ether, aliceNonce, 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); uint256 aliceReqId = liquidityPoolInstance.requestWithdrawWithPermit(alice, 2 ether, permitInputAlice); vm.stopPrank(); - + _finalizeWithdrawalRequest(aliceReqId); - + vm.startPrank(alice); withdrawRequestNFTInstance.claimWithdraw(aliceReqId); assertEq(eETHInstance.balanceOf(alice), 1 ether); @@ -157,7 +149,7 @@ contract LiquidityPoolTest is TestSetup { vm.startPrank(bob); uint256 bobNonce = eETHInstance.nonces(bob); // bob priv key = 3 - ILiquidityPool.PermitInput memory permitInputBob = createPermitInput(3, address(liquidityPoolInstance), 2 ether, bobNonce, 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInputBob = createPermitInput(3, address(liquidityPoolInstance), 2 ether, bobNonce, 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); uint256 bobReqId = liquidityPoolInstance.requestWithdrawWithPermit(bob, 2 ether, permitInputBob); vm.stopPrank(); @@ -173,7 +165,7 @@ contract LiquidityPoolTest is TestSetup { function test_WithdrawLiquidityPoolFails() public { vm.deal(bob, 100 ether); vm.startPrank(bob); - liquidityPoolInstance.deposit{value: 100 ether}(); + liquidityPoolInstance.deposit{value: 100 ether}(); vm.stopPrank(); startHoax(alice); @@ -186,7 +178,7 @@ contract LiquidityPoolTest is TestSetup { vm.deal(alice, 10 ether); vm.prank(bob); - liquidityPoolInstance.deposit{value: 100 ether}(); + liquidityPoolInstance.deposit{value: 100 ether}(); vm.prank(bob); eETHInstance.approve(address(liquidityPoolInstance), 100 ether); @@ -244,23 +236,22 @@ contract LiquidityPoolTest is TestSetup { assertEq(eETHInstance.balanceOf(alice), 3 ether); assertEq(eETHInstance.balanceOf(bob), 3 ether); - (bool sent, ) = address(liquidityPoolInstance).call{value: 1 ether}(""); + (bool sent,) = address(liquidityPoolInstance).call{value: 1 ether}(""); assertEq(sent, true); assertEq(eETHInstance.balanceOf(alice), 3 ether); assertEq(eETHInstance.balanceOf(bob), 3 ether); - (sent, ) = address(liquidityPoolInstance).call{value: 1 ether}(""); + (sent,) = address(liquidityPoolInstance).call{value: 1 ether}(""); assertEq(sent, true); assertEq(eETHInstance.balanceOf(alice), 3 ether); assertEq(eETHInstance.balanceOf(bob), 3 ether); - (sent, ) = address(liquidityPoolInstance).call{value: 1 ether}(""); + (sent,) = address(liquidityPoolInstance).call{value: 1 ether}(""); assertEq(sent, false); assertEq(eETHInstance.balanceOf(alice), 3 ether); assertEq(eETHInstance.balanceOf(bob), 3 ether); } - function test_sendExitRequestFails() public { uint256[] memory newValidators = new uint256[](10); vm.expectRevert(LiquidityPool.IncorrectRole.selector); @@ -285,7 +276,7 @@ contract LiquidityPoolTest is TestSetup { vm.deal(alice, 3 ether); vm.prank(alice); - (bool sent, ) = address(liquidityPoolInstance).call{value: 1 ether}(""); + (bool sent,) = address(liquidityPoolInstance).call{value: 1 ether}(""); assertEq(address(liquidityPoolInstance).balance, 100 ether + 1 ether); assertEq(sent, true); @@ -294,19 +285,19 @@ contract LiquidityPoolTest is TestSetup { function test_RegisterAsBnftHolder() public { //Move past one week - vm.warp(804650); + vm.warp(804_650); vm.expectRevert(LiquidityPool.IncorrectRole.selector); liquidityPoolInstance.registerValidatorSpawner(alice); - + //Let Alice sign up as a BNFT holder vm.startPrank(alice); registerAsBnftHolder(alice); vm.stopPrank(); - bool registered= liquidityPoolInstance.validatorSpawner(alice); + bool registered = liquidityPoolInstance.validatorSpawner(alice); assertEq(registered, true); } - + // TODO(Dave): update for new deposit flow /* function test_DepositAsBnftHolderSimple() public { @@ -411,7 +402,6 @@ contract LiquidityPoolTest is TestSetup { liquidityPoolInstance.unregisterValidatorSpawner(owner); } - // TODO(Dave): update for new deposit flow /* function test_DepositWhenUserDeRegisters() public { @@ -669,8 +659,6 @@ contract LiquidityPoolTest is TestSetup { } */ - - // TODO(dave): update when v3 changes finalized /* @@ -752,7 +740,7 @@ contract LiquidityPoolTest is TestSetup { liquidityPoolInstance.pauseContract(); assertTrue(liquidityPoolInstance.paused()); - + vm.expectRevert(LiquidityPool.IncorrectRole.selector); liquidityPoolInstance.unPauseContract(); diff --git a/test/Liquifier.t.sol b/test/Liquifier.t.sol index ba666f015..7ca976a25 100644 --- a/test/Liquifier.t.sol +++ b/test/Liquifier.t.sol @@ -10,7 +10,6 @@ import "../src/eigenlayer-interfaces/IDelegationManager.sol"; import "../src/eigenlayer-interfaces/IStrategyManager.sol"; contract DummyERC20 is ERC20BurnableUpgradeable { - function mint(address to, uint256 amount) public { _mint(to, amount); } @@ -26,14 +25,12 @@ interface IWBETH { } contract LiquifierTest is TestSetup { - uint256 public testnetFork; DummyERC20 public dummyToken; - address public l1SyncPool = address(100000); + address public l1SyncPool = address(100_000); - function setUp() public { - } + function setUp() public {} function _setUp(uint8 forkEnum) internal { initializeTestingFork(forkEnum); @@ -67,14 +64,14 @@ contract LiquifierTest is TestSetup { initializeRealisticFork(MAINNET_FORK); setUpLiquifier(MAINNET_FORK); - vm.deal(alice, 1000000000 ether); + vm.deal(alice, 1_000_000_000 ether); vm.startPrank(alice); - stEth.submit{value: 100000 ether + 1 ether}(address(0)); - stEth.approve(address(liquifierInstance), 100000 ether); + stEth.submit{value: 100_000 ether + 1 ether}(address(0)); + stEth.approve(address(liquifierInstance), 100_000 ether); vm.expectRevert("CAPPED"); - liquifierInstance.depositWithERC20(address(stEth), 100000 ether, address(0)); + liquifierInstance.depositWithERC20(address(stEth), 100_000 ether, address(0)); vm.stopPrank(); } @@ -132,13 +129,13 @@ contract LiquifierTest is TestSetup { assertEq(eETHInstance.balanceOf(alice), 0); vm.startPrank(alice); - + // Alice minted 2 stETH stEth.submit{value: 2 ether}(address(0)); - // But, she noticed that eETH is a much better choice + // But, she noticed that eETH is a much better choice // and decided to convert her stETH to eETH - + // Deposit 1 stETH after approvals stEth.approve(address(liquifierInstance), 1 ether - 1); vm.expectRevert("ALLOWANCE_EXCEEDED"); @@ -148,12 +145,12 @@ contract LiquifierTest is TestSetup { liquifierInstance.depositWithERC20(address(stEth), 1 ether, address(0)); // Deposit 1 stETH with the approval signature - ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(liquifierInstance), 1 ether - 1, stEth.nonces(alice), 2**256 - 1, stEth.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(liquifierInstance), 1 ether - 1, stEth.nonces(alice), 2 ** 256 - 1, stEth.DOMAIN_SEPARATOR()); ILiquifier.PermitInput memory permitInput2 = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); vm.expectRevert("ALLOWANCE_EXCEEDED"); liquifierInstance.depositWithERC20WithPermit(address(stEth), 1 ether, address(0), permitInput2); - permitInput = createPermitInput(2, address(liquifierInstance), 1 ether, stEth.nonces(alice), 2**256 - 1, stEth.DOMAIN_SEPARATOR()); + permitInput = createPermitInput(2, address(liquifierInstance), 1 ether, stEth.nonces(alice), 2 ** 256 - 1, stEth.DOMAIN_SEPARATOR()); permitInput2 = ILiquifier.PermitInput({value: permitInput.value, deadline: permitInput.deadline, v: permitInput.v, r: permitInput.r, s: permitInput.s}); liquifierInstance.depositWithERC20WithPermit(address(stEth), 1 ether, address(0), permitInput2); } @@ -165,7 +162,7 @@ contract LiquifierTest is TestSetup { vm.startPrank(role); eigenLayerStrategyManager.unpause(0); strategyTVLLimits.unpause(0); - strategyTVLLimits.setTVLLimits(1_000_000_0 ether, 1_000_000_0 ether); + strategyTVLLimits.setTVLLimits(10_000_000 ether, 10_000_000 ether); vm.stopPrank(); } @@ -350,7 +347,6 @@ contract LiquifierTest is TestSetup { vm.prank(owner); liquifierInstance.unPauseContract(); - } function test_getTotalPooledEther() public { diff --git a/test/MembershipManager.t.sol b/test/MembershipManager.t.sol index 36d0c8e7e..4c6a42af6 100644 --- a/test/MembershipManager.t.sol +++ b/test/MembershipManager.t.sol @@ -5,7 +5,6 @@ import "./TestSetup.sol"; import "forge-std/console2.sol"; contract MembershipManagerTest is TestSetup { - bytes32[] public emptyProof; function setUp() public { @@ -21,7 +20,6 @@ contract MembershipManagerTest is TestSetup { vm.prank(admin); withdrawRequestNFTInstance.unPauseContract(); - _upgradeMembershipManagerFromV0ToV1(); } @@ -80,11 +78,10 @@ contract MembershipManagerTest is TestSetup { assertEq(membershipNftInstance.balanceOf(bob, bobToken), 0); } - function test_batchClaimWithdraw() public { vm.prank(alice); membershipManagerV1Instance.setFeeAmounts(0 ether, 0.5 ether, 0 ether, 30); - + vm.deal(bob, 100 ether); vm.startPrank(bob); @@ -109,7 +106,6 @@ contract MembershipManagerTest is TestSetup { assertEq(address(bob).balance, 100 ether - 2 * 0.5 ether); } - // Note that 1 ether membership points earns 1 kwei (10 ** 6) points a day function test_HowPointsGrow() public { vm.deal(alice, 2 ether); @@ -161,7 +157,7 @@ contract MembershipManagerTest is TestSetup { vm.startPrank(alice); withdrawRequestNFTInstance.claimWithdraw(aliceRequestId2); - assertEq(membershipNftInstance.balanceOf(alice, tokenId), 0); + assertEq(membershipNftInstance.balanceOf(alice, tokenId), 0); assertEq(alice.balance, 2 ether); vm.stopPrank(); } @@ -239,7 +235,7 @@ contract MembershipManagerTest is TestSetup { function test_EapMigrationFails() public { /// @notice This test uses ETH to test the withdrawal and deposit flow due to the complexity of deploying a local wETH/ERC20 pool for swaps - // Alice claims her funds after the snapshot has been taken. + // Alice claims her funds after the snapshot has been taken. // She then deposits her ETH into the MembershipManager and has her points allocated to her // Alice deposit into EAP @@ -253,7 +249,7 @@ contract MembershipManagerTest is TestSetup { vm.stopPrank(); /// SNAPSHOT FROM PYTHON SCRIPT GETS TAKEN HERE - // Alice's Points are 103680 + // Alice's Points are 103680 /// MERKLE TREE GETS GENERATED AND UPDATED vm.prank(alice); @@ -271,44 +267,23 @@ contract MembershipManagerTest is TestSetup { vm.startPrank(alice); vm.expectRevert(MembershipManager.InvalidEAPRollover.selector); - membershipManagerV1Instance.wrapEthForEap{value: 0.5 ether}( - 1 ether, - 0, - 16970393 - 10, - 1 ether, - 103680, - aliceProof - ); + membershipManagerV1Instance.wrapEthForEap{value: 0.5 ether}(1 ether, 0, 16_970_393 - 10, 1 ether, 103_680, aliceProof); vm.expectRevert(MembershipManager.InvalidEAPRollover.selector); - membershipManagerV1Instance.wrapEthForEap{value: 3.0 ether}( - 1 ether, - 2 ether, - 16970393 - 10, - 1 ether, - 103680, - aliceProof - ); + membershipManagerV1Instance.wrapEthForEap{value: 3.0 ether}(1 ether, 2 ether, 16_970_393 - 10, 1 ether, 103_680, aliceProof); vm.expectRevert(MembershipManager.InvalidEAPRollover.selector); - membershipManagerV1Instance.wrapEthForEap{value: 1 ether}( - 1 ether, - 0, - 16970393 - 10, - 1 ether, - 0, - aliceProof - ); + membershipManagerV1Instance.wrapEthForEap{value: 1 ether}(1 ether, 0, 16_970_393 - 10, 1 ether, 0, aliceProof); vm.stopPrank(); } function test_EapMigrationWorks() internal { - vm.warp(1689764603 - 8 weeks); - vm.roll(17726813 - (8 weeks) / 12); + vm.warp(1_689_764_603 - 8 weeks); + vm.roll(17_726_813 - (8 weeks) / 12); /// @notice This test uses ETH to test the withdrawal and deposit flow due to the complexity of deploying a local wETH/ERC20 pool for swaps - // Alice claims her funds after the snapshot has been taken. + // Alice claims her funds after the snapshot has been taken. // She then deposits her ETH into the MembershipManager and has her points allocated to her // Actors deposit into EAP @@ -324,13 +299,13 @@ contract MembershipManagerTest is TestSetup { vm.stopPrank(); /// SNAPSHOT FROM PYTHON SCRIPT GETS TAKEN HERE - // Alice's Points are 103680 + // Alice's Points are 103680 /// MERKLE TREE GETS GENERATED AND UPDATED vm.prank(alice); membershipNftInstance.setUpForEap(rootMigration2, requiredEapPointsPerEapDeposit); - vm.roll(17664247 + 1 weeks / 12); + vm.roll(17_664_247 + 1 weeks / 12); // Alice Withdraws vm.startPrank(alice); @@ -339,16 +314,16 @@ contract MembershipManagerTest is TestSetup { // Alice Deposits into MembershipManager and receives eETH in return bytes32[] memory aliceProof; - + vm.deal(alice, 100 ether); startHoax(alice); - + uint256 tokenId = membershipManagerV1Instance.wrapEthForEap{value: 2 ether}( 2 ether, 0, - 16970393 - 10, // 10 blocks before the last gold + 16_970_393 - 10, // 10 blocks before the last gold 1 ether, - 103680, + 103_680, aliceProof ); vm.stopPrank(); @@ -427,13 +402,13 @@ contract MembershipManagerTest is TestSetup { vm.deal(alice, 1000 ether); vm.startPrank(owner); vm.expectRevert(MembershipManager.OnlyAdmin.selector); - membershipManagerV1Instance.updatePointsParams(123, 12345); + membershipManagerV1Instance.updatePointsParams(123, 12_345); vm.expectRevert(MembershipManager.OnlyAdmin.selector); - membershipManagerV1Instance.updatePointsParams(123, 12345); + membershipManagerV1Instance.updatePointsParams(123, 12_345); vm.stopPrank(); vm.startPrank(alice); - membershipManagerV1Instance.updatePointsParams(12345, 12345); + membershipManagerV1Instance.updatePointsParams(12_345, 12_345); vm.stopPrank(); } @@ -457,7 +432,7 @@ contract MembershipManagerTest is TestSetup { // points should get diluted by 25% & the tier is properly updated membershipManagerV1Instance.topUpDepositWithEth{value: 3 ether}(aliceToken, 3 ether, 0 ether); uint256 dilutedPoints = membershipNftInstance.tierPointsOf(aliceToken); - assertEq(dilutedPoints , currentPoints / 4); + assertEq(dilutedPoints, currentPoints / 4); assertEq(membershipNftInstance.tierOf(aliceToken), 1); assertEq(membershipNftInstance.tierOf(aliceToken), membershipManagerV1Instance.tierForPoints(uint40(dilutedPoints))); @@ -475,7 +450,7 @@ contract MembershipManagerTest is TestSetup { // points should not get diluted membershipManagerV1Instance.topUpDepositWithEth{value: 0.15 ether}(bobToken, 0.15 ether, 0 ether); dilutedPoints = membershipNftInstance.tierPointsOf(bobToken); - assertEq(dilutedPoints , currentPoints); + assertEq(dilutedPoints, currentPoints); vm.stopPrank(); } @@ -504,7 +479,7 @@ contract MembershipManagerTest is TestSetup { skip(28 days); - // Alice's NFT has 10 ether in total. + // Alice's NFT has 10 ether in total. // among 10 ether, 1 ether is stake for points (sacrificing the staking rewards) uint40 aliceTierPoints = membershipNftInstance.tierPointsOf(aliceToken); uint40 aliceLoyaltyPoints = membershipNftInstance.loyaltyPointsOf(aliceToken); @@ -555,7 +530,7 @@ contract MembershipManagerTest is TestSetup { assertEq(address(eETHInstance).balance, 0 ether); assertEq(address(membershipManagerV1Instance).balance, 0 ether); assertEq(address(alice).balance, 2 ether); - + assertEq(eETHInstance.balanceOf(address(liquidityPoolInstance)), 0 ether); assertEq(eETHInstance.balanceOf(address(eETHInstance)), 0 ether); assertEq(eETHInstance.balanceOf(address(membershipManagerV1Instance)), 10 ether); @@ -576,19 +551,19 @@ contract MembershipManagerTest is TestSetup { assertEq(address(eETHInstance).balance, 0 ether); assertEq(address(membershipManagerV1Instance).balance, 0 ether); assertEq(address(alice).balance, 0 ether); - + assertEq(eETHInstance.balanceOf(address(liquidityPoolInstance)), 0 ether); assertEq(eETHInstance.balanceOf(address(eETHInstance)), 0 ether); assertEq(eETHInstance.balanceOf(address(membershipManagerV1Instance)), 12 ether); assertEq(eETHInstance.balanceOf(alice), 0 ether); - assertEq(membershipNftInstance.valueOf(token2), 2 ether); + assertEq(membershipNftInstance.valueOf(token2), 2 ether); } function test_WrapEthFailsIfNotCorrectlyEligible() public { //NOTE: Test that wrappingETH fails in both scenarios listed below: - // 1. User is not whitelisted - // 2. User is whitelisted but not registered + // 1. User is not whitelisted + // 2. User is whitelisted but not registered //Giving 12 Ether to alice and henry vm.deal(henry, 12 ether); @@ -611,7 +586,7 @@ contract MembershipManagerTest is TestSetup { // vm.prank(alice); // liquidityPoolInstance.updateWhitelistedAddresses(addrs, true); - + vm.startPrank(henry); membershipManagerV1Instance.wrapEth{value: 10 ether}(10 ether, 0); } @@ -630,7 +605,7 @@ contract MembershipManagerTest is TestSetup { vm.startPrank(alice); // The points growth rate decreased to 5000 from 10000 - membershipManagerV1Instance.updatePointsParams(10000, 5000); + membershipManagerV1Instance.updatePointsParams(10_000, 5000); vm.stopPrank(); assertEq(membershipNftInstance.loyaltyPointsOf(aliceToken), 1 * kwei / 2); @@ -733,10 +708,10 @@ contract MembershipManagerTest is TestSetup { } function test_MixedDeposits() internal { - vm.warp(1689764603 - 8 weeks); - vm.roll(17726813 - (8 weeks) / 12); + vm.warp(1_689_764_603 - 8 weeks); + vm.roll(17_726_813 - (8 weeks) / 12); - // Alice claims her funds after the snapshot has been taken. + // Alice claims her funds after the snapshot has been taken. // She then deposits her ETH into the MembershipManager and has her points allocated to her // Then, she top-ups with ETH and eETH @@ -756,15 +731,15 @@ contract MembershipManagerTest is TestSetup { vm.deal(alice, 100 ether); bytes32[] memory aliceProof; - vm.roll(17664247 + 1 weeks / 12); + vm.roll(17_664_247 + 1 weeks / 12); // Alice Withdraws vm.startPrank(alice); earlyAdopterPoolInstance.withdraw(); // Alice Deposits into MembershipManager and receives membership points in return - uint256 tokenId = membershipManagerV1Instance.wrapEthForEap{value: 2 ether}(2 ether, 0, 16970393 - 10, 1 ether, 103680, aliceProof); - + uint256 tokenId = membershipManagerV1Instance.wrapEthForEap{value: 2 ether}(2 ether, 0, 16_970_393 - 10, 1 ether, 103_680, aliceProof); + assertEq(membershipNftInstance.valueOf(tokenId), 2 ether); assertEq(membershipNftInstance.tierOf(tokenId), 2); // Gold @@ -842,14 +817,14 @@ contract MembershipManagerTest is TestSetup { function test_trackAPR() public { vm.deal(alice, 1 ether); vm.deal(bob, 1 ether); - + // Both Alice & Bob mint the NFT with 1 ether vm.prank(alice); uint256 aliceToken = membershipManagerV1Instance.wrapEth{value: 1 ether}(1 ether, 0); vm.prank(bob); uint256 bobToken = membershipManagerV1Instance.wrapEth{value: 1 ether}(1 ether, 0); - // For testing purposes, + // For testing purposes, // - Bob's NFT is upgraded to tier 1, // - while Alice's NFT remain tier 0 // Note that tier 0 and tier 1 have weight 1 and weight 2, respectively. @@ -894,12 +869,12 @@ contract MembershipManagerTest is TestSetup { uint256 tier0GI2 = membershipManagerV1Instance.ethAmountForVaultShare(0, 1 ether); uint256 tier1GI2 = membershipManagerV1Instance.ethAmountForVaultShare(1, 1 ether); uint256 tier2GI2 = membershipManagerV1Instance.ethAmountForVaultShare(2, 1 ether); - + // Compute APRs - uint256 eETH_apr_bp = 10000 * (LpGI2 - LpGI1) / 1 ether * (365 days) / (t2 - t1); - uint256 tier0_apr_bp = 10000 * (tier0GI2 - tier0GI1) / 1 ether * (365 days) / (t2 - t1); - uint256 tier1_apr_bp = 10000 * (tier1GI2 - tier1GI1) / 1 ether * (365 days) / (t2 - t1); - uint256 tier2_apr_bp = 10000 * (tier2GI2 - tier2GI1) / 1 ether * (365 days) / (t2 - t1); + uint256 eETH_apr_bp = 10_000 * (LpGI2 - LpGI1) / 1 ether * (365 days) / (t2 - t1); + uint256 tier0_apr_bp = 10_000 * (tier0GI2 - tier0GI1) / 1 ether * (365 days) / (t2 - t1); + uint256 tier1_apr_bp = 10_000 * (tier1GI2 - tier1GI1) / 1 ether * (365 days) / (t2 - t1); + uint256 tier2_apr_bp = 10_000 * (tier2GI2 - tier2GI1) / 1 ether * (365 days) / (t2 - t1); assertEq(eETH_apr_bp, 5000); // 50.00% assertEq(tier0_apr_bp, 3333); // 33.33% for tier 0 with weight 1 @@ -907,8 +882,8 @@ contract MembershipManagerTest is TestSetup { assertEq(tier2_apr_bp, 0); // 00.00% for tier 2 with weight 3, because there is no deposited ETH in tier 2 } -// TODO(dave): does this break ether.fan? -/* + // TODO(dave): does this break ether.fan? + /* function calculateAggregatedTVL(uint256[] memory _validatorIds) internal view returns (uint256[] memory) { uint256[] memory tvls = new uint256[](4); @@ -976,7 +951,6 @@ contract MembershipManagerTest is TestSetup { membershipManagerV1Instance.rebase(50 ether); vm.stopPrank(); assertEq(membershipNftInstance.valueOf(aliceToken), 150 ether); - } function get_total_accrued_rewards(uint256[] memory tokens) internal view returns (uint256) { @@ -1002,7 +976,7 @@ contract MembershipManagerTest is TestSetup { vm.stopPrank(); uint256 rounds = 30; - uint256 moneyPerActor = 10000 ether; + uint256 moneyPerActor = 10_000 ether; uint256 moneyPerRebase = 10 ether; uint256 totalMoneySupply = moneyPerActor * actors.length + moneyPerRebase * rounds; @@ -1057,7 +1031,6 @@ contract MembershipManagerTest is TestSetup { vm.stopPrank(); } - } uint256 totalActorsBalance; @@ -1071,7 +1044,7 @@ contract MembershipManagerTest is TestSetup { uint256 requestId = membershipManagerV1Instance.requestWithdrawAndBurn(token); _finalizeWithdrawalRequest(requestId); - + vm.prank(actor); withdrawRequestNFTInstance.claimWithdraw(requestId); @@ -1097,47 +1070,46 @@ contract MembershipManagerTest is TestSetup { function test_eap_migration() public { // Jul-19-2023 13:03:23 - vm.warp(1689764603); - vm.roll(17726813); + vm.warp(1_689_764_603); + vm.roll(17_726_813); { // random EAP degen just for Silver - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(17664247 - 1); - assertEq( membershipManagerV1Instance.tierForPoints(tierPoints), 1); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(17_664_247 - 1); + assertEq(membershipManagerV1Instance.tierForPoints(tierPoints), 1); } { // 0x9b422e571eb2cb9837efdc4f9087194d65fb070a - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16744622); - assertEq( membershipManagerV1Instance.tierForPoints(tierPoints), 3); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_744_622); + assertEq(membershipManagerV1Instance.tierForPoints(tierPoints), 3); } { // 0x33bac50dfa950f79c59d85f9a4f07ca48f6e0b4c - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16926352); - assertEq( membershipManagerV1Instance.tierForPoints(tierPoints), 2); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_926_352); + assertEq(membershipManagerV1Instance.tierForPoints(tierPoints), 2); } { // 0xee1fe7053adf44f1daafe78afb05a5a032016458 - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16726561); - assertEq( membershipManagerV1Instance.tierForPoints(tierPoints), 3); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_726_561); + assertEq(membershipManagerV1Instance.tierForPoints(tierPoints), 3); } { // LAST person in Platinum // 0x484af812ef1c1a1771f1101d09e749c24a7b56a3 - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16755015); - assertEq( membershipManagerV1Instance.tierForPoints(tierPoints), 3); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_755_015); + assertEq(membershipManagerV1Instance.tierForPoints(tierPoints), 3); } { // LAST person in GOLD // 0x48e5112d85a51014e5b46bcd1af740a957f5f629 - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16970393); - assertEq( membershipManagerV1Instance.tierForPoints(tierPoints), 2); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_970_393); + assertEq(membershipManagerV1Instance.tierForPoints(tierPoints), 2); } - } function test_update_tier() public { @@ -1166,7 +1138,7 @@ contract MembershipManagerTest is TestSetup { assertEq(membershipNftInstance.valueOf(tokens[0]), 1 ether + 1 ether * uint256(10) / uint256(100) - 1); assertEq(membershipNftInstance.valueOf(tokens[1]), 1 ether + 1 ether * uint256(15) / uint256(100) - 1); - assertEq(membershipNftInstance.valueOf(tokens[2]), 1 ether + 1 ether * uint256(20) / uint256(100) ); + assertEq(membershipNftInstance.valueOf(tokens[2]), 1 ether + 1 ether * uint256(20) / uint256(100)); assertEq(membershipNftInstance.valueOf(tokens[3]), 1 ether + 1 ether * uint256(25) / uint256(100) - 1); assertEq(membershipNftInstance.valueOf(tokens[4]), 1 ether + 1 ether * uint256(30) / uint256(100) - 1); } @@ -1251,11 +1223,11 @@ contract MembershipManagerTest is TestSetup { vm.stopPrank(); // 10 : 15 : 20 : 25 : 30 ~= 285 : 428 : 571 : 714 : 857 - assertEq(10000 * membershipNftInstance.valueOf(tokens[0]) / ((0 + 1) * 1 ether), 10285); - assertEq(10000 * membershipNftInstance.valueOf(tokens[1]) / ((1 + 1) * 1 ether), 10428); - assertEq(10000 * membershipNftInstance.valueOf(tokens[2]) / ((2 + 1) * 1 ether), 10571); - assertEq(10000 * membershipNftInstance.valueOf(tokens[3]) / ((3 + 1) * 1 ether), 10714); - assertEq(10000 * membershipNftInstance.valueOf(tokens[4]) / ((4 + 1) * 1 ether), 10857); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[0]) / ((0 + 1) * 1 ether), 10_285); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[1]) / ((1 + 1) * 1 ether), 10_428); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[2]) / ((2 + 1) * 1 ether), 10_571); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[3]) / ((3 + 1) * 1 ether), 10_714); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[4]) / ((4 + 1) * 1 ether), 10_857); assertEq(eETHInstance.balanceOf(alice), 1 ether); } @@ -1290,7 +1262,7 @@ contract MembershipManagerTest is TestSetup { vm.startPrank(address(etherFiAdminInstance)); // 10 % loss in eETH - // eETH: 61 ETH -> -6.1 ETH + // eETH: 61 ETH -> -6.1 ETH // Ether.Fan: 5 ETH -> -0.5 ETH membershipManagerV1Instance.rebase(-6.6 ether); vm.stopPrank(); @@ -1335,7 +1307,7 @@ contract MembershipManagerTest is TestSetup { vm.startPrank(address(etherFiAdminInstance)); // 10 % gain in eETH - // eETH: 61 ETH -> +6.1 ETH + // eETH: 61 ETH -> +6.1 ETH // Ether.Fan: 5 ETH -> +0.5 ETH membershipManagerV1Instance.rebase(6.6 ether); vm.stopPrank(); @@ -1354,7 +1326,7 @@ contract MembershipManagerTest is TestSetup { // Set burn fee to 0.05 ether, burn fee waiver requirement as 30 days membershipManagerV1Instance.setFeeAmounts(0 ether, 0.05 ether, 0 ether, 30); - (, uint256 burnFee, ) = membershipManagerV1Instance.getFees(); + (, uint256 burnFee,) = membershipManagerV1Instance.getFees(); vm.deal(alice, 2 ether); diff --git a/test/MembershipManagerV0.t.sol b/test/MembershipManagerV0.t.sol index a9d70521e..8535b9557 100644 --- a/test/MembershipManagerV0.t.sol +++ b/test/MembershipManagerV0.t.sol @@ -5,8 +5,6 @@ import "./TestSetup.sol"; import "forge-std/console2.sol"; contract MembershipManagerV0Test is TestSetup { - - bytes32[] public emptyProof; function setUp() public { @@ -19,7 +17,6 @@ contract MembershipManagerV0Test is TestSetup { eETHInstance.approve(address(membershipManagerInstance), 1_000_000_000 ether); vm.stopPrank(); - vm.prank(admin); withdrawRequestNFTInstance.unPauseContract(); } @@ -89,8 +86,6 @@ contract MembershipManagerV0Test is TestSetup { assertEq(bob.balance, 100 ether, "Bob should have 100 ether"); assertEq(membershipNftInstance.balanceOf(bob, bobToken), 0); - - } // Note that 1 ether membership points earns 1 kwei (10 ** 6) points a day @@ -144,7 +139,7 @@ contract MembershipManagerV0Test is TestSetup { vm.startPrank(alice); withdrawRequestNFTInstance.claimWithdraw(aliceRequestId2); - assertEq(membershipNftInstance.balanceOf(alice, tokenId), 0); + assertEq(membershipNftInstance.balanceOf(alice, tokenId), 0); assertEq(alice.balance, 2 ether); vm.stopPrank(); } @@ -222,7 +217,7 @@ contract MembershipManagerV0Test is TestSetup { function test_EapMigrationFails() public { /// @notice This test uses ETH to test the withdrawal and deposit flow due to the complexity of deploying a local wETH/ERC20 pool for swaps - // Alice claims her funds after the snapshot has been taken. + // Alice claims her funds after the snapshot has been taken. // She then deposits her ETH into the MembershipManager and has her points allocated to her // Alice deposit into EAP @@ -236,7 +231,7 @@ contract MembershipManagerV0Test is TestSetup { vm.stopPrank(); /// SNAPSHOT FROM PYTHON SCRIPT GETS TAKEN HERE - // Alice's Points are 103680 + // Alice's Points are 103680 /// MERKLE TREE GETS GENERATED AND UPDATED vm.prank(alice); @@ -254,34 +249,13 @@ contract MembershipManagerV0Test is TestSetup { vm.startPrank(alice); vm.expectRevert(MembershipManager.InvalidEAPRollover.selector); - membershipManagerInstance.wrapEthForEap{value: 0.5 ether}( - 1 ether, - 0, - 16970393 - 10, - 1 ether, - 103680, - _aliceProof - ); + membershipManagerInstance.wrapEthForEap{value: 0.5 ether}(1 ether, 0, 16_970_393 - 10, 1 ether, 103_680, _aliceProof); vm.expectRevert(MembershipManager.InvalidEAPRollover.selector); - membershipManagerInstance.wrapEthForEap{value: 3.0 ether}( - 1 ether, - 2 ether, - 16970393 - 10, - 1 ether, - 103680, - _aliceProof - ); + membershipManagerInstance.wrapEthForEap{value: 3.0 ether}(1 ether, 2 ether, 16_970_393 - 10, 1 ether, 103_680, _aliceProof); vm.expectRevert(MembershipManager.InvalidEAPRollover.selector); - membershipManagerInstance.wrapEthForEap{value: 1 ether}( - 1 ether, - 0, - 16970393 - 10, - 1 ether, - 0, - _aliceProof - ); + membershipManagerInstance.wrapEthForEap{value: 1 ether}(1 ether, 0, 16_970_393 - 10, 1 ether, 0, _aliceProof); vm.stopPrank(); } @@ -350,17 +324,16 @@ contract MembershipManagerV0Test is TestSetup { vm.deal(alice, 1000 ether); vm.startPrank(owner); vm.expectRevert(MembershipManager.OnlyAdmin.selector); - membershipManagerInstance.updatePointsParams(123, 12345); + membershipManagerInstance.updatePointsParams(123, 12_345); vm.expectRevert(MembershipManager.OnlyAdmin.selector); - membershipManagerInstance.updatePointsParams(123, 12345); + membershipManagerInstance.updatePointsParams(123, 12_345); vm.stopPrank(); vm.startPrank(alice); - membershipManagerInstance.updatePointsParams(12345, 12345); + membershipManagerInstance.updatePointsParams(12_345, 12_345); vm.stopPrank(); } - function test_topUpDilution() public { vm.deal(alice, 100 ether); vm.deal(bob, 100 ether); @@ -381,7 +354,7 @@ contract MembershipManagerV0Test is TestSetup { // points should get diluted by 25% & the tier is properly updated membershipManagerInstance.topUpDepositWithEth{value: 3 ether}(aliceToken, 3 ether, 0 ether); uint256 dilutedPoints = membershipNftInstance.tierPointsOf(aliceToken); - assertEq(dilutedPoints , currentPoints / 4); + assertEq(dilutedPoints, currentPoints / 4); assertEq(membershipNftInstance.tierOf(aliceToken), 1); assertEq(membershipNftInstance.tierOf(aliceToken), membershipManagerInstance.tierForPoints(uint40(dilutedPoints))); @@ -399,7 +372,7 @@ contract MembershipManagerV0Test is TestSetup { // points should not get diluted membershipManagerInstance.topUpDepositWithEth{value: 0.15 ether}(bobToken, 0.15 ether, 0 ether); dilutedPoints = membershipNftInstance.tierPointsOf(bobToken); - assertEq(dilutedPoints , currentPoints); + assertEq(dilutedPoints, currentPoints); vm.stopPrank(); } @@ -428,7 +401,7 @@ contract MembershipManagerV0Test is TestSetup { skip(28 days); - // Alice's NFT has 10 ether in total. + // Alice's NFT has 10 ether in total. // among 10 ether, 1 ether is stake for points (sacrificing the staking rewards) uint40 aliceTierPoints = membershipNftInstance.tierPointsOf(aliceToken); uint40 aliceLoyaltyPoints = membershipNftInstance.loyaltyPointsOf(aliceToken); @@ -438,7 +411,6 @@ contract MembershipManagerV0Test is TestSetup { vm.stopPrank(); } - function test_wrapEth() public { vm.deal(alice, 12 ether); @@ -454,7 +426,7 @@ contract MembershipManagerV0Test is TestSetup { assertEq(address(eETHInstance).balance, 0 ether); assertEq(address(membershipManagerInstance).balance, 0 ether); assertEq(address(alice).balance, 2 ether); - + assertEq(eETHInstance.balanceOf(address(liquidityPoolInstance)), 0 ether); assertEq(eETHInstance.balanceOf(address(eETHInstance)), 0 ether); assertEq(eETHInstance.balanceOf(address(membershipManagerInstance)), 10 ether); @@ -475,19 +447,19 @@ contract MembershipManagerV0Test is TestSetup { assertEq(address(eETHInstance).balance, 0 ether); assertEq(address(membershipManagerInstance).balance, 0 ether); assertEq(address(alice).balance, 0 ether); - + assertEq(eETHInstance.balanceOf(address(liquidityPoolInstance)), 0 ether); assertEq(eETHInstance.balanceOf(address(eETHInstance)), 0 ether); assertEq(eETHInstance.balanceOf(address(membershipManagerInstance)), 12 ether); assertEq(eETHInstance.balanceOf(alice), 0 ether); - assertEq(membershipNftInstance.valueOf(token2), 2 ether); + assertEq(membershipNftInstance.valueOf(token2), 2 ether); } function test_WrapEthFailsIfNotCorrectlyEligible() public { //NOTE: Test that wrappingETH fails in both scenarios listed below: - // 1. User is not whitelisted - // 2. User is whitelisted but not registered + // 1. User is not whitelisted + // 2. User is whitelisted but not registered //Giving 12 Ether to alice and henry vm.deal(henry, 12 ether); @@ -517,7 +489,7 @@ contract MembershipManagerV0Test is TestSetup { vm.startPrank(alice); // The points growth rate decreased to 5000 from 10000 - membershipManagerInstance.updatePointsParams(10000, 5000); + membershipManagerInstance.updatePointsParams(10_000, 5000); vm.stopPrank(); assertEq(membershipNftInstance.loyaltyPointsOf(aliceToken), 1 * kwei / 2); @@ -676,14 +648,14 @@ contract MembershipManagerV0Test is TestSetup { function test_trackAPR() public { vm.deal(alice, 1 ether); vm.deal(bob, 1 ether); - + // Both Alice & Bob mint the NFT with 1 ether vm.prank(alice); uint256 aliceToken = membershipManagerInstance.wrapEth{value: 1 ether}(1 ether, 0); vm.prank(bob); uint256 bobToken = membershipManagerInstance.wrapEth{value: 1 ether}(1 ether, 0); - // For testing purposes, + // For testing purposes, // - Bob's NFT is upgraded to tier 1, // - while Alice's NFT remain tier 0 // Note that tier 0 and tier 1 have weight 1 and weight 2, respectively. @@ -728,12 +700,12 @@ contract MembershipManagerV0Test is TestSetup { uint256 tier0GI2 = membershipManagerInstance.rewardsGlobalIndex(0); uint256 tier1GI2 = membershipManagerInstance.rewardsGlobalIndex(1); uint256 tier2GI2 = membershipManagerInstance.rewardsGlobalIndex(2); - + // Compute APRs - uint256 eETH_apr_bp = 10000 * (LpGI2 - LpGI1) / 1 ether * (365 days) / (t2 - t1); - uint256 tier0_apr_bp = 10000 * (tier0GI2 - tier0GI1) / 1 ether * (365 days) / (t2 - t1); - uint256 tier1_apr_bp = 10000 * (tier1GI2 - tier1GI1) / 1 ether * (365 days) / (t2 - t1); - uint256 tier2_apr_bp = 10000 * (tier2GI2 - tier2GI1) / 1 ether * (365 days) / (t2 - t1); + uint256 eETH_apr_bp = 10_000 * (LpGI2 - LpGI1) / 1 ether * (365 days) / (t2 - t1); + uint256 tier0_apr_bp = 10_000 * (tier0GI2 - tier0GI1) / 1 ether * (365 days) / (t2 - t1); + uint256 tier1_apr_bp = 10_000 * (tier1GI2 - tier1GI1) / 1 ether * (365 days) / (t2 - t1); + uint256 tier2_apr_bp = 10_000 * (tier2GI2 - tier2GI1) / 1 ether * (365 days) / (t2 - t1); assertEq(eETH_apr_bp, 5000); // 50.00% assertEq(tier0_apr_bp, 3333); // 33.33% for tier 0 with weight 1 @@ -741,7 +713,7 @@ contract MembershipManagerV0Test is TestSetup { assertEq(tier2_apr_bp, 0); // 00.00% for tier 2 with weight 3, because there is no deposited ETH in tier 2 } -/* + /* function calculateAggregatedTVL(uint256[] memory _validatorIds) internal view returns (uint256[] memory) { uint256[] memory tvls = new uint256[](4); @@ -792,7 +764,7 @@ contract MembershipManagerV0Test is TestSetup { membershipManagerInstance.setPoints(aliceToken, uint40(28 * kwei), uint40(24 * 28)); assertEq(membershipNftInstance.tierOf(aliceToken), 1); - (amounts, ) = membershipManagerInstance.tokenDeposits(aliceToken); + (amounts,) = membershipManagerInstance.tokenDeposits(aliceToken); (, tier0Amounts) = membershipManagerInstance.tierDeposits(0); (, tier1Amounts) = membershipManagerInstance.tierDeposits(1); assertEq(amounts, 50 ether); @@ -812,47 +784,46 @@ contract MembershipManagerV0Test is TestSetup { function test_eap_migration() public { // Jul-19-2023 13:03:23 - vm.warp(1689764603); - vm.roll(17726813); + vm.warp(1_689_764_603); + vm.roll(17_726_813); { // random EAP degen just for Silver - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(17664247 - 1); - assertEq( membershipManagerInstance.tierForPoints(tierPoints), 1); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(17_664_247 - 1); + assertEq(membershipManagerInstance.tierForPoints(tierPoints), 1); } { // 0x9b422e571eb2cb9837efdc4f9087194d65fb070a - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16744622); - assertEq( membershipManagerInstance.tierForPoints(tierPoints), 3); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_744_622); + assertEq(membershipManagerInstance.tierForPoints(tierPoints), 3); } { // 0x33bac50dfa950f79c59d85f9a4f07ca48f6e0b4c - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16926352); - assertEq( membershipManagerInstance.tierForPoints(tierPoints), 2); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_926_352); + assertEq(membershipManagerInstance.tierForPoints(tierPoints), 2); } { // 0xee1fe7053adf44f1daafe78afb05a5a032016458 - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16726561); - assertEq( membershipManagerInstance.tierForPoints(tierPoints), 3); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_726_561); + assertEq(membershipManagerInstance.tierForPoints(tierPoints), 3); } { // LAST person in Platinum // 0x484af812ef1c1a1771f1101d09e749c24a7b56a3 - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16755015); - assertEq( membershipManagerInstance.tierForPoints(tierPoints), 3); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_755_015); + assertEq(membershipManagerInstance.tierForPoints(tierPoints), 3); } { // LAST person in GOLD // 0x48e5112d85a51014e5b46bcd1af740a957f5f629 - uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16970393); - assertEq( membershipManagerInstance.tierForPoints(tierPoints), 2); + uint40 tierPoints = membershipNftInstance.computeTierPointsForEap(16_970_393); + assertEq(membershipManagerInstance.tierForPoints(tierPoints), 2); } - } function test_update_tier() public { @@ -878,7 +849,7 @@ contract MembershipManagerV0Test is TestSetup { vm.startPrank(alice); membershipManagerInstance.rebase(1 ether); vm.stopPrank(); - + assertEq(membershipNftInstance.valueOf(tokens[0]), 1 ether + 1 ether * uint256(10) / uint256(100)); assertEq(membershipNftInstance.valueOf(tokens[1]), 1 ether + 1 ether * uint256(15) / uint256(100)); assertEq(membershipNftInstance.valueOf(tokens[2]), 1 ether + 1 ether * uint256(20) / uint256(100)); @@ -943,7 +914,7 @@ contract MembershipManagerV0Test is TestSetup { assertEq(membershipNftInstance.tierPointsOf(aliceToken2), 24); vm.startPrank(alice); - // Alice requests to withdraw 10 ETH + // Alice requests to withdraw 10 ETH reqId = membershipManagerV1Instance.requestWithdraw(aliceToken1, 10 ether); assertEq(membershipNftInstance.valueOf(aliceToken1), 190 ether); assertEq(membershipNftInstance.loyaltyPointsOf(aliceToken1), 50 * kwei); @@ -1008,7 +979,7 @@ contract MembershipManagerV0Test is TestSetup { } vm.stopPrank(); - _transferTo(address(membershipManagerInstance), 1 ether); + _transferTo(address(membershipManagerInstance), 1 ether); vm.startPrank(alice); membershipManagerInstance.rebase(0 ether); @@ -1030,7 +1001,7 @@ contract MembershipManagerV0Test is TestSetup { vm.startPrank(alice); // 10 % loss in eETH - // eETH: 61 ETH -> -6.1 ETH + // eETH: 61 ETH -> -6.1 ETH // Ether.Fan: 5 (principal) + 1 (earnings) ETH -> - 0.5 ETH + - 0.1 ETH membershipManagerInstance.rebase(-6.7 ether); vm.stopPrank(); @@ -1072,11 +1043,11 @@ contract MembershipManagerV0Test is TestSetup { vm.stopPrank(); // 10 : 15 : 20 : 25 : 30 ~= 285 : 428 : 571 : 714 : 857 - assertEq(10000 * membershipNftInstance.valueOf(tokens[0]) / ((0 + 1) * 1 ether), 10285); - assertEq(10000 * membershipNftInstance.valueOf(tokens[1]) / ((1 + 1) * 1 ether), 10428); - assertEq(10000 * membershipNftInstance.valueOf(tokens[2]) / ((2 + 1) * 1 ether), 10571); - assertEq(10000 * membershipNftInstance.valueOf(tokens[3]) / ((3 + 1) * 1 ether), 10714); - assertEq(10000 * membershipNftInstance.valueOf(tokens[4]) / ((4 + 1) * 1 ether), 10857); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[0]) / ((0 + 1) * 1 ether), 10_285); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[1]) / ((1 + 1) * 1 ether), 10_428); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[2]) / ((2 + 1) * 1 ether), 10_571); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[3]) / ((3 + 1) * 1 ether), 10_714); + assertEq(10_000 * membershipNftInstance.valueOf(tokens[4]) / ((4 + 1) * 1 ether), 10_857); } function test_rewards_distribution_for_V0_and_V1() public { @@ -1121,7 +1092,7 @@ contract MembershipManagerV0Test is TestSetup { uint256 accruedRewards = uint256(1 * liquidityPoolInstance.getTotalPooledEther()) / uint256(10); assertEq(liquidityPoolInstance.getTotalPooledEther(), 55 ether); assertEq(accruedRewards, 5.5 ether); - + vm.startPrank(address(etherFiAdminInstance)); membershipManagerV1Instance.rebase(int128(uint128(accruedRewards))); vm.stopPrank(); @@ -1137,6 +1108,5 @@ contract MembershipManagerV0Test is TestSetup { assertEq(membershipNftInstance.valueOf(v1_tokens[2]), v1_tokensValues[2] + 5 ether * uint256(20) / uint256(100)); assertEq(membershipNftInstance.valueOf(v1_tokens[3]), v1_tokensValues[3] + 5 ether * uint256(25) / uint256(100) - 1); assertEq(membershipNftInstance.valueOf(v1_tokens[4]), v1_tokensValues[4] + 5 ether * uint256(30) / uint256(100) - 1); - } } diff --git a/test/MembershipNFT.t.sol b/test/MembershipNFT.t.sol index d6493acc7..fea76971a 100644 --- a/test/MembershipNFT.t.sol +++ b/test/MembershipNFT.t.sol @@ -5,7 +5,6 @@ import "./TestSetup.sol"; import "forge-std/console2.sol"; contract MembershipNFTTest is TestSetup { - event MintingPaused(bool isPaused); function setUp() public { @@ -20,7 +19,6 @@ contract MembershipNFTTest is TestSetup { } function test_metadata() public { - // only admin can update uri vm.expectRevert("Caller is not the admin"); membershipNftInstance.setMetadataURI("badURI.com"); @@ -71,7 +69,6 @@ contract MembershipNFTTest is TestSetup { } function test_pauseMinting() public { - // only owner can set pause status vm.startPrank(owner); vm.expectRevert("Caller is not the admin"); @@ -105,12 +102,9 @@ contract MembershipNFTTest is TestSetup { // mint should succeed again vm.startPrank(address(membershipManagerInstance)); membershipNftInstance.mint(alice, 1); - - } function test_permissions() public { - // only membership manager can update call vm.startPrank(alice); vm.expectRevert(MembershipNFT.OnlyMembershipManagerContract.selector); diff --git a/test/NodeOperatorManager.t.sol b/test/NodeOperatorManager.t.sol index 8396dbea4..753f18b8d 100644 --- a/test/NodeOperatorManager.t.sol +++ b/test/NodeOperatorManager.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import "./TestSetup.sol"; import "../src/interfaces/ILiquidityPool.sol"; +import "./TestSetup.sol"; contract NodeOperatorManagerTest is TestSetup { event OperatorRegistered(address user, uint64 totalKeys, uint64 keysUsed, bytes ipfsHash); @@ -20,21 +20,11 @@ contract NodeOperatorManagerTest is TestSetup { nodeOperatorManagerInstance.pauseContract(); vm.expectRevert("Pausable: paused"); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - uint64(10) - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, uint64(10)); nodeOperatorManagerInstance.unPauseContract(); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - uint64(10) - ); - ( - uint64 totalKeys, - uint64 keysUsed, - bytes memory aliceHash - ) = nodeOperatorManagerInstance.addressToOperatorData(alice); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, uint64(10)); + (uint64 totalKeys, uint64 keysUsed, bytes memory aliceHash) = nodeOperatorManagerInstance.addressToOperatorData(alice); assertEq(aliceHash, abi.encodePacked(aliceIPFS_Hash)); assertEq(totalKeys, 10); @@ -44,14 +34,10 @@ contract NodeOperatorManagerTest is TestSetup { assertEq(nodeOperatorManagerInstance.isWhitelisted(alice), true); vm.expectRevert("Already registered"); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - uint64(10) - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, uint64(10)); } function test_RegisterNodeOperatorInMigration() public { - address[] memory operators = new address[](2); operators[0] = address(bob); operators[1] = address(alice); @@ -70,26 +56,12 @@ contract NodeOperatorManagerTest is TestSetup { vm.prank(bob); vm.expectRevert("Ownable: caller is not the owner"); - nodeOperatorManagerInstance.initializeOnUpgrade( - operators, - hashes, - totalKeys, - keysUsed - ); + nodeOperatorManagerInstance.initializeOnUpgrade(operators, hashes, totalKeys, keysUsed); vm.prank(owner); - nodeOperatorManagerInstance.initializeOnUpgrade( - operators, - hashes, - totalKeys, - keysUsed - ); - - ( - uint64 totalKeysUser, - uint64 keysUsedUser, - bytes memory bobHash - ) = nodeOperatorManagerInstance.addressToOperatorData(bob); + nodeOperatorManagerInstance.initializeOnUpgrade(operators, hashes, totalKeys, keysUsed); + + (uint64 totalKeysUser, uint64 keysUsedUser, bytes memory bobHash) = nodeOperatorManagerInstance.addressToOperatorData(bob); assertEq(bobHash, abi.encodePacked(bobIPFS_Hash)); assertEq(totalKeysUser, 10); @@ -99,21 +71,13 @@ contract NodeOperatorManagerTest is TestSetup { vm.prank(owner); vm.expectRevert("Already registered"); - nodeOperatorManagerInstance.initializeOnUpgrade( - operators, - hashes, - totalKeys, - keysUsed - ); + nodeOperatorManagerInstance.initializeOnUpgrade(operators, hashes, totalKeys, keysUsed); } function test_CanAddAddressToWhitelist() public { vm.startPrank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - uint64(10) - ); - + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, uint64(10)); + assertEq(nodeOperatorManagerInstance.isWhitelisted(jess), false); vm.stopPrank(); @@ -128,10 +92,7 @@ contract NodeOperatorManagerTest is TestSetup { function test_CanRemoveAddressFromWhitelist() public { vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - uint64(10) - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, uint64(10)); vm.expectRevert("Caller is not the admin"); vm.prank(owner); @@ -146,38 +107,26 @@ contract NodeOperatorManagerTest is TestSetup { vm.expectEmit(false, false, false, true); emit OperatorRegistered(address(alice), 10, 0, aliceIPFS_Hash); vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - 10 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, 10); } function test_FetchNextKeyIndex() public { vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - uint64(10) - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, uint64(10)); - (, uint64 keysUsed, ) = nodeOperatorManagerInstance - .addressToOperatorData(alice); + (, uint64 keysUsed,) = nodeOperatorManagerInstance.addressToOperatorData(alice); assertEq(keysUsed, 0); hoax(alice); auctionInstance.createBid{value: 0.1 ether}(1, 0.1 ether); - (, keysUsed, ) = nodeOperatorManagerInstance.addressToOperatorData( - alice - ); + (, keysUsed,) = nodeOperatorManagerInstance.addressToOperatorData(alice); assertEq(keysUsed, 1); startHoax(0xCd5EBC2dD4Cb3dc52ac66CEEcc72c838B40A5931); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - 1 - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, 1); vm.expectRevert("Insufficient public keys"); auctionInstance.createBid{value: 0.2 ether}(2, 0.1 ether); vm.stopPrank(); @@ -188,25 +137,17 @@ contract NodeOperatorManagerTest is TestSetup { } function test_CanOnlySetAddressesOnce() public { - vm.startPrank(owner); - vm.expectRevert("Address already set"); - nodeOperatorManagerInstance.setAuctionContractAddress( - address(0) - ); + vm.startPrank(owner); + vm.expectRevert("Address already set"); + nodeOperatorManagerInstance.setAuctionContractAddress(address(0)); } function test_SetStakingTypeApprovals() public { vm.prank(alice); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - uint64(10) - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, uint64(10)); vm.prank(bob); - nodeOperatorManagerInstance.registerNodeOperator( - aliceIPFS_Hash, - uint64(10) - ); + nodeOperatorManagerInstance.registerNodeOperator(aliceIPFS_Hash, uint64(10)); address[] memory users = new address[](2); users[0] = address(alice); @@ -257,6 +198,5 @@ contract NodeOperatorManagerTest is TestSetup { assertEq(nodeOperatorManagerInstance.operatorApprovedTags(address(alice), ILiquidityPool.SourceOfFunds.ETHER_FAN), true); assertEq(nodeOperatorManagerInstance.operatorApprovedTags(address(bob), ILiquidityPool.SourceOfFunds.EETH), true); assertEq(nodeOperatorManagerInstance.operatorApprovedTags(address(bob), ILiquidityPool.SourceOfFunds.ETHER_FAN), true); - } } diff --git a/test/RoleRegistry.t.sol b/test/RoleRegistry.t.sol index 377fc00c6..51fe135f6 100644 --- a/test/RoleRegistry.t.sol +++ b/test/RoleRegistry.t.sol @@ -1,178 +1,172 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.4; -import {Test} from "forge-std/Test.sol"; import {RoleRegistry} from "../src/RoleRegistry.sol"; import {UUPSProxy} from "../src/UUPSProxy.sol"; +import {Test} from "forge-std/Test.sol"; contract RoleRegistryTest is Test { RoleRegistry public implementation; RoleRegistry public registry; - + address public owner; address public user1; address public user2; - + bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); - event RoleSet(address indexed holder, uint256 indexed role, bool active); + event RoleSet(address indexed holder, uint256 indexed role, bool active); function setUp() public { owner = makeAddr("owner"); user1 = makeAddr("user1"); user2 = makeAddr("user2"); - + // Deploy implementation implementation = new RoleRegistry(); - + // Deploy proxy - bytes memory initData = abi.encodeWithSelector( - RoleRegistry.initialize.selector, - owner - ); - - UUPSProxy proxy = new UUPSProxy( - address(implementation), - initData - ); - + bytes memory initData = abi.encodeWithSelector(RoleRegistry.initialize.selector, owner); + + UUPSProxy proxy = new UUPSProxy(address(implementation), initData); + registry = RoleRegistry(address(proxy)); } - + function test_Initialization() public { assertEq(registry.owner(), owner); - + vm.expectRevert("Initializable: contract is already initialized"); registry.initialize(address(1)); } - + function test_GrantRole() public { vm.startPrank(owner); - + // Grant role registry.grantRole(ADMIN_ROLE, user1); assertTrue(registry.hasRole(ADMIN_ROLE, user1)); - + // Verify role holders address[] memory holders = registry.roleHolders(ADMIN_ROLE); assertEq(holders.length, 1); assertEq(holders[0], user1); - + vm.stopPrank(); } - + function test_RevokeRole() public { vm.startPrank(owner); - + // Grant and revoke role registry.grantRole(ADMIN_ROLE, user1); registry.revokeRole(ADMIN_ROLE, user1); - + assertFalse(registry.hasRole(ADMIN_ROLE, user1)); - + // Verify role holders is empty address[] memory holders = registry.roleHolders(ADMIN_ROLE); assertEq(holders.length, 0); - + vm.stopPrank(); } - + function test_CheckRoles() public { vm.startPrank(owner); - + // Grant multiple roles to user1 registry.grantRole(ADMIN_ROLE, user1); registry.grantRole(OPERATOR_ROLE, user1); - + // Encode roles for checking bytes memory encodedRoles = abi.encode(ADMIN_ROLE, OPERATOR_ROLE); - + // Should not revert registry.checkRoles(user1, encodedRoles); - + // Should revert for user2 who has no roles vm.expectRevert(); registry.checkRoles(user2, encodedRoles); - + vm.stopPrank(); } - + function test_OnlyOwnerCanGrantRoles() public { // Try to grant role as non-owner vm.startPrank(user1); vm.expectRevert(); registry.grantRole(ADMIN_ROLE, user2); vm.stopPrank(); - + // Verify role was not granted assertFalse(registry.hasRole(ADMIN_ROLE, user2)); } - + function test_OnlyOwnerCanRevokeRoles() public { // Setup: owner grants role vm.prank(owner); registry.grantRole(ADMIN_ROLE, user2); - + // Try to revoke role as non-owner vm.startPrank(user1); vm.expectRevert(); registry.revokeRole(ADMIN_ROLE, user2); vm.stopPrank(); - + // Verify role was not revoked assertTrue(registry.hasRole(ADMIN_ROLE, user2)); } - + function test_Upgradeability() public { // Deploy new implementation RoleRegistry newImplementation = new RoleRegistry(); - + // Only owner can upgrade vm.prank(user1); vm.expectRevert("Ownable: caller is not the owner"); registry.upgradeTo(address(newImplementation)); - + // Owner can upgrade vm.startPrank(owner); registry.upgradeTo(address(newImplementation)); - + registry.grantRole(ADMIN_ROLE, user1); assertTrue(registry.hasRole(ADMIN_ROLE, user1)); vm.stopPrank(); } - + function test_RoleEnumeration() public { vm.startPrank(owner); - + // Grant roles to multiple users registry.grantRole(ADMIN_ROLE, user1); registry.grantRole(ADMIN_ROLE, user2); - + // Check role holders address[] memory holders = registry.roleHolders(ADMIN_ROLE); assertEq(holders.length, 2); assertTrue(holders[0] == user1 || holders[1] == user1); assertTrue(holders[0] == user2 || holders[1] == user2); - + vm.stopPrank(); } - + function test_TwoStepOwnershipTransfer() public { // Start transfer vm.prank(owner); registry.transferOwnership(user1); - + // Verify pending owner assertEq(registry.pendingOwner(), user1); assertEq(registry.owner(), owner); - + // Accept transfer vm.prank(user1); registry.acceptOwnership(); - + // Verify new owner assertEq(registry.owner(), user1); assertEq(registry.pendingOwner(), address(0)); } -} \ No newline at end of file +} diff --git a/test/StakingManager.t.sol b/test/StakingManager.t.sol index 4e4d98d7c..896b0c70f 100644 --- a/test/StakingManager.t.sol +++ b/test/StakingManager.t.sol @@ -4,21 +4,9 @@ pragma solidity ^0.8.13; import "./TestSetup.sol"; contract StakingManagerTest is TestSetup { - event StakeDeposit( - address indexed staker, - uint256 indexed bidId, - address indexed withdrawSafe, - bool restaked - ); + event StakeDeposit(address indexed staker, uint256 indexed bidId, address indexed withdrawSafe, bool restaked); event DepositCancelled(uint256 id); - event ValidatorRegistered( - address indexed operator, - address indexed bNftOwner, - address indexed tNftOwner, - uint256 validatorId, - bytes validatorPubKey, - string ipfsHashForEncryptedValidatorKey - ); + event ValidatorRegistered(address indexed operator, address indexed bNftOwner, address indexed tNftOwner, uint256 validatorId, bytes validatorPubKey, string ipfsHashForEncryptedValidatorKey); uint256[] public processedBids; uint256[] public validatorArray; @@ -227,7 +215,7 @@ contract StakingManagerTest is TestSetup { bidIdArray[7] = 12; bidIdArray[8] = 19; bidIdArray[9] = 20; - + vm.expectRevert("NOT_ENOUGH_BIDS"); stakingManagerInstance.batchDepositWithBidIds{value: 32 ether}( bidIdArray, @@ -1317,4 +1305,3 @@ contract StakingManagerTest is TestSetup { } */ } - diff --git a/test/TNFT.t.sol b/test/TNFT.t.sol index 5aab94c2a..683da8dad 100644 --- a/test/TNFT.t.sol +++ b/test/TNFT.t.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.13; import "./TestSetup.sol"; contract TnftTest is TestSetup { - function setUp() public { setUpTests(); diff --git a/test/TVLOracle.t.sol b/test/TVLOracle.t.sol index 9c0f16ec3..2669157f8 100644 --- a/test/TVLOracle.t.sol +++ b/test/TVLOracle.t.sol @@ -4,13 +4,11 @@ pragma solidity ^0.8.13; import "./TestSetup.sol"; contract TVLOracleTest is TestSetup { - function setUp() public { setUpTests(); } function test_SetTvlCorrectly() public { - vm.prank(alice); uint256 newTvl = 1000; tvlOracle.setTvl(newTvl); @@ -32,7 +30,6 @@ contract TVLOracleTest is TestSetup { } function test_SetTVLAggregator() public { - address newAggregator = bob; vm.prank(owner); tvlOracle.setTVLAggregator(newAggregator); @@ -67,7 +64,6 @@ contract TVLOracleTest is TestSetup { } function test_OnlyAggregatorCanSetTvlAggregator() public { - vm.prank(bob); vm.expectRevert("Ownable: caller is not the owner"); tvlOracle.setTVLAggregator(bob); @@ -79,4 +75,4 @@ contract TVLOracleTest is TestSetup { vm.prank(owner); tvlOracle.setTVLAggregator(bob); } -} \ No newline at end of file +} diff --git a/test/TestERC20.sol b/test/TestERC20.sol index 58a70a637..168b56a04 100644 --- a/test/TestERC20.sol +++ b/test/TestERC20.sol @@ -4,9 +4,7 @@ pragma solidity ^0.8.13; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract TestERC20 is ERC20 { - constructor(string memory _name, string memory _symbol) - ERC20(_name, _symbol) - {} + constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {} function mint(address _to, uint256 _amount) public { _mint(_to, _amount); diff --git a/test/TestERC721.sol b/test/TestERC721.sol index e80b4d6bb..458558fbb 100644 --- a/test/TestERC721.sol +++ b/test/TestERC721.sol @@ -6,9 +6,7 @@ import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; contract TestERC721 is ERC721 { uint256 private _nextTokenId; - constructor(string memory _name, string memory _symbol) - ERC721(_name, _symbol) - {} + constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {} function mint(address _to) public returns (uint256) { uint256 tokenId = _nextTokenId++; @@ -19,4 +17,4 @@ contract TestERC721 is ERC721 { function mintWithTokenId(address _to, uint256 _tokenId) public { _mint(_to, _tokenId); } -} \ No newline at end of file +} diff --git a/test/TestSetup.sol b/test/TestSetup.sol index 77a997f16..dfd470e1d 100644 --- a/test/TestSetup.sol +++ b/test/TestSetup.sol @@ -3,68 +3,77 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; import "forge-std/console.sol"; -import "../src/eigenlayer-interfaces/IDelayedWithdrawalRouter.sol"; -import "../src/eigenlayer-interfaces/IEigenPodManager.sol"; import "../src/eigenlayer-interfaces/IBeaconChainOracle.sol"; +import "../src/eigenlayer-interfaces/IDelayedWithdrawalRouter.sol"; import "../src/eigenlayer-interfaces/IDelegationManager.sol"; -import "./eigenlayer-mocks/BeaconChainOracleMock.sol"; +import "../src/eigenlayer-interfaces/IEigenPodManager.sol"; + import "../src/eigenlayer-interfaces/ITimelock.sol"; -import "./mocks/MockEigenPodManager.sol"; -import "./mocks/MockDelegationManager.sol"; + import "./common/ArrayTestHelper.sol"; +import "./eigenlayer-mocks/BeaconChainOracleMock.sol"; +import "./mocks/MockDelegationManager.sol"; +import "./mocks/MockEigenPodManager.sol"; -import "../src/interfaces/IStakingManager.sol"; -import "../src/interfaces/IEtherFiNode.sol"; -import "../src/interfaces/ILiquidityPool.sol"; -import "../src/interfaces/ILiquifier.sol"; -import "../src/EtherFiNodesManager.sol"; -import "../src/StakingManager.sol"; -import "../src/NodeOperatorManager.sol"; -import "../src/archive/RegulationsManager.sol"; import "../src/AuctionManager.sol"; -import "../src/archive/ProtocolRevenueManager.sol"; + import "../src/BNFT.sol"; -import "../src/TNFT.sol"; + +import "../src/EETH.sol"; + +import "../src/EarlyAdopterPool.sol"; import "../src/EtherFiNode.sol"; +import "../src/EtherFiNodesManager.sol"; import "../src/EtherFiRateLimiter.sol"; +import "../src/EtherFiRestaker.sol"; import "../src/LiquidityPool.sol"; import "../src/Liquifier.sol"; -import "../src/EtherFiRestaker.sol"; -import "../src/EETH.sol"; -import "../src/WeETH.sol"; + import "../src/MembershipManager.sol"; import "../src/MembershipNFT.sol"; -import "../src/EarlyAdopterPool.sol"; +import "../src/NodeOperatorManager.sol"; +import "../src/StakingManager.sol"; + +import "../src/TNFT.sol"; + import "../src/TVLOracle.sol"; import "../src/UUPSProxy.sol"; +import "../src/WeETH.sol"; import "../src/WithdrawRequestNFT.sol"; +import "../src/archive/ProtocolRevenueManager.sol"; +import "../src/archive/RegulationsManager.sol"; + import "../src/helpers/AddressProvider.sol"; -import "./common/DepositDataGeneration.sol"; -import "./common/DepositContract.sol"; +import "../src/interfaces/IEtherFiNode.sol"; +import "../src/interfaces/ILiquidityPool.sol"; +import "../src/interfaces/ILiquifier.sol"; +import "../src/interfaces/IStakingManager.sol"; + import "./TestERC20.sol"; +import "./common/DepositContract.sol"; +import "./common/DepositDataGeneration.sol"; -import "../src/archive/MembershipManagerV0.sol"; -import "../src/EtherFiOracle.sol"; import "../src/EtherFiAdmin.sol"; +import "../src/EtherFiOracle.sol"; import "../src/EtherFiTimelock.sol"; +import "../src/archive/MembershipManagerV0.sol"; import "../src/BucketRateLimiter.sol"; import "../src/EtherFiRedemptionManager.sol"; import "../script/ContractCodeChecker.sol"; import "../script/Create2Factory.sol"; -import "../src/RoleRegistry.sol"; + import "../src/EtherFiRewardsRouter.sol"; +import "../src/RoleRegistry.sol"; import "../src/CumulativeMerkleRewardsDistributor.sol"; contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { - event Schedule(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt, uint256 delay); event Execute(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt); event Transaction(address to, uint256 value, bytes data); - uint256 public constant kwei = 10 ** 3; uint256 public slippageLimit = 50; @@ -94,7 +103,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { IRewardsCoordinator public eigenLayerRewardsCoordinator; ITimelock public eigenLayerTimelock; - ILidoWithdrawalQueue public lidoWithdrawalQueue; UUPSProxy public auctionManagerProxy; @@ -144,7 +152,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { EarlyAdopterPool public earlyAdopterPoolInstance; AddressProvider public addressProviderInstance; - + RoleRegistry public roleRegistryImplementation; RoleRegistry public roleRegistryInstance; @@ -276,11 +284,9 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { uint256 delay; } - // initialize a fork in which fresh contracts are deployed // and initialized to the same state as the unit tests. function initializeTestingFork(uint8 forkEnum) public { - if (forkEnum == MAINNET_FORK) { vm.selectFork(vm.createFork(vm.envString("MAINNET_RPC_URL"))); @@ -300,7 +306,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { eigenLayerDelegationManager = IDelegationManager(0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A); eigenLayerDelayedWithdrawalRouter = IDelayedWithdrawalRouter(0x7Fe7E9CC0F274d2435AD5d56D5fa73E47F6A23D8); eigenLayerTimelock = ITimelock(0xA6Db1A8C5a981d1536266D2a393c5F8dDb210EAF); - } else if (forkEnum == TESTNET_FORK) { vm.selectFork(vm.createFork(vm.envString("TESTNET_RPC_URL"))); @@ -309,7 +314,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { stEth_Eth_Pool = ICurvePool(0xDC24316b9AE028F1497c275EB9192a3Ea0f67022); // cbEth = IcbETH(0xBe9895146f7AF43049ca1c1AE358B0541Ea49704); // wbEth = IwBETH(0xa2E3356610840701BDf5611a53974510Ae27E2e1); - stEth = ILido(0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034 ); + stEth = ILido(0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034); // cbEthStrategy = IStrategy(0x54945180dB7943c0ed0FEE7EdaB2Bd24620256bc); // wbEthStrategy = IStrategy(0x7CA911E83dabf90C90dD3De5411a10F1A6112184); stEthStrategy = IStrategy(0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3); @@ -335,19 +340,16 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { // the associated network. This allows you to realistically test new transactions against // testnet or mainnet. function initializeRealisticForkWithBlock(uint8 forkEnum, uint256 blockNo) public { - if (forkEnum == MAINNET_FORK) { if (blockNo == 0) { vm.selectFork(vm.createFork(vm.envString("MAINNET_RPC_URL"))); - } - else { + } else { vm.selectFork(vm.createFork(vm.envString("MAINNET_RPC_URL"), blockNo)); } addressProviderInstance = AddressProvider(address(0x8487c5F8550E3C3e7734Fe7DCF77DB2B72E4A848)); owner = addressProviderInstance.getContractAddress("EtherFiTimelock"); admin = 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC; - cbEth_Eth_Pool = ICurvePool(0x5FAE7E604FC3e24fd43A72867ceBaC94c65b404A); wbEth_Eth_Pool = ICurvePool(0xBfAb6FA95E0091ed66058ad493189D2cB29385E6); stEth_Eth_Pool = ICurvePool(0xDC24316b9AE028F1497c275EB9192a3Ea0f67022); @@ -365,7 +367,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { eigenLayerRewardsCoordinator = IRewardsCoordinator(0x7750d328b314EfFa365A0402CcfD489B80B0adda); eigenLayerTimelock = ITimelock(0xA6Db1A8C5a981d1536266D2a393c5F8dDb210EAF); - } else if (forkEnum == TESTNET_FORK) { vm.selectFork(vm.createFork(vm.envString("TESTNET_RPC_URL"))); addressProviderInstance = AddressProvider(address(0x7c5EB0bE8af2eDB7461DfFa0Fd2856b3af63123e)); @@ -377,7 +378,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { stEth_Eth_Pool = ICurvePool(0xDC24316b9AE028F1497c275EB9192a3Ea0f67022); // cbEth = IcbETH(0xBe9895146f7AF43049ca1c1AE358B0541Ea49704); // wbEth = IwBETH(0xa2E3356610840701BDf5611a53974510Ae27E2e1); - stEth = ILido(0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034 ); + stEth = ILido(0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034); // cbEthStrategy = IStrategy(0x54945180dB7943c0ed0FEE7EdaB2Bd24620256bc); // wbEthStrategy = IStrategy(0x7CA911E83dabf90C90dD3De5411a10F1A6112184); stEthStrategy = IStrategy(0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3); @@ -388,7 +389,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { eigenLayerDelegationManager = IDelegationManager(0xA44151489861Fe9e3055d95adC98FbD462B948e7); eigenLayerRewardsCoordinator == IRewardsCoordinator(0x7750d328b314EfFa365A0402CcfD489B80B0adda); eigenLayerTimelock = ITimelock(0xcF19CE0561052a7A7Ff21156730285997B350A7D); - } else { revert("Unimplemented fork"); } @@ -422,8 +422,8 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { function setUpLiquifier(uint8 forkEnum) internal { vm.startPrank(owner); - - if (forkEnum == MAINNET_FORK || forkEnum == TESTNET_FORK) { + + if (forkEnum == MAINNET_FORK || forkEnum == TESTNET_FORK) { liquifierInstance.upgradeTo(address(new Liquifier())); liquifierInstance.updateAdmin(alice, true); } @@ -443,7 +443,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { deployEtherFiRestaker(); vm.stopPrank(); _upgrade_weETH(); - } function deployEtherFiRestaker() internal { @@ -462,12 +461,11 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { admin = alice; - mockDepositContractEth2 = new DepositContract(); depositContractEth2 = IDepositContract(address(mockDepositContractEth2)); // Deploy Contracts and Proxies - treasuryInstance = vm.addr(999999999); + treasuryInstance = vm.addr(999_999_999); roleRegistryImplementation = new RoleRegistry(); roleRegistryProxy = new UUPSProxy(address(roleRegistryImplementation), abi.encodeWithSelector(RoleRegistry.initialize.selector, owner)); @@ -517,7 +515,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { managerImplementation = new EtherFiNodesManager(address(stakingManagerInstance), address(roleRegistryInstance), address(rateLimiterInstance)); etherFiNodeManagerProxy = new UUPSProxy(address(managerImplementation), ""); managerInstance = EtherFiNodesManager(payable(address(etherFiNodeManagerProxy))); - TNFTInstance.initializeOnUpgrade(address(managerInstance)); BNFTInstance.initializeOnUpgrade(address(managerInstance)); @@ -531,7 +528,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { regulationsManagerInstance.initialize(); regulationsManagerInstance.updateAdmin(alice, true); - // TODO(Dave): fill in addresses address eigenPodManager; address delegationManager; @@ -539,7 +535,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { address etherFiNodesManager; node = new EtherFiNode(eigenPodManager, delegationManager, liquidityPool, etherFiNodesManager, address(roleRegistryInstance)); - rETH = new TestERC20("Rocket Pool ETH", "rETH"); rETH.mint(alice, 10e18); rETH.mint(bob, 10e18); @@ -556,7 +551,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { addressProviderInstance = new AddressProvider(address(owner)); liquidityPoolImplementation = new LiquidityPool(); - liquidityPoolProxy = new UUPSProxy(address(liquidityPoolImplementation),""); + liquidityPoolProxy = new UUPSProxy(address(liquidityPoolImplementation), ""); liquidityPoolInstance = LiquidityPool(payable(address(liquidityPoolProxy))); roleRegistryInstance.grantRole(liquidityPoolInstance.LIQUIDITY_POOL_ADMIN_ROLE(), admin); @@ -567,7 +562,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { roleRegistryInstance.grantRole(liquidityPoolInstance.LIQUIDITY_POOL_ADMIN_ROLE(), owner); roleRegistryInstance.grantRole(liquidityPoolInstance.LIQUIDITY_POOL_ADMIN_ROLE(), chad); - liquifierImplementation = new Liquifier(); liquifierProxy = new UUPSProxy(address(liquifierImplementation), ""); liquifierInstance = Liquifier(payable(liquifierProxy)); @@ -616,7 +610,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { withdrawRequestNFTProxy = new UUPSProxy(address(withdrawRequestNFTImplementation), ""); withdrawRequestNFTInstance = WithdrawRequestNFT(payable(withdrawRequestNFTProxy)); - membershipManagerImplementation = new MembershipManagerV0(); membershipManagerProxy = new UUPSProxy(address(membershipManagerImplementation), ""); membershipManagerInstance = MembershipManagerV0(payable(membershipManagerProxy)); @@ -625,7 +618,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { etherFiAdminProxy = new UUPSProxy(address(etherFiAdminImplementation), ""); etherFiAdminInstance = EtherFiAdmin(payable(etherFiAdminProxy)); - cumulativeMerkleRewardsDistributorImplementation = new CumulativeMerkleRewardsDistributor(address(roleRegistryInstance)); cumulativeMerkleRewardsDistributorProxy = new UUPSProxy(address(cumulativeMerkleRewardsDistributorImplementation), ""); cumulativeMerkleRewardsDistributorInstance = CumulativeMerkleRewardsDistributor(address(cumulativeMerkleRewardsDistributorProxy)); @@ -644,36 +636,18 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { etherFiRedemptionManagerProxy = new UUPSProxy(address(new EtherFiRedemptionManager(address(liquidityPoolInstance), address(eETHInstance), address(weEthInstance), address(treasuryInstance), address(roleRegistryInstance))), ""); etherFiRedemptionManagerInstance = EtherFiRedemptionManager(payable(etherFiRedemptionManagerProxy)); - etherFiRedemptionManagerInstance.initialize(10_00, 1_00, 1_00, 5 ether, 0.001 ether); + etherFiRedemptionManagerInstance.initialize(1000, 100, 100, 5 ether, 0.001 ether); roleRegistryInstance.grantRole(keccak256("ETHERFI_REDEMPTION_MANAGER_ADMIN_ROLE"), owner); - + liquidityPoolInstance.initialize(address(eETHInstance), address(stakingManagerInstance), address(etherFiNodeManagerProxy), address(membershipManagerInstance), address(TNFTInstance), address(etherFiAdminProxy), address(withdrawRequestNFTInstance)); liquidityPoolInstance.initializeVTwoDotFourNine(address(roleRegistryInstance), address(etherFiRedemptionManagerInstance)); membershipNftInstance.initialize("https://etherfi-cdn/{id}.json", address(membershipManagerInstance)); withdrawRequestNFTInstance.initialize(payable(address(liquidityPoolInstance)), payable(address(eETHInstance)), payable(address(membershipManagerInstance))); withdrawRequestNFTInstance.initializeOnUpgrade(address(roleRegistryInstance), 1000); - membershipManagerInstance.initialize( - address(eETHInstance), - address(liquidityPoolInstance), - address(membershipNftInstance), - address(treasuryInstance), - address(protocolRevenueManagerInstance) - ); - liquifierInstance.initialize( - address(treasuryInstance), - address(liquidityPoolInstance), - address(eigenLayerStrategyManager), - address(lidoWithdrawalQueue), - address(stEth), - address(cbEth), - address(wbEth), - address(cbEth_Eth_Pool), - address(wbEth_Eth_Pool), - address(stEth_Eth_Pool), - 3600 - ); + membershipManagerInstance.initialize(address(eETHInstance), address(liquidityPoolInstance), address(membershipNftInstance), address(treasuryInstance), address(protocolRevenueManagerInstance)); + liquifierInstance.initialize(address(treasuryInstance), address(liquidityPoolInstance), address(eigenLayerStrategyManager), address(lidoWithdrawalQueue), address(stEth), address(cbEth), address(wbEth), address(cbEth_Eth_Pool), address(wbEth_Eth_Pool), address(stEth_Eth_Pool), 3600); /* managerInstance.initialize( @@ -690,7 +664,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { managerInstance.updateAdmin(alice, true); */ - membershipManagerInstance.updateAdmin(alice, true); membershipNftInstance.updateAdmin(alice, true); // liquidityPoolInstance.updateAdmin(alice, true); @@ -699,13 +672,13 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { // special case for forked tests utilizing oracle // can't use env variable because then it would apply to all tests including non-forked ones if (block.chainid == 1) { - genesisSlotTimestamp = 1606824023; + genesisSlotTimestamp = 1_606_824_023; } else if (block.chainid == 5) { // goerli - genesisSlotTimestamp = uint32(1616508000); - } else if (block.chainid == 17000) { + genesisSlotTimestamp = uint32(1_616_508_000); + } else if (block.chainid == 17_000) { // holesky - genesisSlotTimestamp = 1695902400; + genesisSlotTimestamp = 1_695_902_400; beaconChainOracle = IBeaconChainOracle(0x4C116BB629bff7A8373c2378bBd919f8349B8f25); } else { genesisSlotTimestamp = 0; @@ -722,22 +695,12 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { //managerInstance.setNonExitPenalty(300, 1 ether); membershipManagerInstance.setTopUpCooltimePeriod(28 days); vm.stopPrank(); - + vm.startPrank(owner); tvlOracle = new TVLOracle(alice); - etherFiAdminInstance.initialize( - address(etherFiOracleInstance), - address(stakingManagerInstance), - address(auctionInstance), - address(managerInstance), - address(liquidityPoolInstance), - address(membershipManagerInstance), - address(withdrawRequestNFTInstance), - 10000, - 0 - ); + etherFiAdminInstance.initialize(address(etherFiOracleInstance), address(stakingManagerInstance), address(auctionInstance), address(managerInstance), address(liquidityPoolInstance), address(membershipManagerInstance), address(withdrawRequestNFTInstance), 10_000, 0); uint256 BLOCKS_IN_DAY = 7200; address[] memory tokens = new address[](2); tokens[0] = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); //eth @@ -771,7 +734,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { auctionInstance.initializeOnUpgrade(address(membershipManagerInstance), 1 ether, address(etherFiAdminInstance), address(nodeOperatorManagerInstance)); membershipNftInstance.initializeOnUpgrade(address(liquidityPoolInstance)); - // configure eigenlayer dependency differently for mainnet vs testnet because we rely // on the contracts already deployed by eigenlayer on those chains bool restakingBnftDeposits; @@ -781,7 +743,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { eigenLayerEigenPodManager = IEigenPodManager(0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338); eigenLayerDelegationManager = IDelegationManager(0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A); eigenLayerTimelock = ITimelock(0xA6Db1A8C5a981d1536266D2a393c5F8dDb210EAF); - } else if (block.chainid == 17000) { + } else if (block.chainid == 17_000) { restakingBnftDeposits = false; eigenLayerEigenPodManager = IEigenPodManager(0x30770d7E3e71112d7A6b7259542D1f680a70e315); } else { @@ -851,30 +813,29 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { if (address(liquidityPoolInstance.roleRegistry()) == address(0x0)) { // deploy new versions of role registry roleRegistryImplementation = new RoleRegistry(); - bytes memory initializerData = abi.encodeWithSelector(RoleRegistry.initialize.selector, admin); + bytes memory initializerData = abi.encodeWithSelector(RoleRegistry.initialize.selector, admin); roleRegistryInstance = RoleRegistry(address(new UUPSProxy(address(roleRegistryImplementation), initializerData))); superAdmin = admin; - // upgrade our existing contracts to utilize `roleRegistry` vm.stopPrank(); vm.startPrank(owner); EtherFiRedemptionManager etherFiRedemptionManagerImplementation = new EtherFiRedemptionManager(address(liquidityPoolInstance), address(eETHInstance), address(weEthInstance), address(treasuryInstance), address(roleRegistryInstance)); etherFiRedemptionManagerProxy = new UUPSProxy(address(etherFiRedemptionManagerImplementation), ""); etherFiRedemptionManagerInstance = EtherFiRedemptionManager(payable(etherFiRedemptionManagerProxy)); - etherFiRedemptionManagerInstance.initialize(10_00, 1_00, 1_00, 5 ether, 0.001 ether); // 10% fee split to treasury, 1% exit fee, 1% low watermark - liquidityPoolInstance.initializeVTwoDotFourNine(address(roleRegistryInstance), address(etherFiRedemptionManagerInstance)); - } + etherFiRedemptionManagerInstance.initialize(1000, 100, 100, 5 ether, 0.001 ether); // 10% fee split to treasury, 1% exit fee, 1% low watermark + liquidityPoolInstance.initializeVTwoDotFourNine(address(roleRegistryInstance), address(etherFiRedemptionManagerInstance)); + } if (address(etherFiAdminInstance.roleRegistry()) == address(0x0)) { vm.startPrank(owner); - etherFiAdminInstance.initializeRoleRegistry(address(roleRegistryInstance)); + etherFiAdminInstance.initializeRoleRegistry(address(roleRegistryInstance)); } vm.startPrank(admin); roleRegistryInstance.grantRole(liquidityPoolInstance.LIQUIDITY_POOL_ADMIN_ROLE(), admin); roleRegistryInstance.grantRole(roleRegistryInstance.PROTOCOL_PAUSER(), admin); roleRegistryInstance.grantRole(roleRegistryInstance.PROTOCOL_PAUSER(), address(etherFiAdminInstance)); - roleRegistryInstance.grantRole(roleRegistryInstance.PROTOCOL_UNPAUSER(), admin); + roleRegistryInstance.grantRole(roleRegistryInstance.PROTOCOL_UNPAUSER(), admin); roleRegistryInstance.grantRole(roleRegistryInstance.PROTOCOL_UNPAUSER(), address(etherFiAdminInstance)); roleRegistryInstance.grantRole(liquidityPoolInstance.LIQUIDITY_POOL_ADMIN_ROLE(), alice); @@ -891,10 +852,10 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { uint256[] memory validatorsToApprove = new uint256[](0); uint256[] memory validatorsToExit = new uint256[](0); uint256[] memory exitedValidators = new uint256[](0); - uint32[] memory exitTimestamps = new uint32[](0); + uint32[] memory exitTimestamps = new uint32[](0); uint256[] memory withdrawalRequestsToInvalidate = new uint256[](0); - reportAtPeriod2A = IEtherFiOracle.OracleReport(1, 0, 1024 - 1, 0, 1024 - 1, 1, 0,validatorsToApprove, withdrawalRequestsToInvalidate, 1, 0); - reportAtPeriod2B = IEtherFiOracle.OracleReport(1, 0, 1024 - 1, 0, 1024 - 1, 1, 0,validatorsToApprove, withdrawalRequestsToInvalidate, 1, 0); + reportAtPeriod2A = IEtherFiOracle.OracleReport(1, 0, 1024 - 1, 0, 1024 - 1, 1, 0, validatorsToApprove, withdrawalRequestsToInvalidate, 1, 0); + reportAtPeriod2B = IEtherFiOracle.OracleReport(1, 0, 1024 - 1, 0, 1024 - 1, 1, 0, validatorsToApprove, withdrawalRequestsToInvalidate, 1, 0); reportAtPeriod2C = IEtherFiOracle.OracleReport(2, 0, 1024 - 1, 0, 1024 - 1, 1, 0, validatorsToApprove, withdrawalRequestsToInvalidate, 1, 0); reportAtPeriod3 = IEtherFiOracle.OracleReport(1, 0, 2048 - 1, 0, 2048 - 1, 1, 0, validatorsToApprove, withdrawalRequestsToInvalidate, 1, 0); reportAtPeriod3A = IEtherFiOracle.OracleReport(1, 0, 2048 - 1, 0, 3 * 1024 - 1, 1, 0, validatorsToApprove, withdrawalRequestsToInvalidate, 1, 0); @@ -904,9 +865,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { reportAtSlot4287 = IEtherFiOracle.OracleReport(1, 3264, 4288 - 1, 3264, 4288 - 1, 1, 0, validatorsToApprove, withdrawalRequestsToInvalidate, 1, 0); } - function _merkleSetup() internal { - } - + function _merkleSetup() internal {} function _initializeMembershipTiers() internal { uint40 requiredPointsForTier = 0; @@ -943,8 +902,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { nodeOperatorManagerInstance.addToWhitelist(henry); } - function _merkleSetupMigration() internal { - } + function _merkleSetupMigration() internal {} function _perform_eigenlayer_upgrade() public { vm.warp(block.timestamp + 12 days); @@ -955,7 +913,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { 0, "", hex"6a76120200000000000000000000000040a2accbd92bca938b02010e17a5b8929b49130d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000006248d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000005d3008b9566ada63b64d1e1dcf1418b43fd1433b724440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004499a88ec400000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a0000000000000000000000001784be6401339fc0fedf7e9379409f5c1bfe9dda008b9566ada63b64d1e1dcf1418b43fd1433b724440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004499a88ec4000000000000000000000000d92145c07f8ed1d392c1b88017934e301cc1c3cd000000000000000000000000f3234220163a757edf1e11a8a085638d9b236614008b9566ada63b64d1e1dcf1418b43fd1433b724440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004499a88ec4000000000000000000000000858646372cc42e1a627fce94aa7a7033e7cf075a00000000000000000000000070f44c13944d49a236e3cd7a94f48f5dab6c619b008b9566ada63b64d1e1dcf1418b43fd1433b724440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004499a88ec40000000000000000000000007fe7e9cc0f274d2435ad5d56d5fa73e47f6a23d80000000000000000000000004bb6731b02314d40abbffbc4540f508874014226008b9566ada63b64d1e1dcf1418b43fd1433b724440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004499a88ec400000000000000000000000091e677b07f7af907ec9a428aafa9fc14a0d3a338000000000000000000000000e4297e3dadbc7d99e26a2954820f514cb50c5762005a2a4f2f3c18f09179b6703e63d9edd165909073000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000243659cfe60000000000000000000000008ba40da60f0827d027f029acee62609f0527a2550039053d51b77dc0d36036fc1fcc8cb819df8ef37a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024635bbd10000000000000000000000000000000000000000000000000000000000000c4e00091e677b07f7af907ec9a428aafa9fc14a0d3a33800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024c1de3aef000000000000000000000000343907185b71adf0eba9567538314396aa9854420091e677b07f7af907ec9a428aafa9fc14a0d3a33800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024463db0380000000000000000000000000000000000000000000000000000000065f1b0570039053d51b77dc0d36036fc1fcc8cb819df8ef37a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024fabc1cbc00000000000000000000000000000000000000000000000000000000000000000091e677b07f7af907ec9a428aafa9fc14a0d3a33800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024fabc1cbc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041000000000000000000000000a6db1a8c5a981d1536266d2a393c5f8ddb210eaf00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - 1712559600 + 1_712_559_600 ); } @@ -988,13 +946,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { // values[4] = 0; for (uint256 i = 0; i < targets.length; i++) { - etherFiTimelockInstance.execute( - targets[i], - values[i], - payloads[i], - 0x0, - 0x0 - ); + etherFiTimelockInstance.execute(targets[i], values[i], payloads[i], 0x0, 0x0); } vm.stopPrank(); } @@ -1036,7 +988,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { etherFiOracleInstance.updateAdmin(alice, true); address admin = address(etherFiAdminInstance); - //stakingManagerInstance.updateAdmin(admin, true); + //stakingManagerInstance.updateAdmin(admin, true); // liquidityPoolInstance.updateAdmin(admin, true); membershipManagerInstance.updateAdmin(admin, true); etherFiOracleInstance.updateAdmin(admin, true); @@ -1074,7 +1026,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { bool[] memory aliceApprovals = new bool[](1); aliceApprovals[0] = true; nodeOperatorManagerInstance.batchUpdateOperatorsApprovedTags(aliceUser, aliceApprovedTags, aliceApprovals); - } function _initReportBlockStamp(IEtherFiOracle.OracleReport memory _report) internal view { @@ -1094,13 +1045,14 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { _executeAdminTasks(_report, emptyBytes, emptyBytes, _revertMessage); } - function _executeAdminTasks(IEtherFiOracle.OracleReport memory _report, bytes[] memory _pubKey, bytes[] memory /*_signature*/, string memory _revertMessage) internal { + function _executeAdminTasks(IEtherFiOracle.OracleReport memory _report, bytes[] memory _pubKey, bytes[] memory, /*_signature*/ string memory _revertMessage) internal { _initReportBlockStamp(_report); - + uint32 currentSlot = etherFiOracleInstance.computeSlotAtTimestamp(block.timestamp); uint32 currentEpoch = (currentSlot / 32); uint32 reportEpoch = (_report.refSlotTo / 32) + 3; - if (currentEpoch < reportEpoch) { // ensure report is finalized + if (currentEpoch < reportEpoch) { + // ensure report is finalized uint32 numSlotsToMove = 32 * (reportEpoch - currentEpoch); _moveClock(int256(int32(numSlotsToMove))); } @@ -1137,13 +1089,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { function calculatePermitDigest(address _owner, address spender, uint256 value, uint256 nonce, uint256 deadline, bytes32 domainSeparator) public pure returns (bytes32) { bytes32 permitTypehash = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); - bytes32 digest = keccak256( - abi.encodePacked( - hex"1901", - domainSeparator, - keccak256(abi.encode(permitTypehash, _owner, spender, value, nonce, deadline)) - ) - ); + bytes32 digest = keccak256(abi.encodePacked(hex"1901", domainSeparator, keccak256(abi.encode(permitTypehash, _owner, spender, value, nonce, deadline)))); return digest; } @@ -1151,13 +1097,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { address _owner = vm.addr(privKey); bytes32 digest = calculatePermitDigest(_owner, spender, value, nonce, deadline, domianSeparator); (uint8 v, bytes32 r, bytes32 s) = vm.sign(privKey, digest); - ILiquidityPool.PermitInput memory permitInput = ILiquidityPool.PermitInput({ - value: value, - deadline: deadline, - v: v, - r: r, - s: s - }); + ILiquidityPool.PermitInput memory permitInput = ILiquidityPool.PermitInput({value: value, deadline: deadline, v: v, r: r, s: s}); return permitInput; } @@ -1165,13 +1105,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { address _owner = vm.addr(privKey); bytes32 digest = calculatePermitDigest(_owner, spender, value, nonce, deadline, domianSeparator); (uint8 v, bytes32 r, bytes32 s) = vm.sign(privKey, digest); - IeETH.PermitInput memory permitInput = IeETH.PermitInput({ - value: value, - deadline: deadline, - v: v, - r: r, - s: s - }); + IeETH.PermitInput memory permitInput = IeETH.PermitInput({value: value, deadline: deadline, v: v, r: r, s: s}); return permitInput; } @@ -1179,13 +1113,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { address _owner = vm.addr(privKey); bytes32 digest = calculatePermitDigest(_owner, spender, value, nonce, deadline, domianSeparator); (uint8 v, bytes32 r, bytes32 s) = vm.sign(privKey, digest); - IWeETH.PermitInput memory permitInput = IWeETH.PermitInput({ - value: value, - deadline: deadline, - v: v, - r: r, - s: s - }); + IWeETH.PermitInput memory permitInput = IWeETH.PermitInput({value: value, deadline: deadline, v: v, r: r, s: s}); return permitInput; } @@ -1210,15 +1138,15 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { registerAsBnftHolder(address(liquidityPoolInstance)); vm.stopPrank(); - vm.deal(alice, 100000 ether); - vm.deal(greg, 100000 ether); - vm.deal(bob, 100000 ether); - vm.deal(owner, 100000 ether); - vm.deal(shonee, 100000 ether); - vm.deal(dan, 100000 ether); - vm.deal(elvis, 100000 ether); - vm.deal(henry, 100000 ether); - vm.deal(chad, 100000 ether); + vm.deal(alice, 100_000 ether); + vm.deal(greg, 100_000 ether); + vm.deal(bob, 100_000 ether); + vm.deal(owner, 100_000 ether); + vm.deal(shonee, 100_000 ether); + vm.deal(dan, 100_000 ether); + vm.deal(elvis, 100_000 ether); + vm.deal(henry, 100_000 ether); + vm.deal(chad, 100_000 ether); bool registered = liquidityPoolInstance.validatorSpawner(alice); assertEq(registered, true); @@ -1283,15 +1211,15 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { function launch_validator(uint256 _numValidators, uint256 _validatorIdToCoUseWithdrawalSafe, bool _isLpBnftHolder, address _bnftStaker, address _nodeOperator) internal returns (uint256[] memory) { bytes32 rootForApproval; - vm.deal(owner, 10000 ether); - vm.deal(alice, 10000 ether); - vm.deal(bob, 10000 ether); - vm.deal(_bnftStaker, 10000 ether); + vm.deal(owner, 10_000 ether); + vm.deal(alice, 10_000 ether); + vm.deal(bob, 10_000 ether); + vm.deal(_bnftStaker, 10_000 ether); address admin; if (block.chainid == 1) { admin = 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC; - } else if (block.chainid == 17000) { + } else if (block.chainid == 17_000) { admin = 0xD0d7F8a5a86d8271ff87ff24145Cf40CEa9F7A39; } else { admin = alice; @@ -1306,10 +1234,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { vm.startPrank(_nodeOperator); if (!nodeOperatorManagerInstance.registered(_nodeOperator)) { - nodeOperatorManagerInstance.registerNodeOperator( - _ipfsHash, - 10000 - ); + nodeOperatorManagerInstance.registerNodeOperator(_ipfsHash, 10_000); } vm.stopPrank(); @@ -1346,7 +1271,6 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { //uint256[] memory newValidators = new uint256[](_numValidators); uint256[] memory newValidators = bidIds; - IStakingManager.DepositData[] memory depositDataArray = new IStakingManager.DepositData[](_numValidators); bytes32[] memory depositDataRootsForApproval = new bytes32[](_numValidators); @@ -1354,31 +1278,14 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { bytes[] memory sig = new bytes[](_numValidators); for (uint256 i = 0; i < newValidators.length; i++) { - address safe = address(managerInstance.getEigenPod( - newValidators[i] - )); - root = generateDepositRoot( - hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c", - hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df", - managerInstance.addressToWithdrawalCredentials(safe), - 1 ether - ); + address safe = address(managerInstance.getEigenPod(newValidators[i])); + root = generateDepositRoot(hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c", hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df", managerInstance.addressToWithdrawalCredentials(safe), 1 ether); - rootForApproval = generateDepositRoot( - hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c", - hex"ad899d85dcfcc2506a8749020752f81353dd87e623b2982b7bbfbbdd7964790eab4e06e226917cba1253f063d64a7e5407d8542776631b96c4cea78e0968833b36d4e0ae0b94de46718f905ca6d9b8279e1044a41875640f8cb34dc3f6e4de65", - managerInstance.addressToWithdrawalCredentials(safe), - 31 ether - ); + rootForApproval = generateDepositRoot(hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c", hex"ad899d85dcfcc2506a8749020752f81353dd87e623b2982b7bbfbbdd7964790eab4e06e226917cba1253f063d64a7e5407d8542776631b96c4cea78e0968833b36d4e0ae0b94de46718f905ca6d9b8279e1044a41875640f8cb34dc3f6e4de65", managerInstance.addressToWithdrawalCredentials(safe), 31 ether); depositDataRootsForApproval[i] = rootForApproval; - depositDataArray[i] = IStakingManager.DepositData({ - publicKey: hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c", - signature: hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df", - depositDataRoot: root, - ipfsHashForEncryptedValidatorKey: "test_ipfs" - }); + depositDataArray[i] = IStakingManager.DepositData({publicKey: hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c", signature: hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df", depositDataRoot: root, ipfsHashForEncryptedValidatorKey: "test_ipfs"}); sig[i] = hex"ad899d85dcfcc2506a8749020752f81353dd87e623b2982b7bbfbbdd7964790eab4e06e226917cba1253f063d64a7e5407d8542776631b96c4cea78e0968833b36d4e0ae0b94de46718f905ca6d9b8279e1044a41875640f8cb34dc3f6e4de65"; pubKey[i] = hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c"; @@ -1417,74 +1324,37 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { vm.startPrank(0xcdd57D11476c22d265722F68390b036f3DA48c21); // ├─ emit TimelockTransaction(target: 0x308861A430be4cce5502d0A12724771Fc6DaF216, value: 0, data: 0x3659cfe6000000000000000000000000d27a57bb8f9b7ec7862df87f5143146c161f5a8b, predecessor: 0x0000000000000000000000000000000000000000000000000000000000000000, salt: 0x0000000000000000000000000000000000000000000000000000000000000000, delay: 259200 [2.592e5]) { - etherFiTimelockInstance.execute( - address(0x308861A430be4cce5502d0A12724771Fc6DaF216), - 0, - hex"3659cfe6000000000000000000000000605f17e88027e25e18c95be0d8011ac969426399", - 0x0, - 0x0 - ); + etherFiTimelockInstance.execute(address(0x308861A430be4cce5502d0A12724771Fc6DaF216), 0, hex"3659cfe6000000000000000000000000605f17e88027e25e18c95be0d8011ac969426399", 0x0, 0x0); } // ├─ emit TimelockTransaction(target: 0x25e821b7197B146F7713C3b89B6A4D83516B912d, value: 0, data: 0x3659cfe6000000000000000000000000b27d4e7b8ff1ef21751b50f3821d99719ad5868f, predecessor: 0x0000000000000000000000000000000000000000000000000000000000000000, salt: 0x0000000000000000000000000000000000000000000000000000000000000000, delay: 259200 [2.592e5]) { - etherFiTimelockInstance.execute( - address(0x25e821b7197B146F7713C3b89B6A4D83516B912d), - 0, - hex"3659cfe6000000000000000000000000b27d4e7b8ff1ef21751b50f3821d99719ad5868f", - 0x0, - 0x0 - ); + etherFiTimelockInstance.execute(address(0x25e821b7197B146F7713C3b89B6A4D83516B912d), 0, hex"3659cfe6000000000000000000000000b27d4e7b8ff1ef21751b50f3821d99719ad5868f", 0x0, 0x0); } - + // ├─ emit TimelockTransaction(target: 0x7B5ae07E2AF1C861BcC4736D23f5f66A61E0cA5e, value: 0, data: 0x3659cfe6000000000000000000000000afb82ce44fd8a3431a64742bcd3547eeda1afea7, predecessor: 0x0000000000000000000000000000000000000000000000000000000000000000, salt: 0x0000000000000000000000000000000000000000000000000000000000000000, delay: 259200 [2.592e5]) { - etherFiTimelockInstance.execute( - address(0x7B5ae07E2AF1C861BcC4736D23f5f66A61E0cA5e), - 0, - hex"3659cfe6000000000000000000000000afb82ce44fd8a3431a64742bcd3547eeda1afea7", - 0x0, - 0x0 - ); + etherFiTimelockInstance.execute(address(0x7B5ae07E2AF1C861BcC4736D23f5f66A61E0cA5e), 0, hex"3659cfe6000000000000000000000000afb82ce44fd8a3431a64742bcd3547eeda1afea7", 0x0, 0x0); } - + // ├─ emit TimelockTransaction(target: 0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F, value: 0, data: 0x3659cfe6000000000000000000000000d90c5624a52a3bd4ad006d578b00c3ecf8725fda, predecessor: 0x0000000000000000000000000000000000000000000000000000000000000000, salt: 0x0000000000000000000000000000000000000000000000000000000000000000, delay: 259200 [2.592e5]) { - etherFiTimelockInstance.execute( - address(0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F), - 0, - hex"3659cfe6000000000000000000000000d90c5624a52a3bd4ad006d578b00c3ecf8725fda", - 0x0, - 0x0 - ); + etherFiTimelockInstance.execute(address(0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F), 0, hex"3659cfe6000000000000000000000000d90c5624a52a3bd4ad006d578b00c3ecf8725fda", 0x0, 0x0); } // ├─ emit TimelockTransaction(target: 0x25e821b7197B146F7713C3b89B6A4D83516B912d, value: 0, data: 0x4937097400000000000000000000000052bbf281fbcfa7cf3e9101a52af5dcb32754e3c0, predecessor: 0x0000000000000000000000000000000000000000000000000000000000000000, salt: 0x0000000000000000000000000000000000000000000000000000000000000000, delay: 259200 [2.592e5]) { - etherFiTimelockInstance.execute( - address(0x25e821b7197B146F7713C3b89B6A4D83516B912d), - 0, - hex"4937097400000000000000000000000052bbf281fbcfa7cf3e9101a52af5dcb32754e3c0", - 0x0, - 0x0 - ); + etherFiTimelockInstance.execute(address(0x25e821b7197B146F7713C3b89B6A4D83516B912d), 0, hex"4937097400000000000000000000000052bbf281fbcfa7cf3e9101a52af5dcb32754e3c0", 0x0, 0x0); } - + // ├─ emit TimelockTransaction(target: 0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F, value: 0, data: 0xde5faecc00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a, predecessor: 0x0000000000000000000000000000000000000000000000000000000000000000, salt: 0x0000000000000000000000000000000000000000000000000000000000000000, delay: 259200 [2.592e5]) { - etherFiTimelockInstance.execute( - address(0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F), - 0, - hex"de5faecc00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a", - 0x0, - 0x0 - ); + etherFiTimelockInstance.execute(address(0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F), 0, hex"de5faecc00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a", 0x0, 0x0); } vm.stopPrank(); } function _upgrade_etherfi_node_contract() internal { - revert("FILL IN ADDRESSES"); address eigenPodManager; address delegationManager; @@ -1548,7 +1418,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { vm.startPrank(finalize_role); uint256 currentRate = stEth.getTotalPooledEther() * 1e27 / stEth.getTotalShares(); (uint256 ethToLock, uint256 sharesToBurn) = liquifierInstance.lidoWithdrawalQueue().prefinalize(reqIds, currentRate); - liquifierInstance.lidoWithdrawalQueue().finalize(reqIds[reqIds.length-1], currentRate); + liquifierInstance.lidoWithdrawalQueue().finalize(reqIds[reqIds.length - 1], currentRate); vm.stopPrank(); // The ether.fi admin claims the finalized withdrawal, which sends the ETH to the liquifier contract @@ -1569,19 +1439,9 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { for (uint256 i = 0; i < _validatorIds.length; i++) { address etherFiNode = managerInstance.etherfiNodeAddress(_validatorIds[i]); pubKey[i] = hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c"; - bytes32 root = generateDepositRoot( - pubKey[i], - hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df", - managerInstance.addressToWithdrawalCredentials(etherFiNode), - _depositAmount - ); + bytes32 root = generateDepositRoot(pubKey[i], hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df", managerInstance.addressToWithdrawalCredentials(etherFiNode), _depositAmount); - depositDataArray[i] = IStakingManager.DepositData({ - publicKey: pubKey[i], - signature: hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df", - depositDataRoot: root, - ipfsHashForEncryptedValidatorKey: "test_ipfs" - }); + depositDataArray[i] = IStakingManager.DepositData({publicKey: pubKey[i], signature: hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df", depositDataRoot: root, ipfsHashForEncryptedValidatorKey: "test_ipfs"}); } return depositDataArray; @@ -1626,14 +1486,17 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { return (depositDataArray, depositDataRootsForApproval, sig, pubKey); */ } + function _execute_timelock(address target, bytes memory data, bool _schedule, bool _log_schedule, bool _execute, bool _log_execute) internal { - if(address(0xcdd57D11476c22d265722F68390b036f3DA48c21) == address(etherFiTimelockInstance)) { // 3 Day Timelock + if (address(0xcdd57D11476c22d265722F68390b036f3DA48c21) == address(etherFiTimelockInstance)) { + // 3 Day Timelock vm.startPrank(0xcdd57D11476c22d265722F68390b036f3DA48c21); - } else { // 8hr Timelock + } else { + // 8hr Timelock vm.startPrank(0x2aCA71020De61bb532008049e1Bd41E451aE8AdC); } bytes32 salt = keccak256(abi.encodePacked(target, data, block.number)); - + if (_schedule) etherFiTimelockInstance.schedule(target, 0, data, bytes32(0), salt, etherFiTimelockInstance.getMinDelay()); if (_log_schedule) _output_schedule_txn(target, data, bytes32(0), salt, etherFiTimelockInstance.getMinDelay()); @@ -1662,33 +1525,15 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { vm.stopPrank(); } - - - function _20240428_updateDepositCap() internal { { - _execute_timelock( - 0x9FFDF407cDe9a93c47611799DA23924Af3EF764F, - hex"3BEB551700000000000000000000000083998E169026136760BE6AF93E776C2F352D4B280000000000000000000000000000000000000000000000000000000000000FA00000000000000000000000000000000000000000000000000000000000004E20", - false, - false, - true, - false - ); + _execute_timelock(0x9FFDF407cDe9a93c47611799DA23924Af3EF764F, hex"3BEB551700000000000000000000000083998E169026136760BE6AF93E776C2F352D4B280000000000000000000000000000000000000000000000000000000000000FA00000000000000000000000000000000000000000000000000000000000004E20", false, false, true, false); } { - _execute_timelock( - 0x9FFDF407cDe9a93c47611799DA23924Af3EF764F, - hex"3BEB5517000000000000000000000000DC400F3DA3EA5DF0B7B6C127AE2E54CE55644CF30000000000000000000000000000000000000000000000000000000000000FA00000000000000000000000000000000000000000000000000000000000004E20", - false, - false, - true, - false - ); + _execute_timelock(0x9FFDF407cDe9a93c47611799DA23924Af3EF764F, hex"3BEB5517000000000000000000000000DC400F3DA3EA5DF0B7B6C127AE2E54CE55644CF30000000000000000000000000000000000000000000000000000000000000FA00000000000000000000000000000000000000000000000000000000000004E20", false, false, true, false); } } - function _output_schedule_txn(address target, bytes memory data, bytes32 predecessor, bytes32 salt, uint256 delay) internal { bytes memory txn_data = abi.encodeWithSelector(TimelockController.schedule.selector, target, 0, data, predecessor, salt, delay); emit Transaction(address(etherFiTimelockInstance), 0, txn_data); @@ -1731,7 +1576,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { stdJson.write(output, output_path); } - function _batch_output_execute_timelock_txn(address[] memory targets, bytes[] memory data, uint256[] memory values,bytes32 predecessor, bytes32 salt) internal { + function _batch_output_execute_timelock_txn(address[] memory targets, bytes[] memory data, uint256[] memory values, bytes32 predecessor, bytes32 salt) internal { bytes memory txn_data = abi.encodeWithSelector(TimelockController.executeBatch.selector, targets, values, data, predecessor, salt); emit Transaction(address(etherFiTimelockInstance), 0, txn_data); @@ -1748,14 +1593,7 @@ contract TestSetup is Test, ContractCodeChecker, DepositDataGeneration { function computeAddressByCreate2(address deployer, bytes memory code, bytes32 salt) public view returns (address) { // Compute the final address: // address = keccak256( 0xff ++ this.address ++ salt ++ keccak256(code))[12:] - bytes32 hash = keccak256( - abi.encodePacked( - bytes1(0xff), - deployer, - salt, - keccak256(code) - ) - ); + bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, keccak256(code))); return address(uint160(uint256(hash))); } } diff --git a/test/WeETH.t.sol b/test/WeETH.t.sol index 0e9774482..5b94604da 100644 --- a/test/WeETH.t.sol +++ b/test/WeETH.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import "./TestSetup.sol"; +import {ForceETHSender} from "./EETH.t.sol"; import "./TestERC20.sol"; import "./TestERC721.sol"; -import {ForceETHSender} from "./EETH.t.sol"; +import "./TestSetup.sol"; contract WeETHTest is TestSetup { function setUp() public { @@ -63,11 +63,10 @@ contract WeETHTest is TestSetup { uint256 aliceNonce = eETHInstance.nonces(alice); // alice priv key = 2 - ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(weEthInstance), 2 ether, aliceNonce, 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(weEthInstance), 2 ether, aliceNonce, 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); vm.expectRevert("TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); weEthInstance.wrapWithPermit(5 ether, permitInput); - } function test_WrapWithPermitFailsWithInvalidSignature() public { @@ -82,7 +81,7 @@ contract WeETHTest is TestSetup { uint256 aliceNonce = eETHInstance.nonces(alice); // 69 is an invalid private key for alice - ILiquidityPool.PermitInput memory permitInput = createPermitInput(69, address(weEthInstance), 5 ether, aliceNonce, 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(69, address(weEthInstance), 5 ether, aliceNonce, 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); vm.expectRevert("TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); weEthInstance.wrapWithPermit(5 ether, permitInput); @@ -112,7 +111,7 @@ contract WeETHTest is TestSetup { uint256 aliceNonce = eETHInstance.nonces(alice); // alice priv key = 2 - ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(weEthInstance), 5 ether, aliceNonce, 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(weEthInstance), 5 ether, aliceNonce, 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); weEthInstance.wrapWithPermit(5 ether, permitInput); assertEq(weEthInstance.balanceOf(alice), 5 ether); @@ -235,7 +234,7 @@ contract WeETHTest is TestSetup { vm.prank(address(membershipManagerInstance)); liquidityPoolInstance.rebase(50 ether); - _transferTo(address(liquidityPoolInstance), 50 ether); + _transferTo(address(liquidityPoolInstance), 50 ether); assertEq(liquidityPoolInstance.getTotalPooledEther(), 110 ether); assertEq(eETHInstance.balanceOf(alice), 3.666666666666666667 ether); @@ -292,69 +291,69 @@ contract WeETHTest is TestSetup { weEthInstance.unwrap(1 ether); assertEq(eETHInstance.balanceOf(bob), 1.333333333333333332 ether); } - + function test_WrapWithPermitGriefingAttack() public { // alice sends a `wrapWithPermit` transaction to mempool with the following inputs uint256 aliceNonce = eETHInstance.nonces(alice); - ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(weEthInstance), 5 ether, aliceNonce, 2**256 - 1, eETHInstance.DOMAIN_SEPARATOR()); + ILiquidityPool.PermitInput memory permitInput = createPermitInput(2, address(weEthInstance), 5 ether, aliceNonce, 2 ** 256 - 1, eETHInstance.DOMAIN_SEPARATOR()); - // bob sees alice's `wrapWithPermit` in the mempool and frontruns her transaction with copied inputs + // bob sees alice's `wrapWithPermit` in the mempool and frontruns her transaction with copied inputs vm.prank(bob); - eETHInstance.permit(alice, address(weEthInstance), 5 ether, 2**256 - 1, permitInput.v, permitInput.r, permitInput.s); + eETHInstance.permit(alice, address(weEthInstance), 5 ether, 2 ** 256 - 1, permitInput.v, permitInput.r, permitInput.s); startHoax(alice); // alices transaction still succeeds as the try catch swallows the error weEthInstance.wrapWithPermit(5 ether, permitInput); } - + function test_RecoverETH() public { uint256 amountToSend = 2 ether; // We cannot send ETH directly to eETH contract because it has no fallback/retrieve method ForceETHSender sender = new ForceETHSender(); vm.deal(address(sender), amountToSend); sender.forceSend(payable(address(weEthInstance))); - + // Check that eETH contract now has ETH assertEq(address(weEthInstance).balance, amountToSend); - + // Try to recover ETH without proper role - should fail vm.expectRevert(); vm.prank(bob); weEthInstance.recoverETH(payable(bob), amountToSend); - + // Check alice's balance before recovery uint256 aliceBalanceBefore = alice.balance; - + // Recover ETH as admin vm.prank(admin); weEthInstance.recoverETH(payable(alice), amountToSend); - + // Verify ETH was recovered assertEq(address(weEthInstance).balance, 0); assertEq(alice.balance, aliceBalanceBefore + amountToSend); } - + function test_RecoverERC20() public { // Create a mock ERC20 token TestERC20 mockToken = new TestERC20("Test Token", "TEST"); uint256 amountToSend = 1000e18; - + // Mint tokens to alice and send to eETH contract mockToken.mint(alice, amountToSend); vm.prank(alice); mockToken.transfer(address(weEthInstance), amountToSend); - + assertEq(mockToken.balanceOf(address(weEthInstance)), amountToSend); - + // Try to recover tokens without proper role - should fail vm.expectRevert(); vm.prank(bob); weEthInstance.recoverERC20(address(mockToken), alice, amountToSend); - + // Recover tokens as admin (who has the role) vm.prank(admin); weEthInstance.recoverERC20(address(mockToken), alice, amountToSend); - + // Verify tokens were recovered assertEq(mockToken.balanceOf(address(weEthInstance)), 0); assertEq(mockToken.balanceOf(alice), amountToSend); @@ -363,23 +362,23 @@ contract WeETHTest is TestSetup { function test_RecoverERC721() public { // Create a mock ERC721 token TestERC721 mockNFT = new TestERC721("Test NFT", "TNFT"); - + // Mint NFT to alice and send to eETH contract uint256 tokenId = mockNFT.mint(alice); vm.prank(alice); mockNFT.transferFrom(alice, address(weEthInstance), tokenId); - + assertEq(mockNFT.ownerOf(tokenId), address(weEthInstance)); - + // Try to recover NFT without proper role - should fail vm.expectRevert(); vm.prank(bob); weEthInstance.recoverERC721(address(mockNFT), alice, tokenId); - + // Recover NFT as admin vm.prank(admin); weEthInstance.recoverERC721(address(mockNFT), alice, tokenId); - + // Verify NFT was recovered assertEq(mockNFT.ownerOf(tokenId), alice); } @@ -390,17 +389,17 @@ contract WeETHTest is TestSetup { ForceETHSender sender = new ForceETHSender(); vm.deal(address(sender), amountToSend); sender.forceSend(payable(address(weEthInstance))); - + // Test 1: Try to recover 0 ETH - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); weEthInstance.recoverETH(payable(alice), 0); - + // Test 2: Try to recover more ETH than exists - should revert with InsufficientBalance vm.expectRevert(AssetRecovery.InsufficientBalance.selector); vm.prank(admin); weEthInstance.recoverETH(payable(alice), amountToSend + 1); - + // Test 3: Try to send to zero address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); @@ -410,27 +409,27 @@ contract WeETHTest is TestSetup { function test_RecoverERC20_ErrorConditions() public { TestERC20 mockToken = new TestERC20("Test Token", "TEST"); uint256 amountToSend = 1000e18; - + // Send tokens to eETH contract mockToken.mint(alice, amountToSend); vm.prank(alice); mockToken.transfer(address(weEthInstance), amountToSend); - + // Test 1: Try to recover 0 tokens - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); weEthInstance.recoverERC20(address(mockToken), alice, 0); - + // Test 2: Try to recover more tokens than exists - should revert with InsufficientBalance vm.expectRevert(AssetRecovery.InsufficientBalance.selector); vm.prank(admin); weEthInstance.recoverERC20(address(mockToken), alice, amountToSend + 1); - + // Test 3: Try to send to zero address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); weEthInstance.recoverERC20(address(mockToken), address(0), amountToSend); - + // Test 4: Try to recover from zero token address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); @@ -440,32 +439,31 @@ contract WeETHTest is TestSetup { function test_RecoverERC721_ErrorConditions() public { TestERC721 mockNFT = new TestERC721("Test NFT", "TNFT"); uint256 tokenId = mockNFT.mint(alice); - + // Send NFT to eETH contract vm.prank(alice); mockNFT.transferFrom(alice, address(weEthInstance), tokenId); - + // Test 1: Try to recover NFT that doesn't exist - should revert uint256 nonExistentTokenId = 9999; vm.expectRevert(); // ERC721: invalid token ID or similar vm.prank(admin); weEthInstance.recoverERC721(address(mockNFT), alice, nonExistentTokenId); - + // Test 2: Try to recover NFT that contract doesn't own - should revert with ContractIsNotOwnerOfERC721Token uint256 bobsTokenId = mockNFT.mint(bob); vm.expectRevert(AssetRecovery.ContractIsNotOwnerOfERC721Token.selector); vm.prank(admin); weEthInstance.recoverERC721(address(mockNFT), alice, bobsTokenId); - + // Test 3: Try to send to zero address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); weEthInstance.recoverERC721(address(mockNFT), address(0), tokenId); - + // Test 4: Try to recover from zero token address - should revert with InvalidInput vm.expectRevert(AssetRecovery.InvalidInput.selector); vm.prank(admin); weEthInstance.recoverERC721(address(0), alice, tokenId); } - } diff --git a/test/WithdrawRequestNFT.t.sol b/test/WithdrawRequestNFT.t.sol index ed0aef69a..3387c270d 100644 --- a/test/WithdrawRequestNFT.t.sol +++ b/test/WithdrawRequestNFT.t.sol @@ -3,24 +3,20 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "forge-std/console2.sol"; import "./TestSetup.sol"; - +import "forge-std/console2.sol"; contract WithdrawRequestNFTIntrusive is WithdrawRequestNFT { - constructor() WithdrawRequestNFT(address(0)) {} function updateParam(uint32 _currentRequestIdToScanFromForShareRemainder, uint32 _lastRequestIdToScanUntilForShareRemainder) external { currentRequestIdToScanFromForShareRemainder = _currentRequestIdToScanFromForShareRemainder; lastRequestIdToScanUntilForShareRemainder = _lastRequestIdToScanUntilForShareRemainder; } - } contract WithdrawRequestNFTTest is TestSetup { - - uint32[] public reqIds =[ 20, 388, 478, 714, 726, 729, 735, 815, 861, 916, 941, 1014, 1067, 1154, 1194, 1253]; + uint32[] public reqIds = [20, 388, 478, 714, 726, 729, 735, 815, 861, 916, 941, 1014, 1067, 1154, 1194, 1253]; address etherfi_admin_wallet = 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC; function setUp() public { @@ -237,7 +233,6 @@ contract WithdrawRequestNFTTest is TestSetup { uint256 bobsEndingBalance = address(bob).balance; assertEq(bobsEndingBalance, bobsStartingBalance + 60 ether, "Bobs balance should be 60 ether higher"); - } function test_SD_6() public { @@ -264,10 +259,8 @@ contract WithdrawRequestNFTTest is TestSetup { // Within `LP.requestWithdraw` // - `share` is calculated by `sharesForAmount` as (9 * 98) / 100 = 8.82 ---> (rounded down to) 8 - _finalizeWithdrawalRequest(requestId); - vm.prank(bob); withdrawRequestNFTInstance.claimWithdraw(requestId); // Within `claimWithdraw`, @@ -276,7 +269,7 @@ contract WithdrawRequestNFTTest is TestSetup { // - `amountToTransfer` is min(9, 8) = 8 // Therefore, it calls `LP.withdraw(.., 8)` - // Within `LP.withdraw`, + // Within `LP.withdraw`, // - `share` is calculated by 'sharesForWithdrawalAmount' as (8 * 98 + 100 - 1) / 100 = 8.83 ---> (rounded down to) 8 // As a result, bob received 8 wei ETH which is 1 wei less than 9 wei. @@ -284,13 +277,12 @@ contract WithdrawRequestNFTTest is TestSetup { assertEq(eETHInstance.balanceOf(address(withdrawRequestNFTInstance)), 0); // We burnt 8 wei eETH share which is worth of 8.16 wei eETH amount. - // We processed the withdrawal of 8 wei ETH. + // We processed the withdrawal of 8 wei ETH. // --> The rest 0.16 wei ETH is effectively distributed to the other eETH holders. } - // It depicts the scenario where bob's WithdrawalRequest NFT is stolen by alice. - // The owner invalidates the request + // The owner invalidates the request function test_InvalidatedRequestNft_after_finalization() public returns (uint256 requestId) { startHoax(bob); liquidityPoolInstance.deposit{value: 10 ether}(); @@ -347,7 +339,7 @@ contract WithdrawRequestNFTTest is TestSetup { vm.startPrank(withdrawRequestNFTInstance.owner()); // 1. Upgrade withdrawRequestNFTInstance.upgradeTo(address(new WithdrawRequestNFT(address(owner)))); - withdrawRequestNFTInstance.initializeOnUpgrade(address(roleRegistryInstance), 50_00); + withdrawRequestNFTInstance.initializeOnUpgrade(address(roleRegistryInstance), 5000); // 2. (For test) update the scan range updateParam(1, 200); @@ -399,14 +391,14 @@ contract WithdrawRequestNFTTest is TestSetup { vm.assume(depositAmount >= 1 ether && depositAmount <= 1000 ether); vm.assume(withdrawAmount > 0 && withdrawAmount <= depositAmount); vm.assume(recipient != address(0) && recipient != address(liquidityPoolInstance)); - + // Setup initial balance for bob vm.deal(bob, depositAmount); - + // Deposit ETH and get eETH vm.startPrank(bob); liquidityPoolInstance.deposit{value: depositAmount}(); - + // Approve and request withdraw eETHInstance.approve(address(liquidityPoolInstance), withdrawAmount); uint256 requestId = liquidityPoolInstance.requestWithdraw(recipient, withdrawAmount); @@ -414,12 +406,12 @@ contract WithdrawRequestNFTTest is TestSetup { // Verify the request was created correctly WithdrawRequestNFT.WithdrawRequest memory request = withdrawRequestNFTInstance.getRequest(requestId); - + assertEq(request.amountOfEEth, withdrawAmount, "Incorrect withdrawal amount"); assertEq(request.shareOfEEth, liquidityPoolInstance.sharesForAmount(withdrawAmount), "Incorrect share amount"); assertTrue(request.isValid, "Request should be valid"); assertEq(withdrawRequestNFTInstance.ownerOf(requestId), recipient, "Incorrect NFT owner"); - + // Verify eETH balances assertEq(eETHInstance.balanceOf(bob), depositAmount - withdrawAmount, "Incorrect remaining eETH balance"); assertEq(eETHInstance.balanceOf(address(withdrawRequestNFTInstance)), withdrawAmount, "Incorrect contract eETH balance"); @@ -429,27 +421,20 @@ contract WithdrawRequestNFTTest is TestSetup { uint256 reqAmount = eETHInstance.balanceOf(bob); vm.startPrank(bob); eETHInstance.approve(address(liquidityPoolInstance), reqAmount); - uint256 requestId2 = liquidityPoolInstance.requestWithdraw(recipient, reqAmount); + uint256 requestId2 = liquidityPoolInstance.requestWithdraw(recipient, reqAmount); vm.stopPrank(); assertEq(requestId2, requestId + 1, "Incorrect next request ID"); } } - function testFuzz_ClaimWithdraw( - uint96 depositAmount, - uint96 withdrawAmount, - uint96 rebaseAmount, - uint16 remainderSplitBps, - address recipient - ) public { + function testFuzz_ClaimWithdraw(uint96 depositAmount, uint96 withdrawAmount, uint96 rebaseAmount, uint16 remainderSplitBps, address recipient) public { // Assume valid conditions vm.assume(depositAmount >= 1 ether && depositAmount <= 1e6 ether); vm.assume(withdrawAmount > 0 && withdrawAmount <= depositAmount); vm.assume(rebaseAmount >= 0.5 ether && rebaseAmount <= depositAmount); - vm.assume(remainderSplitBps <= 10000); + vm.assume(remainderSplitBps <= 10_000); vm.assume(recipient != address(0) && recipient != address(liquidityPoolInstance)); - vm.expectRevert("scan is completed"); withdrawRequestNFTInstance.aggregateSumEEthShareAmount(10); @@ -491,7 +476,7 @@ contract WithdrawRequestNFTTest is TestSetup { uint256 initialTotalShares = eETHInstance.totalShares(); _finalizeWithdrawalRequest(requestId); - + vm.prank(recipient); withdrawRequestNFTInstance.claimWithdraw(requestId); @@ -500,50 +485,26 @@ contract WithdrawRequestNFTTest is TestSetup { // Verify share burning assertLe(burnedShares, request.shareOfEEth, "Burned shares should be less than or equal to requested shares"); - assertApproxEqAbs( - burnedShares, - expectedBurnedShares, - 1e3, - "Incorrect amount of shares burnt" - ); - + assertApproxEqAbs(burnedShares, expectedBurnedShares, 1e3, "Incorrect amount of shares burnt"); // Verify total supply reduction - assertApproxEqAbs( - eETHInstance.totalShares(), - initialTotalShares - burnedShares, - 1, - "Total shares not reduced correctly" - ); - assertGe( - eETHInstance.totalShares(), - initialTotalShares - burnedShares, - "Total shares should be greater than or equal to initial shares minus burned shares" - ); + assertApproxEqAbs(eETHInstance.totalShares(), initialTotalShares - burnedShares, 1, "Total shares not reduced correctly"); + assertGe(eETHInstance.totalShares(), initialTotalShares - burnedShares, "Total shares should be greater than or equal to initial shares minus burned shares"); // Verify the withdrawal results WithdrawRequestNFT.WithdrawRequest memory requestAfter = withdrawRequestNFTInstance.getRequest(requestId); - + // Request should be cleared assertEq(requestAfter.amountOfEEth, 0, "Request should be cleared after claim"); - + // NFT should be burned vm.expectRevert("ERC721: invalid token ID"); withdrawRequestNFTInstance.ownerOf(requestId); // Verify recipient received correct ETH amount - assertEq( - address(recipient).balance, - recipientBalanceBefore + expectedWithdrawAmount, - "Recipient should receive correct ETH amount" - ); - - assertApproxEqAbs( - withdrawRequestNFTInstance.totalRemainderEEthShares(), - expectedDustShares, - 1, - "Incorrect remainder shares" - ); + assertEq(address(recipient).balance, recipientBalanceBefore + expectedWithdrawAmount, "Recipient should receive correct ETH amount"); + + assertApproxEqAbs(withdrawRequestNFTInstance.totalRemainderEEthShares(), expectedDustShares, 1, "Incorrect remainder shares"); uint256 dustEEthAmount = withdrawRequestNFTInstance.getEEthRemainderAmount(); console2.log("wtf"); @@ -556,13 +517,13 @@ contract WithdrawRequestNFTTest is TestSetup { vm.assume(depositAmount >= 1 ether && depositAmount <= 1000 ether); vm.assume(withdrawAmount > 0 && withdrawAmount <= depositAmount); vm.assume(recipient != address(0) && recipient != address(liquidityPoolInstance) && recipient != alice && recipient != admin && recipient != (address(etherFiAdminInstance))); - + // Setup initial balance and deposit vm.deal(recipient, depositAmount); - + vm.startPrank(recipient); liquidityPoolInstance.deposit{value: depositAmount}(); - + // Request withdraw eETHInstance.approve(address(liquidityPoolInstance), withdrawAmount); uint256 requestId = liquidityPoolInstance.requestWithdraw(recipient, withdrawAmount); @@ -587,7 +548,7 @@ contract WithdrawRequestNFTTest is TestSetup { // Verify request state after invalidation assertFalse(withdrawRequestNFTInstance.isValid(requestId), "Request should be invalid"); assertEq(withdrawRequestNFTInstance.ownerOf(requestId), recipient, "NFT ownership should remain unchanged"); - + // Verify cannot transfer invalid request vm.prank(recipient); vm.expectRevert("INVALID_REQUEST"); diff --git a/test/common/ArrayTestHelper.sol b/test/common/ArrayTestHelper.sol index 636a15147..cf56798fb 100644 --- a/test/common/ArrayTestHelper.sol +++ b/test/common/ArrayTestHelper.sol @@ -11,36 +11,43 @@ contract ArrayTestHelper { vals[0] = val; return vals; } + function toArray_u256(uint32 val) public pure returns (uint256[] memory) { uint256[] memory vals = new uint256[](1); vals[0] = val; return vals; } + function toArray_u32(uint32 val) public pure returns (uint32[] memory) { uint32[] memory vals = new uint32[](1); vals[0] = val; return vals; } + function toArray_u40(uint40 val) public pure returns (uint40[] memory) { uint40[] memory vals = new uint40[](1); vals[0] = val; return vals; } + function toArray_bytes(bytes memory val) public pure returns (bytes[] memory) { bytes[] memory vals = new bytes[](1); vals[0] = val; return vals; } + function toArray(address val) public pure returns (address[] memory) { address[] memory vals = new address[](1); vals[0] = val; return vals; } + function toArray(IDelegationManager.Withdrawal memory withdrawal) public pure returns (IDelegationManager.Withdrawal[] memory) { IDelegationManager.Withdrawal[] memory vals = new IDelegationManager.Withdrawal[](1); vals[0] = withdrawal; return vals; } + function toArray(IStakingManager.DepositData memory deposit) public pure returns (IStakingManager.DepositData[] memory) { IStakingManager.DepositData[] memory vals = new IStakingManager.DepositData[](1); vals[0] = deposit; diff --git a/test/common/DepositContract.sol b/test/common/DepositContract.sol index bda891647..abb5e506e 100644 --- a/test/common/DepositContract.sol +++ b/test/common/DepositContract.sol @@ -8,9 +8,9 @@ import "src/interfaces/IDepositContract.sol"; /// @notice This is the Ethereum 2.0 deposit contract interface. /// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs contract DepositContract is IDepositContract { - uint constant DEPOSIT_CONTRACT_TREE_DEPTH = 32; + uint256 constant DEPOSIT_CONTRACT_TREE_DEPTH = 32; // NOTE: this also ensures `deposit_count` will fit into 64-bits - uint constant MAX_DEPOSIT_COUNT = 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1; + uint256 constant MAX_DEPOSIT_COUNT = 2 ** DEPOSIT_CONTRACT_TREE_DEPTH - 1; bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] branch; uint256 deposit_count; @@ -19,37 +19,30 @@ contract DepositContract is IDepositContract { constructor() public { // Compute hashes in empty sparse Merkle tree - for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH - 1; height++) + for (uint256 height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH - 1; height++) { zero_hashes[height + 1] = sha256(abi.encodePacked(zero_hashes[height], zero_hashes[height])); + } } - function get_deposit_root() override external view returns (bytes32) { + function get_deposit_root() external view override returns (bytes32) { bytes32 node; - uint size = deposit_count; - for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) { - if ((size & 1) == 1) + uint256 size = deposit_count; + for (uint256 height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) { + if ((size & 1) == 1) { node = sha256(abi.encodePacked(branch[height], node)); - else + } else { node = sha256(abi.encodePacked(node, zero_hashes[height])); + } size /= 2; } - return sha256(abi.encodePacked( - node, - to_little_endian_64(uint64(deposit_count)), - bytes24(0) - )); + return sha256(abi.encodePacked(node, to_little_endian_64(uint64(deposit_count)), bytes24(0))); } - function get_deposit_count() override external view returns (bytes memory) { + function get_deposit_count() external view override returns (bytes memory) { return to_little_endian_64(uint64(deposit_count)); } - function deposit( - bytes calldata pubkey, - bytes calldata withdrawal_credentials, - bytes calldata signature, - bytes32 deposit_data_root - ) override external payable { + function deposit(bytes calldata pubkey, bytes calldata withdrawal_credentials, bytes calldata signature, bytes32 deposit_data_root) external payable override { // Extended ABI length checks since dynamic types are used. require(pubkey.length == 48, "DepositContract: invalid pubkey length"); require(withdrawal_credentials.length == 32, "DepositContract: invalid withdrawal_credentials length"); @@ -58,29 +51,17 @@ contract DepositContract is IDepositContract { // Check deposit amount require(msg.value >= 1 ether, "DepositContract: deposit value too low"); require(msg.value % 1 gwei == 0, "DepositContract: deposit value not multiple of gwei"); - uint deposit_amount = msg.value / 1 gwei; + uint256 deposit_amount = msg.value / 1 gwei; require(deposit_amount <= type(uint64).max, "DepositContract: deposit value too high"); // Emit `DepositEvent` log bytes memory amount = to_little_endian_64(uint64(deposit_amount)); - emit DepositEvent( - pubkey, - withdrawal_credentials, - amount, - signature, - to_little_endian_64(uint64(deposit_count)) - ); + emit DepositEvent(pubkey, withdrawal_credentials, amount, signature, to_little_endian_64(uint64(deposit_count))); // Compute deposit data root (`DepositData` hash tree root) bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0))); - bytes32 signature_root = sha256(abi.encodePacked( - sha256(abi.encodePacked(signature[:64])), - sha256(abi.encodePacked(signature[64:], bytes32(0))) - )); - bytes32 node = sha256(abi.encodePacked( - sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)), - sha256(abi.encodePacked(amount, bytes24(0), signature_root)) - )); + bytes32 signature_root = sha256(abi.encodePacked(sha256(abi.encodePacked(signature[:64])), sha256(abi.encodePacked(signature[64:], bytes32(0))))); + bytes32 node = sha256(abi.encodePacked(sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)), sha256(abi.encodePacked(amount, bytes24(0), signature_root)))); // Verify computed and expected deposit data roots match require(node == deposit_data_root, "DepositContract: reconstructed DepositData does not match supplied deposit_data_root"); @@ -90,8 +71,8 @@ contract DepositContract is IDepositContract { //Add deposit data root to Merkle tree (update a single `branch` node) deposit_count += 1; - uint size = deposit_count; - for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) { + uint256 size = deposit_count; + for (uint256 height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) { if ((size & 1) == 1) { branch[height] = node; return; @@ -103,7 +84,7 @@ contract DepositContract is IDepositContract { //this code should be unreachable. We assert `false` just to be safe. assert(false); } - + function to_little_endian_64(uint64 value) internal pure returns (bytes memory ret) { ret = new bytes(8); bytes8 bytesValue = bytes8(value); @@ -119,7 +100,7 @@ contract DepositContract is IDepositContract { } function withdrawFunds(address _address) external { - (bool sent, ) = _address.call{value: address(this).balance}(""); + (bool sent,) = _address.call{value: address(this).balance}(""); require(sent, "Failed to send Ether"); } -} \ No newline at end of file +} diff --git a/test/common/DepositDataGeneration.sol b/test/common/DepositDataGeneration.sol index d212074a5..69954b63a 100644 --- a/test/common/DepositDataGeneration.sol +++ b/test/common/DepositDataGeneration.sol @@ -4,54 +4,34 @@ pragma solidity ^0.8.13; contract DepositDataGeneration { uint64 constant GWEI = 1e9; - function generateDepositRoot( - bytes memory pubkey, - bytes memory signature, - bytes memory withdrawal_credentials, - uint256 _amountIn - ) internal pure returns (bytes32) { + function generateDepositRoot(bytes memory pubkey, bytes memory signature, bytes memory withdrawal_credentials, uint256 _amountIn) internal pure returns (bytes32) { uint64 deposit_amount = uint64(_amountIn / GWEI); bytes memory amount = to_little_endian_64(deposit_amount); bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0))); - + // Extract first 64 bytes of signature bytes memory firstChunk = extractBytes(signature, 0, 64); // Extract remaining bytes of signature bytes memory secondChunk = extractBytes(signature, 64, signature.length - 64); - - bytes32 signature_root = sha256( - abi.encodePacked( - sha256(abi.encodePacked(firstChunk)), - sha256(abi.encodePacked(secondChunk, bytes32(0))) - ) - ); - return - sha256( - abi.encodePacked( - sha256( - abi.encodePacked(pubkey_root, withdrawal_credentials) - ), - sha256(abi.encodePacked(amount, bytes24(0), signature_root)) - ) - ); + + bytes32 signature_root = sha256(abi.encodePacked(sha256(abi.encodePacked(firstChunk)), sha256(abi.encodePacked(secondChunk, bytes32(0))))); + return sha256(abi.encodePacked(sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)), sha256(abi.encodePacked(amount, bytes24(0), signature_root)))); } // Helper function to extract a portion of a bytes array function extractBytes(bytes memory data, uint256 startIndex, uint256 length) internal pure returns (bytes memory) { require(startIndex + length <= data.length, "Range out of bounds"); - + bytes memory result = new bytes(length); for (uint256 i = 0; i < length; i++) { result[i] = data[startIndex + i]; } - + return result; } - function to_little_endian_64( - uint64 value - ) internal pure returns (bytes memory ret) { + function to_little_endian_64(uint64 value) internal pure returns (bytes memory ret) { ret = new bytes(8); bytes8 bytesValue = bytes8(value); // Byteswapping during copying to bytes. diff --git a/test/eigenlayer-mocks/BeaconChainOracleMock.sol b/test/eigenlayer-mocks/BeaconChainOracleMock.sol index 8d06db5b5..db8dee7fb 100644 --- a/test/eigenlayer-mocks/BeaconChainOracleMock.sol +++ b/test/eigenlayer-mocks/BeaconChainOracleMock.sol @@ -3,13 +3,10 @@ pragma solidity ^0.8.12; import "../../src/eigenlayer-interfaces/IBeaconChainOracle.sol"; - - contract BeaconChainOracleMock is IBeaconChainOracle { - bytes32 public mockBeaconChainStateRoot; - function getOracleBlockRootAtTimestamp() external view returns(bytes32) { + function getOracleBlockRootAtTimestamp() external view returns (bytes32) { return mockBeaconChainStateRoot; } @@ -17,37 +14,37 @@ contract BeaconChainOracleMock is IBeaconChainOracle { mockBeaconChainStateRoot = beaconChainStateRoot; } - function timestampToBlockRoot(uint256 /*blockNumber*/) external view returns(bytes32) { + function timestampToBlockRoot(uint256 /*blockNumber*/ ) external view returns (bytes32) { return mockBeaconChainStateRoot; } - function isOracleSigner(address /*_oracleSigner*/) external pure returns(bool) { + function isOracleSigner(address /*_oracleSigner*/ ) external pure returns (bool) { return true; } - function hasVoted(uint64 /*blockNumber*/, address /*oracleSigner*/) external pure returns(bool) { + function hasVoted(uint64, /*blockNumber*/ address /*oracleSigner*/ ) external pure returns (bool) { return true; } - function stateRootVotes(uint64 /*blockNumber*/, bytes32 /*stateRoot*/) external pure returns(uint256) { + function stateRootVotes(uint64, /*blockNumber*/ bytes32 /*stateRoot*/ ) external pure returns (uint256) { return 0; } - function totalOracleSigners() external pure returns(uint256) { + function totalOracleSigners() external pure returns (uint256) { return 0; } - function threshold() external pure returns(uint256) { + function threshold() external pure returns (uint256) { return 0; } - function setThreshold(uint256 /*_threshold*/) external pure {} + function setThreshold(uint256 /*_threshold*/ ) external pure {} - function addOracleSigners(address[] memory /*_oracleSigners*/) external pure {} + function addOracleSigners(address[] memory /*_oracleSigners*/ ) external pure {} - function removeOracleSigners(address[] memory /*_oracleSigners*/) external pure {} + function removeOracleSigners(address[] memory /*_oracleSigners*/ ) external pure {} - function voteForBeaconChainStateRoot(uint64 /*blockNumber*/, bytes32 /*stateRoot*/) external pure {} + function voteForBeaconChainStateRoot(uint64, /*blockNumber*/ bytes32 /*stateRoot*/ ) external pure {} - function latestConfirmedOracleBlockNumber() external pure returns(uint64) {} + function latestConfirmedOracleBlockNumber() external pure returns (uint64) {} } diff --git a/test/eigenlayer-mocks/ETHDepositMock.sol b/test/eigenlayer-mocks/ETHDepositMock.sol index aa9939daf..01d0ca98c 100644 --- a/test/eigenlayer-mocks/ETHDepositMock.sol +++ b/test/eigenlayer-mocks/ETHDepositMock.sol @@ -3,16 +3,8 @@ pragma solidity ^0.8.12; import "../../src/eigenlayer-interfaces/IETHPOSDeposit.sol"; - contract ETHPOSDepositMock is IETHPOSDeposit { - - function deposit( - bytes calldata pubkey, - bytes calldata withdrawal_credentials, - bytes calldata signature, - bytes32 deposit_data_root - ) external payable {} - + function deposit(bytes calldata pubkey, bytes calldata withdrawal_credentials, bytes calldata signature, bytes32 deposit_data_root) external payable {} function get_deposit_root() external pure returns (bytes32) { bytes32 root; @@ -25,7 +17,4 @@ contract ETHPOSDepositMock is IETHPOSDeposit { bytes memory root; return root; } - - } - diff --git a/test/eigenlayer-mocks/IBeaconChainOracleMock.sol b/test/eigenlayer-mocks/IBeaconChainOracleMock.sol index 8bfc227a8..15a237369 100644 --- a/test/eigenlayer-mocks/IBeaconChainOracleMock.sol +++ b/test/eigenlayer-mocks/IBeaconChainOracleMock.sol @@ -8,34 +8,32 @@ pragma solidity ^0.8.12; */ interface IBeaconChainOracleMock { /// @notice Largest blockNumber that has been confirmed by the oracle. - function latestConfirmedOracleBlockNumber() external view returns(uint64); + function latestConfirmedOracleBlockNumber() external view returns (uint64); /// @notice Mapping: Beacon Chain blockNumber => the Beacon Chain state root at the specified blockNumber. /// @dev This will return `bytes32(0)` if the state root is not yet finalized at the blockNumber. - function beaconStateRootAtBlockNumber(uint64 blockNumber) external view returns(bytes32); + function beaconStateRootAtBlockNumber(uint64 blockNumber) external view returns (bytes32); /// @notice Mapping: address => whether or not the address is in the set of oracle signers. - function isOracleSigner(address _oracleSigner) external view returns(bool); + function isOracleSigner(address _oracleSigner) external view returns (bool); /// @notice Mapping: Beacon Chain blockNumber => oracle signer address => whether or not the oracle signer has voted on the state root at the blockNumber. - function hasVoted(uint64 blockNumber, address oracleSigner) external view returns(bool); + function hasVoted(uint64 blockNumber, address oracleSigner) external view returns (bool); - /// @notice Mapping: Beacon Chain blockNumber => state root => total number of oracle signer votes for the state root at the blockNumber. - function stateRootVotes(uint64 blockNumber, bytes32 stateRoot) external view returns(uint256); + /// @notice Mapping: Beacon Chain blockNumber => state root => total number of oracle signer votes for the state root at the blockNumber. + function stateRootVotes(uint64 blockNumber, bytes32 stateRoot) external view returns (uint256); /// @notice Total number of members of the set of oracle signers. - function totalOracleSigners() external view returns(uint256); - + function totalOracleSigners() external view returns (uint256); function setOracleBlockRootAtTimestamp(bytes32 beaconChainStateRoot) external; - /** * @notice Number of oracle signers that must vote for a state root in order for the state root to be confirmed. * Adjustable by this contract's owner through use of the `setThreshold` function. * @dev We note that there is an edge case -- when the threshold is adjusted downward, if a state root already has enough votes to meet the *new* threshold, * the state root must still receive one additional vote from an oracle signer to be confirmed. This behavior is intended, to minimize unexpected root confirmations. */ - function threshold() external view returns(uint256); + function threshold() external view returns (uint256); /** * @notice Owner-only function used to modify the value of the `threshold` variable. @@ -64,4 +62,4 @@ interface IBeaconChainOracleMock { * @param stateRoot The Beacon Chain state root that the caller asserts was the correct root, at the specified `blockNumber`. */ function voteForBeaconChainStateRoot(uint64 blockNumber, bytes32 stateRoot) external; -} \ No newline at end of file +} diff --git a/test/eigenlayer-utils/Operators.sol b/test/eigenlayer-utils/Operators.sol index 68bdc6b12..840e3b7ee 100644 --- a/test/eigenlayer-utils/Operators.sol +++ b/test/eigenlayer-utils/Operators.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.12; -import "forge-std/Test.sol"; import "forge-std/Script.sol"; import "forge-std/StdJson.sol"; +import "forge-std/Test.sol"; contract Operators is Test { string internal operatorConfigJson; @@ -12,19 +12,19 @@ contract Operators is Test { operatorConfigJson = vm.readFile("./src/test/test-data/operators.json"); } - function operatorPrefix(uint256 index) public returns(string memory) { + function operatorPrefix(uint256 index) public returns (string memory) { return string.concat(".operators[", string.concat(vm.toString(index), "].")); } - function getNumOperators() public returns(uint256) { + function getNumOperators() public returns (uint256) { return stdJson.readUint(operatorConfigJson, ".numOperators"); } - function getOperatorAddress(uint256 index) public returns(address) { + function getOperatorAddress(uint256 index) public returns (address) { return stdJson.readAddress(operatorConfigJson, string.concat(operatorPrefix(index), "Address")); } - function getOperatorSecretKey(uint256 index) public returns(uint256) { + function getOperatorSecretKey(uint256 index) public returns (uint256) { return readUint(operatorConfigJson, index, "SecretKey"); } @@ -37,11 +37,12 @@ contract Operators is Test { uint256 result = 0; for (uint256 i = 0; i < b.length; i++) { if (uint256(uint8(b[i])) >= 48 && uint256(uint8(b[i])) <= 57) { - result = result * 10 + (uint256(uint8(b[i])) - 48); + result = result * 10 + (uint256(uint8(b[i])) - 48); } } return result; } + function setOperatorJsonFilePath(string memory filepath) public { operatorConfigJson = vm.readFile(filepath); } diff --git a/test/eigenlayer-utils/Owners.sol b/test/eigenlayer-utils/Owners.sol index 82790fefa..e3ffee90a 100644 --- a/test/eigenlayer-utils/Owners.sol +++ b/test/eigenlayer-utils/Owners.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.12; -import "forge-std/Test.sol"; import "forge-std/Script.sol"; import "forge-std/StdJson.sol"; +import "forge-std/Test.sol"; contract Owners is Test { string internal ownersConfigJson; @@ -13,35 +13,34 @@ contract Owners is Test { ownersConfigJson = vm.readFile("./src/test/test-data/owners.json"); } - function ownerPrefix(uint256 index) public returns(string memory) { + function ownerPrefix(uint256 index) public returns (string memory) { return string.concat(".owners[", string.concat(vm.toString(index), "].")); } - function getNumOperators() public returns(uint256) { + function getNumOperators() public returns (uint256) { return stdJson.readUint(ownersConfigJson, ".numOwners"); } - function getOwnerAddress(uint256 index) public returns(address) { + function getOwnerAddress(uint256 index) public returns (address) { return stdJson.readAddress(ownersConfigJson, string.concat(ownerPrefix(index), "Address")); } - function getOwnerAddresses() public returns(address[] memory) { + function getOwnerAddresses() public returns (address[] memory) { for (uint256 i = 0; i < getNumOperators(); i++) { addresses.push(getOwnerAddress(i)); } - return addresses; + return addresses; } - function getReputedOwnerAddresses() public returns(address[] memory) { + function getReputedOwnerAddresses() public returns (address[] memory) { resetOwnersConfigJson("reputedOwners.json"); for (uint256 i = 0; i < getNumOperators(); i++) { addresses.push(getOwnerAddress(i)); } - return addresses; + return addresses; } function resetOwnersConfigJson(string memory newConfig) public { ownersConfigJson = vm.readFile(newConfig); } - } diff --git a/test/eigenlayer-utils/ProofParsing.sol b/test/eigenlayer-utils/ProofParsing.sol index 0e90f9c26..04504ca92 100644 --- a/test/eigenlayer-utils/ProofParsing.sol +++ b/test/eigenlayer-utils/ProofParsing.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.12; -import "forge-std/Test.sol"; import "forge-std/StdJson.sol"; +import "forge-std/Test.sol"; contract ProofParsing is Test { string internal proofConfigJson; @@ -26,175 +26,174 @@ contract ProofParsing is Test { proofConfigJson = vm.readFile(path); } - function getSlot() public returns(uint256) { + function getSlot() public returns (uint256) { return stdJson.readUint(proofConfigJson, ".slot"); } - function getValidatorIndex() public returns(uint256) { + function getValidatorIndex() public returns (uint256) { return stdJson.readUint(proofConfigJson, ".validatorIndex"); } - function getValidatorPubkeyHash() public returns(bytes32) { + function getValidatorPubkeyHash() public returns (bytes32) { return stdJson.readBytes32(proofConfigJson, ".ValidatorFields[0]"); } - function getWithdrawalIndex() public returns(uint256) { + function getWithdrawalIndex() public returns (uint256) { return stdJson.readUint(proofConfigJson, ".withdrawalIndex"); } - function getBlockRootIndex() public returns(uint256) { + function getBlockRootIndex() public returns (uint256) { return stdJson.readUint(proofConfigJson, ".blockHeaderRootIndex"); } - function getHistoricalSummaryIndex() public returns(uint256) { + function getHistoricalSummaryIndex() public returns (uint256) { return stdJson.readUint(proofConfigJson, ".historicalSummaryIndex"); } - function getBeaconStateRoot() public returns(bytes32) { + function getBeaconStateRoot() public returns (bytes32) { return stdJson.readBytes32(proofConfigJson, ".beaconStateRoot"); } - function getBlockRoot() public returns(bytes32) { + function getBlockRoot() public returns (bytes32) { return stdJson.readBytes32(proofConfigJson, ".blockHeaderRoot"); } - function getSlotRoot() public returns(bytes32) { + function getSlotRoot() public returns (bytes32) { return stdJson.readBytes32(proofConfigJson, ".slotRoot"); } - function getTimestampRoot() public returns(bytes32) { + function getTimestampRoot() public returns (bytes32) { return stdJson.readBytes32(proofConfigJson, ".timestampRoot"); } - function getExecutionPayloadRoot() public returns(bytes32) { + function getExecutionPayloadRoot() public returns (bytes32) { return stdJson.readBytes32(proofConfigJson, ".executionPayloadRoot"); } - function getLatestBlockRoot() public returns(bytes32) { + function getLatestBlockRoot() public returns (bytes32) { return stdJson.readBytes32(proofConfigJson, ".latestBlockHeaderRoot"); } - function getExecutionPayloadProof () public returns(bytes32[7] memory) { - for (uint i = 0; i < 7; i++) { + + function getExecutionPayloadProof() public returns (bytes32[7] memory) { + for (uint256 i = 0; i < 7; i++) { prefix = string.concat(".ExecutionPayloadProof[", string.concat(vm.toString(i), "]")); - executionPayloadProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + executionPayloadProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return executionPayloadProof; } - function getTimestampProofDeneb() public returns(bytes32[5] memory) { - for (uint i = 0; i < 5; i++) { + function getTimestampProofDeneb() public returns (bytes32[5] memory) { + for (uint256 i = 0; i < 5; i++) { prefix = string.concat(".TimestampProof[", string.concat(vm.toString(i), "]")); - timestampProofsCapella[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + timestampProofsCapella[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return timestampProofsCapella; } - function getTimestampProofCapella() public returns(bytes32[4] memory) { - for (uint i = 0; i < 4; i++) { + function getTimestampProofCapella() public returns (bytes32[4] memory) { + for (uint256 i = 0; i < 4; i++) { prefix = string.concat(".TimestampProof[", string.concat(vm.toString(i), "]")); - timestampProofsDeneb[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + timestampProofsDeneb[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return timestampProofsDeneb; } - - - function getBlockHeaderProof() public returns(bytes32[18] memory) { - for (uint i = 0; i < 18; i++) { + function getBlockHeaderProof() public returns (bytes32[18] memory) { + for (uint256 i = 0; i < 18; i++) { prefix = string.concat(".BlockHeaderProof[", string.concat(vm.toString(i), "]")); - blockHeaderProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + blockHeaderProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return blockHeaderProof; } - function getSlotProof() public returns(bytes32[3] memory) { - for (uint i = 0; i < 3; i++) { + function getSlotProof() public returns (bytes32[3] memory) { + for (uint256 i = 0; i < 3; i++) { prefix = string.concat(".SlotProof[", string.concat(vm.toString(i), "]")); - slotProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + slotProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return slotProof; } - function getStateRootProof() public returns(bytes memory) { + function getStateRootProof() public returns (bytes memory) { bytes32[] memory stateRootProof = new bytes32[](3); - for (uint i = 0; i < 3; i++) { + for (uint256 i = 0; i < 3; i++) { prefix = string.concat(".StateRootAgainstLatestBlockHeaderProof[", string.concat(vm.toString(i), "]")); - stateRootProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + stateRootProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } // return stateRootProof; return abi.encodePacked(stateRootProof); } - function getWithdrawalProofDeneb() public returns(bytes32[10] memory) { - for (uint i = 0; i < 10; i++) { + function getWithdrawalProofDeneb() public returns (bytes32[10] memory) { + for (uint256 i = 0; i < 10; i++) { prefix = string.concat(".WithdrawalProof[", string.concat(vm.toString(i), "]")); - withdrawalProofDeneb[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + withdrawalProofDeneb[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return withdrawalProofDeneb; } - function getWithdrawalProofCapella() public returns(bytes32[9] memory) { - for (uint i = 0; i < 9; i++) { + function getWithdrawalProofCapella() public returns (bytes32[9] memory) { + for (uint256 i = 0; i < 9; i++) { prefix = string.concat(".WithdrawalProof[", string.concat(vm.toString(i), "]")); - withdrawalProofCapella[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + withdrawalProofCapella[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return withdrawalProofCapella; } - function getValidatorProof() public returns(bytes32[46] memory) { - for (uint i = 0; i < 46; i++) { + function getValidatorProof() public returns (bytes32[46] memory) { + for (uint256 i = 0; i < 46; i++) { prefix = string.concat(".ValidatorProof[", string.concat(vm.toString(i), "]")); - validatorProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + validatorProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return validatorProof; } - function getHistoricalSummaryProof() public returns(bytes32[44] memory) { - for (uint i = 0; i < 44; i++) { + function getHistoricalSummaryProof() public returns (bytes32[44] memory) { + for (uint256 i = 0; i < 44; i++) { prefix = string.concat(".HistoricalSummaryProof[", string.concat(vm.toString(i), "]")); - historicalSummaryProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + historicalSummaryProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return historicalSummaryProof; } - - function getWithdrawalFields() public returns(bytes32[] memory) { + + function getWithdrawalFields() public returns (bytes32[] memory) { bytes32[] memory withdrawalFields = new bytes32[](4); - for (uint i = 0; i < 4; i++) { + for (uint256 i = 0; i < 4; i++) { prefix = string.concat(".WithdrawalFields[", string.concat(vm.toString(i), "]")); - withdrawalFields[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + withdrawalFields[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } - return withdrawalFields; + return withdrawalFields; } - function getValidatorFields() public returns(bytes32[] memory) { + function getValidatorFields() public returns (bytes32[] memory) { bytes32[] memory validatorFields = new bytes32[](8); - for (uint i = 0; i < 8; i++) { + for (uint256 i = 0; i < 8; i++) { prefix = string.concat(".ValidatorFields[", string.concat(vm.toString(i), "]")); - validatorFields[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + validatorFields[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return validatorFields; } - function getBalanceUpdateProof() public returns(bytes32[] memory) { + function getBalanceUpdateProof() public returns (bytes32[] memory) { // Balance update proofs are the same as withdrawal credential proofs return getWithdrawalCredentialProof(); } - function getWithdrawalCredentialProof() public returns(bytes32[] memory) { + function getWithdrawalCredentialProof() public returns (bytes32[] memory) { bytes32[] memory withdrawalCredentialProof = new bytes32[](46); - for (uint i = 0; i < 46; i++) { + for (uint256 i = 0; i < 46; i++) { prefix = string.concat(".WithdrawalCredentialProof[", string.concat(vm.toString(i), "]")); - withdrawalCredentialProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + withdrawalCredentialProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return withdrawalCredentialProof; } - function getValidatorFieldsProof() public returns(bytes32[] memory) { + function getValidatorFieldsProof() public returns (bytes32[] memory) { bytes32[] memory validatorFieldsProof = new bytes32[](46); - for (uint i = 0; i < 46; i++) { + for (uint256 i = 0; i < 46; i++) { prefix = string.concat(".ValidatorFieldsProof[", string.concat(vm.toString(i), "]")); - validatorFieldsProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); + validatorFieldsProof[i] = (stdJson.readBytes32(proofConfigJson, prefix)); } return validatorFieldsProof; } -} \ No newline at end of file +} diff --git a/test/mocks/MockDelegationManager.sol b/test/mocks/MockDelegationManager.sol index 8915fa827..3b3108678 100644 --- a/test/mocks/MockDelegationManager.sol +++ b/test/mocks/MockDelegationManager.sol @@ -1,15 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.27; -import "../../test/mocks/MockDelegationManagerBase.sol"; import "../../src/eigenlayer-interfaces/IDelegationManager.sol"; +import "../../test/mocks/MockDelegationManagerBase.sol"; import "../../test/mocks/MockStrategy.sol"; -import "forge-std/console2.sol"; -import "forge-std/Test.sol"; +import "forge-std/Test.sol"; +import "forge-std/console2.sol"; contract MockDelegationManager is MockDelegationManagerBase, Test { - constructor() { mock_beaconChainETHStrategy = new MockStrategy(); } @@ -20,6 +19,7 @@ contract MockDelegationManager is MockDelegationManagerBase, Test { // beaconChainETHStrategy() //************************************************************ IStrategy mock_beaconChainETHStrategy; + function beaconChainETHStrategy() external view override returns (IStrategy) { return mock_beaconChainETHStrategy; } @@ -29,11 +29,13 @@ contract MockDelegationManager is MockDelegationManagerBase, Test { //************************************************************ mapping(address => mapping(IStrategy => uint256)) public mock_withdrawableShares; mapping(address => mapping(IStrategy => uint256)) public mock_depositShares; + function mockSet_withdrawableShares(address staker, IStrategy strategy, uint256 withdrawableShares, uint256 depositShares) external { mock_withdrawableShares[staker][strategy] = withdrawableShares; mock_depositShares[staker][strategy] = depositShares; } - function getWithdrawableShares(address staker, IStrategy[] memory strategies) external override view returns (uint256[] memory withdrawableShares, uint256[] memory depositShares) { + + function getWithdrawableShares(address staker, IStrategy[] memory strategies) external view override returns (uint256[] memory withdrawableShares, uint256[] memory depositShares) { withdrawableShares = new uint256[](strategies.length); depositShares = new uint256[](strategies.length); for (uint256 i; i < strategies.length; i++) { @@ -46,6 +48,7 @@ contract MockDelegationManager is MockDelegationManagerBase, Test { // queueWithdrawals() //************************************************************ event mockEvent_queuedWithdrawalShares(uint256 shares); + function queueWithdrawals(IDelegationManagerTypes.QueuedWithdrawalParams[] calldata params) external override returns (bytes32[] memory) { uint256 queuedShares; for (uint256 i = 0; i < params.length; i++) { @@ -61,16 +64,10 @@ contract MockDelegationManager is MockDelegationManagerBase, Test { return withdrawalRoots; } - //************************************************************ // completeQueuedWithdrawals() //************************************************************ - function completeQueuedWithdrawals( - Withdrawal[] calldata withdrawals, - IERC20[][] calldata tokens, - bool[] calldata receiveAsTokens - ) external override { - + function completeQueuedWithdrawals(Withdrawal[] calldata withdrawals, IERC20[][] calldata tokens, bool[] calldata receiveAsTokens) external override { // EtherfiNode currently doesn't support any tokens other than beacon ETH // so I just assume it here for (uint256 i = 0; i < withdrawals.length; i++) { diff --git a/test/mocks/MockDelegationManagerBase.sol b/test/mocks/MockDelegationManagerBase.sol index 42ab98ce1..e0928c54a 100644 --- a/test/mocks/MockDelegationManagerBase.sol +++ b/test/mocks/MockDelegationManagerBase.sol @@ -3,14 +3,13 @@ pragma solidity ^0.8.27; import "src/eigenlayer-interfaces/IDelegationManager.sol"; -import "../../src/eigenlayer-interfaces/IStrategy.sol"; import "../../src/eigenlayer-interfaces/IPauserRegistry.sol"; import "../../src/eigenlayer-interfaces/ISignatureUtilsMixin.sol"; +import "../../src/eigenlayer-interfaces/IStrategy.sol"; import "../../src/eigenlayer-libraries/SlashingLib.sol"; // IDelegationManager but with all functions made virtual contract MockDelegationManagerBase is IDelegationManager { - /** * @dev Initializes the initial owner and paused status. */ @@ -31,11 +30,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @dev This function will revert if the caller is already delegated to an operator. * @dev Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event */ - function registerAsOperator( - address initDelegationApprover, - uint32 allocationDelay, - string calldata metadataURI - ) external virtual {} + function registerAsOperator(address initDelegationApprover, uint32 allocationDelay, string calldata metadataURI) external virtual {} /** * @notice Updates an operator's stored `delegationApprover`. @@ -62,11 +57,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @dev The signature/salt are used ONLY if the operator has configured a delegationApprover. * If they have not, these params can be left empty. */ - function delegateTo( - address operator, - SignatureWithExpiry memory approverSignatureAndExpiry, - bytes32 approverSalt - ) external virtual {} + function delegateTo(address operator, SignatureWithExpiry memory approverSignatureAndExpiry, bytes32 approverSalt) external virtual {} /** * @notice Undelegates the staker from their operator and queues a withdrawal for all of their shares @@ -78,9 +69,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @dev Reverts if the caller is not the staker, nor the operator who the staker is delegated to, nor the operator's specified "delegationApprover" * @dev Reverts if the `staker` is not delegated to an operator */ - function undelegate( - address staker - ) external virtual returns (bytes32[] memory withdrawalRoots) {} + function undelegate(address staker) external virtual returns (bytes32[] memory withdrawalRoots) {} /** * @notice Undelegates the staker from their current operator, and redelegates to `newOperator` @@ -93,11 +82,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @param newOperatorApproverSig A signature from the operator's `delegationApprover` * @param approverSalt A unique single use value tied to the approver's signature */ - function redelegate( - address newOperator, - SignatureWithExpiry memory newOperatorApproverSig, - bytes32 approverSalt - ) external virtual returns (bytes32[] memory withdrawalRoots) {} + function redelegate(address newOperator, SignatureWithExpiry memory newOperatorApproverSig, bytes32 approverSalt) external virtual returns (bytes32[] memory withdrawalRoots) {} /** * @notice Allows a staker to queue a withdrawal of their deposit shares. The withdrawal can be @@ -110,9 +95,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @dev To view all the staker's strategies/deposit shares that can be queued for withdrawal, see `getDepositedShares` * @dev To view the current conversion between a staker's deposit shares and withdrawable shares, see `getWithdrawableShares` */ - function queueWithdrawals( - QueuedWithdrawalParams[] calldata params - ) external virtual returns (bytes32[] memory) {} + function queueWithdrawals(QueuedWithdrawalParams[] calldata params) external virtual returns (bytes32[] memory) {} /** * @notice Used to complete a queued withdrawal @@ -125,11 +108,7 @@ contract MockDelegationManagerBase is IDelegationManager { * NOTE: if the caller receives shares and is currently delegated to an operator, the received shares are * automatically delegated to the caller's current operator. */ - function completeQueuedWithdrawal( - Withdrawal calldata withdrawal, - IERC20[] calldata tokens, - bool receiveAsTokens - ) external virtual {} + function completeQueuedWithdrawal(Withdrawal calldata withdrawal, IERC20[] calldata tokens, bool receiveAsTokens) external virtual {} /** * @notice Used to complete multiple queued withdrawals @@ -138,11 +117,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @param receiveAsTokens Whether or not to complete each withdrawal as tokens. See `completeQueuedWithdrawal` for the usage of a single boolean. * @dev See `completeQueuedWithdrawal` for relevant dev tags */ - function completeQueuedWithdrawals( - Withdrawal[] calldata withdrawals, - IERC20[][] calldata tokens, - bool[] calldata receiveAsTokens - ) external virtual {} + function completeQueuedWithdrawals(Withdrawal[] calldata withdrawals, IERC20[][] calldata tokens, bool[] calldata receiveAsTokens) external virtual {} /** * @notice Called by a share manager when a staker's deposit share balance in a strategy increases. @@ -157,12 +132,7 @@ contract MockDelegationManagerBase is IDelegationManager { * staker has been slashed 100% on the beacon chain such that the calculated slashing factor is 0, this * method WILL REVERT. */ - function increaseDelegatedShares( - address staker, - IStrategy strategy, - uint256 prevDepositShares, - uint256 addedShares - ) external virtual {} + function increaseDelegatedShares(address staker, IStrategy strategy, uint256 prevDepositShares, uint256 addedShares) external virtual {} /** * @notice If the staker is delegated, decreases its operator's shares in response to @@ -173,11 +143,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @dev Note: `beaconChainSlashingFactorDecrease` are assumed to ALWAYS be < 1 WAD. * These invariants are maintained in the EigenPodManager. */ - function decreaseDelegatedShares( - address staker, - uint256 curDepositShares, - uint64 beaconChainSlashingFactorDecrease - ) external virtual {} + function decreaseDelegatedShares(address staker, uint256 curDepositShares, uint64 beaconChainSlashingFactorDecrease) external virtual {} /** * @notice Decreases the operators shares in storage after a slash and increases the burnable shares by calling @@ -190,12 +156,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @dev Note: Assumes `prevMaxMagnitude <= newMaxMagnitude`. This invariant is maintained in * the AllocationManager. */ - function slashOperatorShares( - address operator, - IStrategy strategy, - uint64 prevMaxMagnitude, - uint64 newMaxMagnitude - ) external virtual {} + function slashOperatorShares(address operator, IStrategy strategy, uint64 prevMaxMagnitude, uint64 newMaxMagnitude) external virtual {} /** * @@ -208,63 +169,47 @@ contract MockDelegationManagerBase is IDelegationManager { * @notice Mapping: staker => operator whom the staker is currently delegated to. * @dev Note that returning address(0) indicates that the staker is not actively delegated to any operator. */ - function delegatedTo( - address staker - ) external virtual view returns (address) {} + function delegatedTo(address staker) external view virtual returns (address) {} /** * @notice Mapping: delegationApprover => 32-byte salt => whether or not the salt has already been used by the delegationApprover. * @dev Salts are used in the `delegateTo` function. Note that this function only processes the delegationApprover's * signature + the provided salt if the operator being delegated to has specified a nonzero address as their `delegationApprover`. */ - function delegationApproverSaltIsSpent(address _delegationApprover, bytes32 salt) external virtual view returns (bool) {} + function delegationApproverSaltIsSpent(address _delegationApprover, bytes32 salt) external view virtual returns (bool) {} /// @notice Mapping: staker => cumulative number of queued withdrawals they have ever initiated. /// @dev This only increments (doesn't decrement), and is used to help ensure that otherwise identical withdrawals have unique hashes. - function cumulativeWithdrawalsQueued( - address staker - ) external virtual view returns (uint256) {} + function cumulativeWithdrawalsQueued(address staker) external view virtual returns (uint256) {} /** * @notice Returns 'true' if `staker` *is* actively delegated, and 'false' otherwise. */ - function isDelegated( - address staker - ) external virtual view returns (bool) {} + function isDelegated(address staker) external view virtual returns (bool) {} /** * @notice Returns true is an operator has previously registered for delegation. */ - function isOperator( - address operator - ) external virtual view returns (bool) {} + function isOperator(address operator) external view virtual returns (bool) {} /** * @notice Returns the delegationApprover account for an operator */ - function delegationApprover( - address operator - ) external virtual view returns (address) {} + function delegationApprover(address operator) external view virtual returns (address) {} /** * @notice Returns the shares that an operator has delegated to them in a set of strategies * @param operator the operator to get shares for * @param strategies the strategies to get shares for */ - function getOperatorShares( - address operator, - IStrategy[] memory strategies - ) external virtual view returns (uint256[] memory) {} + function getOperatorShares(address operator, IStrategy[] memory strategies) external view virtual returns (uint256[] memory) {} /** * @notice Returns the shares that a set of operators have delegated to them in a set of strategies * @param operators the operators to get shares for * @param strategies the strategies to get shares for */ - function getOperatorsShares( - address[] memory operators, - IStrategy[] memory strategies - ) external virtual view returns (uint256[][] memory) {} + function getOperatorsShares(address[] memory operators, IStrategy[] memory strategies) external view virtual returns (uint256[][] memory) {} /** * @notice Returns amount of withdrawable shares from an operator for a strategy that is still in the queue @@ -274,7 +219,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @param strategy the strategy to get shares for * @return the amount of shares that are slashable in the withdrawal queue for an operator and a strategy */ - function getSlashableSharesInQueue(address operator, IStrategy strategy) external virtual view returns (uint256) {} + function getSlashableSharesInQueue(address operator, IStrategy strategy) external view virtual returns (uint256) {} /** * @notice Given a staker and a set of strategies, return the shares they can queue for withdrawal and the @@ -283,31 +228,24 @@ contract MockDelegationManagerBase is IDelegationManager { * The shares amount returned is the actual amount of Strategy shares the staker would receive (subject * to each strategy's underlying shares to token ratio). */ - function getWithdrawableShares( - address staker, - IStrategy[] memory strategies - ) external virtual view returns (uint256[] memory withdrawableShares, uint256[] memory depositShares) {} + function getWithdrawableShares(address staker, IStrategy[] memory strategies) external view virtual returns (uint256[] memory withdrawableShares, uint256[] memory depositShares) {} /** * @notice Returns the number of shares in storage for a staker and all their strategies */ - function getDepositedShares( - address staker - ) external virtual view returns (IStrategy[] memory, uint256[] memory) {} + function getDepositedShares(address staker) external view virtual returns (IStrategy[] memory, uint256[] memory) {} /** * @notice Returns the scaling factor applied to a staker's deposits for a given strategy */ - function depositScalingFactor(address staker, IStrategy strategy) external virtual view returns (uint256) {} + function depositScalingFactor(address staker, IStrategy strategy) external view virtual returns (uint256) {} /** * @notice Returns the Withdrawal associated with a `withdrawalRoot`. * @param withdrawalRoot The hash identifying the queued withdrawal. * @return withdrawal The withdrawal details. */ - function queuedWithdrawals( - bytes32 withdrawalRoot - ) external view returns (Withdrawal memory withdrawal) {} + function queuedWithdrawals(bytes32 withdrawalRoot) external view returns (Withdrawal memory withdrawal) {} /** * @notice Returns the Withdrawal and corresponding shares associated with a `withdrawalRoot` @@ -317,9 +255,7 @@ contract MockDelegationManagerBase is IDelegationManager { * @dev The shares are what a user would receive from completing a queued withdrawal, assuming all slashings are applied * @dev Withdrawals queued before the slashing release cannot be queried with this method */ - function getQueuedWithdrawal( - bytes32 withdrawalRoot - ) external virtual view returns (Withdrawal memory withdrawal, uint256[] memory shares) {} + function getQueuedWithdrawal(bytes32 withdrawalRoot) external view virtual returns (Withdrawal memory withdrawal, uint256[] memory shares) {} /** * @notice Returns all queued withdrawals and their corresponding shares for a staker. @@ -328,15 +264,11 @@ contract MockDelegationManagerBase is IDelegationManager { * @return shares 2D array of shares, where each inner array corresponds to the strategies in the withdrawal. * @dev The shares are what a user would receive from completing a queued withdrawal, assuming all slashings are applied. */ - function getQueuedWithdrawals( - address staker - ) external virtual view returns (Withdrawal[] memory withdrawals, uint256[][] memory shares) {} + function getQueuedWithdrawals(address staker) external view virtual returns (Withdrawal[] memory withdrawals, uint256[][] memory shares) {} /// @notice Returns a list of queued withdrawal roots for the `staker`. /// NOTE that this only returns withdrawals queued AFTER the slashing release. - function getQueuedWithdrawalRoots( - address staker - ) external virtual view returns (bytes32[] memory) {} + function getQueuedWithdrawalRoots(address staker) external view virtual returns (bytes32[] memory) {} /** * @notice Converts shares for a set of strategies to deposit shares, likely in order to input into `queueWithdrawals` @@ -346,16 +278,10 @@ contract MockDelegationManagerBase is IDelegationManager { * @return the deposit shares * @dev will be a few wei off due to rounding errors */ - function convertToDepositShares( - address staker, - IStrategy[] memory strategies, - uint256[] memory withdrawableShares - ) external virtual view returns (uint256[] memory) {} + function convertToDepositShares(address staker, IStrategy[] memory strategies, uint256[] memory withdrawableShares) external view virtual returns (uint256[] memory) {} /// @notice Returns the keccak256 hash of `withdrawal`. - function calculateWithdrawalRoot( - Withdrawal memory withdrawal - ) external virtual pure returns (bytes32) {} + function calculateWithdrawalRoot(Withdrawal memory withdrawal) external pure virtual returns (bytes32) {} /** * @notice Calculates the digest hash to be signed by the operator's delegationApprove and used in the `delegateTo` function. @@ -365,16 +291,10 @@ contract MockDelegationManagerBase is IDelegationManager { * @param approverSalt A unique and single use value associated with the approver signature. * @param expiry Time after which the approver's signature becomes invalid */ - function calculateDelegationApprovalDigestHash( - address staker, - address operator, - address _delegationApprover, - bytes32 approverSalt, - uint256 expiry - ) external virtual view returns (bytes32) {} + function calculateDelegationApprovalDigestHash(address staker, address operator, address _delegationApprover, bytes32 approverSalt, uint256 expiry) external view virtual returns (bytes32) {} /// @notice return address of the beaconChainETHStrategy - function beaconChainETHStrategy() external virtual view returns (IStrategy) {} + function beaconChainETHStrategy() external view virtual returns (IStrategy) {} /** * @notice Returns the minimum withdrawal delay in blocks to pass for withdrawals queued to be completable. @@ -383,8 +303,8 @@ contract MockDelegationManagerBase is IDelegationManager { * @dev Backwards-compatible interface to return the internal `MIN_WITHDRAWAL_DELAY_BLOCKS` value * @dev Previous value in storage was deprecated. See `__deprecated_minWithdrawalDelayBlocks` */ - function minWithdrawalDelayBlocks() external virtual view returns (uint32) {} + function minWithdrawalDelayBlocks() external view virtual returns (uint32) {} /// @notice The EIP-712 typehash for the DelegationApproval struct used by the contract - function DELEGATION_APPROVAL_TYPEHASH() external virtual view returns (bytes32) {} + function DELEGATION_APPROVAL_TYPEHASH() external view virtual returns (bytes32) {} } diff --git a/test/mocks/MockEigenPod.sol b/test/mocks/MockEigenPod.sol index b909b3fc9..4b1de67ef 100644 --- a/test/mocks/MockEigenPod.sol +++ b/test/mocks/MockEigenPod.sol @@ -1,19 +1,22 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.9; -import "forge-std/Test.sol"; import "../../test/mocks/MockEigenPodBase.sol"; +import "forge-std/Test.sol"; contract MockEigenPod is MockEigenPodBase, Test { - // OVERRIDES //************************************************************ // activeValidatorCount() //************************************************************ - function activeValidatorCount() external override view returns (uint256) { return mock_activeValidatorCount; } + function activeValidatorCount() external view override returns (uint256) { + return mock_activeValidatorCount; + } + uint256 public mock_activeValidatorCount; - function mockSet_activeValidatorCount(uint256 count) public { mock_activeValidatorCount = count; } + function mockSet_activeValidatorCount(uint256 count) public { + mock_activeValidatorCount = count; + } } - diff --git a/test/mocks/MockEigenPodBase.sol b/test/mocks/MockEigenPodBase.sol index a1d110059..4f50403bd 100644 --- a/test/mocks/MockEigenPodBase.sol +++ b/test/mocks/MockEigenPodBase.sol @@ -7,18 +7,18 @@ import "../../src/eigenlayer-interfaces/ISemVerMixin.sol"; contract MockEigenPodBase is IEigenPod { constructor() {} - function version() external virtual view returns (string memory) {} + function version() external view virtual returns (string memory) {} - function nonBeaconChainETHBalanceWei() external virtual view returns(uint256) {} + function nonBeaconChainETHBalanceWei() external view virtual returns (uint256) {} - /// @notice the amount of execution layer ETH in this contract that is staked in EigenLayer (i.e. withdrawn from beaconchain but not EigenLayer), - function withdrawableRestakedExecutionLayerGwei() external virtual view returns(uint64) {} + /// @notice the amount of execution layer ETH in this contract that is staked in EigenLayer (i.e. withdrawn from beaconchain but not EigenLayer), + function withdrawableRestakedExecutionLayerGwei() external view virtual returns (uint64) {} /// @notice Used to initialize the pointers to contracts crucial to the pod's functionality, in beacon proxy construction from EigenPodManager function initialize(address owner) external virtual {} /// @notice Called by EigenPodManager when the owner wants to create another ETH validator. - function stake(bytes calldata pubkey, bytes calldata signature, bytes32 depositDataRoot) external virtual payable {} + function stake(bytes calldata pubkey, bytes calldata signature, bytes32 depositDataRoot) external payable virtual {} /** * @notice Transfers `amountWei` in ether from this contract to the specified `recipient` address @@ -29,57 +29,44 @@ contract MockEigenPodBase is IEigenPod { function withdrawRestakedBeaconChainETH(address recipient, uint256 amount) external virtual {} /// @notice The single EigenPodManager for EigenLayer - function eigenPodManager() external virtual view returns (IEigenPodManager) {} + function eigenPodManager() external view virtual returns (IEigenPodManager) {} /// @notice The owner of this EigenPod - function podOwner() external virtual view returns (address) {} + function podOwner() external view virtual returns (address) {} /// @notice an indicator of whether or not the podOwner has ever "fully restaked" by successfully calling `verifyCorrectWithdrawalCredentials`. - function hasRestaked() external virtual view returns (bool) {} + function hasRestaked() external view virtual returns (bool) {} /// @notice block timestamp of the most recent withdrawal - function mostRecentWithdrawalTimestamp() external virtual view returns (uint64) {} + function mostRecentWithdrawalTimestamp() external view virtual returns (uint64) {} /// @notice Returns the validatorInfo struct for the provided pubkeyHash - function validatorPubkeyHashToInfo(bytes32 validatorPubkeyHash) external virtual view returns (ValidatorInfo memory) {} + function validatorPubkeyHashToInfo(bytes32 validatorPubkeyHash) external view virtual returns (ValidatorInfo memory) {} /// @notice This returns the status of a given validator - function validatorStatus(bytes32 pubkeyHash) external virtual view returns(VALIDATOR_STATUS) {} + function validatorStatus(bytes32 pubkeyHash) external view virtual returns (VALIDATOR_STATUS) {} /// @notice Number of validators with proven withdrawal credentials, who do not have proven full withdrawals - function activeValidatorCount() external virtual view returns (uint256) {} + function activeValidatorCount() external view virtual returns (uint256) {} /// @notice The timestamp of the last checkpoint finalized - function lastCheckpointTimestamp() external virtual view returns (uint64) {} + function lastCheckpointTimestamp() external view virtual returns (uint64) {} /// @notice The timestamp of the currently-active checkpoint. Will be 0 if there is not active checkpoint - function currentCheckpointTimestamp() external virtual view returns (uint64) {} + function currentCheckpointTimestamp() external view virtual returns (uint64) {} /// @notice Returns the currently-active checkpoint - function currentCheckpoint() external virtual view returns (Checkpoint memory) {} + function currentCheckpoint() external view virtual returns (Checkpoint memory) {} - function checkpointBalanceExitedGwei(uint64) external virtual view returns (uint64) {} + function checkpointBalanceExitedGwei(uint64) external view virtual returns (uint64) {} function startCheckpoint(bool revertIfNoBalance) external virtual {} - function verifyCheckpointProofs( - BeaconChainProofs.BalanceContainerProof calldata balanceContainerProof, - BeaconChainProofs.BalanceProof[] calldata proofs - ) external virtual {} - - function verifyStaleBalance( - uint64 beaconTimestamp, - BeaconChainProofs.StateRootProof calldata stateRootProof, - BeaconChainProofs.ValidatorProof calldata proof - ) external virtual {} - - function verifyWithdrawalCredentials( - uint64 oracleTimestamp, - BeaconChainProofs.StateRootProof calldata stateRootProof, - uint40[] calldata validatorIndices, - bytes[] calldata withdrawalCredentialProofs, - bytes32[][] calldata validatorFields - ) external virtual {} + function verifyCheckpointProofs(BeaconChainProofs.BalanceContainerProof calldata balanceContainerProof, BeaconChainProofs.BalanceProof[] calldata proofs) external virtual {} + + function verifyStaleBalance(uint64 beaconTimestamp, BeaconChainProofs.StateRootProof calldata stateRootProof, BeaconChainProofs.ValidatorProof calldata proof) external virtual {} + + function verifyWithdrawalCredentials(uint64 oracleTimestamp, BeaconChainProofs.StateRootProof calldata stateRootProof, uint40[] calldata validatorIndices, bytes[] calldata withdrawalCredentialProofs, bytes32[][] calldata validatorFields) external virtual {} /// @notice Called by the pod owner to withdraw the balance of the pod when `hasRestaked` is set to false function activateRestaking() external virtual {} @@ -95,18 +82,18 @@ contract MockEigenPodBase is IEigenPod { function setProofSubmitter(address newProofSubmitter) external virtual {} - function proofSubmitter() external virtual view returns (address) {} + function proofSubmitter() external view virtual returns (address) {} - function validatorStatus(bytes calldata pubkey) external virtual view returns (VALIDATOR_STATUS){} - function validatorPubkeyToInfo(bytes calldata validatorPubkey) external virtual view returns (ValidatorInfo memory){} + function validatorStatus(bytes calldata pubkey) external view virtual returns (VALIDATOR_STATUS) {} + function validatorPubkeyToInfo(bytes calldata validatorPubkey) external view virtual returns (ValidatorInfo memory) {} /// @notice Query the 4788 oracle to get the parent block root of the slot with the given `timestamp` /// @param timestamp of the block for which the parent block root will be returned. MUST correspond /// to an existing slot within the last 24 hours. If the slot at `timestamp` was skipped, this method /// will revert. - function getParentBlockRoot(uint64 timestamp) external virtual view returns (bytes32) {} - function getWithdrawalRequestFee() external view returns (uint256){} + function getParentBlockRoot(uint64 timestamp) external view virtual returns (bytes32) {} + function getWithdrawalRequestFee() external view returns (uint256) {} function requestWithdrawal(WithdrawalRequest[] calldata requests) external payable {} - function getConsolidationRequestFee() external view returns (uint256){} + function getConsolidationRequestFee() external view returns (uint256) {} function requestConsolidation(ConsolidationRequest[] calldata requests) external payable {} } diff --git a/test/mocks/MockEigenPodManager.sol b/test/mocks/MockEigenPodManager.sol index 9d5469193..9b868f2fb 100644 --- a/test/mocks/MockEigenPodManager.sol +++ b/test/mocks/MockEigenPodManager.sol @@ -1,15 +1,16 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.27; -import "../../test/mocks/MockEigenPodManagerBase.sol"; -import "../../test/mocks/MockEigenPod.sol"; import "../../src/eigenlayer-interfaces/IEigenPodManager.sol"; +import "../../test/mocks/MockEigenPod.sol"; +import "../../test/mocks/MockEigenPodManagerBase.sol"; + import "../../test/mocks/MockStrategy.sol"; -import "forge-std/console2.sol"; + import "forge-std/Test.sol"; +import "forge-std/console2.sol"; contract MockEigenPodManager is MockEigenPodManagerBase, Test { - // Overrides function createPod() external override returns (address) { diff --git a/test/mocks/MockEigenPodManagerBase.sol b/test/mocks/MockEigenPodManagerBase.sol index ac4456784..f9c78d94c 100644 --- a/test/mocks/MockEigenPodManagerBase.sol +++ b/test/mocks/MockEigenPodManagerBase.sol @@ -2,17 +2,16 @@ pragma solidity ^0.8.27; import "../../src/eigenlayer-interfaces/IEigenPodManager.sol"; -import "./MockShareManagerBase.sol"; + import "./MockEigenPod.sol"; import "./MockPausableBase.sol"; - +import "./MockShareManagerBase.sol"; // IEigenPodManager but all functions are virtual contract MockEigenPodManagerBase is IEigenPodManager, MockShareManagerBase, MockPausableBase { + function version() external view virtual returns (string memory) {} - function version() external virtual view returns (string memory) {} - - /** + /** * @notice Creates an EigenPod for the sender. * @dev Function will revert if the `msg.sender` already has an EigenPod. * @dev Returns EigenPod address @@ -26,7 +25,7 @@ contract MockEigenPodManagerBase is IEigenPodManager, MockShareManagerBase, Mock * @param signature The validator's signature of the deposit data. * @param depositDataRoot The root/hash of the deposit data for the validator's deposit. */ - function stake(bytes calldata pubkey, bytes calldata signature, bytes32 depositDataRoot) external virtual payable {} + function stake(bytes calldata pubkey, bytes calldata signature, bytes32 depositDataRoot) external payable virtual {} /** * @notice Adds any positive share delta to the pod owner's deposit shares, and delegates them to the pod @@ -39,35 +38,25 @@ contract MockEigenPodManagerBase is IEigenPodManager, MockShareManagerBase, Mock * @dev Callable only by the podOwner's EigenPod contract. * @dev Reverts if `sharesDelta` is not a whole Gwei amount */ - function recordBeaconChainETHBalanceUpdate( - address podOwner, - uint256 prevRestakedBalanceWei, - int256 balanceDeltaWei - ) external virtual {} + function recordBeaconChainETHBalanceUpdate(address podOwner, uint256 prevRestakedBalanceWei, int256 balanceDeltaWei) external virtual {} /// @notice Returns the address of the `podOwner`'s EigenPod if it has been deployed. - function ownerToPod( - address podOwner - ) external virtual view returns (IEigenPod) {} + function ownerToPod(address podOwner) external view virtual returns (IEigenPod) {} /// @notice Returns the address of the `podOwner`'s EigenPod (whether it is deployed yet or not). - function getPod( - address podOwner - ) external virtual view returns (IEigenPod) {} + function getPod(address podOwner) external view virtual returns (IEigenPod) {} /// @notice The ETH2 Deposit Contract - function ethPOS() external virtual view returns (IETHPOSDeposit) {} + function ethPOS() external view virtual returns (IETHPOSDeposit) {} /// @notice Beacon proxy to which the EigenPods point - function eigenPodBeacon() external virtual view returns (IBeacon) {} + function eigenPodBeacon() external view virtual returns (IBeacon) {} /// @notice Returns 'true' if the `podOwner` has created an EigenPod, and 'false' otherwise. - function hasPod( - address podOwner - ) external virtual view returns (bool) {} + function hasPod(address podOwner) external view virtual returns (bool) {} /// @notice Returns the number of EigenPods that have been created - function numPods() external virtual view returns (uint256) {} + function numPods() external view virtual returns (uint256) {} /** * @notice Mapping from Pod owner owner to the number of shares they have in the virtual beacon chain ETH strategy. @@ -77,37 +66,27 @@ contract MockEigenPodManagerBase is IEigenPodManager, MockShareManagerBase, Mock * Likewise, when a withdrawal is completed, this "deficit" is decreased and the withdrawal amount is decreased {} We can think of this * as the withdrawal "paying off the deficit". */ - function podOwnerDepositShares( - address podOwner - ) external virtual view returns (int256) {} + function podOwnerDepositShares(address podOwner) external view virtual returns (int256) {} /// @notice returns canonical, virtual beaconChainETH strategy - function beaconChainETHStrategy() external virtual view returns (IStrategy) {} + function beaconChainETHStrategy() external view virtual returns (IStrategy) {} /** * @notice Returns the historical sum of proportional balance decreases a pod owner has experienced when * updating their pod's balance. */ - function beaconChainSlashingFactor( - address staker - ) external virtual view returns (uint64) {} + function beaconChainSlashingFactor(address staker) external view virtual returns (uint64) {} /// @notice Returns the accumulated amount of beacon chain ETH Strategy shares - function burnableETHShares() external virtual view returns (uint256) {} + function burnableETHShares() external view virtual returns (uint256) {} /// @notice Sets the address that can set proof timestamps - function setProofTimestampSetter( - address newProofTimestampSetter - ) external {} + function setProofTimestampSetter(address newProofTimestampSetter) external {} /// @notice Sets the Pectra fork timestamp, only callable by `proofTimestampSetter` - function setPectraForkTimestamp( - uint64 timestamp - ) external {} + function setPectraForkTimestamp(uint64 timestamp) external {} /// @notice Returns the timestamp of the Pectra hard fork /// @dev Specifically, this returns the timestamp of the first non-missed slot at or after the Pectra hard fork function pectraForkTimestamp() external view returns (uint64) {} - - } diff --git a/test/mocks/MockPausableBase.sol b/test/mocks/MockPausableBase.sol index 1448eaf23..00562f0c7 100644 --- a/test/mocks/MockPausableBase.sol +++ b/test/mocks/MockPausableBase.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "../../src/eigenlayer-interfaces/IPauserRegistry.sol"; import "../../src/eigenlayer-interfaces/IPausable.sol"; +import "../../src/eigenlayer-interfaces/IPauserRegistry.sol"; /** * @title Adds pausability to a contract, with pausing & unpausing controlled by the `pauser` and `unpauser` of a PauserRegistry contract. @@ -23,9 +23,8 @@ import "../../src/eigenlayer-interfaces/IPausable.sol"; // IPausible but all functions are virtual contract MockPausableBase is IPausable { - /// @notice Address of the `PauserRegistry` contract that this contract defers to for determining access control (for pausing). - function pauserRegistry() external virtual view returns (IPauserRegistry) {} + function pauserRegistry() external view virtual returns (IPauserRegistry) {} /** * @notice This function is used to pause an EigenLayer contract's functionality. @@ -33,9 +32,7 @@ contract MockPausableBase is IPausable { * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only pause functionality, and thus cannot 'unflip' any bit in `_paused` from 1 to 0. */ - function pause( - uint256 newPausedStatus - ) external virtual {} + function pause(uint256 newPausedStatus) external virtual {} /** * @notice Alias for `pause(type(uint256).max)`. @@ -48,15 +45,11 @@ contract MockPausableBase is IPausable { * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only unpause functionality, and thus cannot 'flip' any bit in `_paused` from 0 to 1. */ - function unpause( - uint256 newPausedStatus - ) external virtual {} + function unpause(uint256 newPausedStatus) external virtual {} /// @notice Returns the current paused status as a uint256. - function paused() external virtual view returns (uint256) {} + function paused() external view virtual returns (uint256) {} /// @notice Returns 'true' if the `indexed`th bit of `_paused` is 1, and 'false' otherwise - function paused( - uint8 index - ) external virtual view returns (bool) {} + function paused(uint8 index) external view virtual returns (bool) {} } diff --git a/test/mocks/MockShareManagerBase.sol b/test/mocks/MockShareManagerBase.sol index 970890c8b..8aeb82f7c 100644 --- a/test/mocks/MockShareManagerBase.sol +++ b/test/mocks/MockShareManagerBase.sol @@ -1,22 +1,18 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.27; -import "../../src/eigenlayer-libraries/SlashingLib.sol"; -import "../../src/eigenlayer-interfaces/IStrategy.sol"; import "../../src/eigenlayer-interfaces/IShareManager.sol"; +import "../../src/eigenlayer-interfaces/IStrategy.sol"; +import "../../src/eigenlayer-libraries/SlashingLib.sol"; + import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; // ShareManager but all calls made virtual contract MockShareManagerBase is IShareManager { - /// @notice Used by the DelegationManager to remove a Staker's shares from a particular strategy when entering the withdrawal queue /// @dev strategy must be beaconChainETH when talking to the EigenPodManager /// @return updatedShares the staker's deposit shares after decrement - function removeDepositShares( - address staker, - IStrategy strategy, - uint256 depositSharesToRemove - ) external virtual returns (uint256) {} + function removeDepositShares(address staker, IStrategy strategy, uint256 depositSharesToRemove) external virtual returns (uint256) {} /// @notice Used by the DelegationManager to award a Staker some shares that have passed through the withdrawal queue /// @dev strategy must be beaconChainETH when talking to the EigenPodManager @@ -32,7 +28,7 @@ contract MockShareManagerBase is IShareManager { /// @notice Returns the current shares of `user` in `strategy` /// @dev strategy must be beaconChainETH when talking to the EigenPodManager /// @dev returns 0 if the user has negative shares - function stakerDepositShares(address user, IStrategy strategy) external virtual view returns (uint256 depositShares) {} + function stakerDepositShares(address user, IStrategy strategy) external view virtual returns (uint256 depositShares) {} /** * @notice Increase the amount of burnable shares for a given Strategy. This is called by the DelegationManager diff --git a/test/mocks/MockStrategy.sol b/test/mocks/MockStrategy.sol index 3545f1b75..a5868a964 100644 --- a/test/mocks/MockStrategy.sol +++ b/test/mocks/MockStrategy.sol @@ -5,10 +5,9 @@ import "../../src/eigenlayer-interfaces/IStrategy.sol"; // See MockStrategy contract below this contract for testing overrides contract MockStrategyBase is IStrategy { - function version() external view returns (string memory) {} - /** + /** * @notice Used to deposit tokens into this Strategy * @param token is the ERC20 token being deposited * @param amount is the amount of token being deposited @@ -28,7 +27,6 @@ contract MockStrategyBase is IStrategy { */ function withdraw(address recipient, IERC20 token, uint256 amountShares) external {} - /** * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy. * @notice In contrast to `sharesToUnderlyingView`, this function **may** make state modifications @@ -36,9 +34,7 @@ contract MockStrategyBase is IStrategy { * @return The amount of underlying tokens corresponding to the input `amountShares` * @dev Implementation for these functions in particular may vary significantly for different strategies */ - function sharesToUnderlying( - uint256 amountShares - ) external virtual returns (uint256) {} + function sharesToUnderlying(uint256 amountShares) external virtual returns (uint256) {} /** * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy. @@ -47,25 +43,19 @@ contract MockStrategyBase is IStrategy { * @return The amount of underlying tokens corresponding to the input `amountShares` * @dev Implementation for these functions in particular may vary significantly for different strategies */ - function underlyingToShares( - uint256 amountUnderlying - ) external virtual returns (uint256) {} + function underlyingToShares(uint256 amountUnderlying) external virtual returns (uint256) {} /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlyingView`, this function **may** make state modifications */ - function userUnderlying( - address user - ) external returns (uint256) {} + function userUnderlying(address user) external returns (uint256) {} /** * @notice convenience function for fetching the current total shares of `user` in this strategy, by * querying the `strategyManager` contract */ - function shares( - address user - ) external view returns (uint256) {} + function shares(address user) external view returns (uint256) {} /** * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy. @@ -74,9 +64,7 @@ contract MockStrategyBase is IStrategy { * @return The amount of shares corresponding to the input `amountUnderlying` * @dev Implementation for these functions in particular may vary significantly for different strategies */ - function sharesToUnderlyingView( - uint256 amountShares - ) external view returns (uint256) {} + function sharesToUnderlyingView(uint256 amountShares) external view returns (uint256) {} /** * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy. @@ -85,17 +73,13 @@ contract MockStrategyBase is IStrategy { * @return The amount of shares corresponding to the input `amountUnderlying` * @dev Implementation for these functions in particular may vary significantly for different strategies */ - function underlyingToSharesView( - uint256 amountUnderlying - ) external view returns (uint256) {} + function underlyingToSharesView(uint256 amountUnderlying) external view returns (uint256) {} /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlying`, this function guarantees no state modifications */ - function userUnderlyingView( - address user - ) external view returns (uint256) {} + function userUnderlyingView(address user) external view returns (uint256) {} /// @notice The underlying token for shares in this Strategy function underlyingToken() external view returns (IERC20) {} @@ -108,18 +92,20 @@ contract MockStrategyBase is IStrategy { } contract MockStrategy is MockStrategyBase { - // OVERRIDES //************************************************************ // sharesToUnderlying() //************************************************************ uint256 internal mock_sharesToUnderlying; - function mockSet_sharesToUnderlying(uint256 underlying) public { mock_sharesToUnderlying = underlying; } - function sharesToUnderlying(uint256) external override view returns (uint256) { - return mock_sharesToUnderlying; + + function mockSet_sharesToUnderlying(uint256 underlying) public { + mock_sharesToUnderlying = underlying; } + function sharesToUnderlying(uint256) external view override returns (uint256) { + return mock_sharesToUnderlying; + } //************************************************************ // underlyingToShares() diff --git a/test/prelude.t.sol b/test/prelude.t.sol index 276ff8974..269c80afc 100644 --- a/test/prelude.t.sol +++ b/test/prelude.t.sol @@ -1,27 +1,28 @@ pragma solidity ^0.8.27; -import "forge-std/console2.sol"; -import "forge-std/Test.sol"; -import "../test/common/ArrayTestHelper.sol"; -import "../src/interfaces/ILiquidityPool.sol"; -import "../src/interfaces/IStakingManager.sol"; -import "../src/StakingManager.sol"; -import "../src/interfaces/IEtherFiNodesManager.sol"; -import "../src/EtherFiNodesManager.sol"; -import "../src/interfaces/IEtherFiNode.sol"; -import {IEigenPod, IEigenPodTypes } from "../src/eigenlayer-interfaces/IEigenPod.sol"; +import "../src/AuctionManager.sol"; import "../src/EtherFiNode.sol"; +import "../src/EtherFiNodesManager.sol"; import "../src/EtherFiRateLimiter.sol"; -import "../src/UUPSProxy.sol"; import "../src/NodeOperatorManager.sol"; -import "../src/interfaces/ITNFT.sol"; +import "../src/StakingManager.sol"; +import "../src/UUPSProxy.sol"; +import {IEigenPod, IEigenPodTypes} from "../src/eigenlayer-interfaces/IEigenPod.sol"; + import "../src/interfaces/IBNFT.sol"; -import "../src/AuctionManager.sol"; -import "../src/libraries/DepositDataRootGenerator.sol"; +import "../src/interfaces/IEtherFiNode.sol"; +import "../src/interfaces/IEtherFiNodesManager.sol"; +import "../src/interfaces/ILiquidityPool.sol"; +import "../src/interfaces/IStakingManager.sol"; +import "../src/interfaces/ITNFT.sol"; -contract PreludeTest is Test, ArrayTestHelper { +import "../src/libraries/DepositDataRootGenerator.sol"; +import "../test/common/ArrayTestHelper.sol"; +import "forge-std/Test.sol"; +import "forge-std/console2.sol"; +contract PreludeTest is Test, ArrayTestHelper { StakingManager stakingManager; ILiquidityPool liquidityPool; EtherFiNodesManager etherFiNodesManager; @@ -59,7 +60,6 @@ contract PreludeTest is Test, ArrayTestHelper { EtherFiRateLimiter rateLimiter; function setUp() public { - vm.selectFork(vm.createFork(vm.envString("MAINNET_RPC_URL"))); stakingManager = StakingManager(0x25e821b7197B146F7713C3b89B6A4D83516B912d); @@ -68,14 +68,7 @@ contract PreludeTest is Test, ArrayTestHelper { auctionManager = AuctionManager(0x00C452aFFee3a17d9Cecc1Bcd2B8d5C7635C4CB9); // deploy new staking manager implementation - StakingManager stakingManagerImpl = new StakingManager( - address(liquidityPool), - address(etherFiNodesManager), - address(stakingDepositContract), - address(auctionManager), - address(etherFiNodeBeacon), - address(roleRegistry) - ); + StakingManager stakingManagerImpl = new StakingManager(address(liquidityPool), address(etherFiNodesManager), address(stakingDepositContract), address(auctionManager), address(etherFiNodeBeacon), address(roleRegistry)); vm.prank(stakingManager.owner()); stakingManager.upgradeTo(address(stakingManagerImpl)); @@ -88,15 +81,9 @@ contract PreludeTest is Test, ArrayTestHelper { UUPSProxy rateLimiterProxy = new UUPSProxy(address(rateLimiterImpl), ""); rateLimiter = EtherFiRateLimiter(address(rateLimiterProxy)); rateLimiter.initialize(); - + // upgrade etherFiNode impl - etherFiNodeImpl = new EtherFiNode( - address(liquidityPool), - address(etherFiNodesManager), - eigenPodManager, - delegationManager, - address(roleRegistry) - ); + etherFiNodeImpl = new EtherFiNode(address(liquidityPool), address(etherFiNodesManager), eigenPodManager, delegationManager, address(roleRegistry)); vm.prank(stakingManager.owner()); stakingManager.upgradeEtherFiNode(address(etherFiNodeImpl)); @@ -132,22 +119,21 @@ contract PreludeTest is Test, ArrayTestHelper { defaultTestValidatorParams = TestValidatorParams({ nodeOperator: address(0), // attach to a random node operator - etherFiNode: address(0), // create a new etherfiNode - bidId: 0, // create and claim a new bid - withdrawable: true, // simulate validator being ready to withdraw from pod + etherFiNode: address(0), // create a new etherfiNode + bidId: 0, // create and claim a new bid + withdrawable: true, // simulate validator being ready to withdraw from pod validatorSize: 32 ether, pubkey: "" }); - } struct TestValidatorParams { - address nodeOperator; // if none specified a new operator will be created - address etherFiNode; // if none specified a new node will be deployed - uint256 bidId; // if none specified a new bid will be placed + address nodeOperator; // if none specified a new operator will be created + address etherFiNode; // if none specified a new node will be deployed + uint256 bidId; // if none specified a new bid will be placed uint256 validatorSize; // if none specified default to 32 eth - bool withdrawable; // give the eigenpod "validatorSize" worth of withdrawable beacon shares - bytes pubkey; // if none specified a random pubkey is generated + bool withdrawable; // give the eigenpod "validatorSize" worth of withdrawable beacon shares + bytes pubkey; // if none specified a random pubkey is generated } struct TestValidator { @@ -161,7 +147,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function helper_createValidator(TestValidatorParams memory _params) public returns (TestValidator memory) { - // create a copy or else successive calls of this method can mutate the input unexpectedly TestValidatorParams memory params = TestValidatorParams(_params.nodeOperator, _params.etherFiNode, _params.bidId, _params.validatorSize, _params.withdrawable, _params.pubkey); @@ -184,7 +169,7 @@ contract PreludeTest is Test, ArrayTestHelper { // create a new node if none provided if (params.etherFiNode == address(0)) { vm.prank(admin); - params.etherFiNode = stakingManager.instantiateEtherFiNode(/*createEigenPod=*/ true); + params.etherFiNode = stakingManager.instantiateEtherFiNode( /*createEigenPod=*/ true); } // default validator size if not provided if (params.validatorSize == 0) { @@ -196,37 +181,17 @@ contract PreludeTest is Test, ArrayTestHelper { // initial deposit address eigenPod = address(IEtherFiNode(params.etherFiNode).getEigenPod()); - bytes32 initialDepositRoot = depositDataRootGenerator.generateDepositDataRoot( - pubkey, - signature, - etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod), - 1 ether - ); - IStakingManager.DepositData memory initialDepositData = IStakingManager.DepositData({ - publicKey: pubkey, - signature: signature, - depositDataRoot: initialDepositRoot, - ipfsHashForEncryptedValidatorKey: "test_ipfs_hash" - }); - vm.deal(address(liquidityPool), 10000 ether); + bytes32 initialDepositRoot = depositDataRootGenerator.generateDepositDataRoot(pubkey, signature, etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod), 1 ether); + IStakingManager.DepositData memory initialDepositData = IStakingManager.DepositData({publicKey: pubkey, signature: signature, depositDataRoot: initialDepositRoot, ipfsHashForEncryptedValidatorKey: "test_ipfs_hash"}); + vm.deal(address(liquidityPool), 10_000 ether); vm.prank(address(liquidityPool)); stakingManager.createBeaconValidators{value: 1 ether}(toArray(initialDepositData), toArray_u256(params.bidId), params.etherFiNode); uint256 confirmAmount = params.validatorSize - 1 ether; // remaining deposit - bytes32 confirmDepositRoot = depositDataRootGenerator.generateDepositDataRoot( - pubkey, - signature, - etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod), - confirmAmount - ); - IStakingManager.DepositData memory confirmDepositData = IStakingManager.DepositData({ - publicKey: pubkey, - signature: signature, - depositDataRoot: confirmDepositRoot, - ipfsHashForEncryptedValidatorKey: "test_ipfs_hash" - }); + bytes32 confirmDepositRoot = depositDataRootGenerator.generateDepositDataRoot(pubkey, signature, etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod), confirmAmount); + IStakingManager.DepositData memory confirmDepositData = IStakingManager.DepositData({publicKey: pubkey, signature: signature, depositDataRoot: confirmDepositRoot, ipfsHashForEncryptedValidatorKey: "test_ipfs_hash"}); vm.prank(address(liquidityPool)); stakingManager.confirmAndFundBeaconValidators{value: confirmAmount}(toArray(confirmDepositData), params.validatorSize); @@ -234,7 +199,7 @@ contract PreludeTest is Test, ArrayTestHelper { // Poke some withdrawable funds into the restakedExecutionLayerGwei storage slot of the eigenpod. // This is much easier than trying to do the full proof based workflow which relies on beacon state. address eigenpod = etherFiNodesManager.getEigenPod(uint256(params.bidId)); - vm.store(eigenpod, bytes32(uint256(52)) /*slot*/, bytes32(uint256(params.validatorSize / 1 gwei))); + vm.store(eigenpod, bytes32(uint256(52)), /*slot*/ bytes32(uint256(params.validatorSize / 1 gwei))); // grant shares via delegation manager so that withdrawals work vm.prank(delegationManager); @@ -244,20 +209,11 @@ contract PreludeTest is Test, ArrayTestHelper { vm.deal(eigenpod, params.validatorSize); } - TestValidator memory out = TestValidator({ - etherFiNode: params.etherFiNode, - eigenPod: eigenPod, - legacyId: params.bidId, - pubkeyHash: stakingManager.calculateValidatorPubkeyHash(pubkey), - nodeOperator: params.nodeOperator, - validatorSize: params.validatorSize, - pubkey: pubkey - }); + TestValidator memory out = TestValidator({etherFiNode: params.etherFiNode, eigenPod: eigenPod, legacyId: params.bidId, pubkeyHash: stakingManager.calculateValidatorPubkeyHash(pubkey), nodeOperator: params.nodeOperator, validatorSize: params.validatorSize, pubkey: pubkey}); return out; } function test_validatorHelper() public { - // deploy 2 validators with default settings TestValidator memory val = helper_createValidator(defaultTestValidatorParams); console2.log("------------------------------------"); @@ -307,8 +263,7 @@ contract PreludeTest is Test, ArrayTestHelper { // After the v3-prelude upgrade is complete and any leftover validators in this state // have been approved, we can delete this test as this state can't happen anymore function test_approveExisting1EthBid() public { - - uint256 bidId = 114850; + uint256 bidId = 114_850; bytes memory pubkey = hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c"; bytes memory signature = hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df"; @@ -320,21 +275,16 @@ contract PreludeTest is Test, ArrayTestHelper { liquidityPool.setValidatorSizeWei(33 ether); vm.prank(admin); - liquidityPool.batchApproveRegistration( - toArray_u256(bidId), - toArray_bytes(pubkey), - toArray_bytes(signature) - ); + liquidityPool.batchApproveRegistration(toArray_u256(bidId), toArray_bytes(pubkey), toArray_bytes(signature)); } function test_forwardingWhitelist() public { - // create a node + pod vm.prank(admin); - address etherFiNode = stakingManager.instantiateEtherFiNode(true /*createEigenPod*/); + address etherFiNode = stakingManager.instantiateEtherFiNode(true /*createEigenPod*/ ); // link it to an arbitrary id - uint256 legacyID = 10885; + uint256 legacyID = 10_885; bytes memory pubkey = hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c"; vm.prank(admin); etherFiNodesManager.linkLegacyValidatorIds(toArray_u256(legacyID), toArray_bytes(pubkey)); @@ -360,7 +310,7 @@ contract PreludeTest is Test, ArrayTestHelper { bytes4 decimalsSelector = hex"313ce567"; // ERC20 decimals() bytes4 checkpointSelector = hex"47d28372"; // eigenpod currentCheckpoint() bytes memory data = hex"313ce567"; - bytes memory checkpointData = hex"47d28372" ; + bytes memory checkpointData = hex"47d28372"; address target = 0xFe0c30065B384F05761f15d0CC899D4F9F9Cc0eB; // ethfi // user should fail due to calls not being whitelisted @@ -389,16 +339,15 @@ contract PreludeTest is Test, ArrayTestHelper { etherFiNodesManager.forwardExternalCall(toArray(etherFiNode), toArray_bytes(data), target); } vm.stopPrank(); - } function test_granularForwardingWhitelist() public { // Setup: create node + pod vm.prank(admin); - address etherFiNode = stakingManager.instantiateEtherFiNode(true /*createEigenPod*/); + address etherFiNode = stakingManager.instantiateEtherFiNode(true /*createEigenPod*/ ); // Setup: link to legacy ID - uint256 legacyID = 10886; + uint256 legacyID = 10_886; bytes memory pubkey = hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c"; vm.prank(admin); etherFiNodesManager.linkLegacyValidatorIds(toArray_u256(legacyID), toArray_bytes(pubkey)); @@ -406,7 +355,7 @@ contract PreludeTest is Test, ArrayTestHelper { // Setup: create two users with CALL_FORWARDER_ROLE address user1 = vm.addr(0x1001); address user2 = vm.addr(0x1002); - + vm.startPrank(roleRegistry.owner()); { roleRegistry.grantRole(etherFiNodesManager.ETHERFI_NODES_MANAGER_CALL_FORWARDER_ROLE(), user1); @@ -419,13 +368,13 @@ contract PreludeTest is Test, ArrayTestHelper { bytes4 transferSelector = 0xa9059cbb; // transfer address rewardsCoordinator = 0x7750d328b314EfFa365A0402CcfD489B80B0adda; address usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - + // Test 1: User-specific whitelist (no more general fallback) vm.startPrank(admin); { // User1 specifically allowed for processClaim etherFiNodesManager.updateAllowedForwardedExternalCalls(user1, processClaimSelector, rewardsCoordinator, true); - + // User2 NOT specifically allowed } vm.stopPrank(); @@ -493,7 +442,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_deployedEtherFiNodes() public { - // creating a node should add it to the mapping vm.prank(admin); address restakedNode = stakingManager.instantiateEtherFiNode(true); @@ -518,16 +466,8 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_StakingManagerUpgradePermissions() public { - // deploy new staking manager implementation - StakingManager stakingManagerImpl = new StakingManager( - address(liquidityPool), - address(etherFiNodesManager), - address(stakingDepositContract), - address(auctionManager), - address(etherFiNodeBeacon), - address(roleRegistry) - ); + StakingManager stakingManagerImpl = new StakingManager(address(liquidityPool), address(etherFiNodesManager), address(stakingDepositContract), address(auctionManager), address(etherFiNodeBeacon), address(roleRegistry)); // only owner should be able to upgrade vm.expectRevert(IRoleRegistry.OnlyProtocolUpgrader.selector); @@ -540,7 +480,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_createBeaconValidators() public { - address nodeOperator = vm.addr(0x123456); vm.prank(nodeOperator); nodeOperatorManager.registerNodeOperator("test_ipfs_hash", 1000); @@ -548,30 +487,17 @@ contract PreludeTest is Test, ArrayTestHelper { // create a bid vm.deal(nodeOperator, 33 ether); vm.prank(nodeOperator); - uint256[] memory bidIds = auctionManager.createBid{value: 0.1 ether}( - 1, - 0.1 ether - ); + uint256[] memory bidIds = auctionManager.createBid{value: 0.1 ether}(1, 0.1 ether); bytes memory pubkey = hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c"; bytes memory signature = hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df"; vm.prank(admin); - address etherFiNode = stakingManager.instantiateEtherFiNode(true /*createEigenPod*/); + address etherFiNode = stakingManager.instantiateEtherFiNode(true /*createEigenPod*/ ); address eigenPod = address(IEtherFiNode(etherFiNode).getEigenPod()); - bytes32 initialDepositRoot = depositDataRootGenerator.generateDepositDataRoot( - pubkey, - signature, - etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod), - 1 ether - ); - IStakingManager.DepositData memory initialDepositData = IStakingManager.DepositData({ - publicKey: pubkey, - signature: signature, - depositDataRoot: initialDepositRoot, - ipfsHashForEncryptedValidatorKey: "test_ipfs_hash" - }); + bytes32 initialDepositRoot = depositDataRootGenerator.generateDepositDataRoot(pubkey, signature, etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod), 1 ether); + IStakingManager.DepositData memory initialDepositData = IStakingManager.DepositData({publicKey: pubkey, signature: signature, depositDataRoot: initialDepositRoot, ipfsHashForEncryptedValidatorKey: "test_ipfs_hash"}); vm.deal(address(liquidityPool), 100 ether); vm.prank(address(liquidityPool)); @@ -580,29 +506,18 @@ contract PreludeTest is Test, ArrayTestHelper { uint256 validatorSize = 32 ether; uint256 confirmAmount = validatorSize - 1 ether; - bytes32 confirmDepositRoot = depositDataRootGenerator.generateDepositDataRoot( - pubkey, - signature, - etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod), - confirmAmount - ); - - IStakingManager.DepositData memory confirmDepositData = IStakingManager.DepositData({ - publicKey: pubkey, - signature: signature, - depositDataRoot: confirmDepositRoot, - ipfsHashForEncryptedValidatorKey: "test_ipfs_hash" - }); + bytes32 confirmDepositRoot = depositDataRootGenerator.generateDepositDataRoot(pubkey, signature, etherFiNodesManager.addressToCompoundingWithdrawalCredentials(eigenPod), confirmAmount); + + IStakingManager.DepositData memory confirmDepositData = IStakingManager.DepositData({publicKey: pubkey, signature: signature, depositDataRoot: confirmDepositRoot, ipfsHashForEncryptedValidatorKey: "test_ipfs_hash"}); vm.prank(address(liquidityPool)); stakingManager.confirmAndFundBeaconValidators{value: confirmAmount}(toArray(confirmDepositData), validatorSize); } function test_withdrawRestakedValidatorETH() public { - bytes memory validatorPubkey = hex"892c95f4e93ab042ee39397bff22cc43298ff4b2d6d6dec3f28b8b8ebcb5c65ab5e6fc29301c1faee473ec095f9e4306"; bytes32 pubkeyHash = etherFiNodesManager.calculateValidatorPubkeyHash(validatorPubkey); - uint256 legacyID = 10885; + uint256 legacyID = 10_885; // force link this validator vm.prank(admin); @@ -622,7 +537,7 @@ contract PreludeTest is Test, ArrayTestHelper { // poke some withdrawable funds into the restakedExecutionLayerGwei storage slot of the eigenpod address eigenpod = etherFiNodesManager.getEigenPod(uint256(pubkeyHash)); - vm.store(eigenpod, bytes32(uint256(52)) /*slot*/, bytes32(uint256(50 ether / 1 gwei))); + vm.store(eigenpod, bytes32(uint256(52)), /*slot*/ bytes32(uint256(50 ether / 1 gwei))); uint256 startingBalance = address(liquidityPool).balance; @@ -635,7 +550,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_EtherFiNodePermissions() public { - // create a node vm.prank(admin); IEtherFiNode node = IEtherFiNode(stakingManager.instantiateEtherFiNode(true)); @@ -652,7 +566,7 @@ contract PreludeTest is Test, ArrayTestHelper { vm.expectRevert(IEtherFiNode.InvalidCaller.selector); node.startCheckpoint(); - BeaconChainProofs.BalanceContainerProof memory containerProof = BeaconChainProofs.BalanceContainerProof({balanceContainerRoot: bytes32(uint256(1)),proof: ""}); + BeaconChainProofs.BalanceContainerProof memory containerProof = BeaconChainProofs.BalanceContainerProof({balanceContainerRoot: bytes32(uint256(1)), proof: ""}); BeaconChainProofs.BalanceProof[] memory balanceProofs = new BeaconChainProofs.BalanceProof[](1); vm.expectRevert(IEtherFiNode.InvalidCaller.selector); node.verifyCheckpointProofs(containerProof, balanceProofs); @@ -687,9 +601,7 @@ contract PreludeTest is Test, ArrayTestHelper { vm.stopPrank(); } - function test_EtherFiNodesManagerPermissions() public { - uint256 nodeId = 1; // none of the EFNM roles should be allowed to upgrade @@ -713,10 +625,7 @@ contract PreludeTest is Test, ArrayTestHelper { etherFiNodesManager.startCheckpoint(nodeId); BeaconChainProofs.BalanceProof[] memory balanceProofs = new BeaconChainProofs.BalanceProof[](1); - BeaconChainProofs.BalanceContainerProof memory containerProof = BeaconChainProofs.BalanceContainerProof({ - balanceContainerRoot: bytes32(uint256(1)), - proof: "" - }); + BeaconChainProofs.BalanceContainerProof memory containerProof = BeaconChainProofs.BalanceContainerProof({balanceContainerRoot: bytes32(uint256(1)), proof: ""}); vm.expectRevert(IEtherFiNodesManager.IncorrectRole.selector); etherFiNodesManager.verifyCheckpointProofs(nodeId, containerProof, balanceProofs); @@ -753,18 +662,12 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_StakingManagerPermissions() public { - bytes memory pubkey = hex"8f9c0aab19ee7586d3d470f132842396af606947a0589382483308fdffdaf544078c3be24210677a9c471ce70b3b4c2c"; bytes memory signature = hex"877bee8d83cac8bf46c89ce50215da0b5e370d282bb6c8599aabdbc780c33833687df5e1f5b5c2de8a6cd20b6572c8b0130b1744310a998e1079e3286ff03e18e4f94de8cdebecf3aaac3277b742adb8b0eea074e619c20d13a1dda6cba6e3df"; // only liquidityPool can call createBeaconValidators bytes32 initialDepositDataRoot = depositDataRootGenerator.generateDepositDataRoot(pubkey, signature, "", 1 ether); - IStakingManager.DepositData memory initialDepositData = IStakingManager.DepositData({ - publicKey: pubkey, - signature: signature, - depositDataRoot: initialDepositDataRoot, - ipfsHashForEncryptedValidatorKey: "test_ipfs_hash" - }); + IStakingManager.DepositData memory initialDepositData = IStakingManager.DepositData({publicKey: pubkey, signature: signature, depositDataRoot: initialDepositDataRoot, ipfsHashForEncryptedValidatorKey: "test_ipfs_hash"}); uint256[] memory bidIds = new uint256[](1); vm.prank(admin); vm.expectRevert(IStakingManager.InvalidCaller.selector); @@ -772,17 +675,11 @@ contract PreludeTest is Test, ArrayTestHelper { // only liquidityPool can call confirmAndFundBeaconValidators bytes32 confirmDepositDataRoot = depositDataRootGenerator.generateDepositDataRoot(pubkey, signature, "", 31 ether); - IStakingManager.DepositData memory confirmDepositData = IStakingManager.DepositData({ - publicKey: pubkey, - signature: signature, - depositDataRoot: 0, - ipfsHashForEncryptedValidatorKey: "test_ipfs_hash" - }); + IStakingManager.DepositData memory confirmDepositData = IStakingManager.DepositData({publicKey: pubkey, signature: signature, depositDataRoot: 0, ipfsHashForEncryptedValidatorKey: "test_ipfs_hash"}); vm.prank(address(admin)); vm.expectRevert(IStakingManager.InvalidCaller.selector); stakingManager.confirmAndFundBeaconValidators(toArray(confirmDepositData), 32 ether); - // only protocolUpgrader can upgrade etherFiNode EtherFiNode nodeImpl = new EtherFiNode(address(0), address(0), address(0), address(0), address(0)); vm.prank(admin); @@ -794,7 +691,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_getEigenPod() public { - // node that has existing eigenpod IEtherFiNode node = IEtherFiNode(0xbD0BFF833DE891aDcFF6Ee5502B23f516bECBf6F); address eigenPod = address(node.getEigenPod()); @@ -803,15 +699,14 @@ contract PreludeTest is Test, ArrayTestHelper { // new node that doesn't have existing eigenpod // should return zero address vm.prank(admin); - IEtherFiNode newNode = IEtherFiNode(stakingManager.instantiateEtherFiNode(/*createEigenPod=*/false)); + IEtherFiNode newNode = IEtherFiNode(stakingManager.instantiateEtherFiNode( /*createEigenPod=*/ false)); assertEq(address(newNode.getEigenPod()), address(0)); } function test_createEigenPod() public { - // create pod without eigenpod vm.prank(admin); - IEtherFiNode newNode = IEtherFiNode(stakingManager.instantiateEtherFiNode(/*createEigenPod=*/false)); + IEtherFiNode newNode = IEtherFiNode(stakingManager.instantiateEtherFiNode( /*createEigenPod=*/ false)); assertEq(address(newNode.getEigenPod()), address(0)); // admin creates one and it should be connected @@ -822,9 +717,8 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_setProofSubmitter() public { - vm.prank(admin); - IEtherFiNode newNode = IEtherFiNode(stakingManager.instantiateEtherFiNode(/*createEigenPod=*/true)); + IEtherFiNode newNode = IEtherFiNode(stakingManager.instantiateEtherFiNode( /*createEigenPod=*/ true)); address newSubmitter = vm.addr(0xabc123); vm.prank(eigenlayerAdmin); @@ -832,11 +726,9 @@ contract PreludeTest is Test, ArrayTestHelper { IEigenPod pod = newNode.getEigenPod(); assertEq(pod.proofSubmitter(), newSubmitter); - } function test_pubkeyHashAndLegacyId() public { - // create a new validator TestValidator memory val = helper_createValidator(defaultTestValidatorParams); @@ -848,7 +740,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_startCheckpoint() public { - // create a new validator with an eigenpod TestValidator memory val = helper_createValidator(defaultTestValidatorParams); @@ -865,12 +756,7 @@ contract PreludeTest is Test, ArrayTestHelper { //Need to store activeValidatorCount > 0 so that proofsSubmitted isn't 0 //If it is 0 then currentCheckpointTimestamp is reset to 0 as no proofs are needed. - vm.store( - val.eigenPod, - bytes32(uint256(57)) /*slot*/, - bytes32(uint256(1)) - ); - + vm.store(val.eigenPod, bytes32(uint256(57)), /*slot*/ bytes32(uint256(1))); // only POD_PROVER can start checkpoint vm.prank(eigenlayerAdmin); @@ -884,12 +770,11 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_linkLegacyValidatorIds() public { - // grab some legacyIds that existed before the upgrade uint256[] memory legacyIds = new uint256[](3); - legacyIds[0] = 10270; - legacyIds[1] = 10271; - legacyIds[2] = 26606; + legacyIds[0] = 10_270; + legacyIds[1] = 10_271; + legacyIds[2] = 26_606; // random pubkeys to attach bytes[] memory pubkeys = new bytes[](3); @@ -910,12 +795,11 @@ contract PreludeTest is Test, ArrayTestHelper { etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); // should fail if attempt to link unknown node - uint256 badId = 9999999; + uint256 badId = 9_999_999; bytes memory badPubkey = vm.randomBytes(48); vm.expectRevert(IEtherFiNodesManager.UnknownNode.selector); vm.prank(admin); etherFiNodesManager.linkLegacyValidatorIds(toArray_u256(badId), toArray_bytes(badPubkey)); - } function test_withdrawMultipleLargeValidators() public { @@ -959,7 +843,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_withdrawMultipleSimultaneousWithdrawals() public { - TestValidatorParams memory params = defaultTestValidatorParams; params.validatorSize = 64 ether; TestValidator memory val = helper_createValidator(params); @@ -992,11 +875,7 @@ contract PreludeTest is Test, ArrayTestHelper { vm.stopPrank(); } - function _requestsFromPubkeys(bytes[] memory pubkeys, uint64[] memory amountsGwei) - internal - pure - returns (IEigenPod.WithdrawalRequest[] memory reqs) - { + function _requestsFromPubkeys(bytes[] memory pubkeys, uint64[] memory amountsGwei) internal pure returns (IEigenPod.WithdrawalRequest[] memory reqs) { require(pubkeys.length == amountsGwei.length, "test: length mismatch"); reqs = new IEigenPod.WithdrawalRequest[](pubkeys.length); for (uint256 i = 0; i < pubkeys.length; ++i) { @@ -1014,7 +893,6 @@ contract PreludeTest is Test, ArrayTestHelper { // ---------- tests for EL exits ---------- function test_requestExecutionLayerTriggeredWithdrawal_samePod_fullExit_success() public { - bytes[] memory pubkeys = new bytes[](3); uint256[] memory legacyIds = new uint256[](3); uint64[] memory amounts = new uint64[](3); @@ -1022,31 +900,30 @@ contract PreludeTest is Test, ArrayTestHelper { pubkeys[1] = PK_16172; pubkeys[2] = PK_16173; - legacyIds[0] = 51715; - legacyIds[1] = 51716; - legacyIds[2] = 51717; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; + legacyIds[2] = 51_717; vm.startPrank(admin); - etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); + etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); vm.stopPrank(); - _setExitRateLimit(172800, 2); + _setExitRateLimit(172_800, 2); - ( , IEigenPod pod0) = _resolvePod(pubkeys[0]); - ( , IEigenPod pod1) = _resolvePod(pubkeys[1]); - ( , IEigenPod pod2) = _resolvePod(pubkeys[2]); + (, IEigenPod pod0) = _resolvePod(pubkeys[0]); + (, IEigenPod pod1) = _resolvePod(pubkeys[1]); + (, IEigenPod pod2) = _resolvePod(pubkeys[2]); assertEq(address(pod0), address(pod1)); assertEq(address(pod0), address(pod2)); // Build requests: full exits (amountGwei == 0) - amounts[0] = 0; amounts[1] = 0; amounts[2] = 0; + amounts[0] = 0; + amounts[1] = 0; + amounts[2] = 0; IEigenPod.WithdrawalRequest[] memory reqs = _requestsFromPubkeys(pubkeys, amounts); // Grant role to the triggering EOA vm.startPrank(roleRegistry.owner()); - roleRegistry.grantRole( - etherFiNodesManager.ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(), - elExiter - ); + roleRegistry.grantRole(etherFiNodesManager.ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(), elExiter); vm.stopPrank(); // Fetch the current per-request fee from the pod; value = fee * n + small headroom @@ -1059,11 +936,7 @@ contract PreludeTest is Test, ArrayTestHelper { for (uint256 i = 0; i < n; ++i) { bytes32 pkHash = etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[i]); vm.expectEmit(true, true, true, true, address(etherFiNodesManager)); - emit IEtherFiNodesManager.ValidatorWithdrawalRequestSent( - address(pod0), - pkHash, - pubkeys[i] - ); + emit IEtherFiNodesManager.ValidatorWithdrawalRequestSent(address(pod0), pkHash, pubkeys[i]); } vm.prank(elExiter); @@ -1071,7 +944,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_requestExecutionLayerTriggeredWithdrawal_samePod_partialExit_success() public { - bytes[] memory pubkeys = new bytes[](3); uint256[] memory legacyIds = new uint256[](3); uint64[] memory amounts = new uint64[](3); @@ -1079,15 +951,15 @@ contract PreludeTest is Test, ArrayTestHelper { pubkeys[1] = PK_16172; pubkeys[2] = PK_16173; - legacyIds[0] = 51715; - legacyIds[1] = 51716; - legacyIds[2] = 51717; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; + legacyIds[2] = 51_717; // Link and init vm.startPrank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); vm.stopPrank(); - _setExitRateLimit(172800, 2); + _setExitRateLimit(172_800, 2); (, IEigenPod pod0) = _resolvePod(pubkeys[0]); (, IEigenPod pod1) = _resolvePod(pubkeys[1]); @@ -1097,15 +969,12 @@ contract PreludeTest is Test, ArrayTestHelper { // Build partial-exit requests (non-zero amounts) amounts[0] = 0; - amounts[1] = 2_000 gwei; - amounts[2] = 3_000 gwei; + amounts[1] = 2000 gwei; + amounts[2] = 3000 gwei; IEigenPod.WithdrawalRequest[] memory reqs = _requestsFromPubkeys(pubkeys, amounts); vm.startPrank(roleRegistry.owner()); - roleRegistry.grantRole( - etherFiNodesManager.ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(), - elExiter - ); + roleRegistry.grantRole(etherFiNodesManager.ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(), elExiter); vm.stopPrank(); // exact required ETH for fees @@ -1118,9 +987,7 @@ contract PreludeTest is Test, ArrayTestHelper { for (uint256 i = 0; i < reqs.length; ++i) { bytes32 pkHash = etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[i]); vm.expectEmit(true, true, true, true, address(etherFiNodesManager)); - emit IEtherFiNodesManager.ValidatorWithdrawalRequestSent( - address(pod0), pkHash, pubkeys[i] - ); + emit IEtherFiNodesManager.ValidatorWithdrawalRequestSent(address(pod0), pkHash, pubkeys[i]); } vm.prank(elExiter); @@ -1134,7 +1001,7 @@ contract PreludeTest is Test, ArrayTestHelper { // Unauthorized caller -> revert vm.prank(user); vm.expectRevert(); - rateLimiter.setCapacity(limitId, 172800); + rateLimiter.setCapacity(limitId, 172_800); vm.prank(user); vm.expectRevert(); @@ -1142,7 +1009,7 @@ contract PreludeTest is Test, ArrayTestHelper { // Authorized caller (admin in fork has the config role) -> success vm.startPrank(admin); - rateLimiter.setCapacity(limitId, 172800); + rateLimiter.setCapacity(limitId, 172_800); rateLimiter.setRefillRate(limitId, 2); vm.stopPrank(); } @@ -1155,9 +1022,9 @@ contract PreludeTest is Test, ArrayTestHelper { pubkeys[1] = PK_16172; pubkeys[2] = PK_16173; - legacyIds[0] = 51715; - legacyIds[1] = 51716; - legacyIds[2] = 51717; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; + legacyIds[2] = 51_717; vm.startPrank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); @@ -1169,7 +1036,6 @@ contract PreludeTest is Test, ArrayTestHelper { } function test_requestExecutionLayerTriggeredWithdrawal_requires_role_reverts() public { - bytes[] memory pubkeys = new bytes[](3); uint256[] memory legacyIds = new uint256[](3); uint64[] memory amounts = new uint64[](3); @@ -1177,14 +1043,14 @@ contract PreludeTest is Test, ArrayTestHelper { pubkeys[1] = PK_16172; pubkeys[2] = PK_16173; - legacyIds[0] = 51715; - legacyIds[1] = 51716; - legacyIds[2] = 51717; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; + legacyIds[2] = 51_717; vm.startPrank(admin); - etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); + etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); vm.stopPrank(); - _setExitRateLimit(172800, 2); + _setExitRateLimit(172_800, 2); // All same pod (sanity) (, IEigenPod pod0) = _resolvePod(pubkeys[0]); @@ -1194,7 +1060,9 @@ contract PreludeTest is Test, ArrayTestHelper { assertEq(address(pod0), address(pod2)); // full exits - amounts[0] = 0; amounts[1] = 0; amounts[2] = 0; + amounts[0] = 0; + amounts[1] = 0; + amounts[2] = 0; IEigenPod.WithdrawalRequest[] memory reqs = _requestsFromPubkeys(pubkeys, amounts); // No EL_TRIGGER_EXIT role granted to msg.sender -> revert @@ -1260,8 +1128,7 @@ contract PreludeTest is Test, ArrayTestHelper { vm.stopPrank(); // Create withdrawal params with shares (shares = wei, so 15 ether = 15 ETH) - IDelegationManager.QueuedWithdrawalParams[] memory params = - new IDelegationManager.QueuedWithdrawalParams[](1); + IDelegationManager.QueuedWithdrawalParams[] memory params = new IDelegationManager.QueuedWithdrawalParams[](1); IStrategy[] memory strategies = new IStrategy[](1); strategies[0] = IStrategy(address(0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0)); @@ -1289,14 +1156,14 @@ contract PreludeTest is Test, ArrayTestHelper { // Initialize exit rate limiter with large capacity vm.prank(admin); - rateLimiter.setCapacity(limitId, 5000_000_000_000); // 5000 ETH + rateLimiter.setCapacity(limitId, 5_000_000_000_000); // 5000 ETH // Setup validator for partial exit bytes[] memory pubkeys = new bytes[](1); uint256[] memory legacyIds = new uint256[](1); uint64[] memory amounts = new uint64[](1); pubkeys[0] = PK_16171; - legacyIds[0] = 51715; + legacyIds[0] = 51_715; amounts[0] = 1_000_000_000; // 1 ETH partial exit vm.prank(admin); @@ -1304,10 +1171,7 @@ contract PreludeTest is Test, ArrayTestHelper { // Grant role to the triggering EOA vm.startPrank(roleRegistry.owner()); - roleRegistry.grantRole( - etherFiNodesManager.ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(), - elExiter - ); + roleRegistry.grantRole(etherFiNodesManager.ETHERFI_NODES_MANAGER_EL_TRIGGER_EXIT_ROLE(), elExiter); vm.stopPrank(); IEigenPod.WithdrawalRequest[] memory reqs = _requestsFromPubkeys(pubkeys, amounts); @@ -1349,7 +1213,7 @@ contract PreludeTest is Test, ArrayTestHelper { TestValidatorParams memory params = defaultTestValidatorParams; params.validatorSize = 100 ether; // Large validator to support multiple withdrawals TestValidator memory val = helper_createValidator(params); - + bytes32 limitId = etherFiNodesManager.UNRESTAKING_LIMIT_ID(); // Set capacity to 50 ETH and reset remaining vm.startPrank(admin); @@ -1360,22 +1224,22 @@ contract PreludeTest is Test, ArrayTestHelper { // Test consuming within capacity - should succeed vm.prank(eigenlayerAdmin); etherFiNodesManager.queueETHWithdrawal(uint256(val.pubkeyHash), 30 ether); - + // Check remaining capacity is reduced - (, uint64 remaining, , ) = rateLimiter.getLimit(limitId); + (, uint64 remaining,,) = rateLimiter.getLimit(limitId); assertEq(remaining, 20_000_000_000); // 50 - 30 = 20 ETH in gwei - + // Test consuming more than remaining capacity - should fail vm.expectRevert(abi.encodeWithSignature("LimitExceeded()")); vm.prank(eigenlayerAdmin); etherFiNodesManager.queueETHWithdrawal(uint256(val.pubkeyHash), 25 ether); - + // Test consuming exactly remaining capacity - should succeed vm.prank(eigenlayerAdmin); etherFiNodesManager.queueETHWithdrawal(uint256(val.pubkeyHash), 20 ether); - + // Verify capacity is now exhausted - (, remaining, , ) = rateLimiter.getLimit(limitId); + (, remaining,,) = rateLimiter.getLimit(limitId); assertEq(remaining, 0); } @@ -1393,7 +1257,7 @@ contract PreludeTest is Test, ArrayTestHelper { rateLimiter.setRefillRate(limitId, 3_000_000_000); // 3 ETH/sec // Verify the values were set correctly - (uint64 capacity, , uint64 refillRate, ) = rateLimiter.getLimit(limitId); + (uint64 capacity,, uint64 refillRate,) = rateLimiter.getLimit(limitId); assertEq(capacity, 100_000_000_000); assertEq(refillRate, 3_000_000_000); @@ -1407,7 +1271,7 @@ contract PreludeTest is Test, ArrayTestHelper { rateLimiter.setRefillRate(limitId, 5_000_000_000); // Verify values remain unchanged after failed attempts - (capacity, , refillRate, ) = rateLimiter.getLimit(limitId); + (capacity,, refillRate,) = rateLimiter.getLimit(limitId); assertEq(capacity, 100_000_000_000); assertEq(refillRate, 3_000_000_000); } @@ -1421,7 +1285,7 @@ contract PreludeTest is Test, ArrayTestHelper { TestValidator memory val2 = helper_createValidator(params); params.validatorSize = 100 ether; TestValidator memory val3 = helper_createValidator(params); - + bytes32 limitId = etherFiNodesManager.UNRESTAKING_LIMIT_ID(); // Set capacity to 100 ETH and reset remaining vm.startPrank(admin); @@ -1432,37 +1296,37 @@ contract PreludeTest is Test, ArrayTestHelper { // Test multiple consumption attempts within capacity - all should succeed vm.prank(eigenlayerAdmin); etherFiNodesManager.queueETHWithdrawal(uint256(val1.pubkeyHash), 25 ether); - + vm.prank(eigenlayerAdmin); etherFiNodesManager.queueETHWithdrawal(uint256(val2.pubkeyHash), 30 ether); - + vm.prank(eigenlayerAdmin); etherFiNodesManager.queueETHWithdrawal(uint256(val3.pubkeyHash), 20 ether); - + // Check remaining capacity after multiple consumptions (100 - 25 - 30 - 20 = 25 ETH) - (, uint64 remaining, , ) = rateLimiter.getLimit(limitId); + (, uint64 remaining,,) = rateLimiter.getLimit(limitId); assertEq(remaining, 25_000_000_000); - + // Test that unauthorized access is blocked by the access control vm.expectRevert(IEtherFiNodesManager.IncorrectRole.selector); vm.prank(user); etherFiNodesManager.queueETHWithdrawal(uint256(val1.pubkeyHash), 10 ether); - + // Verify remaining capacity is unchanged after failed attempt - (, remaining, , ) = rateLimiter.getLimit(limitId); + (, remaining,,) = rateLimiter.getLimit(limitId); assertEq(remaining, 25_000_000_000); - + // Test final consumption that would exceed remaining capacity should fail vm.expectRevert(abi.encodeWithSignature("LimitExceeded()")); vm.prank(eigenlayerAdmin); etherFiNodesManager.queueETHWithdrawal(uint256(val1.pubkeyHash), 30 ether); - + // Test final consumption within remaining capacity should succeed vm.prank(eigenlayerAdmin); etherFiNodesManager.queueETHWithdrawal(uint256(val1.pubkeyHash), 25 ether); - + // Verify capacity is now exhausted - (, remaining, , ) = rateLimiter.getLimit(limitId); + (, remaining,,) = rateLimiter.getLimit(limitId); assertEq(remaining, 0); } @@ -1472,11 +1336,11 @@ contract PreludeTest is Test, ArrayTestHelper { bytes[] memory pubkeys = new bytes[](3); uint256[] memory legacyIds = new uint256[](3); pubkeys[0] = PK_16171; - pubkeys[1] = PK_16172; + pubkeys[1] = PK_16172; pubkeys[2] = PK_16173; - legacyIds[0] = 51715; - legacyIds[1] = 51716; - legacyIds[2] = 51717; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; + legacyIds[2] = 51_717; vm.prank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); @@ -1491,35 +1355,17 @@ contract PreludeTest is Test, ArrayTestHelper { // Create consolidation requests IEigenPodTypes.ConsolidationRequest[] memory reqs = new IEigenPodTypes.ConsolidationRequest[](2); - reqs[0] = IEigenPodTypes.ConsolidationRequest({ - srcPubkey: pubkeys[0], - targetPubkey: pubkeys[1] - }); - reqs[1] = IEigenPodTypes.ConsolidationRequest({ - srcPubkey: pubkeys[1], - targetPubkey: pubkeys[2] - }); + reqs[0] = IEigenPodTypes.ConsolidationRequest({srcPubkey: pubkeys[0], targetPubkey: pubkeys[1]}); + reqs[1] = IEigenPodTypes.ConsolidationRequest({srcPubkey: pubkeys[1], targetPubkey: pubkeys[2]}); uint256 feePer = pod0.getConsolidationRequestFee(); uint256 valueToSend = feePer * reqs.length; // Expect consolidation events vm.expectEmit(true, true, true, true, address(etherFiNodesManager)); - emit IEtherFiNodesManager.ValidatorConsolidationRequested( - address(pod0), - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[0]), - pubkeys[0], - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[1]), - pubkeys[1] - ); + emit IEtherFiNodesManager.ValidatorConsolidationRequested(address(pod0), etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[0]), pubkeys[0], etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[1]), pubkeys[1]); vm.expectEmit(true, true, true, true, address(etherFiNodesManager)); - emit IEtherFiNodesManager.ValidatorConsolidationRequested( - address(pod0), - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[1]), - pubkeys[1], - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[2]), - pubkeys[2] - ); + emit IEtherFiNodesManager.ValidatorConsolidationRequested(address(pod0), etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[1]), pubkeys[1], etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[2]), pubkeys[2]); vm.deal(admin, 1 ether); vm.prank(admin); etherFiNodesManager.requestConsolidation{value: valueToSend}(reqs); @@ -1530,7 +1376,7 @@ contract PreludeTest is Test, ArrayTestHelper { bytes[] memory pubkeys = new bytes[](1); uint256[] memory legacyIds = new uint256[](1); pubkeys[0] = PK_16171; - legacyIds[0] = 51715; + legacyIds[0] = 51_715; vm.prank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); @@ -1548,8 +1394,8 @@ contract PreludeTest is Test, ArrayTestHelper { uint256[] memory legacyIds = new uint256[](2); pubkeys[0] = PK_16171; pubkeys[1] = PK_16172; - legacyIds[0] = 51715; - legacyIds[1] = 51716; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; vm.startPrank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); @@ -1565,11 +1411,11 @@ contract PreludeTest is Test, ArrayTestHelper { IEigenPodTypes.ConsolidationRequest[] memory reqs = new IEigenPodTypes.ConsolidationRequest[](2); reqs[0] = IEigenPodTypes.ConsolidationRequest({ srcPubkey: pubkeys[0], - targetPubkey: pubkeys[0] // Same pubkey = switch to compounding + targetPubkey: pubkeys[0] // Same pubkey = switch to compounding }); reqs[1] = IEigenPodTypes.ConsolidationRequest({ srcPubkey: pubkeys[1], - targetPubkey: pubkeys[1] // Same pubkey = switch to compounding + targetPubkey: pubkeys[1] // Same pubkey = switch to compounding }); uint256 feePer = pod0.getConsolidationRequestFee(); @@ -1577,17 +1423,9 @@ contract PreludeTest is Test, ArrayTestHelper { // Expect switch to compounding events vm.expectEmit(true, true, true, true, address(etherFiNodesManager)); - emit IEtherFiNodesManager.ValidatorSwitchToCompoundingRequested( - address(pod0), - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[0]), - pubkeys[0] - ); + emit IEtherFiNodesManager.ValidatorSwitchToCompoundingRequested(address(pod0), etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[0]), pubkeys[0]); vm.expectEmit(true, true, true, true, address(etherFiNodesManager)); - emit IEtherFiNodesManager.ValidatorSwitchToCompoundingRequested( - address(pod0), - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[1]), - pubkeys[1] - ); + emit IEtherFiNodesManager.ValidatorSwitchToCompoundingRequested(address(pod0), etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[1]), pubkeys[1]); vm.deal(admin, 1 ether); vm.prank(admin); @@ -1600,9 +1438,9 @@ contract PreludeTest is Test, ArrayTestHelper { pubkeys[0] = PK_16171; pubkeys[1] = PK_16172; pubkeys[2] = PK_16173; - legacyIds[0] = 51715; - legacyIds[1] = 51716; - legacyIds[2] = 51717; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; + legacyIds[2] = 51_717; vm.startPrank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); @@ -1614,11 +1452,11 @@ contract PreludeTest is Test, ArrayTestHelper { IEigenPodTypes.ConsolidationRequest[] memory reqs = new IEigenPodTypes.ConsolidationRequest[](2); reqs[0] = IEigenPodTypes.ConsolidationRequest({ srcPubkey: pubkeys[0], - targetPubkey: pubkeys[1] // Consolidation + targetPubkey: pubkeys[1] // Consolidation }); reqs[1] = IEigenPodTypes.ConsolidationRequest({ srcPubkey: pubkeys[2], - targetPubkey: pubkeys[2] // Switch to compounding + targetPubkey: pubkeys[2] // Switch to compounding }); uint256 feePer = pod0.getConsolidationRequestFee(); @@ -1626,19 +1464,9 @@ contract PreludeTest is Test, ArrayTestHelper { // Expect mixed events vm.expectEmit(true, true, true, true, address(etherFiNodesManager)); - emit IEtherFiNodesManager.ValidatorConsolidationRequested( - address(pod0), - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[0]), - pubkeys[0], - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[1]), - pubkeys[1] - ); + emit IEtherFiNodesManager.ValidatorConsolidationRequested(address(pod0), etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[0]), pubkeys[0], etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[1]), pubkeys[1]); vm.expectEmit(true, true, true, true, address(etherFiNodesManager)); - emit IEtherFiNodesManager.ValidatorSwitchToCompoundingRequested( - address(pod0), - etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[2]), - pubkeys[2] - ); + emit IEtherFiNodesManager.ValidatorSwitchToCompoundingRequested(address(pod0), etherFiNodesManager.calculateValidatorPubkeyHash(pubkeys[2]), pubkeys[2]); vm.deal(admin, 1 ether); vm.prank(admin); @@ -1649,7 +1477,7 @@ contract PreludeTest is Test, ArrayTestHelper { bytes[] memory pubkeys = new bytes[](1); uint256[] memory legacyIds = new uint256[](1); pubkeys[0] = PK_16171; - legacyIds[0] = 51715; + legacyIds[0] = 51_715; vm.startPrank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); @@ -1659,10 +1487,7 @@ contract PreludeTest is Test, ArrayTestHelper { // Create consolidation request IEigenPodTypes.ConsolidationRequest[] memory reqs = new IEigenPodTypes.ConsolidationRequest[](1); - reqs[0] = IEigenPodTypes.ConsolidationRequest({ - srcPubkey: pubkeys[0], - targetPubkey: pubkeys[0] - }); + reqs[0] = IEigenPodTypes.ConsolidationRequest({srcPubkey: pubkeys[0], targetPubkey: pubkeys[0]}); uint256 feePer = pod0.getConsolidationRequestFee(); uint256 valueToSend = feePer * reqs.length; @@ -1685,8 +1510,8 @@ contract PreludeTest is Test, ArrayTestHelper { uint256[] memory legacyIds = new uint256[](2); pubkeys[0] = PK_16171; pubkeys[1] = PK_16172; - legacyIds[0] = 51715; - legacyIds[1] = 51716; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; vm.startPrank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); @@ -1696,14 +1521,8 @@ contract PreludeTest is Test, ArrayTestHelper { // Create consolidation requests IEigenPodTypes.ConsolidationRequest[] memory reqs = new IEigenPodTypes.ConsolidationRequest[](2); - reqs[0] = IEigenPodTypes.ConsolidationRequest({ - srcPubkey: pubkeys[0], - targetPubkey: pubkeys[1] - }); - reqs[1] = IEigenPodTypes.ConsolidationRequest({ - srcPubkey: pubkeys[1], - targetPubkey: pubkeys[0] - }); + reqs[0] = IEigenPodTypes.ConsolidationRequest({srcPubkey: pubkeys[0], targetPubkey: pubkeys[1]}); + reqs[1] = IEigenPodTypes.ConsolidationRequest({srcPubkey: pubkeys[1], targetPubkey: pubkeys[0]}); uint256 feePer = pod0.getConsolidationRequestFee(); uint256 correctFee = feePer * reqs.length; @@ -1738,9 +1557,9 @@ contract PreludeTest is Test, ArrayTestHelper { pubkeys[0] = PK_16171; pubkeys[1] = PK_16172; pubkeys[2] = PK_16173; - legacyIds[0] = 51715; - legacyIds[1] = 51716; - legacyIds[2] = 51717; + legacyIds[0] = 51_715; + legacyIds[1] = 51_716; + legacyIds[2] = 51_717; vm.startPrank(admin); etherFiNodesManager.linkLegacyValidatorIds(legacyIds, pubkeys); @@ -1754,10 +1573,7 @@ contract PreludeTest is Test, ArrayTestHelper { for (uint256 batchSize = 1; batchSize <= 3; batchSize++) { IEigenPodTypes.ConsolidationRequest[] memory reqs = new IEigenPodTypes.ConsolidationRequest[](batchSize); for (uint256 i = 0; i < batchSize; i++) { - reqs[i] = IEigenPodTypes.ConsolidationRequest({ - srcPubkey: pubkeys[i], - targetPubkey: pubkeys[(i + 1) % pubkeys.length] - }); + reqs[i] = IEigenPodTypes.ConsolidationRequest({srcPubkey: pubkeys[i], targetPubkey: pubkeys[(i + 1) % pubkeys.length]}); } uint256 expectedFee = feePer * batchSize; @@ -1767,6 +1583,4 @@ contract PreludeTest is Test, ArrayTestHelper { etherFiNodesManager.requestConsolidation{value: expectedFee}(reqs); } } - } -