test(contracts): cover allowlist removal revocation flow

Add regression coverage for registered and unregistered allowlist removals, and
verify removed validators no longer appear in validator-set message generation.
This commit is contained in:
Gonza Montiel 2026-03-18 18:31:50 +01:00
parent a57bb1634c
commit cee942e989
2 changed files with 90 additions and 0 deletions

View file

@ -6,6 +6,7 @@ import {DataHavenServiceManager} from "../src/DataHavenServiceManager.sol";
import {
IAllocationManagerTypes
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
import {Test} from "forge-std/Test.sol";
contract OperatorAddressMappingsTest is AVSDeployer {
@ -172,6 +173,68 @@ contract OperatorAddressMappingsTest is AVSDeployer {
serviceManager.deregisterOperator(operator1, address(serviceManager), operatorSetIds);
}
function test_removeValidatorFromAllowlist_deregistersRegisteredOperator() public {
address solo1 = address(0xBEEF);
_registerOperator(operator1, solo1);
assertEq(
serviceManager.validatorEthAddressToSolochainAddress(operator1),
solo1,
"forward mapping should be set before removal"
);
assertTrue(serviceManager.validatorsAllowlist(operator1), "operator should start allowlisted");
assertTrue(
allocationManager.isMemberOfOperatorSet(
operator1,
OperatorSet({avs: address(serviceManager), id: serviceManager.VALIDATORS_SET_ID()})
),
"operator should start in validator set"
);
vm.prank(avsOwner);
serviceManager.removeValidatorFromAllowlist(operator1);
assertFalse(
serviceManager.validatorsAllowlist(operator1), "operator should be removed from allowlist"
);
assertFalse(
allocationManager.isMemberOfOperatorSet(
operator1,
OperatorSet({avs: address(serviceManager), id: serviceManager.VALIDATORS_SET_ID()})
),
"operator should be removed from validator set"
);
assertEq(
serviceManager.validatorEthAddressToSolochainAddress(operator1),
address(0),
"forward mapping should be cleared"
);
assertEq(
serviceManager.validatorSolochainAddressToEthAddress(solo1),
address(0),
"reverse mapping should be cleared"
);
}
function test_removeValidatorFromAllowlist_succeedsForUnregisteredValidator() public {
vm.prank(avsOwner);
serviceManager.addValidatorToAllowlist(operator1);
assertTrue(serviceManager.validatorsAllowlist(operator1), "operator should start allowlisted");
vm.prank(avsOwner);
serviceManager.removeValidatorFromAllowlist(operator1);
assertFalse(
serviceManager.validatorsAllowlist(operator1), "operator should be removed from allowlist"
);
assertEq(
serviceManager.validatorEthAddressToSolochainAddress(operator1),
address(0),
"forward mapping should remain empty"
);
}
function test_updateSolochainAddressForValidator_revertsIfSameAddress() public {
address solo1 = address(0xBEEF);

View file

@ -519,6 +519,33 @@ contract ValidatorSetSelectionTest is SnowbridgeAndAVSDeployer {
);
}
function test_removeValidatorFromAllowlist_excludesOperatorFromValidatorSetMessage() public {
_setupMultipliers(_uniformMultipliers());
address op1 = vm.addr(601);
address solochain1 = address(uint160(0x4001));
_registerOperator(op1, solochain1, _uniformStakes(100 ether));
address op2 = vm.addr(602);
address solochain2 = address(uint160(0x4002));
_registerOperator(op2, solochain2, _uniformStakes(200 ether));
_advancePastAllocationConfigDelay();
_allocateForOperator(op1);
_allocateForOperator(op2);
_advancePastAllocationEffect();
vm.prank(avsOwner);
serviceManager.removeValidatorFromAllowlist(op2);
address[] memory expected = new address[](1);
expected[0] = solochain1;
assertEq(
serviceManager.buildNewValidatorSetMessageForEra(0), _buildExpectedMessage(expected, 0)
);
}
// Test #6: A zero multiplier is accepted and causes that strategy's stake to contribute
// no weight. The operator is still included if other strategies have non-zero multipliers.
function test_zeroMultiplier_accepted_contributesNoWeight() public {