Skip to content

Commit

Permalink
Define "expected behavior" tests for Summit
Browse files Browse the repository at this point in the history
  • Loading branch information
ChiTimesChi committed Oct 30, 2023
1 parent 7b54ce2 commit 35e9211
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 2 deletions.
48 changes: 46 additions & 2 deletions packages/contracts-core/test/suite/Summit.t.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {CallerNotInbox, NotaryInDispute} from "../../contracts/libs/Errors.sol";
import {CallerNotInbox, DisputeTimeoutNotOver, NotaryInDispute} from "../../contracts/libs/Errors.sol";
import {IAgentSecured} from "../../contracts/interfaces/IAgentSecured.sol";
import {InterfaceDestination} from "../../contracts/interfaces/InterfaceDestination.sol";
import {ISnapshotHub} from "../../contracts/interfaces/ISnapshotHub.sol";
import {SNAPSHOT_TREE_HEIGHT} from "../../contracts/libs/Constants.sol";
import {DISPUTE_TIMEOUT_NOTARY, SNAPSHOT_TREE_HEIGHT} from "../../contracts/libs/Constants.sol";
import {MerkleMath} from "../../contracts/libs/merkle/MerkleMath.sol";

import {InterfaceSummit} from "../../contracts/Summit.sol";
Expand Down Expand Up @@ -403,6 +403,50 @@ contract SummitTest is AgentSecuredTest {
inbox.submitSnapshot(snapPayload, guardSig);
}

// ═════════════════════════════════════════ TESTS: NOTARY WON DISPUTE ═════════════════════════════════════════════

function prepareSubmitSnapshotDisputeTest() internal returns (bytes memory snapPayload, bytes memory notarySig) {
address notary = domains[DOMAIN_LOCAL].agent;
address reportGuard = domains[0].agent;
address snapshotGuard = domains[0].agents[1];

Random memory random = Random("salt");
RawSnapshot memory rawSnap = random.nextSnapshot();
// Another Guard signs the snapshot
bytes memory guardSignature;
(snapPayload, guardSignature) = signSnapshot(snapshotGuard, rawSnap);
notarySig = signSnapshot(notary, snapPayload);
inbox.submitSnapshot(snapPayload, guardSignature);
openTestDispute({guardIndex: agentIndex[reportGuard], notaryIndex: agentIndex[notary]});
}

/// @dev Resolves test dispute above in favor of the Notary.
function prepareNotaryWonDisputeTest() internal {
address notary = domains[DOMAIN_LOCAL].agent;
address guard = domains[0].agent;
resolveTestDispute({slashedIndex: agentIndex[guard], rivalIndex: agentIndex[notary]});
}

function test_submitSnapshot_revert_notaryWonDisputeTimeout() public {
(bytes memory snapPayload, bytes memory notarySig) = prepareSubmitSnapshotDisputeTest();
skip(7 days);
prepareNotaryWonDisputeTest();
skip(DISPUTE_TIMEOUT_NOTARY - 1);
vm.expectRevert(DisputeTimeoutNotOver.selector);
inbox.submitSnapshot(snapPayload, notarySig);
}

function test_submitSnapshot_afterNotaryDisputeTimeout() public {
address notary = domains[DOMAIN_LOCAL].agent;
(bytes memory snapPayload, bytes memory notarySig) = prepareSubmitSnapshotDisputeTest();
skip(7 days);
prepareNotaryWonDisputeTest();
skip(DISPUTE_TIMEOUT_NOTARY);
inbox.submitSnapshot(snapPayload, notarySig);
(bytes memory snapPayload_,) = ISnapshotHub(summit).getNotarySnapshot(0);
assertEq(snapPayload_, snapPayload);
}

// ═════════════════════════════════════════════════ OVERRIDES ═════════════════════════════════════════════════════

