Skip to content

Commit 59e22ce

Browse files
test(coverage): slashing release (#383)
* test: improve signature checker coverage * test: improve operator state retriever coverage * test: improve service manager base coverage * test: improve service manager base coverage * chore: forge fmt * test: improve service manager base coverage * fix: ci * test: improve service manager base coverage * chore: forge fmt
1 parent 9e4afb8 commit 59e22ce

File tree

4 files changed

+533
-8
lines changed

4 files changed

+533
-8
lines changed

.github/workflows/foundry.yml

-8
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,6 @@ jobs:
101101
run-coverage:
102102
name: Coverage
103103
runs-on: ubuntu-latest
104-
# Only run coverage checks on dev, testnet-holesky, and mainnet branches, or PRs targeting these branches
105-
if: |
106-
github.ref == 'refs/heads/dev' ||
107-
github.ref == 'refs/heads/testnet-holesky' ||
108-
github.ref == 'refs/heads/mainnet' ||
109-
github.base_ref == 'dev' ||
110-
github.base_ref == 'testnet-holesky' ||
111-
github.base_ref == 'mainnet'
112104
strategy:
113105
fail-fast: true
114106
steps:

test/unit/BLSSignatureCheckerUnit.t.sol

+71
Original file line numberDiff line numberDiff line change
@@ -582,4 +582,75 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer {
582582
msgHash, quorumNumbers, referenceBlockNumber, nonSignerStakesAndSignature
583583
);
584584
}
585+
586+
function test_trySignatureAndApkVerification_success() public {
587+
uint256 numNonSigners = 0;
588+
uint256 quorumBitmap = 1;
589+
(
590+
uint32 referenceBlockNumber,
591+
BLSSignatureChecker.NonSignerStakesAndSignature memory nonSignerStakesAndSignature
592+
) = _registerSignatoriesAndGetNonSignerStakeAndSignatureRandom(
593+
1, numNonSigners, quorumBitmap
594+
);
595+
596+
(bool pairingSuccessful, bool signatureIsValid) = blsSignatureChecker
597+
.trySignatureAndApkVerification(
598+
msgHash,
599+
nonSignerStakesAndSignature.quorumApks[0],
600+
nonSignerStakesAndSignature.apkG2,
601+
nonSignerStakesAndSignature.sigma
602+
);
603+
604+
assertTrue(pairingSuccessful, "Pairing should be successful");
605+
assertTrue(signatureIsValid, "Signature should be valid");
606+
}
607+
608+
function test_trySignatureAndApkVerification_invalidSignature() public {
609+
uint256 numNonSigners = 0;
610+
uint256 quorumBitmap = 1;
611+
(
612+
uint32 referenceBlockNumber,
613+
BLSSignatureChecker.NonSignerStakesAndSignature memory nonSignerStakesAndSignature
614+
) = _registerSignatoriesAndGetNonSignerStakeAndSignatureRandom(
615+
1, numNonSigners, quorumBitmap
616+
);
617+
618+
// Modify sigma to make it invalid
619+
nonSignerStakesAndSignature.sigma.X++;
620+
621+
cheats.expectRevert();
622+
blsSignatureChecker.trySignatureAndApkVerification(
623+
msgHash,
624+
nonSignerStakesAndSignature.quorumApks[0],
625+
nonSignerStakesAndSignature.apkG2,
626+
nonSignerStakesAndSignature.sigma
627+
);
628+
}
629+
630+
function test_trySignatureAndApkVerification_invalidPairing() public {
631+
uint256 numNonSigners = 0;
632+
uint256 quorumBitmap = 1;
633+
(
634+
uint32 referenceBlockNumber,
635+
BLSSignatureChecker.NonSignerStakesAndSignature memory nonSignerStakesAndSignature
636+
) = _registerSignatoriesAndGetNonSignerStakeAndSignatureRandom(
637+
1, numNonSigners, quorumBitmap
638+
);
639+
640+
// Create invalid G2 point
641+
BN254.G2Point memory invalidG2Point = BN254.G2Point(
642+
[type(uint256).max, type(uint256).max], [type(uint256).max, type(uint256).max]
643+
);
644+
645+
(bool pairingSuccessful, bool signatureIsValid) = blsSignatureChecker
646+
.trySignatureAndApkVerification(
647+
msgHash,
648+
nonSignerStakesAndSignature.quorumApks[0],
649+
invalidG2Point,
650+
nonSignerStakesAndSignature.sigma
651+
);
652+
653+
assertFalse(pairingSuccessful, "Pairing should fail");
654+
assertFalse(signatureIsValid, "Signature should be invalid");
655+
}
585656
}

