Skip to content

Commit

Permalink
test: added back avsRegistration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
8sunyuan committed Jan 25, 2024
1 parent fcb32f5 commit 0c59ad7
Show file tree
Hide file tree
Showing 3 changed files with 289 additions and 126 deletions.
15 changes: 15 additions & 0 deletions src/test/events/IAVSDirectoryEvents.sol
Original file line number Diff line number Diff line change
@@ -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);
}
378 changes: 274 additions & 104 deletions src/test/unit/AVSDirectoryUnit.t.sol
Original file line number Diff line number Diff line change
@@ -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();
// }
// }
// 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();
}
}
Loading

0 comments on commit 0c59ad7

Please sign in to comment.