Skip to content

Commit 10a4ea7

Browse files
authored
chore: deploy local avs w/ anvil (#195)
* chore: deploy local avs w/ anvil * test: handle signature in tests * fix: nit spacing * fix: nit newline end of file * fix: use msg.sender in mock registerOperatorToAVS
1 parent 985b84f commit 10a4ea7

4 files changed

Lines changed: 139 additions & 27 deletions

File tree

contracts/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ deploy-core:
2020
forge clean
2121
DEPLOY_TYPE="core" RPC_URL="http://localhost:8545" PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" CHAIN_ID="17864" ./entrypoint.sh
2222

23+
deploy-avs-with-mock-eigen:
24+
forge clean
25+
forge script scripts/validator-registry/avs/DeployAVSWithMockEigen.s.sol:DeployAVSWithMockEigen --rpc-url http://localhost:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --via-ir --broadcast
26+
2327
run-stake-example:
2428
forge script scripts/validator-registry/ValidatorExampleScript.s.sol:StakeExample --rpc-url http://localhost:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --via-ir --broadcast
2529

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// SPDX-License-Identifier: BSL 1.1
2+
pragma solidity ^0.8.20;
3+
4+
// solhint-disable no-console
5+
// solhint-disable one-contract-per-file
6+
7+
import {Script} from "forge-std/Script.sol";
8+
import {console} from "forge-std/console.sol";
9+
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
10+
import {MevCommitAVS} from "../../../contracts/validator-registry/avs/MevCommitAVS.sol";
11+
import {StrategyManagerMock} from "eigenlayer-contracts/src/test/mocks/StrategyManagerMock.sol";
12+
import {DelegationManagerMock} from "eigenlayer-contracts/src/test/mocks/DelegationManagerMock.sol";
13+
import {EigenPodManagerMock} from "../../../test/validator-registry/avs/EigenPodManagerMock.sol";
14+
import {AVSDirectoryMock} from "../../../test/validator-registry/avs/AVSDirectoryMock.sol";
15+
16+
contract DeployAVSWithMockEigen is Script {
17+
function run() external {
18+
require(block.chainid == 31337, "must deploy on anvil");
19+
vm.startBroadcast();
20+
21+
StrategyManagerMock strategyManagerMock = new StrategyManagerMock();
22+
DelegationManagerMock delegationManagerMock = new DelegationManagerMock();
23+
EigenPodManagerMock eigenPodManagerMock = new EigenPodManagerMock();
24+
AVSDirectoryMock avsDirectoryMock = new AVSDirectoryMock();
25+
26+
address[] memory restakeableStrategies = new address[](3);
27+
restakeableStrategies[0] = address(0x1);
28+
restakeableStrategies[1] = address(0x2);
29+
restakeableStrategies[2] = address(0x3);
30+
31+
address freezeOracle = address(0x5);
32+
uint256 unfreezeFee = 1 ether;
33+
address unfreezeReceiver = address(0x6);
34+
uint256 unfreezePeriodBlocks = 100;
35+
uint256 operatorDeregPeriodBlocks = 200;
36+
uint256 validatorDeregPeriodBlocks = 300;
37+
uint256 lstRestakerDeregPeriodBlocks = 400;
38+
string memory metadataUrl = "https://raw.githubusercontent.com/primev/mev-commit/main/static/avs-metadata.json";
39+
40+
address proxy = Upgrades.deployUUPSProxy(
41+
"MevCommitAVS.sol",
42+
abi.encodeCall(MevCommitAVS.initialize, (
43+
msg.sender,
44+
delegationManagerMock,
45+
eigenPodManagerMock,
46+
strategyManagerMock,
47+
avsDirectoryMock,
48+
restakeableStrategies,
49+
freezeOracle,
50+
unfreezeFee,
51+
unfreezeReceiver,
52+
unfreezePeriodBlocks,
53+
operatorDeregPeriodBlocks,
54+
validatorDeregPeriodBlocks,
55+
lstRestakerDeregPeriodBlocks,
56+
metadataUrl
57+
))
58+
);
59+
MevCommitAVS mevCommitAVS = MevCommitAVS(payable(proxy));
60+
61+
console.log("StrategyManagerMock deployed at:", address(strategyManagerMock));
62+
console.log("DelegationManagerMock deployed at:", address(delegationManagerMock));
63+
console.log("EigenPodManagerMock deployed at:", address(eigenPodManagerMock));
64+
console.log("AVSDirectoryMock deployed at:", address(avsDirectoryMock));
65+
console.log("MevCommitAVS deployed at:", address(mevCommitAVS));
66+
67+
delegationManagerMock.setIsOperator(msg.sender, true);
68+
69+
vm.stopBroadcast();
70+
}
71+
}

contracts/test/validator-registry/avs/AVSDirectoryMock.sol

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@ pragma solidity 0.8.20;
44
import "forge-std/Test.sol";
55
import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
66
import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol";
7+
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
78

89
// Eigenlayer core does not define their own mock for AVSDirectory.sol, hence we define our own.
910
contract AVSDirectoryMock is IAVSDirectory, Test {
1011
mapping(address => bool) public isOperatorRegistered;
12+
address public avs_;
13+
14+
bytes32 public constant OPERATOR_AVS_REGISTRATION_TYPEHASH =
15+
keccak256("OperatorAVSRegistration(address operator,address avs,bytes32 salt,uint256 expiry)");
16+
17+
bytes32 public constant DOMAIN_TYPEHASH =
18+
keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
1119

1220
function registerOperator(address operator) external {
1321
isOperatorRegistered[operator] = true;
@@ -17,16 +25,28 @@ contract AVSDirectoryMock is IAVSDirectory, Test {
1725
isOperatorRegistered[operator] = false;
1826
}
1927

20-
function isRegisteredOperator(address operator) external view returns (bool) {
21-
return isOperatorRegistered[operator];
22-
}
23-
2428
function registerOperatorToAVS(
2529
address operator,
2630
ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature
2731
) external override {
28-
require(operator != address(0), "Operator cannot be zero");
29-
require(operatorSignature.salt != bytes32(0), "Salt cannot be zero");
32+
require(operator != address(0), "Operator required");
33+
require(keccak256(operatorSignature.signature) != keccak256(bytes("")), "Signature required");
34+
require(operatorSignature.salt != bytes32(0), "Salt required");
35+
require(operatorSignature.expiry != 0, "Expiry required");
36+
37+
bytes32 operatorRegistrationDigestHash = calculateOperatorAVSRegistrationDigestHash({
38+
operator: operator,
39+
avs: msg.sender,
40+
salt: operatorSignature.salt,
41+
expiry: operatorSignature.expiry
42+
});
43+
44+
// solhint-disable-next-line reason-string
45+
require(
46+
ECDSA.recover(operatorRegistrationDigestHash, operatorSignature.signature) == operator,
47+
"EIP1271SignatureUtils.checkSignature_EIP1271: signature not from signer"
48+
);
49+
3050
isOperatorRegistered[operator] = true;
3151
emit OperatorAVSRegistrationStatusUpdated(operator, msg.sender, OperatorAVSRegistrationStatus.REGISTERED);
3252
}
@@ -40,6 +60,10 @@ contract AVSDirectoryMock is IAVSDirectory, Test {
4060
emit AVSMetadataURIUpdated(msg.sender, metadataURI);
4161
}
4262

63+
function isRegisteredOperator(address operator) external view returns (bool) {
64+
return isOperatorRegistered[operator];
65+
}
66+
4367
function operatorSaltIsSpent(address operator, bytes32 salt) external pure override returns (bool) {
4468
require(operator != address(0), "Operator cannot be zero");
4569
require(salt != bytes32(0), "Salt cannot be zero");
@@ -51,11 +75,17 @@ contract AVSDirectoryMock is IAVSDirectory, Test {
5175
address avs,
5276
bytes32 salt,
5377
uint256 expiry
54-
) external pure override returns (bytes32) {
55-
return keccak256(abi.encodePacked(operator, avs, salt, expiry));
78+
) public view returns (bytes32) {
79+
bytes32 structHash = keccak256(
80+
abi.encode(OPERATOR_AVS_REGISTRATION_TYPEHASH, operator, avs, salt, expiry)
81+
);
82+
bytes32 digestHash = keccak256(
83+
abi.encodePacked("\x19\x01", domainSeparator(), structHash)
84+
);
85+
return digestHash;
5686
}
5787

58-
function OPERATOR_AVS_REGISTRATION_TYPEHASH() external pure override returns (bytes32) {
59-
return keccak256("OperatorAVSRegistration(address operator,address avs,bytes32 salt,uint256 expiry)");
88+
function domainSeparator() public view returns (bytes32) {
89+
return keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes("EigenLayer")), block.chainid, address(this)));
6090
}
6191
}

contracts/test/validator-registry/avs/MevCommitAVSTest.sol

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ contract MevCommitAVSTest is Test {
3131
uint256 public lstRestakerDeregPeriodBlocks;
3232
string public metadataUrl;
3333

34+
address public operator = address(0x18A8E44e0E225B10a4Af86CEC6e4c514BB95B342);
35+
uint256 public operatorPrivateKey = uint256(0xe0ea92e36ee0c574bc092425926b3bfe817ec9471afbe90b577757ee16f60fd8);
36+
3437
event OperatorRegistered(address indexed operator);
3538
event OperatorDeregistrationRequested(address indexed operator);
3639
event OperatorDeregistered(address indexed operator);
@@ -95,9 +98,16 @@ contract MevCommitAVSTest is Test {
9598

9699
function testRegisterOperator() public {
97100

98-
address operator = address(0x888);
101+
bytes32 digestHash = avsDirectoryMock.calculateOperatorAVSRegistrationDigestHash({
102+
operator: operator,
103+
avs: address(mevCommitAVS),
104+
salt: bytes32("salt"),
105+
expiry: block.timestamp + 1 days
106+
});
107+
108+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(operatorPrivateKey, digestHash);
99109
ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = ISignatureUtils.SignatureWithSaltAndExpiry({
100-
signature: bytes("signature"),
110+
signature: abi.encodePacked(r, s, v),
101111
salt: bytes32("salt"),
102112
expiry: block.timestamp + 1 days
103113
});
@@ -133,8 +143,6 @@ contract MevCommitAVSTest is Test {
133143
function testRequestOperatorDeregistration() public {
134144
vm.roll(108);
135145

136-
address operator = address(0x888);
137-
138146
vm.prank(owner);
139147
mevCommitAVS.pause();
140148
vm.expectRevert(PausableUpgradeable.EnforcedPause.selector);
@@ -176,8 +184,6 @@ contract MevCommitAVSTest is Test {
176184
function testDeregisterOperator() public {
177185
vm.roll(11);
178186

179-
address operator = address(0x888);
180-
181187
vm.prank(owner);
182188
mevCommitAVS.pause();
183189
vm.expectRevert(PausableUpgradeable.EnforcedPause.selector);
@@ -232,7 +238,6 @@ contract MevCommitAVSTest is Test {
232238
function testRegisterValidatorsByPodOwners() public {
233239
vm.roll(55);
234240

235-
address operator = address(0x888);
236241
address podOwner = address(0x420);
237242
ISignatureUtils.SignatureWithExpiry memory sig = ISignatureUtils.SignatureWithExpiry({
238243
signature: bytes("signature"),
@@ -332,7 +337,6 @@ contract MevCommitAVSTest is Test {
332337

333338
function testRequestValidatorsDeregistration() public {
334339

335-
address operator = address(0x888);
336340
address podOwner = address(0x420);
337341

338342
bytes[] memory valPubkeys = new bytes[](2);
@@ -388,7 +392,6 @@ contract MevCommitAVSTest is Test {
388392

389393
function testDeregisterValidator() public {
390394

391-
address operator = address(0x888);
392395
address podOwner = address(0x420);
393396
bytes[] memory valPubkeys = new bytes[](1);
394397
valPubkeys[0] = bytes("valPubkey1");
@@ -447,7 +450,6 @@ contract MevCommitAVSTest is Test {
447450

448451
function testRegisterLSTRestaker() public {
449452

450-
address operator = address(0x888);
451453
address lstRestaker = address(0x34443);
452454
address otherAcct = address(0x777);
453455
bytes[] memory chosenVals = new bytes[](0);
@@ -631,7 +633,6 @@ contract MevCommitAVSTest is Test {
631633

632634
vm.roll(403);
633635

634-
address operator = address(0x888);
635636
bytes[] memory valPubkeys2 = new bytes[](1);
636637
valPubkeys2[0] = bytes("valPubkey1");
637638
vm.prank(operator);
@@ -699,7 +700,6 @@ contract MevCommitAVSTest is Test {
699700
assertTrue(mevCommitAVS.getValidatorRegInfo(valPubkeys[1]).freezeHeight.exists);
700701

701702
address lstRestaker = address(0x34443);
702-
address operator = address(0x888);
703703
ISignatureUtils.SignatureWithExpiry memory sig = ISignatureUtils.SignatureWithExpiry({
704704
signature: bytes("signature"),
705705
expiry: 10
@@ -933,7 +933,6 @@ contract MevCommitAVSTest is Test {
933933
function testValidatorsWithReqDeregisteredOperatorsCannotRegister() public {
934934
testRegisterOperator();
935935

936-
address operator = address(0x888);
937936
vm.prank(operator);
938937
mevCommitAVS.requestOperatorDeregistration(operator);
939938

@@ -1012,19 +1011,28 @@ contract MevCommitAVSTest is Test {
10121011
assertTrue(mevCommitAVS.isValidatorOptedIn(valPubkeys[0]));
10131012
assertTrue(mevCommitAVS.isValidatorOptedIn(valPubkeys[1]));
10141013

1015-
address operator = address(0x888);
10161014
vm.prank(operator);
10171015
mevCommitAVS.requestOperatorDeregistration(operator);
10181016

10191017
assertFalse(mevCommitAVS.isValidatorOptedIn(valPubkeys[0]));
10201018
assertFalse(mevCommitAVS.isValidatorOptedIn(valPubkeys[1]));
10211019

1022-
address newOperator = address(0x999);
1020+
address newOperator = address(0x0c94D2aE152F29Bf68A78dc9747BEa59B6f01418);
1021+
uint256 newOperatorPrivateKey = uint256(0x61437e7186d6d418e8c3221a88ce4c4aafba32347414d113ed31c425a99085a6);
10231022
delegationManagerMock.setIsOperator(newOperator, true);
10241023

1024+
bytes32 digestHash = avsDirectoryMock.calculateOperatorAVSRegistrationDigestHash({
1025+
operator: newOperator,
1026+
avs: address(mevCommitAVS),
1027+
salt: bytes32("salt"),
1028+
expiry: block.timestamp + 1 days
1029+
});
1030+
1031+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(newOperatorPrivateKey, digestHash);
1032+
10251033
vm.prank(newOperator);
10261034
ISignatureUtils.SignatureWithSaltAndExpiry memory newOperatorSigWithSalt = ISignatureUtils.SignatureWithSaltAndExpiry({
1027-
signature: bytes("signature"),
1035+
signature: abi.encodePacked(r, s, v),
10281036
salt: bytes32("salt"),
10291037
expiry: block.timestamp + 1 days
10301038
});
@@ -1046,7 +1054,6 @@ contract MevCommitAVSTest is Test {
10461054
function testDeregisteredOperatorCanStillDeregisterValidators() public {
10471055
testRegisterValidatorsByPodOwners();
10481056

1049-
address operator = address(0x888);
10501057
vm.prank(operator);
10511058
mevCommitAVS.requestOperatorDeregistration(operator);
10521059
assertTrue(mevCommitAVS.getOperatorRegInfo(operator).exists);

0 commit comments

Comments
 (0)