Skip to content

Feat/operator sets #579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Jun 26, 2024
Merged
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5dbd94a
feat: operator set scaffold
ypatil12 Jun 3, 2024
51ff168
fix: impl/storage compile errors; pending updating of tests
ypatil12 Jun 3, 2024
d477943
chore: `forge fmt`
0xClandestine Jun 4, 2024
bcf7d21
fix: `OperatorSet` struct misuse
0xClandestine Jun 4, 2024
3ff5cb6
fix: comment
ypatil12 Jun 5, 2024
b31d4ed
Merge branch 'feat/operator-sets' of https://github.com/Layr-Labs/eig…
0xClandestine Jun 5, 2024
73cf5e2
chore: verbose use of `OperatorSet`
0xClandestine Jun 5, 2024
5d6a28c
test: `registerOperatorToOperatorSet`
0xClandestine Jun 5, 2024
e94c74b
feat: `registerOperatorToOperatorSets`
0xClandestine Jun 6, 2024
331afaa
chore: `forge fmt`
0xClandestine Jun 6, 2024
b4724c0
feat: interface changes
0xClandestine Jun 6, 2024
17e9f78
fix: operator set digest
0xClandestine Jun 6, 2024
6bcc71c
fix: `OPERATOR_SET_REGISTRATION_TYPEHASH`
0xClandestine Jun 6, 2024
08aa8fc
chore: `forge fmt`
0xClandestine Jun 6, 2024
0b07f47
test: wrong avs using signature
0xClandestine Jun 6, 2024
97a6dba
fix: optimize for SSTOREs
0xClandestine Jun 6, 2024
e9359ad
test: `deregisterOperatorFromOperatorSets`
0xClandestine Jun 6, 2024
b92b285
chore: rename `operatorSetStrategies`
0xClandestine Jun 6, 2024
18c7133
test: `addStrategiesToOperatorSet`
0xClandestine Jun 6, 2024
b869392
test: `removeStrategiesFromOperatorSet`
0xClandestine Jun 6, 2024
c4437c6
test: more coverage
0xClandestine Jun 7, 2024
5d09658
chore: improve natspec
0xClandestine Jun 7, 2024
648cc94
WIP: simp mode
0xClandestine Jun 17, 2024
d8c046f
WIP: simp mode
0xClandestine Jun 17, 2024
d12ea4c
WIP: simp mode
0xClandestine Jun 17, 2024
c926f2f
test: simp mode
0xClandestine Jun 18, 2024
92479e2
test: simp mode
0xClandestine Jun 18, 2024
27ed1a1
test: simp mode
0xClandestine Jun 18, 2024
3b0450e
refactor: simp mode storage
0xClandestine Jun 19, 2024
5f90d78
Revert "refactor: simp mode storage"
0xClandestine Jun 19, 2024
f4c3ae5
Reapply "refactor: simp mode storage"
0xClandestine Jun 19, 2024
c190c1b
feat: simp mode
0xClandestine Jun 20, 2024
3b984ab
fix(optimize): salt cancellation
0xClandestine Jun 20, 2024
b944193
test: improvements
0xClandestine Jun 20, 2024
98d0c4f
test: improvements
0xClandestine Jun 20, 2024
d83a870
fix: move `isOperatorSetAVS` update out of loop
0xClandestine Jun 24, 2024
1fa4a42
fix: standby update typehash
0xClandestine Jun 24, 2024
1e9609f
test: cleanup
0xClandestine Jun 25, 2024
1328e23
fix: move mutation out of loop
0xClandestine Jun 25, 2024
0553d18
nit: cleanup
0xClandestine Jun 25, 2024
22ceb9c
fix: remove unused events
ypatil12 Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 139 additions & 10 deletions src/test/unit/AVSDirectoryUnit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import "src/test/utils/EigenLayerUnitTestSetup.sol";
* Contracts not mocked: DelegationManager
*/
contract AVSDirectoryUnitTests is EigenLayerUnitTestSetup, IAVSDirectoryEvents {
uint256 internal constant MAX_PRIVATE_KEY = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140;

// Contract under test
AVSDirectory avsDirectory;
AVSDirectory avsDirectoryImplementation;
Expand Down Expand Up @@ -170,14 +172,137 @@ contract AVSDirectoryUnitTests is EigenLayerUnitTestSetup, IAVSDirectoryEvents {
}
}

