Skip to content

Commit

Permalink
Merge branch 'test/property-ebo-request-creator' into test/prop-disputer
Browse files Browse the repository at this point in the history
  • Loading branch information
simon-something authored Nov 27, 2024
2 parents 56aa7bd + bc114a9 commit 9d65334
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 91 deletions.
4 changes: 2 additions & 2 deletions test/invariants/handlers/BaseHandler.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ contract BaseHandler is Setup, Actors {
mapping(uint256 _epoch => mapping(string _chainId => bytes32[] _requestIds)) internal _ghost_requestsPerEpochChainId;

// Track the chainId->chain (reverse the hash)
mapping(bytes32 _hash => string _chain) internal ghost_chainIdToChain;
mapping(bytes32 _hash => string _chain) internal _ghost_chainIdToChain;

// Track request details
mapping(bytes32 _requestId => IOracle.Request _data) internal _ghost_requestData;
Expand Down Expand Up @@ -40,7 +40,7 @@ contract BaseHandler is Setup, Actors {
bytes32[] memory chainIds = eboRequestCreator.getAllowedChainIds();
if (chainIds.length == 0) return '';

return string(ghost_chainIdToChain[chainIds[_seed % chainIds.length]]);
return _ghost_chainIdToChain[chainIds[_seed % chainIds.length]];
}

function _getRandomRequestId(uint256 _seed) internal view returns (bytes32) {
Expand Down
92 changes: 11 additions & 81 deletions test/invariants/handlers/HandlerEBORequestCreator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ contract HandlerEBORequestCreator is BaseHandler {
constructor() {
// Initialize the ghost mapping, allowing to reverse lookup the chain
for (uint256 i; i < INITIAL_CHAINS.length; i++) {
ghost_chainIdToChain[keccak256(abi.encodePacked(INITIAL_CHAINS[i]))] = INITIAL_CHAINS[i];
_ghost_chainIdToChain[keccak256(abi.encodePacked(INITIAL_CHAINS[i]))] = INITIAL_CHAINS[i];
}
}

function handleCreateRequest(uint256 _epoch, uint256 _chainIdSeed) external {
_epoch = bound(_epoch, START_EPOCH, block.timestamp);

string memory chainId = _getRandomChainId(_chainIdSeed);
if (bytes(chainId).length == 0) return;

Expand Down Expand Up @@ -56,87 +58,15 @@ contract HandlerEBORequestCreator is BaseHandler {
emit RequestCreated(requestId, _epoch, chainId);
}

function handleAddChain(string memory chainId) external {
eboRequestCreator.addChain(chainId);
ghost_chainIdToChain[keccak256(abi.encodePacked(chainId))] = chainId;
}

function handleRemoveChain(uint256 _chainIdSeed) external {
string memory chainId = _getRandomChainId(_chainIdSeed);
eboRequestCreator.removeChain(chainId);
}

function handleSetRequestModuleData() external {
// Deploy new request module
eboRequestModule = new EBORequestModule(oracle, eboRequestCreator, arbitrable);

// Set up request module parameters
IEBORequestModule.RequestParameters memory requestParams = IEBORequestModule.RequestParameters({
epoch: START_EPOCH,
chainId: 'mainnet',
accountingExtension: IAccountingExtension(address(horizonAccountingExtension)),
paymentAmount: PAYMENT_AMOUNT
});

eboRequestCreator.setRequestModuleData(address(eboRequestModule), requestParams);
}

function handleSetResponseModuleData() external {
// Deploy new response module
bondedResponseModule = new BondedResponseModule(oracle);

// Set up response module parameters
IBondedResponseModule.RequestParameters memory responseParams = IBondedResponseModule.RequestParameters({
accountingExtension: IAccountingExtension(address(horizonAccountingExtension)),
bondToken: GRT,
bondSize: RESPONSE_BOND_SIZE,
deadline: RESPONSE_DEADLINE,
disputeWindow: RESPONSE_DISPUTE_WINDOW
});

eboRequestCreator.setResponseModuleData(address(bondedResponseModule), responseParams);
}

function handleSetDisputeModuleData() external {
// Deploy new dispute module
bondEscalationModule = new BondEscalationModule(oracle);

// Set up dispute module parameters
IBondEscalationModule.RequestParameters memory disputeParams = IBondEscalationModule.RequestParameters({
accountingExtension: IBondEscalationAccounting(address(horizonAccountingExtension)),
bondToken: GRT,
bondSize: DISPUTE_BOND_SIZE,
maxNumberOfEscalations: MAX_NB_ESCALATION,
bondEscalationDeadline: DISPUTE_DEADLINE,
tyingBuffer: TYING_BUFFER,
disputeWindow: DISPUTE_DISPUTE_WINDOW
});

eboRequestCreator.setDisputeModuleData(address(bondEscalationModule), disputeParams);
}

function handleSetResolutionModuleData() external {
// Deploy new resolution module
arbitratorModule = new ArbitratorModule(oracle);
function handleAddChain(string memory _chainId) external {
eboRequestCreator.addChain(_chainId);

// Set up resolution module parameters
IArbitratorModule.RequestParameters memory resolutionParams =
IArbitratorModule.RequestParameters({arbitrator: address(councilArbitrator)});

eboRequestCreator.setResolutionModuleData(address(arbitratorModule), resolutionParams);
}

function handleSetFinalityModuleData() external {
// Deploy new finality module
eboFinalityModule = new EBOFinalityModule(oracle, eboRequestCreator, arbitrable);

eboRequestCreator.setFinalityModuleData(address(eboFinalityModule));
// Track the chain
_ghost_chainIdToChain[keccak256(abi.encodePacked(_chainId))] = _chainId;
}

function handleSetEpochManager() external {
// Deploy new epoch manager
epochManager = IEpochManager(address(new MockEpochManager()));

eboRequestCreator.setEpochManager(epochManager);
}
// function handleRemoveChain(uint256 _chainIdSeed) external {
// string memory chainId = _getRandomChainId(_chainIdSeed);
// eboRequestCreator.removeChain(chainId);
// }
}
66 changes: 66 additions & 0 deletions test/invariants/helpers/Utils.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,28 @@ contract Utils {
}
}

function assertEq(bytes32 a, bytes32 b) internal {
assertEq(a, b, 'assertEq: a != b');
}

function assertEq(bytes32 a, bytes32 b, string memory reason) internal {
if (a != b) {
emit TestFailure(reason);
assert(false);
}
}

function assertNotEq(bytes32 a, bytes32 b) internal {
assertNotEq(a, b, 'assertNotEq: a == b');
}

function assertNotEq(bytes32 a, bytes32 b, string memory reason) internal {
if (a == b) {
emit TestFailure(reason);
assert(false);
}
}

function assertEq(bytes memory a, bytes memory b) internal {
assertEq(a, b, 'assertEq: a != b');
}
Expand Down Expand Up @@ -144,6 +166,50 @@ contract Utils {
}
}

function assertLt(uint256 a, uint256 b) internal {
assertLt(a, b, 'assertLt: a >= b');
}

function assertLt(uint256 a, uint256 b, string memory reason) internal {
if (a >= b) {
emit TestFailure(reason);
assert(false);
}
}

function assertLte(uint256 a, uint256 b) internal {
assertLte(a, b, 'assertLte: a > b');
}

function assertLte(uint256 a, uint256 b, string memory reason) internal {
if (a > b) {
emit TestFailure(reason);
assert(false);
}
}

function assertGt(uint256 a, uint256 b) internal {
assertGt(a, b, 'assertGt: a <= b');
}

function assertGt(uint256 a, uint256 b, string memory reason) internal {
if (a <= b) {
emit TestFailure(reason);
assert(false);
}
}

function assertGte(uint256 a, uint256 b) internal {
assertGte(a, b, 'assertGte: a < b');
}

function assertGte(uint256 a, uint256 b, string memory reason) internal {
if (a < b) {
emit TestFailure(reason);
assert(false);
}
}

function assertTrue(bool a) internal {
assertTrue(a, 'assertTrue: !a');
}
Expand Down
45 changes: 37 additions & 8 deletions test/invariants/properties/PropertyRequester.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,34 @@ contract PropertyRequester is HandlerParent {
constructor() {}

/// @custom:property-id 1
/// @custom:property Requester can always create a request as long as the same chainId/epoch isn't requested yet
/// @custom:property Requester can always create a request as long as the same chainId/epoch isn't already active
/// or finalized with response
function property_canAlwaysCreateRequest(uint256 _epoch, uint256 _chainIdSeed) external {
string memory chainId = _getRandomChainId(_chainIdSeed);
_epoch = bound(_epoch, START_EPOCH, block.timestamp);

string memory chainId = _getRandomChainId(_chainIdSeed);
if (bytes(chainId).length == 0) return;

// Prevent duplicate chainId for same epoch
if (_ghost_requestsPerEpochChainId[_epoch][chainId].length > 0) return;
uint256 requestsPerEpochChainId = _ghost_requestsPerEpochChainId[_epoch][chainId].length;
bytes32 requestId;
uint256 activeRequests;
bool isFinalizedWithResponse;

// Create request via EBORequestCreator
try eboRequestCreator.createRequest(_epoch, chainId) {
// Check if there are active requests and a request finalized with response
for (uint256 i; i < requestsPerEpochChainId; ++i) {
requestId = _ghost_requestsPerEpochChainId[_epoch][chainId][i];
if (oracle.finalizedAt(requestId) == 0) ++activeRequests;
if (oracle.finalizedResponseId(requestId) != 0) {
isFinalizedWithResponse = true;
break;
}
}

assertFalse(isFinalizedWithResponse, 'prop-1: same chainId/epoch request already finalized with response');
assertEq(activeRequests, 0, 'prop-1: same chainId/epoch active request');

// Get current request data
IOracle.Request memory requestData = eboRequestCreator.getRequestData();

Expand All @@ -42,7 +58,17 @@ contract PropertyRequester is HandlerParent {

emit RequestCreated(requestId, _epoch, chainId);
} catch {
assertTrue(false, 'prop-1: create request reverted');
// Check if there are active requests and a request finalized with response
for (uint256 i; i < requestsPerEpochChainId; ++i) {
requestId = _ghost_requestsPerEpochChainId[_epoch][chainId][i];
if (oracle.finalizedAt(requestId) == 0) ++activeRequests;
if (oracle.finalizedResponseId(requestId) != 0) {
isFinalizedWithResponse = true;
break;
}
}

assertTrue(isFinalizedWithResponse || activeRequests > 0, 'prop-1: create request reverted');
}
}

Expand All @@ -57,11 +83,14 @@ contract PropertyRequester is HandlerParent {
abi.decode(requestData.requestModuleData, (IEBORequestModule.RequestParameters));

uint256 requestsPerEpochChainId = _ghost_requestsPerEpochChainId[requestParams.epoch][requestParams.chainId].length;
if (requestsPerEpochChainId < 2) return;
uint256 activeRequests;

for (uint256 i; i < requestsPerEpochChainId - 1; ++i) {
// Check if there are active requests
for (uint256 i; i < requestsPerEpochChainId; ++i) {
requestId = _ghost_requestsPerEpochChainId[requestParams.epoch][requestParams.chainId][i];
assertNotEq(oracle.finalizedAt(requestId), 0, 'prop-2: same chainId/epoch active request');
if (oracle.finalizedAt(requestId) == 0) ++activeRequests;
}

assertLte(activeRequests, 1, 'prop-2: same chainId/epoch active requests');
}
}

0 comments on commit 9d65334

Please sign in to comment.