From 0c59ad713f10c5882386eb77e8664a2cd678e941 Mon Sep 17 00:00:00 2001 From: 8sunyuan Date: Thu, 25 Jan 2024 04:25:54 -0500 Subject: [PATCH 1/3] test: added back avsRegistration tests --- src/test/events/IAVSDirectoryEvents.sol | 15 + src/test/unit/AVSDirectoryUnit.t.sol | 378 +++++++++++++++++------- src/test/unit/DelegationUnit.t.sol | 22 -- 3 files changed, 289 insertions(+), 126 deletions(-) create mode 100644 src/test/events/IAVSDirectoryEvents.sol diff --git a/src/test/events/IAVSDirectoryEvents.sol b/src/test/events/IAVSDirectoryEvents.sol new file mode 100644 index 0000000000..ff344d9948 --- /dev/null +++ b/src/test/events/IAVSDirectoryEvents.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity =0.8.12; + +import "src/contracts/interfaces/IAVSDirectory.sol"; + +interface IAVSDirectoryEvents { + /** + * @notice Emitted when @param avs indicates that they are updating their MetadataURI string + * @dev Note that these strings are *never stored in storage* and are instead purely emitted in events for off-chain indexing + */ + event AVSMetadataURIUpdated(address indexed avs, string metadataURI); + + /// @notice Emitted when an operator's registration status for an AVS is updated + event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, IAVSDirectory.OperatorAVSRegistrationStatus status); +} \ No newline at end of file diff --git a/src/test/unit/AVSDirectoryUnit.t.sol b/src/test/unit/AVSDirectoryUnit.t.sol index 9c7cd20ae7..bf06d46b44 100644 --- a/src/test/unit/AVSDirectoryUnit.t.sol +++ b/src/test/unit/AVSDirectoryUnit.t.sol @@ -1,104 +1,274 @@ -// contract DelegationManagerUnitTests_operatorAVSRegisterationStatus is DelegationManagerUnitTests { -// // @notice Tests that an avs who calls `updateAVSMetadataURI` will correctly see an `AVSMetadataURIUpdated` event emitted with their input -// function testFuzz_UpdateAVSMetadataURI(string memory metadataURI) public { -// // call `updateAVSMetadataURI` and check for event -// cheats.expectEmit(true, true, true, true, address(delegationManager)); -// cheats.prank(defaultAVS); -// emit AVSMetadataURIUpdated(defaultAVS, metadataURI); -// delegationManager.updateAVSMetadataURI(metadataURI); -// } - -// // @notice Verifies an operator registers successfull to avs and see an `OperatorAVSRegistrationStatusUpdated` event emitted -// function testFuzz_registerOperatorToAVS(bytes32 salt) public { -// address operator = cheats.addr(delegationSignerPrivateKey); -// assertFalse(delegationManager.isOperator(operator), "bad test setup"); -// _registerOperatorWithBaseDetails(operator); - -// cheats.expectEmit(true, true, true, true, address(delegationManager)); -// emit OperatorAVSRegistrationStatusUpdated(operator, defaultAVS, OperatorAVSRegistrationStatus.REGISTERED); - -// uint256 expiry = type(uint256).max; - -// cheats.prank(defaultAVS); -// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( -// delegationSignerPrivateKey, -// operator, -// defaultAVS, -// salt, -// expiry -// ); - -// delegationManager.registerOperatorToAVS(operator, operatorSignature); -// } - -// // @notice Verifies an operator registers successfull to avs and see an `OperatorAVSRegistrationStatusUpdated` event emitted -// function testFuzz_revert_whenOperatorNotRegisteredToEigenLayerYet(bytes32 salt) public { -// address operator = cheats.addr(delegationSignerPrivateKey); -// assertFalse(delegationManager.isOperator(operator), "bad test setup"); - -// cheats.prank(defaultAVS); -// uint256 expiry = type(uint256).max; -// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( -// delegationSignerPrivateKey, -// operator, -// defaultAVS, -// salt, -// expiry -// ); - -// cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator not registered to EigenLayer yet"); -// delegationManager.registerOperatorToAVS(operator, operatorSignature); -// } - -// // @notice Verifies an operator registers fails when the signature is not from the operator -// function testFuzz_revert_whenSignatureAddressIsNotOperator(bytes32 salt) public { -// address operator = cheats.addr(delegationSignerPrivateKey); -// assertFalse(delegationManager.isOperator(operator), "bad test setup"); -// _registerOperatorWithBaseDetails(operator); - -// uint256 expiry = type(uint256).max; -// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( -// delegationSignerPrivateKey, -// operator, -// defaultAVS, -// salt, -// expiry -// ); - -// cheats.expectRevert("EIP1271SignatureUtils.checkSignature_EIP1271: signature not from signer"); -// cheats.prank(operator); -// delegationManager.registerOperatorToAVS(operator, operatorSignature); -// } - -// // @notice Verifies an operator registers fails when the signature expiry already expires -// function testFuzz_revert_whenExpiryHasExpired(bytes32 salt, uint256 expiry, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature) public { -// address operator = cheats.addr(delegationSignerPrivateKey); -// cheats.assume(operatorSignature.expiry < block.timestamp); - -// cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator signature expired"); -// delegationManager.registerOperatorToAVS(operator, operatorSignature); -// } - -// // @notice Verifies an operator registers fails when it's already registered to the avs -// function testFuzz_revert_whenOperatorAlreadyRegisteredToAVS(bytes32 salt) public { -// address operator = cheats.addr(delegationSignerPrivateKey); -// assertFalse(delegationManager.isOperator(operator), "bad test setup"); -// _registerOperatorWithBaseDetails(operator); - -// uint256 expiry = type(uint256).max; -// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( -// delegationSignerPrivateKey, -// operator, -// defaultAVS, -// salt, -// expiry -// ); - -// cheats.startPrank(defaultAVS); -// delegationManager.registerOperatorToAVS(operator, operatorSignature); - -// cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator already registered"); -// delegationManager.registerOperatorToAVS(operator, operatorSignature); -// cheats.stopPrank(); -// } -// } \ No newline at end of file +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity =0.8.12; + +import "@openzeppelin/contracts/mocks/ERC1271WalletMock.sol"; + +import "src/contracts/core/DelegationManager.sol"; +import "src/contracts/core/AVSDirectory.sol"; + +import "src/test/events/IAVSDirectoryEvents.sol"; +import "src/test/utils/EigenLayerUnitTestSetup.sol"; + +/** + * @notice Unit testing of the AVSDirectory contract. An AVSs' service manager contract will + * call this to register an operator with the AVS. + * Contracts tested: AVSDirectory + * Contracts not mocked: DelegationManager + */ +contract AVSDirectoryUnitTests is EigenLayerUnitTestSetup, IAVSDirectoryEvents { + // Contract under test + AVSDirectory avsDirectory; + AVSDirectory avsDirectoryImplementation; + + // Contract dependencies + DelegationManager delegationManager; + DelegationManager delegationManagerImplementation; + + // Delegation signer + uint256 delegationSignerPrivateKey = uint256(0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80); + uint256 stakerPrivateKey = uint256(123_456_789); + + // empty string reused across many tests + string emptyStringForMetadataURI; + + // reused in various tests. in storage to help handle stack-too-deep errors + address defaultAVS = address(this); + + uint256 minWithdrawalDelayBlocks = 216_000; + IStrategy[] public initializeStrategiesToSetDelayBlocks; + uint256[] public initializeWithdrawalDelayBlocks; + + // Index for flag that pauses registering/deregistering for AVSs + uint8 internal constant PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS = 0; + + function setUp() public virtual override { + // Setup + EigenLayerUnitTestSetup.setUp(); + + // Deploy DelegationManager implmentation and proxy + initializeStrategiesToSetDelayBlocks = new IStrategy[](0); + initializeWithdrawalDelayBlocks = new uint256[](0); + delegationManagerImplementation = new DelegationManager(strategyManagerMock, slasherMock, eigenPodManagerMock); + delegationManager = DelegationManager( + address( + new TransparentUpgradeableProxy( + address(delegationManagerImplementation), + address(eigenLayerProxyAdmin), + abi.encodeWithSelector( + DelegationManager.initialize.selector, + address(this), + pauserRegistry, + 0, // 0 is initialPausedStatus + minWithdrawalDelayBlocks, + initializeStrategiesToSetDelayBlocks, + initializeWithdrawalDelayBlocks + ) + ) + ) + ); + + // Deploy AVSDirectory implmentation and proxy + avsDirectoryImplementation = new AVSDirectory(delegationManager); + avsDirectory = AVSDirectory( + address( + new TransparentUpgradeableProxy( + address(avsDirectoryImplementation), + address(eigenLayerProxyAdmin), + abi.encodeWithSelector( + AVSDirectory.initialize.selector, + address(this), + pauserRegistry, + 0 // 0 is initialPausedStatus + ) + ) + ) + ); + + // Exclude delegation manager from fuzzed tests + addressIsExcludedFromFuzzedInputs[address(avsDirectory)] = true; + } + + /** + * INTERNAL / HELPER FUNCTIONS + */ + + /** + * @notice internal function for calculating a signature from the operator corresponding to `_operatorPrivateKey`, delegating them to + * the `operator`, and expiring at `expiry`. + */ + function _getOperatorSignature( + uint256 _operatorPrivateKey, + address operator, + address avs, + bytes32 salt, + uint256 expiry + ) internal view returns (ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature) { + operatorSignature.expiry = expiry; + operatorSignature.salt = salt; + { + bytes32 digestHash = avsDirectory.calculateOperatorAVSRegistrationDigestHash(operator, avs, salt, expiry); + (uint8 v, bytes32 r, bytes32 s) = cheats.sign(_operatorPrivateKey, digestHash); + operatorSignature.signature = abi.encodePacked(r, s, v); + } + return operatorSignature; + } + + function _registerOperatorWithBaseDetails(address operator) internal { + IDelegationManager.OperatorDetails memory operatorDetails = IDelegationManager.OperatorDetails({ + earningsReceiver: operator, + delegationApprover: address(0), + stakerOptOutWindowBlocks: 0 + }); + _registerOperator(operator, operatorDetails, emptyStringForMetadataURI); + } + + function _registerOperatorWithDelegationApprover(address operator) internal { + IDelegationManager.OperatorDetails memory operatorDetails = IDelegationManager.OperatorDetails({ + earningsReceiver: operator, + delegationApprover: cheats.addr(delegationSignerPrivateKey), + stakerOptOutWindowBlocks: 0 + }); + _registerOperator(operator, operatorDetails, emptyStringForMetadataURI); + } + + function _registerOperatorWith1271DelegationApprover(address operator) internal returns (ERC1271WalletMock) { + address delegationSigner = cheats.addr(delegationSignerPrivateKey); + /** + * deploy a ERC1271WalletMock contract with the `delegationSigner` address as the owner, + * so that we can create valid signatures from the `delegationSigner` for the contract to check when called + */ + ERC1271WalletMock wallet = new ERC1271WalletMock(delegationSigner); + + IDelegationManager.OperatorDetails memory operatorDetails = IDelegationManager.OperatorDetails({ + earningsReceiver: operator, + delegationApprover: address(wallet), + stakerOptOutWindowBlocks: 0 + }); + _registerOperator(operator, operatorDetails, emptyStringForMetadataURI); + + return wallet; + } + + function _registerOperator( + address operator, + IDelegationManager.OperatorDetails memory operatorDetails, + string memory metadataURI + ) internal filterFuzzedAddressInputs(operator) { + _filterOperatorDetails(operator, operatorDetails); + cheats.prank(operator); + delegationManager.registerAsOperator(operatorDetails, metadataURI); + } + + function _filterOperatorDetails( + address operator, + IDelegationManager.OperatorDetails memory operatorDetails + ) internal view { + // filter out zero address since people can't delegate to the zero address and operators are delegated to themselves + cheats.assume(operator != address(0)); + // filter out zero address since people can't set their earningsReceiver address to the zero address (special test case to verify) + cheats.assume(operatorDetails.earningsReceiver != address(0)); + // filter out disallowed stakerOptOutWindowBlocks values + cheats.assume(operatorDetails.stakerOptOutWindowBlocks <= delegationManager.MAX_STAKER_OPT_OUT_WINDOW_BLOCKS()); + } +} + +contract AVSDirectoryUnitTests_operatorAVSRegisterationStatus is AVSDirectoryUnitTests { + function test_revert_whenRegisterDeregisterToAVSPaused() public { + // set the pausing flag + cheats.prank(pauser); + avsDirectory.pause(2 ** PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS); + + cheats.expectRevert("Pausable: index is paused"); + avsDirectory.registerOperatorToAVS(address(0), ISignatureUtils.SignatureWithSaltAndExpiry(abi.encodePacked(""), 0, 0)); + + cheats.expectRevert("Pausable: index is paused"); + avsDirectory.deregisterOperatorFromAVS(address(0)); + } + + // @notice Tests that an avs who calls `updateAVSMetadataURI` will correctly see an `AVSMetadataURIUpdated` event emitted with their input + function testFuzz_UpdateAVSMetadataURI(string memory metadataURI) public { + // call `updateAVSMetadataURI` and check for event + cheats.expectEmit(true, true, true, true, address(avsDirectory)); + cheats.prank(defaultAVS); + emit AVSMetadataURIUpdated(defaultAVS, metadataURI); + avsDirectory.updateAVSMetadataURI(metadataURI); + } + + // @notice Verifies an operator registers successfull to avs and see an `OperatorAVSRegistrationStatusUpdated` event emitted + function testFuzz_registerOperatorToAVS(bytes32 salt) public { + address operator = cheats.addr(delegationSignerPrivateKey); + assertFalse(delegationManager.isOperator(operator), "bad test setup"); + _registerOperatorWithBaseDetails(operator); + + cheats.expectEmit(true, true, true, true, address(avsDirectory)); + emit OperatorAVSRegistrationStatusUpdated( + operator, defaultAVS, IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED + ); + + uint256 expiry = type(uint256).max; + + cheats.prank(defaultAVS); + ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = + _getOperatorSignature(delegationSignerPrivateKey, operator, defaultAVS, salt, expiry); + + avsDirectory.registerOperatorToAVS(operator, operatorSignature); + } + + // @notice Verifies an operator registers successfull to avs and see an `OperatorAVSRegistrationStatusUpdated` event emitted + function testFuzz_revert_whenOperatorNotRegisteredToEigenLayerYet(bytes32 salt) public { + address operator = cheats.addr(delegationSignerPrivateKey); + assertFalse(delegationManager.isOperator(operator), "bad test setup"); + + cheats.prank(defaultAVS); + uint256 expiry = type(uint256).max; + ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = + _getOperatorSignature(delegationSignerPrivateKey, operator, defaultAVS, salt, expiry); + + cheats.expectRevert("AVSDirectory.registerOperatorToAVS: operator not registered to EigenLayer yet"); + avsDirectory.registerOperatorToAVS(operator, operatorSignature); + } + + // @notice Verifies an operator registers fails when the signature is not from the operator + function testFuzz_revert_whenSignatureAddressIsNotOperator(bytes32 salt) public { + address operator = cheats.addr(delegationSignerPrivateKey); + assertFalse(delegationManager.isOperator(operator), "bad test setup"); + _registerOperatorWithBaseDetails(operator); + + uint256 expiry = type(uint256).max; + ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = + _getOperatorSignature(delegationSignerPrivateKey, operator, defaultAVS, salt, expiry); + + cheats.expectRevert("EIP1271SignatureUtils.checkSignature_EIP1271: signature not from signer"); + cheats.prank(operator); + avsDirectory.registerOperatorToAVS(operator, operatorSignature); + } + + // @notice Verifies an operator registers fails when the signature expiry already expires + function testFuzz_revert_whenExpiryHasExpired( + ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature + ) public { + address operator = cheats.addr(delegationSignerPrivateKey); + cheats.assume(operatorSignature.expiry < block.timestamp); + + cheats.expectRevert("AVSDirectory.registerOperatorToAVS: operator signature expired"); + avsDirectory.registerOperatorToAVS(operator, operatorSignature); + } + + // @notice Verifies an operator registers fails when it's already registered to the avs + function testFuzz_revert_whenOperatorAlreadyRegisteredToAVS(bytes32 salt) public { + address operator = cheats.addr(delegationSignerPrivateKey); + assertFalse(delegationManager.isOperator(operator), "bad test setup"); + _registerOperatorWithBaseDetails(operator); + + uint256 expiry = type(uint256).max; + ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = + _getOperatorSignature(delegationSignerPrivateKey, operator, defaultAVS, salt, expiry); + + cheats.startPrank(defaultAVS); + avsDirectory.registerOperatorToAVS(operator, operatorSignature); + + cheats.expectRevert("AVSDirectory.registerOperatorToAVS: operator already registered"); + avsDirectory.registerOperatorToAVS(operator, operatorSignature); + cheats.stopPrank(); + } +} diff --git a/src/test/unit/DelegationUnit.t.sol b/src/test/unit/DelegationUnit.t.sol index 16ed6a0b84..acb98819f5 100644 --- a/src/test/unit/DelegationUnit.t.sol +++ b/src/test/unit/DelegationUnit.t.sol @@ -188,28 +188,6 @@ contract DelegationManagerUnitTests is EigenLayerUnitTestSetup, IDelegationManag return stakerSignatureAndExpiry; } - /** - * @notice internal function for calculating a signature from the operator corresponding to `_operatorPrivateKey`, delegating them to - * the `operator`, and expiring at `expiry`. - */ - function _getOperatorSignature( - uint256 _operatorPrivateKey, - address operator, - address avs, - bytes32 salt, - uint256 expiry - ) internal view returns (ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature) { - operatorSignature.expiry = expiry; - operatorSignature.salt = salt; - { - bytes32 digestHash = delegationManager.calculateOperatorAVSRegistrationDigestHash(operator, avs, salt, expiry); - (uint8 v, bytes32 r, bytes32 s) = cheats.sign(_operatorPrivateKey, digestHash); - operatorSignature.signature = abi.encodePacked(r, s, v); - } - return operatorSignature; - } - - // @notice Assumes operator does not have a delegation approver & staker != approver function _delegateToOperatorWhoAcceptsAllStakers(address staker, address operator) internal { ISignatureUtils.SignatureWithExpiry memory approverSignatureAndExpiry; From 2c5db2bc47a5bfaa6b9c46b9bc17b54d253de649 Mon Sep 17 00:00:00 2001 From: 8sunyuan Date: Thu, 25 Jan 2024 07:02:25 -0500 Subject: [PATCH 2/3] fix: fuzz runs 4096 --- src/test/mocks/ERC20Mock.sol | 5 +++++ src/test/unit/AVSDirectoryUnit.t.sol | 2 +- src/test/unit/DelegationUnit.t.sol | 30 +++++++++++++++---------- src/test/unit/EigenPodManagerUnit.t.sol | 6 +++-- src/test/unit/StrategyManagerUnit.t.sol | 5 +++-- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/test/mocks/ERC20Mock.sol b/src/test/mocks/ERC20Mock.sol index d1e1198468..3835b6f871 100644 --- a/src/test/mocks/ERC20Mock.sol +++ b/src/test/mocks/ERC20Mock.sol @@ -82,6 +82,11 @@ contract ERC20Mock is Context, IERC20 { return _allowances[owner][spender]; } + function mint(address to, uint256 amount) public virtual { + address owner = _msgSender(); + _mint(owner, amount); + } + /** * @dev See {IERC20-approve}. * diff --git a/src/test/unit/AVSDirectoryUnit.t.sol b/src/test/unit/AVSDirectoryUnit.t.sol index bf06d46b44..f37beeca13 100644 --- a/src/test/unit/AVSDirectoryUnit.t.sol +++ b/src/test/unit/AVSDirectoryUnit.t.sol @@ -248,7 +248,7 @@ contract AVSDirectoryUnitTests_operatorAVSRegisterationStatus is AVSDirectoryUni ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature ) public { address operator = cheats.addr(delegationSignerPrivateKey); - cheats.assume(operatorSignature.expiry < block.timestamp); + operatorSignature.expiry = bound(operatorSignature.expiry, 0, block.timestamp - 1); cheats.expectRevert("AVSDirectory.registerOperatorToAVS: operator signature expired"); avsDirectory.registerOperatorToAVS(operator, operatorSignature); diff --git a/src/test/unit/DelegationUnit.t.sol b/src/test/unit/DelegationUnit.t.sol index acb98819f5..8aa8731778 100644 --- a/src/test/unit/DelegationUnit.t.sol +++ b/src/test/unit/DelegationUnit.t.sol @@ -1097,9 +1097,9 @@ contract DelegationManagerUnitTests_delegateTo is DelegationManagerUnitTests { uint256 expiry ) public filterFuzzedAddressInputs(staker) { // roll to a very late timestamp - cheats.roll(type(uint256).max / 2); + skip(type(uint256).max / 2); // filter to only *invalid* `expiry` values - cheats.assume(expiry < block.timestamp); + expiry = bound(expiry, 0, block.timestamp - 1); // filter inputs, since this will fail when the staker is already registered as an operator cheats.assume(staker != defaultOperator); @@ -1183,7 +1183,7 @@ contract DelegationManagerUnitTests_delegateTo is DelegationManagerUnitTests { uint256 expiry ) public filterFuzzedAddressInputs(staker) { // filter to only valid `expiry` values - cheats.assume(expiry >= block.timestamp); + expiry = bound(expiry, block.timestamp + 1, type(uint256).max); // filter inputs, since this will fail when the staker is already registered as an operator cheats.assume(staker != defaultOperator); @@ -1570,10 +1570,9 @@ contract DelegationManagerUnitTests_delegateTo is DelegationManagerUnitTests { uint256 expiry ) public filterFuzzedAddressInputs(staker) { // roll to a very late timestamp - cheats.roll(type(uint256).max / 2); + skip(type(uint256).max / 2); // filter to only *invalid* `expiry` values - cheats.assume(expiry < block.timestamp); - + expiry = bound(expiry, 0, block.timestamp - 1); // filter inputs, since this will fail when the staker is already registered as an operator cheats.assume(staker != defaultOperator); @@ -1824,7 +1823,7 @@ contract DelegationManagerUnitTests_delegateToBySignature is DelegationManagerUn uint256 expiry, bytes memory signature ) public filterFuzzedAddressInputs(staker) filterFuzzedAddressInputs(operator) { - cheats.assume(expiry < block.timestamp); + expiry = bound(expiry, 0, block.timestamp - 1); cheats.expectRevert("DelegationManager.delegateToBySignature: staker signature expired"); ISignatureUtils.SignatureWithExpiry memory signatureWithExpiry = ISignatureUtils.SignatureWithExpiry({ signature: signature, @@ -1961,12 +1960,18 @@ contract DelegationManagerUnitTests_delegateToBySignature is DelegationManagerUn uint256 stakerExpiry, uint256 delegationApproverExpiry ) public filterFuzzedAddressInputs(caller) { - // filter to only valid `stakerExpiry` values - cheats.assume(stakerExpiry >= block.timestamp); // roll to a very late timestamp - cheats.roll(type(uint256).max / 2); + skip(type(uint256).max / 2); + + // filter to only valid `stakerExpiry` values + stakerExpiry = bound(stakerExpiry, block.timestamp + 1, type(uint256).max); // filter to only *invalid* `delegationApproverExpiry` values - cheats.assume(delegationApproverExpiry < block.timestamp); + delegationApproverExpiry = bound(delegationApproverExpiry, 0, block.timestamp - 1); + + console.log("timestamp: %s", block.timestamp); + console.log(stakerExpiry); + console.log(delegationApproverExpiry); + _registerOperatorWithDelegationApprover(defaultOperator); @@ -3027,6 +3032,7 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage uint256 withdrawalAmount ) public filterFuzzedAddressInputs(staker) { cheats.assume(staker != defaultOperator); + cheats.assume(withdrawer != address(0)); cheats.assume(withdrawalAmount > 0 && withdrawalAmount <= depositAmount); _registerOperatorWithBaseDetails(defaultOperator); ( @@ -3071,7 +3077,7 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage uint256 withdrawalAmount ) public filterFuzzedAddressInputs(staker) { cheats.assume(staker != defaultOperator); - cheats.assume(withdrawer != defaultOperator); + cheats.assume(withdrawer != defaultOperator && withdrawer != address(0)); cheats.assume(withdrawalAmount > 0 && withdrawalAmount <= depositAmount); _registerOperatorWithBaseDetails(defaultOperator); ( diff --git a/src/test/unit/EigenPodManagerUnit.t.sol b/src/test/unit/EigenPodManagerUnit.t.sol index 8d797923fc..d03b4f516f 100644 --- a/src/test/unit/EigenPodManagerUnit.t.sol +++ b/src/test/unit/EigenPodManagerUnit.t.sol @@ -289,7 +289,7 @@ contract EigenPodManagerUnitTests_ShareUpdateTests is EigenPodManagerUnitTests { function testFuzz_addShares(uint256 shares) public { // Fuzz inputs cheats.assume(defaultStaker != address(0)); - cheats.assume(shares % GWEI_TO_WEI == 0); + shares = shares - (shares % GWEI_TO_WEI); // Round down to nearest Gwei cheats.assume(int256(shares) >= 0); // Add shares @@ -361,7 +361,9 @@ contract EigenPodManagerUnitTests_ShareUpdateTests is EigenPodManagerUnitTests { function testFuzz_removeShares_zeroShares(address podOwner, uint256 shares) public filterFuzzedAddressInputs(podOwner) { // Constrain inputs cheats.assume(podOwner != address(0)); - cheats.assume(shares % GWEI_TO_WEI == 0); + cheats.assume(shares < type(uint256).max / 2); + shares = shares - (shares % GWEI_TO_WEI); // Round down to nearest Gwei + assertTrue(int256(shares) % int256(GWEI_TO_WEI) == 0, "Shares must be a whole Gwei amount"); // Initialize pod with shares _initializePodWithShares(podOwner, int256(shares)); diff --git a/src/test/unit/StrategyManagerUnit.t.sol b/src/test/unit/StrategyManagerUnit.t.sol index c50ff9d0bd..64ff9345f4 100644 --- a/src/test/unit/StrategyManagerUnit.t.sol +++ b/src/test/unit/StrategyManagerUnit.t.sol @@ -902,7 +902,7 @@ contract StrategyManagerUnitTests_removeShares is StrategyManagerUnitTests { strategies[1] = dummyStrat2; strategies[2] = dummyStrat3; for (uint256 i = 0; i < 3; ++i) { - cheats.assume(amounts[i] > 0 && amounts[i] < dummyToken.totalSupply()); + amounts[i] = bound(amounts[i], 1, dummyToken.totalSupply() - 1); _depositIntoStrategySuccessfully(strategies[i], staker, amounts[i]); } IStrategy removeStrategy = strategies[randStrategy % 3]; @@ -944,7 +944,8 @@ contract StrategyManagerUnitTests_removeShares is StrategyManagerUnitTests { strategies[2] = dummyStrat3; uint256[] memory sharesBefore = new uint256[](3); for (uint256 i = 0; i < 3; ++i) { - cheats.assume(sharesAmounts[i] > 0 && sharesAmounts[i] <= depositAmounts[i]); + depositAmounts[i] = bound(depositAmounts[i], 1, strategies[i].underlyingToken().totalSupply()); + sharesAmounts[i] = bound(sharesAmounts[i], 1, depositAmounts[i]); _depositIntoStrategySuccessfully(strategies[i], staker, depositAmounts[i]); sharesBefore[i] = strategyManager.stakerStrategyShares(staker, strategies[i]); assertEq(sharesBefore[i], depositAmounts[i], "Staker has not deposited amount into strategy"); From 77c2943e8a524a003b597d4940a820be8a2883f5 Mon Sep 17 00:00:00 2001 From: 8sunyuan Date: Thu, 25 Jan 2024 07:55:20 -0500 Subject: [PATCH 3/3] fix: broken fuzz test --- src/test/unit/DelegationUnit.t.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/unit/DelegationUnit.t.sol b/src/test/unit/DelegationUnit.t.sol index 8aa8731778..c432f2d312 100644 --- a/src/test/unit/DelegationUnit.t.sol +++ b/src/test/unit/DelegationUnit.t.sol @@ -1185,7 +1185,8 @@ contract DelegationManagerUnitTests_delegateTo is DelegationManagerUnitTests { // filter to only valid `expiry` values expiry = bound(expiry, block.timestamp + 1, type(uint256).max); // filter inputs, since this will fail when the staker is already registered as an operator - cheats.assume(staker != defaultOperator); + address delegationApprover = cheats.addr(delegationSignerPrivateKey); + cheats.assume(staker != defaultOperator && staker != delegationApprover); _registerOperatorWithDelegationApprover(defaultOperator);