contract AVSDirectoryUnitTests_registerOperatorToOperatorSet is AVSDirectoryUnitTests {
event OperatorAddedToOperatorSet(address operator, IAVSDirectory.OperatorSet operatorSet);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: import events from IAVSDirectoryEvents


function testFuzz_revert_SignatureIsExpired(
address operator,
uint32 oid,
bytes32 salt,
uint256 expiry
) public virtual {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might want to add filterFuzzedAddressInputs(operator)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for all fuzzed address inputs, we get a couple flakey fuzz tests in our CI occasionally when we forget this modifier

expiry = bound(expiry, 0, type(uint256).max - 1);

cheats.warp(type(uint256).max);
cheats.expectRevert("AVSDirectory.registerOperatorToOperatorSet: operator signature expired");

avsDirectory.registerOperatorToOperatorSet(
operator, oid, ISignatureUtils.SignatureWithSaltAndExpiry(new bytes(0), salt, expiry)
);
}

function testFuzz_revert_OperatorRegistered(
uint256 operatorPk,
uint32 oid,
bytes32 salt,
uint256 expiry
) public virtual {
operatorPk = bound(operatorPk, 1, MAX_PRIVATE_KEY);
expiry = bound(expiry, 1, type(uint256).max);

cheats.warp(0);

address operator = cheats.addr(operatorPk);
(uint8 v, bytes32 r, bytes32 s) = cheats.sign(
operatorPk, avsDirectory.calculateOperatorAVSRegistrationDigestHash(operator, address(this), salt, expiry)
);

_registerOperatorWithBaseDetails(operator);

avsDirectory.registerOperatorToOperatorSet(
operator, oid, ISignatureUtils.SignatureWithSaltAndExpiry(abi.encodePacked(r, s, v), salt, expiry)
);

cheats.expectRevert("AVSDirectory.registerOperatorToOperatorSet: operator already registered to operator set");
avsDirectory.registerOperatorToOperatorSet(
operator, oid, ISignatureUtils.SignatureWithSaltAndExpiry(new bytes(0), salt, expiry)
);
}

function testFuzz_revert_OperatorNotRegistered(
address operator,
uint32 oid,
bytes32 salt,
uint256 expiry
) public virtual {
vm.assume(operator != address(0));

expiry = bound(expiry, 1, type(uint256).max);

cheats.warp(0);

cheats.expectRevert("AVSDirectory.registerOperatorToAVS: operator not registered to EigenLayer yet");
avsDirectory.registerOperatorToOperatorSet(
operator, oid, ISignatureUtils.SignatureWithSaltAndExpiry(new bytes(0), salt, expiry)
);
}

function testFuzz_revert_SaltSpent(uint256 operatorPk, uint32 oid, bytes32 salt, uint256 expiry) public virtual {
oid = uint32(bound(oid, 1, type(uint32).max));
operatorPk = bound(operatorPk, 1, MAX_PRIVATE_KEY);
expiry = bound(expiry, 1, type(uint256).max);

cheats.warp(0);

address operator = cheats.addr(operatorPk);
(uint8 v, bytes32 r, bytes32 s) = cheats.sign(
operatorPk, avsDirectory.calculateOperatorAVSRegistrationDigestHash(operator, address(this), salt, expiry)
);

_registerOperatorWithBaseDetails(operator);

avsDirectory.registerOperatorToOperatorSet(
operator, oid, ISignatureUtils.SignatureWithSaltAndExpiry(abi.encodePacked(r, s, v), salt, expiry)
);

cheats.expectRevert("AVSDirectory.registerOperatorToAVS: salt already spent");
avsDirectory.registerOperatorToOperatorSet(
operator, 0, ISignatureUtils.SignatureWithSaltAndExpiry(new bytes(0), salt, expiry)
);
}

function testFuzz_Correctness(uint256 operatorPk, uint32 oid, bytes32 salt, uint256 expiry) public virtual {
operatorPk = bound(operatorPk, 1, MAX_PRIVATE_KEY);
expiry = bound(expiry, 1, type(uint256).max);

cheats.warp(0);

address operator = cheats.addr(operatorPk);
(uint8 v, bytes32 r, bytes32 s) = cheats.sign(
operatorPk, avsDirectory.calculateOperatorAVSRegistrationDigestHash(operator, address(this), salt, expiry)
);

_registerOperatorWithBaseDetails(operator);

cheats.expectEmit(true, false, false, false, address(avsDirectory));
emit OperatorAVSRegistrationStatusUpdated(
operator, address(this), IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED
);

cheats.expectEmit(true, false, false, false, address(avsDirectory));
emit OperatorAddedToOperatorSet(operator, IAVSDirectory.OperatorSet(address(this), oid));
avsDirectory.registerOperatorToOperatorSet(
operator, oid, ISignatureUtils.SignatureWithSaltAndExpiry(abi.encodePacked(r, s, v), salt, expiry)
);

assertEq(avsDirectory.operatorAVSOperatorSetCount(address(this), operator), 1);
assertEq(uint8(avsDirectory.avsOperatorStatus(address(this), operator)), 1);
assertTrue(avsDirectory.operatorSetRegistrations(address(this), operator, oid));
assertTrue(avsDirectory.operatorSaltIsSpent(operator, salt));
assertTrue(avsDirectory.isOperatorSetAVS(address(this)));
}
}

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));
avsDirectory.registerOperatorToAVS(
address(0), ISignatureUtils.SignatureWithSaltAndExpiry(abi.encodePacked(""), 0, 0)
);

