Skip to content

Commit d7e14c7

Browse files
committed
feat(dkg): add WrongDKGContract guard to all submit functions
Added `error WrongDKGContract` and `_checkDKGContract(uint64 keyperSetIndex)` helper that reverts if the Keyper Set's `dkgContract` field does not match `address(this)` (address(0) is treated as a mismatch — no special case). Called before `_checkMember` in `submitDealing`, `submitAccusation`, `submitApology`, and `submitSuccessVote`. Files changed: - src/common/DKGContract.sol: error + helper + 4 call sites - test/DKGContract.t.sol: setUp wires setDKGContract; 5 new revert tests Decision: check runs after phase/success guards so misconfigured keypers get a clear WrongDKGContract error rather than a phase error.
1 parent 892cb92 commit d7e14c7

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

src/common/DKGContract.sol

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ contract DKGContract {
1919
error EmptyAccusation();
2020
error MismatchedArrays();
2121
error AlreadyVoted();
22+
error WrongDKGContract();
2223

2324
event DealingSubmitted(
2425
uint64 indexed keyperSetIndex,
@@ -119,6 +120,15 @@ contract DKGContract {
119120
}
120121
}
121122

123+
function _checkDKGContract(uint64 keyperSetIndex) internal view {
124+
address keyperSetAddress = keyperSetManager.getKeyperSetAddress(
125+
keyperSetIndex
126+
);
127+
if (KeyperSet(keyperSetAddress).getDKGContract() != address(this)) {
128+
revert WrongDKGContract();
129+
}
130+
}
131+
122132
function _checkMember(
123133
uint64 keyperSetIndex,
124134
uint64 keyperIndex
@@ -150,6 +160,7 @@ contract DKGContract {
150160
) external {
151161
_requireNotSucceeded(keyperSetIndex);
152162
_requirePhase(keyperSetIndex, retryCounter, Phase.Dealing);
163+
_checkDKGContract(keyperSetIndex);
153164
_checkMember(keyperSetIndex, keyperIndex);
154165
emit DealingSubmitted(
155166
keyperSetIndex,
@@ -170,6 +181,7 @@ contract DKGContract {
170181
) external {
171182
_requireNotSucceeded(keyperSetIndex);
172183
_requirePhase(keyperSetIndex, retryCounter, Phase.Accusing);
184+
_checkDKGContract(keyperSetIndex);
173185
_checkMember(keyperSetIndex, keyperIndex);
174186
if (accusedIndices.length == 0) {
175187
revert EmptyAccusation();
@@ -191,6 +203,7 @@ contract DKGContract {
191203
) external {
192204
_requireNotSucceeded(keyperSetIndex);
193205
_requirePhase(keyperSetIndex, retryCounter, Phase.Apologizing);
206+
_checkDKGContract(keyperSetIndex);
194207
_checkMember(keyperSetIndex, keyperIndex);
195208
if (accuserIndices.length != polyEvalData.length) {
196209
revert MismatchedArrays();
@@ -211,6 +224,7 @@ contract DKGContract {
211224
bytes calldata eonPublicKey
212225
) external {
213226
_requirePhase(keyperSetIndex, retryCounter, Phase.Finalizing);
227+
_checkDKGContract(keyperSetIndex);
214228
_checkMember(keyperSetIndex, keyperIndex);
215229
if (hasVoted[keyperSetIndex][retryCounter][msg.sender]) {
216230
revert AlreadyVoted();

test/DKGContract.t.sol

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ contract DKGContractTest is Test {
8484
keyperSet0.addMembers(members);
8585
keyperSet0.setThreshold(2);
8686
keyperSet0.setPublisher(address(dkgContract));
87+
keyperSet0.setDKGContract(address(dkgContract));
8788
keyperSet0.setFinalized();
8889
vm.prank(dao);
8990
keyperSetManager.addKeyperSet(ACTIVATION_BLOCK_0, address(keyperSet0));
@@ -550,6 +551,7 @@ contract DKGContractTest is Test {
550551
keyperSet1.addMembers(members);
551552
keyperSet1.setThreshold(2);
552553
keyperSet1.setPublisher(address(0xDEAD)); // not the DKG contract
554+
keyperSet1.setDKGContract(address(dkgContract));
553555
keyperSet1.setFinalized();
554556
uint64 activation1 = ACTIVATION_BLOCK_0 * 2;
555557
vm.prank(dao);
@@ -652,6 +654,7 @@ contract DKGContractTest is Test {
652654
keyperSet1.addMembers(members);
653655
keyperSet1.setThreshold(2);
654656
keyperSet1.setPublisher(address(dkgContract));
657+
keyperSet1.setDKGContract(address(dkgContract));
655658
keyperSet1.setFinalized();
656659
uint64 activation1 = ACTIVATION_BLOCK_0 * 2; // 2000
657660
vm.prank(dao);
@@ -706,4 +709,87 @@ contract DKGContractTest is Test {
706709
vm.prank(keyper0);
707710
dkgContract.submitDealing(0, 1, 0, hex"01", emptyEvals);
708711
}
712+
713+
// ---------------------------------------------------------------------
714+
// WrongDKGContract guard tests
715+
// ---------------------------------------------------------------------
716+
717+
function _makeKeyperSetWithWrongDKGContract()
718+
internal
719+
returns (KeyperSet ks, uint64 ksi)
720+
{
721+
ks = new KeyperSet();
722+
address[] memory members = new address[](3);
723+
members[0] = keyper0;
724+
members[1] = keyper1;
725+
members[2] = keyper2;
726+
ks.addMembers(members);
727+
ks.setThreshold(2);
728+
ks.setPublisher(address(dkgContract));
729+
// dkgContract left as address(0) — intentional mismatch
730+
ks.setFinalized();
731+
uint64 activation = ACTIVATION_BLOCK_0 * 10;
732+
vm.prank(dao);
733+
keyperSetManager.addKeyperSet(activation, address(ks));
734+
ksi = 1; // first new set added after keyperSet0
735+
}
736+
737+
function testSubmitDealingRevertsOnWrongDKGContract() public {
738+
(, uint64 ksi) = _makeKeyperSetWithWrongDKGContract();
739+
uint64 activation = ACTIVATION_BLOCK_0 * 10;
740+
uint64 dealingBlock = activation - DKG_LEAD_LENGTH;
741+
vm.roll(dealingBlock);
742+
bytes[] memory evals = new bytes[](0);
743+
vm.prank(keyper0);
744+
vm.expectRevert(DKGContract.WrongDKGContract.selector);
745+
dkgContract.submitDealing(ksi, 0, 0, hex"01", evals);
746+
}
747+
748+
function testSubmitAccusationRevertsOnWrongDKGContract() public {
749+
(, uint64 ksi) = _makeKeyperSetWithWrongDKGContract();
750+
uint64 activation = ACTIVATION_BLOCK_0 * 10;
751+
uint64 accusingBlock = activation - DKG_LEAD_LENGTH + PHASE_LENGTH;
752+
vm.roll(accusingBlock);
753+
uint64[] memory accused = new uint64[](1);
754+
accused[0] = 1;
755+
vm.prank(keyper0);
756+
vm.expectRevert(DKGContract.WrongDKGContract.selector);
757+
dkgContract.submitAccusation(ksi, 0, 0, accused);
758+
}
759+
760+
function testSubmitApologyRevertsOnWrongDKGContract() public {
761+
(, uint64 ksi) = _makeKeyperSetWithWrongDKGContract();
762+
uint64 activation = ACTIVATION_BLOCK_0 * 10;
763+
uint64 apologizingBlock = activation - DKG_LEAD_LENGTH + 2 * PHASE_LENGTH;
764+
vm.roll(apologizingBlock);
765+
uint64[] memory accusers = new uint64[](1);
766+
accusers[0] = 1;
767+
bytes[] memory evals = new bytes[](1);
768+
evals[0] = hex"aa";
769+
vm.prank(keyper0);
770+
vm.expectRevert(DKGContract.WrongDKGContract.selector);
771+
dkgContract.submitApology(ksi, 0, 0, accusers, evals);
772+
}
773+
774+
function testSubmitSuccessVoteRevertsOnWrongDKGContract() public {
775+
(, uint64 ksi) = _makeKeyperSetWithWrongDKGContract();
776+
uint64 activation = ACTIVATION_BLOCK_0 * 10;
777+
uint64 finalizingBlock = activation - DKG_LEAD_LENGTH + 3 * PHASE_LENGTH;
778+
vm.roll(finalizingBlock);
779+
vm.prank(keyper0);
780+
vm.expectRevert(DKGContract.WrongDKGContract.selector);
781+
dkgContract.submitSuccessVote(ksi, 0, 0, EON_KEY_A);
782+
}
783+
784+
function testSubmitDealingRevertsWhenDKGContractIsZero() public {
785+
// address(0) is an explicit mismatch — no special case.
786+
(, uint64 ksi) = _makeKeyperSetWithWrongDKGContract();
787+
uint64 activation = ACTIVATION_BLOCK_0 * 10;
788+
uint64 dealingBlock = activation - DKG_LEAD_LENGTH;
789+
vm.roll(dealingBlock);
790+
bytes[] memory evals = new bytes[](0);
791+
vm.prank(keyper0);
792+
vm.expectRevert(DKGContract.WrongDKGContract.selector);
793+
dkgContract.submitDealing(ksi, 0, 0, hex"01", evals);
794+
}
709795
}

0 commit comments

Comments
 (0)