function localContract() public view override returns (address) {
Expand Down
96 changes: 96 additions & 0 deletions packages/contracts-core/test/suite/SummitTips.t.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {DISPUTE_TIMEOUT_NOTARY} from "../../contracts/libs/Constants.sol";
import {
AgentNotNotary,
CallerNotInbox,
DisputeTimeoutNotOver,
IncorrectSnapshotRoot,
IncorrectTipsProof,
NotaryInDispute,
Expand Down Expand Up @@ -125,6 +127,19 @@ contract SummitTipsTest is AgentSecuredTest {
Summit(localContract()).initialize();
}

function prepareNotaryInDisputeTest() internal {
address notary = domains[DOMAIN_REMOTE].agent;
address guard = domains[0].agent;
openTestDispute({guardIndex: agentIndex[guard], notaryIndex: agentIndex[notary]});
}

/// @dev Resolves test dispute above in favor of the Notary.
function prepareNotaryWonDisputeTest() internal {
address notary = domains[DOMAIN_REMOTE].agent;
address guard = domains[0].agent;
resolveTestDispute({slashedIndex: agentIndex[guard], rivalIndex: agentIndex[notary]});
}

// ══════════════════════════════════════════ TESTS: SUBMIT RECEIPTS ═══════════════════════════════════════════════

function test_submitReceipt(
Expand Down Expand Up @@ -183,6 +198,35 @@ contract SummitTipsTest is AgentSecuredTest {
inbox.submitReceipt(rcptPayload, rcptSignature, tips.encodeTips(), rtp.headerHash, rtp.bodyHash);
}

function test_submitReceipt_revert_notaryWonDisputeTimeout() public {
address notary = domains[DOMAIN_REMOTE].agent;
(RawExecReceipt memory re, RawTips memory tips, RawTipsProof memory rtp) = mockReceipt("First");
prepareReceipt(re, tips, rtp, false, 0, false);
(bytes memory rcptPayload, bytes memory rcptSignature) = signReceipt(notary, re);
// Put DOMAIN_REMOTE notary in Dispute
prepareNotaryInDisputeTest();
skip(7 days);
prepareNotaryWonDisputeTest();
skip(DISPUTE_TIMEOUT_NOTARY - 1);
vm.expectRevert(DisputeTimeoutNotOver.selector);
inbox.submitReceipt(rcptPayload, rcptSignature, tips.encodeTips(), rtp.headerHash, rtp.bodyHash);
}

function test_submitReceipt_afterNotaryDisputeTimeout() public checkQueueLength(1) {
address notary = domains[DOMAIN_REMOTE].agent;
(RawExecReceipt memory re, RawTips memory tips, RawTipsProof memory rtp) = mockReceipt("First");
prepareReceipt(re, tips, rtp, false, 0, false);
(bytes memory rcptPayload, bytes memory rcptSignature) = signReceipt(notary, re);
// Put DOMAIN_REMOTE notary in Dispute
prepareNotaryInDisputeTest();
skip(7 days);
prepareNotaryWonDisputeTest();
skip(DISPUTE_TIMEOUT_NOTARY);
bool wasAccepted =
inbox.submitReceipt(rcptPayload, rcptSignature, tips.encodeTips(), rtp.headerHash, rtp.bodyHash);
assertTrue(wasAccepted);
}

function test_submitReceipt_revert_unknownSnapRoot() public {
(RawExecReceipt memory re, RawTips memory tips, RawTipsProof memory rtp) = mockReceipt("First");
prepareReceipt(re, tips, rtp, false, 0, false);
Expand Down Expand Up @@ -297,6 +341,32 @@ contract SummitTipsTest is AgentSecuredTest {
assertFalse(InterfaceSummit(summit).distributeTips());
}

/// @dev When Notary in "Dispute Won Timeout" mode, the receipt is moved to the end of the queue,
/// therefore two receipts in the queue are expected in the modifier.
function test_distributeTips_attestationNotary_wonDisputeTimeout() public checkQueueLength(2) {
// rcptNotary: agents[1], attNotary: agents[0]
prepareTwoReceiptTest(1, 0);
prepareNotaryInDisputeTest();
skip(BONDING_OPTIMISTIC_PERIOD);
prepareNotaryWonDisputeTest();
skip(DISPUTE_TIMEOUT_NOTARY - 1);
assertTrue(InterfaceSummit(summit).distributeTips());
}

/// @dev Should distribute tips if the "dispute won" timeout is over.
function test_distributeTips_attestationNotary_afterNotaryDisputeTimeout() public checkQueueLength(1) {
// rcptNotary: agents[1], attNotary: agents[0]
prepareTwoReceiptTest(1, 0);
prepareNotaryInDisputeTest();
skip(BONDING_OPTIMISTIC_PERIOD);
prepareNotaryWonDisputeTest();
skip(DISPUTE_TIMEOUT_NOTARY);
vm.recordLogs();
assertTrue(InterfaceSummit(summit).distributeTips());
// Should end up emitting TipsAwarded logs (TODO: better way to check this)
assertGt(vm.getRecordedLogs().length, 0);
}

function test_distributeTips_attestationNotaryDispute() public checkQueueLength(2) {
// rcptNotary: agents[1], attNotary: agents[0]
prepareTwoReceiptTest(1, 0);
Expand Down Expand Up @@ -336,6 +406,32 @@ contract SummitTipsTest is AgentSecuredTest {
assertTrue(InterfaceSummit(summit).distributeTips());
}

/// @dev When Notary in "Dispute Won Timeout" mode, the receipt is moved to the end of the queue,
/// therefore two receipts in the queue are expected in the modifier.
function test_distributeTips_receiptNotary_wonDisputeTimeout() public checkQueueLength(2) {
// rcptNotary: agents[0], attNotary: agents[1]
prepareTwoReceiptTest(0, 1);
prepareNotaryInDisputeTest();
skip(BONDING_OPTIMISTIC_PERIOD);
prepareNotaryWonDisputeTest();
skip(DISPUTE_TIMEOUT_NOTARY - 1);
assertTrue(InterfaceSummit(summit).distributeTips());
}

/// @dev Should distribute tips if the "dispute won" timeout is over.
function test_distributeTips_receiptNotary_afterNotaryDisputeTimeout() public checkQueueLength(1) {
// rcptNotary: agents[0], attNotary: agents[1]
prepareTwoReceiptTest(0, 1);
prepareNotaryInDisputeTest();
skip(BONDING_OPTIMISTIC_PERIOD);
prepareNotaryWonDisputeTest();
skip(DISPUTE_TIMEOUT_NOTARY);
vm.recordLogs();
assertTrue(InterfaceSummit(summit).distributeTips());
// Should end up emitting TipsAwarded logs (TODO: better way to check this)
assertGt(vm.getRecordedLogs().length, 0);
}

function test_distributeTips_receiptNotaryFraudulent() public checkQueueLength(1) {
// rcptNotary: agents[0], attNotary: agents[1]
prepareTwoReceiptTest(0, 1);
Expand Down

0 comments on commit 35e9211

Please sign in to comment.