cheats.expectRevert("Pausable: index is paused");
avsDirectory.deregisterOperatorFromAVS(address(0));
Expand Down Expand Up @@ -242,9 +367,9 @@ contract AVSDirectoryUnitTests_operatorAVSRegisterationStatus is AVSDirectoryUni
}

// @notice Verifies an operator registers fails when the signature expiry already expires
function testFuzz_revert_whenExpiryHasExpired(
ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature
) public {
function testFuzz_revert_whenExpiryHasExpired(ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature)
public
{
address operator = cheats.addr(delegationSignerPrivateKey);
operatorSignature.expiry = bound(operatorSignature.expiry, 0, block.timestamp - 1);

Expand Down Expand Up @@ -283,10 +408,14 @@ contract AVSDirectoryUnitTests_operatorAVSRegisterationStatus is AVSDirectoryUni
avsDirectory.cancelSalt(salt);

assertTrue(avsDirectory.operatorSaltIsSpent(operator, salt), "salt was not successfully cancelled");
assertFalse(avsDirectory.operatorSaltIsSpent(defaultAVS, salt), "salt should only be cancelled for the operator");
assertFalse(
avsDirectory.operatorSaltIsSpent(defaultAVS, salt), "salt should only be cancelled for the operator"
);

bytes32 newSalt;
unchecked { newSalt = bytes32(uint(salt) + 1); }
bytes32 newSalt;
unchecked {
newSalt = bytes32(uint256(salt) + 1);
}

assertFalse(salt == newSalt, "bad test setup");

Expand Down Expand Up @@ -321,9 +450,9 @@ contract AVSDirectoryUnitTests_operatorAVSRegisterationStatus is AVSDirectoryUni
assertFalse(delegationManager.isOperator(operator), "bad test setup");
_registerOperatorWithBaseDetails(operator);

uint256 expiry = type(uint256).max;
ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature =
_getOperatorSignature(delegationSignerPrivateKey, operator, defaultAVS, salt, expiry);
// uint256 expiry = type(uint256).max;
// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature =
// _getOperatorSignature(delegationSignerPrivateKey, operator, defaultAVS, salt, expiry);

cheats.startPrank(operator);
avsDirectory.cancelSalt(salt);
Expand Down