test/unit/OperatorStateRetrieverUnit.t.sol

+78
Original file line numberDiff line numberDiff line change
@@ -649,4 +649,82 @@ contract OperatorStateRetrieverUnitTests is MockAVSDeployer {
649649
}
650650
}
651651
}
652+
653+
function test_getBatchOperatorId_emptyArray() public {
654+
address[] memory operators = new address[](0);
655+
bytes32[] memory operatorIds =
656+
operatorStateRetriever.getBatchOperatorId(registryCoordinator, operators);
657+
assertEq(operatorIds.length, 0, "Should return empty array for empty input");
658+
}
659+
660+
function test_getBatchOperatorId_unregisteredOperators() public {
661+
address[] memory operators = new address[](2);
662+
operators[0] = address(1);
663+
operators[1] = address(2);
664+
665+
bytes32[] memory operatorIds =
666+
operatorStateRetriever.getBatchOperatorId(registryCoordinator, operators);
667+
668+
assertEq(operatorIds.length, 2, "Should return array of same length as input");
669+
assertEq(operatorIds[0], bytes32(0), "Unregistered operator should return 0");
670+
assertEq(operatorIds[1], bytes32(0), "Unregistered operator should return 0");
671+
}
672+
673+
function test_getBatchOperatorId_mixedRegistration() public {
674+
// Register one operator
675+
cheats.roll(registrationBlockNumber);
676+
_registerOperatorWithCoordinator(defaultOperator, 1, defaultPubKey);
677+
678+
// Create test array with one registered and one unregistered operator
679+
address[] memory operators = new address[](2);
680+
operators[0] = defaultOperator;
681+
operators[1] = address(2); // unregistered
682+
683+
bytes32[] memory operatorIds =
684+
operatorStateRetriever.getBatchOperatorId(registryCoordinator, operators);
685+
686+
assertEq(operatorIds.length, 2, "Should return array of same length as input");
687+
assertEq(
688+
operatorIds[0], defaultOperatorId, "Should return correct ID for registered operator"
689+
);
690+
assertEq(operatorIds[1], bytes32(0), "Should return 0 for unregistered operator");
691+
}
692+
693+
function test_getBatchOperatorFromId_emptyArray() public {
694+
bytes32[] memory operatorIds = new bytes32[](0);
695+
address[] memory operators =
696+
operatorStateRetriever.getBatchOperatorFromId(registryCoordinator, operatorIds);
697+
assertEq(operators.length, 0, "Should return empty array for empty input");
698+
}
699+
700+
function test_getBatchOperatorFromId_unregisteredIds() public {
701+
bytes32[] memory operatorIds = new bytes32[](2);
702+
operatorIds[0] = bytes32(uint256(1));
703+
operatorIds[1] = bytes32(uint256(2));
704+
705+
address[] memory operators =
706+
operatorStateRetriever.getBatchOperatorFromId(registryCoordinator, operatorIds);
707+
708+
assertEq(operators.length, 2, "Should return array of same length as input");
709+
assertEq(operators[0], address(0), "Unregistered ID should return address(0)");
710+
assertEq(operators[1], address(0), "Unregistered ID should return address(0)");
711+
}
712+
713+
function test_getBatchOperatorFromId_mixedRegistration() public {
714+
// Register one operator
715+
cheats.roll(registrationBlockNumber);
716+
_registerOperatorWithCoordinator(defaultOperator, 1, defaultPubKey);
717+
718+
// Create test array with one registered and one unregistered operator ID
719+
bytes32[] memory operatorIds = new bytes32[](2);
720+
operatorIds[0] = defaultOperatorId;
721+
operatorIds[1] = bytes32(uint256(2)); // unregistered
722+
723+
address[] memory operators =
724+
operatorStateRetriever.getBatchOperatorFromId(registryCoordinator, operatorIds);
725+
726+
assertEq(operators.length, 2, "Should return array of same length as input");
727+
assertEq(operators[0], defaultOperator, "Should return correct address for registered ID");
728+
assertEq(operators[1], address(0), "Should return address(0) for unregistered ID");
729+
}
652730
}

0 commit comments

Comments
 (0)