Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: medusa tests #51

Draft
wants to merge 29 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5d5fd14
chore: properties md update
simon-something Oct 29, 2024
3b77715
test(medusa): handlers and working setup
simon-something Nov 10, 2024
1b53763
test(medusa): add lib to crytic compile
simon-something Nov 10, 2024
98de161
test(medusa): prop 0 sanity check ok
simon-something Nov 10, 2024
92a50e3
test(medusa): git ignore corpus
simon-something Nov 10, 2024
1e78bdb
test(medusa): git ignore corpus
simon-something Nov 10, 2024
efc8876
test(medusa): typo medusa json
simon-something Nov 10, 2024
e4cf1e5
test(medusa): rm corpus
simon-something Nov 10, 2024
c0ffee6
test(medusa): natspec
simon-something Nov 11, 2024
c0ffee7
test(medusa): rm non-sensical handlers onlyoracle etc
simon-something Nov 11, 2024
c0ffeed
test(medusa): ghosts refactor
simon-something Nov 13, 2024
c0ffee6
test(medusa): more handler fixes
simon-something Nov 13, 2024
c0ffeee
test(medusa): properties md update
simon-something Nov 20, 2024
9c8dce2
test(medusa): requester properties (#57)
0xJabberwock Nov 28, 2024
c0ffee9
test(medusa): dispute window in prop6
simon-something Nov 28, 2024
c0ffeef
test(medusa): fix approveModule
simon-something Nov 28, 2024
c0ffeeb
test(medusa): fix approveModule
simon-something Nov 28, 2024
97fff3c
test(medusa): rename PropertyDispute to PropertyDisputer
0xJabberwock Nov 29, 2024
80d145f
test(medusa): correct prop-6
0xJabberwock Nov 29, 2024
1d45342
test(medusa): assert prop-7
0xJabberwock Nov 29, 2024
c0ffee6
test(medusa): properties 13
simon-something Nov 30, 2024
c0ffee9
test(medusa): fix prop1 for empty finalized req
simon-something Dec 7, 2024
c0ffee7
test(medusa): fix fp
simon-something Dec 11, 2024
7218056
test(medusa): proposer properties
0xJabberwock Dec 13, 2024
2b8bc63
test(medusa): fix prop8b
simon-something Dec 11, 2024
c0ffee2
test(medusa): false pos fix
simon-something Dec 16, 2024
c0ffeea
test(medusa): false pos fix
simon-something Dec 16, 2024
a3b8f1c
Merge branch 'dev' into test/handler-cov
simon-something Dec 18, 2024
c0ffee8
Revert "Merge branch 'dev' into test/handler-cov"
simon-something Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion test/invariants/PROPERTIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,4 @@ Oracle
| disputeResponse(Request,Response,Dispute) external returns (bytes32) | [] |
| escalateDispute(Request,Response,Dispute) external | [] |
| resolveDispute(Request,Response,Dispute) external | [] |
| updateDisputeStatus(Request,Response,Dispute,DisputeStatus) external | [] |
| finalize(Request,Response) external | [] |
7 changes: 3 additions & 4 deletions test/invariants/handlers/BaseHandler.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ contract BaseHandler is Setup, Actors {
mapping(bytes32 _requestId => IOracle.Request _data) internal _ghost_requestData;

// Track responses for requests
mapping(bytes32 _requestId => bytes32 _responseId) internal _ghost_activeResponses; // requestId => responseId
mapping(bytes32 _requestId => bytes32[] _responsesId) internal _ghost_activeResponses; // requestId => responseId's
mapping(bytes32 _responseId => IOracle.Response _data) internal _ghost_responseData;
mapping(bytes32 _responseId => bool _isFinalized) internal _ghost_finalizedResponses;

// Track disputes
mapping(bytes32 _requestId => bytes32[] _disputeIds) internal _ghost_disputes; // requestId => disputeIds
mapping(bytes32 _disputeId => IOracle.Dispute _data) internal _ghost_disputeData;
mapping(bytes32 _disputeId => IOracle.DisputeStatus _status) internal _ghost_disputeStatuses;

// Track which requests came from EBORequestCreator
mapping(bytes32 _requestId => bool _isFromRequestCreator) internal _ghost_validRequests;
Expand Down Expand Up @@ -56,8 +55,8 @@ contract BaseHandler is Setup, Actors {
return _ghost_requests[_seed % _ghost_requests.length];
}

function _getRandomActiveResponse(bytes32 _requestId) internal view returns (IOracle.Response memory) {
bytes32 responseId = _ghost_activeResponses[_requestId];
function _getRandomActiveResponse(bytes32 _requestId, uint256 _seed) internal view returns (IOracle.Response memory) {
bytes32 responseId = _ghost_activeResponses[_requestId][_seed % _ghost_activeResponses[_requestId].length];
return _ghost_responseData[responseId];
}

Expand Down
5 changes: 0 additions & 5 deletions test/invariants/handlers/HandlerArbitrable.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ pragma solidity 0.8.26;
import {BaseHandler} from './BaseHandler.t.sol';

contract HandlerArbitrable is BaseHandler {
function handleValidateArbitrator(uint256 _actorSeed) external {
address caller = _pickActor(_actorSeed);
arbitrable.validateArbitrator(caller);
}

function handleSetArbitrator(uint256 _actorSeed) external {
address newArbitrator = _pickActor(_actorSeed);
arbitrable.setArbitrator(newArbitrator);
Expand Down
6 changes: 2 additions & 4 deletions test/invariants/handlers/HandlerBondEscalationModule.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ contract HandlerBondEscalationModule is BaseHandler {
IOracle.Dispute memory dispute = _getRandomDispute(requestId, _disputeIndex);
if (dispute.requestId == bytes32(0)) return;

if (_ghost_disputeStatuses[keccak256(abi.encode(dispute))] != IOracle.DisputeStatus.Escalated) return;
if (oracle.disputeStatus(keccak256(abi.encode(dispute))) != IOracle.DisputeStatus.Escalated) return;

address pledger = _pickActor(_actorSeed);
bondEscalationModule.pledgeForDispute(_ghost_requestData[requestId], dispute);
Expand All @@ -28,7 +28,7 @@ contract HandlerBondEscalationModule is BaseHandler {
IOracle.Dispute memory dispute = _getRandomDispute(requestId, _disputeIndex);
if (dispute.requestId == bytes32(0)) return;

if (_ghost_disputeStatuses[keccak256(abi.encode(dispute))] != IOracle.DisputeStatus.Escalated) return;
if (oracle.disputeStatus(keccak256(abi.encode(dispute))) != IOracle.DisputeStatus.Escalated) return;

address pledger = _pickActor(_actorSeed);
bondEscalationModule.pledgeAgainstDispute(_ghost_requestData[requestId], dispute);
Expand All @@ -53,7 +53,5 @@ contract HandlerBondEscalationModule is BaseHandler {
// Clear dispute pledges as they're now settled
delete _ghost_pledgesFor[dispute.disputer][disputeId];
delete _ghost_pledgesAgainst[dispute.disputer][disputeId];
// Update dispute status
_ghost_disputeStatuses[disputeId] = IOracle.DisputeStatus.NoResolution;
}
}
2 changes: 1 addition & 1 deletion test/invariants/handlers/HandlerBondedResponseModule.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ contract HandlerBondedResponseModule is BaseHandler {
bytes32 requestId = _getRandomRequest(_requestSeed);
if (requestId == bytes32(0)) return;

IOracle.Response memory response = _getRandomActiveResponse(requestId);
IOracle.Response memory response = _getRandomActiveResponse(requestId, _requestSeed);
if (response.requestId == bytes32(0)) return;

bondedResponseModule.releaseUnutilizedResponse(_ghost_requestData[requestId], response);
Expand Down
2 changes: 0 additions & 2 deletions test/invariants/handlers/HandlerCouncilArbitrator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ contract HandlerCouncilArbitrator is BaseHandler {
);

councilArbitrator.arbitrateDispute(disputeId, status);
// Update ghost variables
_ghost_disputeStatuses[disputeId] = status;

// If dispute lost, potentially update request finalization state
if (status == IOracle.DisputeStatus.Lost) {
Expand Down
42 changes: 6 additions & 36 deletions test/invariants/handlers/HandlerOracle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ contract HandlerOracle is BaseHandler {
if (requestId == bytes32(0) || !_ghost_validRequests[requestId]) {
return bytes32(0);
}
if (_ghost_activeResponses[requestId] != bytes32(0)) return bytes32(0);

address proposer = _pickActor(_actorSeed);
_blockNumber = _boundBlockNumber(_blockNumber);
Expand All @@ -32,7 +31,7 @@ contract HandlerOracle is BaseHandler {
bytes32 responseId = oracle.proposeResponse(request, response);

// Track response
_ghost_activeResponses[requestId] = responseId;
_ghost_activeResponses[requestId].push(responseId);
_ghost_responseData[responseId] = response;

emit ResponseProposed(requestId, responseId);
Expand All @@ -46,8 +45,8 @@ contract HandlerOracle is BaseHandler {
return bytes32(0);
}

bytes32 responseId = _ghost_activeResponses[requestId];
if (responseId == bytes32(0)) return bytes32(0);
if (_ghost_activeResponses[requestId].length == 0) return (bytes32(0));
bytes32 responseId = _ghost_activeResponses[requestId][0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't _getRandomActiveResponse() be used in these situations (seen in handleDisputeResponseOracle() and handleFinalize()) so to fuzz _ghost_activeResponses?


IOracle.Response memory response = _ghost_responseData[responseId];
if (_ghost_finalizedResponses[responseId]) return bytes32(0);
Expand All @@ -64,7 +63,6 @@ contract HandlerOracle is BaseHandler {
_ghost_disputes[requestId].push(disputeId);
_ghost_disputeData[disputeId] = dispute;
_ghost_bonds[disputer][requestId] = bond;
_ghost_disputeStatuses[disputeId] = IOracle.DisputeStatus.Escalated;

emit DisputeCreated(requestId, responseId, disputeId);

Expand All @@ -78,7 +76,7 @@ contract HandlerOracle is BaseHandler {
IOracle.Dispute memory dispute = _getRandomDispute(requestId, _disputeIndex);
if (dispute.requestId == bytes32(0)) return;

if (_ghost_disputeStatuses[keccak256(abi.encode(dispute))] != IOracle.DisputeStatus.Escalated) return;
if (oracle.disputeStatus(keccak256(abi.encode(dispute))) != IOracle.DisputeStatus.Escalated) return;

IOracle.Response memory response = _ghost_responseData[dispute.responseId];
oracle.escalateDispute(_ghost_requestData[requestId], response, dispute);
Expand All @@ -95,54 +93,26 @@ contract HandlerOracle is BaseHandler {
oracle.resolveDispute(_ghost_requestData[requestId], response, dispute);
}

function handleUpdateDisputeStatus(uint256 _requestSeed, uint256 _disputeIndex, uint256 _statusSeed) external {
bytes32 requestId = _getRandomRequest(_requestSeed);
if (requestId == bytes32(0)) return;

IOracle.Dispute memory dispute = _getRandomDispute(requestId, _disputeIndex);
if (dispute.requestId == bytes32(0)) return;

// Generate a valid dispute status (NoResolution, Won, Lost)
IOracle.DisputeStatus status = IOracle.DisputeStatus(
bound(_statusSeed, uint8(IOracle.DisputeStatus.NoResolution), uint8(IOracle.DisputeStatus.Lost))
);

IOracle.Response memory response = _ghost_responseData[dispute.responseId];
oracle.updateDisputeStatus(_ghost_requestData[requestId], response, dispute, status);

bytes32 disputeId = keccak256(abi.encode(dispute));
_ghost_disputeStatuses[disputeId] = status;

// If dispute resolved with Lost status, mark response as finalized
if (status == IOracle.DisputeStatus.Lost) {
_ghost_finalizedResponses[response.requestId] = true;
}

emit DisputeResolved(disputeId, status);
}

function handleFinalize(uint256 _requestSeed) external {
bytes32 requestId = _getRandomRequest(_requestSeed);
if (requestId == bytes32(0)) return;

bytes32 responseId = _ghost_activeResponses[requestId];
if (responseId == bytes32(0)) return;
if (_ghost_activeResponses[requestId].length == 0) return;
bytes32 responseId = _ghost_activeResponses[requestId][0];

IOracle.Response memory response = _ghost_responseData[responseId];
oracle.finalize(_ghost_requestData[requestId], response);

// Update ghost variables
_ghost_finalizedResponses[responseId] = true;
delete _ghost_activeResponses[requestId]; // Clear active response
delete _ghost_disputeStatuses[responseId]; // Clear any dispute status
_ghost_validRequests[requestId] = false; // Mark request as no longer valid/active

// If there were any disputes, clear their state
bytes32[] storage disputes = _ghost_disputes[requestId];
for (uint256 i = 0; i < disputes.length; i++) {
bytes32 disputeId = disputes[i];
delete _ghost_disputeData[disputeId];
delete _ghost_disputeStatuses[disputeId];
}
delete _ghost_disputes[requestId];

Expand Down
8 changes: 4 additions & 4 deletions test/invariants/properties/PropertyEbo.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ contract PropertyEbo is HandlerParent {

/// @custom:property-id 1
/// @custom:property Requester can always create a request as long as the same chainId/epoch isn't requested yet
function property_canAlwaysCreateRequest(uint256 _epoch, uint256 _chainId) external {
_epoch = _boundEpoch(_epoch);
string memory _chainId = _generateChainId(_chainId);
}
// function property_canAlwaysCreateRequest(uint256 _epoch, uint256 _chainId) external {
// _epoch = _boundEpoch(_epoch);
// string memory _chainId = _generateChainId(_chainId);
// }
}
Loading