From 004c3699b944113c686a193729b480cd87f0bf63 Mon Sep 17 00:00:00 2001 From: Gas <86567384+gas1cent@users.noreply.github.com> Date: Thu, 19 Oct 2023 18:24:36 +0400 Subject: [PATCH] test: bond escalation integration tests (#11) * feat: update prophet package * refactor: remove an unused mapping * refactor: rename an event * feat: e2e tests and fixed WIP * feat: update the oracle address * test: fix the caller * refactor: shorten event names * test: bond escalation integration tests WIP * fix: typos * fix: remove obsolete comment * test: remove unused mocks * style: remove commented out code * refactor: clarify the meaning of an error * test: bond escalation integration tests WIP * feat: allow to set the answer in the mock arbitrator * test: fixing `test_proposerLoses` * test: fixing `test_bondEscalationTied` * test: fixing `test_externalParties` * feat: add console to `IntegrationBase` * fix: release disputer's bond * fix: compilation warning * fix: comments * fix: fuzzing error --- package.json | 2 +- .../extensions/BondEscalationAccounting.sol | 1 - .../modules/dispute/BondEscalationModule.sol | 117 ++--- .../modules/dispute/IBondEscalationModule.sol | 10 +- solidity/scripts/Deploy.sol | 2 +- .../test/integration/BondEscalation.t.sol | 459 ++++++++++++++++++ solidity/test/integration/IntegrationBase.sol | 7 +- solidity/test/mocks/MockArbitrator.sol | 10 +- .../dispute/BondEscalationModule.t.sol | 81 +--- solidity/test/utils/Helpers.sol | 2 +- yarn.lock | 8 +- 11 files changed, 570 insertions(+), 129 deletions(-) create mode 100644 solidity/test/integration/BondEscalation.t.sol diff --git a/package.json b/package.json index 4a390cc0..5869cbc7 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core-contracts": "0.0.0-bb56cdd7", + "@defi-wonderland/prophet-core-contracts": "0.0.0-d6780d39", "@defi-wonderland/solidity-utils": "0.0.0-3e9c8e8b", "@openzeppelin/contracts": "^4.9.3", "ds-test": "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0", diff --git a/solidity/contracts/extensions/BondEscalationAccounting.sol b/solidity/contracts/extensions/BondEscalationAccounting.sol index bf6177a1..3efe1e2a 100644 --- a/solidity/contracts/extensions/BondEscalationAccounting.sol +++ b/solidity/contracts/extensions/BondEscalationAccounting.sol @@ -24,7 +24,6 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount /// @inheritdoc IBondEscalationAccounting function pledge( address _pledger, - // TODO: leaving this request id here for the allowed module check until the audit fix is defined bytes32 _requestId, bytes32 _disputeId, IERC20 _token, diff --git a/solidity/contracts/modules/dispute/BondEscalationModule.sol b/solidity/contracts/modules/dispute/BondEscalationModule.sol index 2e51138f..e0785b51 100644 --- a/solidity/contracts/modules/dispute/BondEscalationModule.sol +++ b/solidity/contracts/modules/dispute/BondEscalationModule.sol @@ -20,11 +20,6 @@ contract BondEscalationModule is Module, IBondEscalationModule { */ mapping(bytes32 _requestId => BondEscalation) internal _escalations; - /** - * @notice Mapping storing all dispute IDs to request IDs. - */ - mapping(bytes32 _disputeId => bytes32 _requestId) internal _disputeToRequest; - constructor(IOracle _oracle) Module(_oracle) {} /// @inheritdoc IModule @@ -75,20 +70,22 @@ contract BondEscalationModule is Module, IBondEscalationModule { address _proposer ) external onlyOracle returns (IOracle.Dispute memory _dispute) { RequestParameters memory _params = decodeRequestData(_requestId); - IOracle.Response memory _response = ORACLE.getResponse(_responseId); + if (block.timestamp > _response.createdAt + _params.disputeWindow) { revert BondEscalationModule_DisputeWindowOver(); } BondEscalation storage _escalation = _escalations[_requestId]; - if (block.timestamp > _params.bondEscalationDeadline) revert BondEscalationModule_BondEscalationOver(); - + // Only the first dispute of a request should go through the bond escalation + // Consecutive disputes should be handled by the resolution module if (_escalation.status == BondEscalationStatus.None) { - _escalation.status = BondEscalationStatus.Active; + if (block.timestamp > _params.bondEscalationDeadline) revert BondEscalationModule_BondEscalationOver(); + // Note: this imitates the way _disputeId is calculated on the Oracle, it must always match bytes32 _disputeId = keccak256(abi.encodePacked(_disputer, _requestId, _responseId)); + _escalation.status = BondEscalationStatus.Active; _escalation.disputeId = _disputeId; emit BondEscalationStatusUpdated(_requestId, _disputeId, BondEscalationStatus.Active); } @@ -126,35 +123,58 @@ contract BondEscalationModule is Module, IBondEscalationModule { _amount: _params.bondSize }); - _params.accountingExtension.release({ - _bonder: _won ? _dispute.disputer : _dispute.proposer, - _requestId: _dispute.requestId, - _token: _params.bondToken, - _amount: _params.bondSize - }); + if (_won) { + _params.accountingExtension.release({ + _requestId: _dispute.requestId, + _bonder: _dispute.disputer, + _token: _params.bondToken, + _amount: _params.bondSize + }); + } BondEscalation storage _escalation = _escalations[_dispute.requestId]; - if (_disputeId == _escalation.disputeId && _escalation.status == BondEscalationStatus.Escalated) { - if (_escalation.amountOfPledgesAgainstDispute == 0) { - return; + if (_disputeId == _escalation.disputeId) { + // The dispute has been escalated to the Resolution module + if (_escalation.status == BondEscalationStatus.Escalated) { + if (_escalation.amountOfPledgesAgainstDispute == 0) { + return; + } + + BondEscalationStatus _newStatus = _won ? BondEscalationStatus.DisputerWon : BondEscalationStatus.DisputerLost; + _escalation.status = _newStatus; + + emit BondEscalationStatusUpdated(_dispute.requestId, _disputeId, _newStatus); + + _params.accountingExtension.onSettleBondEscalation({ + _requestId: _dispute.requestId, + _disputeId: _disputeId, + _forVotesWon: _won, + _token: _params.bondToken, + _amountPerPledger: _params.bondSize << 1, + _winningPledgersLength: _won ? _escalation.amountOfPledgesForDispute : _escalation.amountOfPledgesAgainstDispute + }); + } else { + // The status has changed to Won or Lost + uint256 _pledgesForDispute = _escalation.amountOfPledgesForDispute; + uint256 _pledgesAgainstDispute = _escalation.amountOfPledgesAgainstDispute; + bool _disputersWon = _pledgesForDispute > _pledgesAgainstDispute; + + uint256 _amountToPay = _disputersWon + ? _params.bondSize + FixedPointMathLib.mulDivDown(_pledgesAgainstDispute, _params.bondSize, _pledgesForDispute) + : _params.bondSize + FixedPointMathLib.mulDivDown(_pledgesForDispute, _params.bondSize, _pledgesAgainstDispute); + + _params.accountingExtension.onSettleBondEscalation({ + _requestId: _dispute.requestId, + _disputeId: _escalation.disputeId, + _forVotesWon: _disputersWon, + _token: _params.bondToken, + _amountPerPledger: _amountToPay, + _winningPledgersLength: _disputersWon ? _pledgesForDispute : _pledgesAgainstDispute + }); } - - BondEscalationStatus _newStatus = _won ? BondEscalationStatus.DisputerWon : BondEscalationStatus.DisputerLost; - - _escalation.status = _newStatus; - - emit BondEscalationStatusUpdated(_dispute.requestId, _disputeId, _newStatus); - - _params.accountingExtension.onSettleBondEscalation({ - _requestId: _dispute.requestId, - _disputeId: _disputeId, - _forVotesWon: _won, - _token: _params.bondToken, - _amountPerPledger: _params.bondSize << 1, - _winningPledgersLength: _won ? _escalation.amountOfPledgesForDispute : _escalation.amountOfPledgesAgainstDispute - }); } + emit DisputeStatusChanged({ _requestId: _dispute.requestId, _responseId: _dispute.responseId, @@ -182,7 +202,7 @@ contract BondEscalationModule is Module, IBondEscalationModule { _amount: _params.bondSize }); - emit PledgedInFavorOfDisputer(_disputeId, msg.sender, _params.bondSize); + emit PledgedForDispute(_disputeId, msg.sender, _params.bondSize); } /// @inheritdoc IBondEscalationModule @@ -199,7 +219,7 @@ contract BondEscalationModule is Module, IBondEscalationModule { _amount: _params.bondSize }); - emit PledgedInFavorOfProposer(_disputeId, msg.sender, _params.bondSize); + emit PledgedAgainstDispute(_disputeId, msg.sender, _params.bondSize); } /// @inheritdoc IBondEscalationModule @@ -223,26 +243,13 @@ contract BondEscalationModule is Module, IBondEscalationModule { } bool _disputersWon = _pledgesForDispute > _pledgesAgainstDispute; + _escalation.status = _disputersWon ? BondEscalationStatus.DisputerWon : BondEscalationStatus.DisputerLost; - uint256 _amountToPay = _disputersWon - ? _params.bondSize + FixedPointMathLib.mulDivDown(_pledgesAgainstDispute, _params.bondSize, _pledgesForDispute) - : _params.bondSize + FixedPointMathLib.mulDivDown(_pledgesForDispute, _params.bondSize, _pledgesAgainstDispute); - - BondEscalationStatus _newStatus = - _disputersWon ? BondEscalationStatus.DisputerWon : BondEscalationStatus.DisputerLost; - - _escalation.status = _newStatus; + emit BondEscalationStatusUpdated(_requestId, _escalation.disputeId, _escalation.status); - emit BondEscalationStatusUpdated(_requestId, _escalation.disputeId, _newStatus); - - _params.accountingExtension.onSettleBondEscalation({ - _requestId: _requestId, - _disputeId: _escalation.disputeId, - _forVotesWon: _disputersWon, - _token: _params.bondToken, - _amountPerPledger: _amountToPay, - _winningPledgersLength: _disputersWon ? _pledgesForDispute : _pledgesAgainstDispute - }); + ORACLE.updateDisputeStatus( + _escalation.disputeId, _disputersWon ? IOracle.DisputeStatus.Won : IOracle.DisputeStatus.Lost + ); } /** @@ -262,7 +269,7 @@ contract BondEscalationModule is Module, IBondEscalationModule { BondEscalation memory _escalation = _escalations[_requestId]; if (_disputeId != _escalation.disputeId) { - revert BondEscalationModule_DisputeNotEscalated(); + revert BondEscalationModule_InvalidDispute(); } _params = decodeRequestData(_requestId); @@ -287,7 +294,7 @@ contract BondEscalationModule is Module, IBondEscalationModule { } if (block.timestamp > _params.bondEscalationDeadline && _numPledgersForDispute == _numPledgersAgainstDispute) { - revert BondEscalationModule_CanOnlyTieDuringTyingBuffer(); + revert BondEscalationModule_CannotBreakTieDuringTyingBuffer(); } } diff --git a/solidity/interfaces/modules/dispute/IBondEscalationModule.sol b/solidity/interfaces/modules/dispute/IBondEscalationModule.sol index 2860d3cd..79800363 100644 --- a/solidity/interfaces/modules/dispute/IBondEscalationModule.sol +++ b/solidity/interfaces/modules/dispute/IBondEscalationModule.sol @@ -24,7 +24,7 @@ interface IBondEscalationModule is IDisputeModule { * @param _pledger The address of the pledger. * @param _amount The amount pledged. */ - event PledgedInFavorOfDisputer(bytes32 indexed _disputeId, address indexed _pledger, uint256 indexed _amount); + event PledgedForDispute(bytes32 indexed _disputeId, address indexed _pledger, uint256 indexed _amount); /** * @notice A pledge has been made against a dispute. @@ -33,7 +33,7 @@ interface IBondEscalationModule is IDisputeModule { * @param _pledger The address of the pledger. * @param _amount The amount pledged. */ - event PledgedInFavorOfProposer(bytes32 indexed _disputeId, address indexed _pledger, uint256 indexed _amount); + event PledgedAgainstDispute(bytes32 indexed _disputeId, address indexed _pledger, uint256 indexed _amount); /** * @notice The status of the bond escalation mechanism has been updated. @@ -57,7 +57,7 @@ interface IBondEscalationModule is IDisputeModule { /** * @notice Thrown when trying to pledge for a dispute that is not going through the bond escalation mechanism. */ - error BondEscalationModule_DisputeNotEscalated(); + error BondEscalationModule_InvalidDispute(); /** * @notice Thrown when the number of escalation pledges of a given dispute has reached its maximum. */ @@ -71,9 +71,9 @@ interface IBondEscalationModule is IDisputeModule { */ error BondEscalationModule_ShouldBeEscalated(); /** - * @notice Thrown when trying to tie outside of the tying buffer. + * @notice Thrown when trying to break a tie after the tying buffer has started. */ - error BondEscalationModule_CanOnlyTieDuringTyingBuffer(); + error BondEscalationModule_CannotBreakTieDuringTyingBuffer(); /** * @notice Thrown when the max number of escalations or the bond size is set to 0. */ diff --git a/solidity/scripts/Deploy.sol b/solidity/scripts/Deploy.sol index e9d58688..15b23cfa 100644 --- a/solidity/scripts/Deploy.sol +++ b/solidity/scripts/Deploy.sol @@ -28,7 +28,7 @@ import {BondEscalationAccounting} from '../contracts/extensions/BondEscalationAc // solhint-disable no-console contract Deploy is Script { - IOracle oracle = IOracle(0x19cEcCd6942ad38562Ee10bAfd44776ceB67e923); + IOracle oracle = IOracle(0xe40DED509A3806Eed8065b478BB681953bD9B554); ArbitratorModule arbitratorModule; BondedDisputeModule bondedDisputeModule; diff --git a/solidity/test/integration/BondEscalation.t.sol b/solidity/test/integration/BondEscalation.t.sol new file mode 100644 index 00000000..cb3cb8e8 --- /dev/null +++ b/solidity/test/integration/BondEscalation.t.sol @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import './IntegrationBase.sol'; + +contract Integration_BondEscalation is IntegrationBase { + bytes internal _responseData = abi.encode('response'); + bytes32 internal _requestId; + bytes32 internal _responseId; + bytes32 internal _disputeId; + uint256 internal _bondEscalationDeadline; + uint256 internal _tyingBuffer = 1 days; + uint256 internal _disputeWindow = 3 days; + // TODO: There is a bug in the accounting, try with pledge size = 1 ether + // uint256 internal _pledgeSize = 5 ether; + uint256 internal _pledgeSize = _expectedBondSize; + + function setUp() public override { + super.setUp(); + _expectedDeadline = block.timestamp + 10 days; + _bondEscalationDeadline = block.timestamp + 5 days; + + IOracle.NewRequest memory _request = IOracle.NewRequest({ + requestModuleData: abi.encode( + IHttpRequestModule.RequestParameters({ + url: _expectedUrl, + method: _expectedMethod, + body: _expectedBody, + accountingExtension: _bondEscalationAccounting, + paymentToken: usdc, + paymentAmount: _expectedReward + }) + ), + responseModuleData: abi.encode( + IBondedResponseModule.RequestParameters({ + accountingExtension: _bondEscalationAccounting, + bondToken: usdc, + bondSize: _expectedBondSize, + deadline: _expectedDeadline, + disputeWindow: _baseDisputeWindow + }) + ), + disputeModuleData: abi.encode( + IBondEscalationModule.RequestParameters({ + accountingExtension: _bondEscalationAccounting, + bondToken: usdc, + bondSize: _pledgeSize, + maxNumberOfEscalations: 10, + bondEscalationDeadline: _bondEscalationDeadline, + tyingBuffer: _tyingBuffer, + disputeWindow: _disputeWindow + }) + ), + resolutionModuleData: abi.encode(_mockArbitrator), + finalityModuleData: abi.encode( + ICallbackModule.RequestParameters({target: address(_mockCallback), data: abi.encode(_expectedCallbackValue)}) + ), + requestModule: _requestModule, + responseModule: _responseModule, + disputeModule: _bondEscalationModule, + resolutionModule: _arbitratorModule, + finalityModule: IFinalityModule(_callbackModule), + ipfsHash: _ipfsHash + }); + + // Requester creates a request + _forBondDepositERC20(_bondEscalationAccounting, requester, usdc, _expectedReward, _expectedReward); + vm.startPrank(requester); + _bondEscalationAccounting.approveModule(address(_requestModule)); + _requestId = oracle.createRequest(_request); + vm.stopPrank(); + + // Proposer proposes a response + _forBondDepositERC20(_bondEscalationAccounting, proposer, usdc, _expectedBondSize, _expectedBondSize); + vm.startPrank(proposer); + _bondEscalationAccounting.approveModule(address(_responseModule)); + _responseId = oracle.proposeResponse(_requestId, _responseData); + vm.stopPrank(); + + // Disputer disputes the response + _forBondDepositERC20(_bondEscalationAccounting, disputer, usdc, _expectedBondSize, _expectedBondSize); + vm.startPrank(disputer); + _bondEscalationAccounting.approveModule(address(_bondEscalationModule)); + _disputeId = oracle.disputeResponse(_requestId, _responseId); + vm.stopPrank(); + } + + function test_proposerWins() public { + // Step 1: Proposer pledges against the dispute + _forBondDepositERC20(_bondEscalationAccounting, proposer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(proposer); + _bondEscalationAccounting.approveModule(address(_bondEscalationModule)); + _bondEscalationModule.pledgeAgainstDispute(_disputeId); + vm.stopPrank(); + + // Step 2: Disputer doubles down + _forBondDepositERC20(_bondEscalationAccounting, disputer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(disputer); + _bondEscalationModule.pledgeForDispute(_disputeId); + vm.stopPrank(); + + // Step 3: Proposer doubles down + _forBondDepositERC20(_bondEscalationAccounting, proposer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(proposer); + _bondEscalationModule.pledgeAgainstDispute(_disputeId); + vm.stopPrank(); + + // Step 4: Disputer runs out of capital + // Step 5: External parties see that Disputer's dispute was wrong so they don't join to escalate + // Step 6: Proposer response's is deemed correct and final once the bond escalation window is over + vm.warp(_expectedDeadline + _tyingBuffer + 1); + _bondEscalationModule.settleBondEscalation(_requestId); + + IOracle.Dispute memory _dispute = oracle.getDispute(_disputeId); + assertEq(uint256(_dispute.status), uint256(IOracle.DisputeStatus.Lost), 'Mismatch: Dispute status'); + + // Step 7: Participants claim the rewards + // Test: The requester has not participated in pledging, claiming shouldn't change his balance + _bondEscalationAccounting.claimEscalationReward(_disputeId, requester); + assertEq(_bondEscalationAccounting.balanceOf(requester, usdc), 0, 'Mismatch: Requester balance'); + + // Test: The proposer receives 2x pledging amount + disputer's bond + disputer's pledge + _bondEscalationAccounting.claimEscalationReward(_disputeId, proposer); + assertEq( + _bondEscalationAccounting.balanceOf(proposer, usdc), + _pledgeSize * 3 + _expectedBondSize, + 'Mismatch: Proposer balance' + ); + + // Test: The disputer has lost his pledge + _bondEscalationAccounting.claimEscalationReward(_disputeId, disputer); + assertEq(_bondEscalationAccounting.balanceOf(disputer, usdc), 0, 'Mismatch: Disputer balance'); + + // Step 8: Finalize request and check balances again + oracle.finalize(_requestId, _responseId); + + // Test: The requester has no balance because he has paid the proposer + assertEq(_bondEscalationAccounting.balanceOf(requester, usdc), 0, 'Mismatch: Requester balance'); + + // Test: The proposer receives the requester's reward for proposing a correct response and his bond back + assertEq( + _bondEscalationAccounting.balanceOf(proposer, usdc), + _pledgeSize * 3 + _expectedBondSize * 2 + _expectedReward, + 'Mismatch: Proposer balance' + ); + + // Test: The disputer's balance has not changed + assertEq(_bondEscalationAccounting.balanceOf(disputer, usdc), 0, 'Mismatch: Disputer balance'); + } + + function test_proposerLoses() public { + // Step 1: Proposer pledges against the dispute + _forBondDepositERC20(_bondEscalationAccounting, proposer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(proposer); + _bondEscalationAccounting.approveModule(address(_bondEscalationModule)); + _bondEscalationModule.pledgeAgainstDispute(_disputeId); + vm.stopPrank(); + + // Step 2: Disputer doubles down + _forBondDepositERC20(_bondEscalationAccounting, disputer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(disputer); + _bondEscalationModule.pledgeForDispute(_disputeId); + vm.stopPrank(); + + // Step 3: Another party joins the dispute + address _secondDisputer = makeAddr('secondDisputer'); + _forBondDepositERC20(_bondEscalationAccounting, _secondDisputer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(_secondDisputer); + _bondEscalationModule.pledgeForDispute(_disputeId); + vm.stopPrank(); + + // Step 4: Proposer runs out of capital and doesn't pledge anymore + // External parties see that Proposer's proposal was wrong so they don't join to escalate + + // Step 5: Proposer response's is deemed incorrect. The bond escalation process along with the tying buffer is terminated + vm.warp(_bondEscalationDeadline + _tyingBuffer + 1); + _bondEscalationModule.settleBondEscalation(_requestId); + + IOracle.Dispute memory _dispute = oracle.getDispute(_disputeId); + assertEq(uint256(_dispute.status), uint256(IOracle.DisputeStatus.Won), 'Mismatch: Dispute status'); + + // Step 6: Participants claim the rewards + // Test: The requester has not participated in pledging, claiming shouldn't change his balance + _bondEscalationAccounting.claimEscalationReward(_disputeId, requester); + assertEq(_bondEscalationAccounting.balanceOf(requester, usdc), 0, 'Mismatch: Requester balance'); + + // Test: The proposer has lost his pledge + _bondEscalationAccounting.claimEscalationReward(_disputeId, proposer); + assertEq(_bondEscalationAccounting.balanceOf(proposer, usdc), 0, 'Mismatch: Proposer balance'); + + // Test: The disputer has received his pledge and bond back, a half of the proposer's pledge and the proposer's bond + _bondEscalationAccounting.claimEscalationReward(_disputeId, disputer); + assertEq( + _bondEscalationAccounting.balanceOf(disputer, usdc), + _pledgeSize + _pledgeSize / 2 + _expectedBondSize * 2, + 'Mismatch: Disputer balance' + ); + + // Test: The second disputer has received his pledge back and a half of the proposer's pledge + _bondEscalationAccounting.claimEscalationReward(_disputeId, _secondDisputer); + assertEq( + _bondEscalationAccounting.balanceOf(_secondDisputer, usdc), + _pledgeSize + _pledgeSize / 2, + 'Mismatch: Second Disputer balance' + ); + + // Step 7: Other parties can now propose different answers. Another proposer proposes a new answer + address _anotherProposer = makeAddr('anotherProposer'); + _forBondDepositERC20(_bondEscalationAccounting, _anotherProposer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(_anotherProposer); + _bondEscalationAccounting.approveModule(address(_responseModule)); + _responseId = oracle.proposeResponse(_requestId, abi.encode('anotherResponse')); + vm.stopPrank(); + + // Step 8: Disputer disputes Another proposer's answer + // _forBondDepositERC20(_bondEscalationAccounting, disputer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(disputer); + _bondEscalationAccounting.approveModule(address(_bondEscalationModule)); + _disputeId = oracle.disputeResponse(_requestId, _responseId); + vm.stopPrank(); + + // Step 9: Shouldn't be able to pledge for or against the dispute due to the bond escalation deadline being over + _forBondDepositERC20(_bondEscalationAccounting, disputer, usdc, _pledgeSize, _pledgeSize); + vm.expectRevert(IBondEscalationModule.BondEscalationModule_InvalidDispute.selector); + vm.startPrank(disputer); + _bondEscalationModule.pledgeForDispute(_disputeId); + vm.stopPrank(); + + // Step 10: The dispute goes to the resolution module + oracle.escalateDispute(_disputeId); + _dispute = oracle.getDispute(_disputeId); + assertEq(uint256(_dispute.status), uint256(IOracle.DisputeStatus.Escalated), 'Mismatch: Dispute status'); + + // Step 11: Because Another proposer's answer is disputed, a third party can propose a new answer + address _thirdProposer = makeAddr('thirdProposer'); + _forBondDepositERC20(_bondEscalationAccounting, _thirdProposer, usdc, _expectedBondSize, _expectedBondSize); + vm.startPrank(_thirdProposer); + _bondEscalationAccounting.approveModule(address(_responseModule)); + _responseId = oracle.proposeResponse(_requestId, abi.encode('thirdResponse')); + vm.stopPrank(); + + // Step 12: It goes undisputed for three days, therefore it's deemed correct and final + vm.warp(_expectedDeadline + 1); + oracle.finalize(_requestId, _responseId); + + // Test: The requester has paid out the reward + assertEq(_bondEscalationAccounting.balanceOf(requester, usdc), 0, 'Mismatch: Requester balance'); + + // Test: The first proposer has received nothing + assertEq(_bondEscalationAccounting.balanceOf(proposer, usdc), 0, 'Mismatch: Proposer balance'); + + // Test: The second proposer has received nothing + assertEq(_bondEscalationAccounting.balanceOf(_anotherProposer, usdc), 0, 'Mismatch: Another Proposer balance'); + + // Test: The third proposer has received the reward and this bond + assertEq( + _bondEscalationAccounting.balanceOf(_thirdProposer, usdc), + _expectedReward + _expectedBondSize, + 'Mismatch: Third Proposer balance' + ); + + // Test: The disputer has received his pledge and bond back, a half of the proposer's pledge and the proposer's bond + assertEq( + _bondEscalationAccounting.balanceOf(disputer, usdc), + _pledgeSize + _pledgeSize / 2 + _expectedBondSize * 2, + 'Mismatch: Disputer balance' + ); + + // Test: The second disputer has not participated in a new dispute, his balance is the same + assertEq( + _bondEscalationAccounting.balanceOf(_secondDisputer, usdc), + _pledgeSize + _pledgeSize / 2, + 'Mismatch: Second Disputer balance' + ); + + // Step 13: Two days after the deadline, the resolution module says that Another proposer's answer was correct + // So Another proposer gets paid Disputer's bond + vm.warp(_expectedDeadline + 2 days); + _mockArbitrator.setAnswer(IOracle.DisputeStatus.Lost); + oracle.resolveDispute(_disputeId); + + // Test: The requester still has nothing + assertEq(_bondEscalationAccounting.balanceOf(requester, usdc), 0, 'Mismatch: Requester balance'); + + // Test: The first proposer still has nothing + assertEq(_bondEscalationAccounting.balanceOf(proposer, usdc), 0, 'Mismatch: Proposer balance'); + + // Test: The second proposer has received the Disputer's bond + assertEq( + _bondEscalationAccounting.balanceOf(_anotherProposer, usdc), + _expectedBondSize, + 'Mismatch: Another Proposer balance' + ); + + // Test: The third proposer has not done anything + assertEq( + _bondEscalationAccounting.balanceOf(_thirdProposer, usdc), + _expectedReward + _expectedBondSize, + 'Mismatch: Third Proposer balance' + ); + + // Test: The disputer has lost a bond + assertEq( + _bondEscalationAccounting.balanceOf(disputer, usdc), + _pledgeSize + _pledgeSize / 2 + _expectedBondSize * 2, + 'Mismatch: Disputer balance' + ); + + // Test: The second disputer has not has not done anything + assertEq( + _bondEscalationAccounting.balanceOf(_secondDisputer, usdc), + _pledgeSize + _pledgeSize / 2, + 'Mismatch: Second Disputer balance' + ); + } + + function test_bondEscalationTied() public { + // Step 1: Proposer pledges against the dispute + _forBondDepositERC20(_bondEscalationAccounting, proposer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(proposer); + _bondEscalationAccounting.approveModule(address(_bondEscalationModule)); + _bondEscalationModule.pledgeAgainstDispute(_disputeId); + vm.stopPrank(); + + // Step 2: Disputer doubles down + _forBondDepositERC20(_bondEscalationAccounting, disputer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(disputer); + _bondEscalationModule.pledgeForDispute(_disputeId); + vm.stopPrank(); + + // Step 3: Proposer doubles down + _forBondDepositERC20(_bondEscalationAccounting, proposer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(proposer); + _bondEscalationModule.pledgeAgainstDispute(_disputeId); + vm.stopPrank(); + + // Step 4: Disputer runs out of capital + // Step 5: The tying buffer kicks in + vm.warp(_bondEscalationDeadline + 1); + + // Step 6: An external party sees that Proposer's response is incorrect, so they bond the required WETH + address _secondDisputer = makeAddr('secondDisputer'); + _forBondDepositERC20(_bondEscalationAccounting, _secondDisputer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(_secondDisputer); + _bondEscalationModule.pledgeForDispute(_disputeId); + vm.stopPrank(); + + // Step 7: They go into the dispute resolution module + oracle.escalateDispute(_disputeId); + + // Step 8: At this point, new answers can be proposed + address _secondProposer = makeAddr('secondProposer'); + _forBondDepositERC20(_bondEscalationAccounting, _secondProposer, usdc, _expectedBondSize, _expectedBondSize); + vm.startPrank(_secondProposer); + _bondEscalationAccounting.approveModule(address(_responseModule)); + _responseId = oracle.proposeResponse(_requestId, _responseData); + vm.stopPrank(); + + // Step 9: After some time, the resolution module deems Disputer's dispute as correct + _mineBlocks(100); + oracle.resolveDispute(_disputeId); + IOracle.Dispute memory _dispute = oracle.getDispute(_disputeId); + assertEq(uint256(_dispute.status), uint256(IOracle.DisputeStatus.Won), 'Mismatch: Dispute status'); + + // Step 10: Participants claim their rewards + // Test: The requester has paid out the reward and is left with no balance + _bondEscalationAccounting.claimEscalationReward(_disputeId, requester); + assertEq(_bondEscalationAccounting.balanceOf(requester, usdc), 0, 'Mismatch: Requester balance'); + + // Test: The proposer has lost his pledge and bond + _bondEscalationAccounting.claimEscalationReward(_disputeId, proposer); + assertEq(_bondEscalationAccounting.balanceOf(proposer, usdc), 0, 'Mismatch: Proposer balance'); + + // Test: The second proposer hasn't received the reward yet + _bondEscalationAccounting.claimEscalationReward(_disputeId, _secondProposer); + assertEq(_bondEscalationAccounting.balanceOf(_secondProposer, usdc), 0, 'Mismatch: Second Proposer balance'); + assertEq( + _bondEscalationAccounting.bondedAmountOf(_secondProposer, usdc, _requestId), + _expectedBondSize, + 'Mismatch: Second Proposer bonded balance' + ); + + // Test: The Disputer has received his pledge and bond, the proposer's pledge and the proposer's bond + _bondEscalationAccounting.claimEscalationReward(_disputeId, disputer); + assertEq( + _bondEscalationAccounting.balanceOf(disputer, usdc), + _pledgeSize * 2 + _expectedBondSize * 2, + 'Mismatch: Disputer balance' + ); + + // Test: The second disputer has received his pledge and the proposer's pledge + _bondEscalationAccounting.claimEscalationReward(_disputeId, _secondDisputer); + assertEq( + _bondEscalationAccounting.balanceOf(_secondDisputer, usdc), _pledgeSize * 2, 'Mismatch: Second Disputer balance' + ); + } + + function test_externalParties() public { + // Step 1: Proposer pledges against the dispute + _forBondDepositERC20(_bondEscalationAccounting, proposer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(proposer); + _bondEscalationAccounting.approveModule(address(_bondEscalationModule)); + _bondEscalationModule.pledgeAgainstDispute(_disputeId); + vm.stopPrank(); + + // Step 2: Disputer doesn't have money + // Step 3: External actor sees that Proposer's answer was incorrect so they pledge in favor of the dispute + address _secondDisputer = makeAddr('secondDisputer'); + _forBondDepositERC20(_bondEscalationAccounting, _secondDisputer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(_secondDisputer); + _bondEscalationModule.pledgeForDispute(_disputeId); + vm.stopPrank(); + + // Step 4: Proposer doubles down + _forBondDepositERC20(_bondEscalationAccounting, proposer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(proposer); + _bondEscalationAccounting.approveModule(address(_bondEscalationModule)); + _bondEscalationModule.pledgeAgainstDispute(_disputeId); + vm.stopPrank(); + + // Step 5: External actor sees that Proposer's answer was incorrect so they pledge in favor of the dispute, tying the bond escalation + address _thirdDisputer = makeAddr('thirdDisputer'); + _forBondDepositERC20(_bondEscalationAccounting, _thirdDisputer, usdc, _pledgeSize, _pledgeSize); + vm.startPrank(_thirdDisputer); + _bondEscalationModule.pledgeForDispute(_disputeId); + vm.stopPrank(); + + // Step 6: Proposer loses in resolution + vm.warp(_bondEscalationDeadline + 1); + oracle.escalateDispute(_disputeId); + oracle.resolveDispute(_disputeId); + + IOracle.Dispute memory _dispute = oracle.getDispute(_disputeId); + assertEq(uint256(_dispute.status), uint256(IOracle.DisputeStatus.Won), 'Mismatch: Dispute status'); + + // Step 7: Participants claim the rewards + // Test: The requester has not participated in pledging, claiming shouldn't change his balance + _bondEscalationAccounting.claimEscalationReward(_disputeId, requester); + assertEq(_bondEscalationAccounting.balanceOf(requester, usdc), 0, 'Mismatch: Requester balance'); + + // Test: Proposer's initial bond goes to Disputer + _bondEscalationAccounting.claimEscalationReward(_disputeId, proposer); + assertEq(_bondEscalationAccounting.balanceOf(proposer, usdc), 0, 'Mismatch: Proposer balance'); + + // Test: Disputers split the proposer's pledges + _bondEscalationAccounting.claimEscalationReward(_disputeId, disputer); + assertEq(_bondEscalationAccounting.balanceOf(disputer, usdc), _pledgeSize * 2, 'Mismatch: Disputer balance'); + + _bondEscalationAccounting.claimEscalationReward(_disputeId, _secondDisputer); + assertEq( + _bondEscalationAccounting.balanceOf(_secondDisputer, usdc), _pledgeSize * 2, 'Mismatch: Second Disputer balance' + ); + + _bondEscalationAccounting.claimEscalationReward(_disputeId, _thirdDisputer); + assertEq( + _bondEscalationAccounting.balanceOf(_thirdDisputer, usdc), _pledgeSize * 2, 'Mismatch: Third Disputer balance' + ); + } +} diff --git a/solidity/test/integration/IntegrationBase.sol b/solidity/test/integration/IntegrationBase.sol index 7f749205..28ab52a4 100644 --- a/solidity/test/integration/IntegrationBase.sol +++ b/solidity/test/integration/IntegrationBase.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -/* solhint-disable no-unused-import */ +// solhint-disable no-unused-import +// solhint-disable-next-line no-console +import {console} from 'forge-std/console.sol'; + import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {DSTestPlus} from '@defi-wonderland/solidity-utils/solidity/test/DSTestPlus.sol'; import {Oracle, IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/contracts/Oracle.sol'; @@ -34,7 +37,7 @@ import {MockArbitrator} from '../mocks/MockArbitrator.sol'; import {TestConstants} from '../utils/TestConstants.sol'; import {Helpers} from '../utils/Helpers.sol'; -/* solhint-enable no-unused-import */ +// solhint-enable no-unused-import contract IntegrationBase is DSTestPlus, TestConstants, Helpers { uint256 public constant FORK_BLOCK = 756_611; diff --git a/solidity/test/mocks/MockArbitrator.sol b/solidity/test/mocks/MockArbitrator.sol index ca281f03..3d4730d3 100644 --- a/solidity/test/mocks/MockArbitrator.sol +++ b/solidity/test/mocks/MockArbitrator.sol @@ -4,12 +4,18 @@ pragma solidity ^0.8.19; import {IArbitrator, IOracle} from '../../interfaces/IArbitrator.sol'; contract MockArbitrator is IArbitrator { + IOracle.DisputeStatus internal _answer = IOracle.DisputeStatus.Won; + + function setAnswer(IOracle.DisputeStatus _disputeStatus) external { + _answer = _disputeStatus; + } + function resolve(bytes32 /* _dispute */ ) external pure returns (bytes memory _result) { _result = new bytes(0); } - function getAnswer(bytes32 /* _dispute */ ) external pure returns (IOracle.DisputeStatus _answer) { - _answer = IOracle.DisputeStatus.Won; + function getAnswer(bytes32 /* _dispute */ ) external view returns (IOracle.DisputeStatus _disputeStatus) { + _disputeStatus = _answer; } function supportsInterface(bytes4 /* interfaceId */ ) external pure returns (bool _supported) { diff --git a/solidity/test/unit/modules/dispute/BondEscalationModule.t.sol b/solidity/test/unit/modules/dispute/BondEscalationModule.t.sol index 4d487e07..75c9ad7b 100644 --- a/solidity/test/unit/modules/dispute/BondEscalationModule.t.sol +++ b/solidity/test/unit/modules/dispute/BondEscalationModule.t.sol @@ -54,10 +54,6 @@ contract ForTest_BondEscalationModule is BondEscalationModule { function forTest_setEscalatedDispute(bytes32 _requestId, bytes32 _disputeId) public { _escalations[_requestId].disputeId = _disputeId; } - - function forTest_setDisputeToRequest(bytes32 _disputeId, bytes32 _requestId) public { - _disputeToRequest[_disputeId] = _requestId; - } } /** @@ -93,8 +89,8 @@ contract BaseTest is Test, Helpers { IOracle.Response internal _mockResponse; // Events - event PledgedInFavorOfDisputer(bytes32 indexed _disputeId, address indexed _pledger, uint256 indexed _amount); - event PledgedInFavorOfProposer(bytes32 indexed _disputeId, address indexed _pledger, uint256 indexed _amount); + event PledgedForDispute(bytes32 indexed _disputeId, address indexed _pledger, uint256 indexed _amount); + event PledgedAgainstDispute(bytes32 indexed _disputeId, address indexed _pledger, uint256 indexed _amount); event BondEscalationStatusUpdated( bytes32 indexed _requestId, bytes32 indexed _disputeId, IBondEscalationModule.BondEscalationStatus _status ); @@ -452,7 +448,7 @@ contract BondEscalationModule_Unit_EscalateDispute is BaseTest { // Set the number of pledgers for both sides _setBondEscalation(_requestId, _numForPledgers, _numAgainstPledgers); - // Check: is the event emmited? + // Check: is the event emitted? vm.expectEmit(true, true, true, true, address(bondEscalationModule)); emit BondEscalationStatusUpdated(_requestId, _disputeId, IBondEscalationModule.BondEscalationStatus.Escalated); @@ -649,6 +645,8 @@ contract BondEscalationModule_Unit_OnDisputeStatusChange is BaseTest { * @notice Tests that onDisputeStatusChange pays the proposer if the disputer lost */ function test_callPayIfNormalDisputeLost(bytes32 _disputeId, bytes32 _requestId) public { + vm.assume(_disputeId > 0 && _requestId > 0); + IOracle.DisputeStatus _status = IOracle.DisputeStatus.Lost; IOracle.Dispute memory _dispute = _getRandomDispute(_requestId, _status); @@ -661,13 +659,6 @@ contract BondEscalationModule_Unit_OnDisputeStatusChange is BaseTest { abi.encode(true) ); - // Mock and expect IAccountingExtension.release to be called - _mockAndExpect( - address(accounting), - abi.encodeCall(IAccountingExtension.release, (_dispute.proposer, _requestId, token, bondSize)), - abi.encode(true) - ); - vm.prank(address(oracle)); bondEscalationModule.onDisputeStatusChange(_disputeId, _dispute); } @@ -712,7 +703,7 @@ contract BondEscalationModule_Unit_OnDisputeStatusChange is BaseTest { abi.encode(true) ); - // Mock and expect IAccountingExtension.pay to be called + // Mock and expect IAccountingExtension.release to be called _mockAndExpect( address(accounting), abi.encodeCall(IAccountingExtension.release, (_dispute.disputer, _requestId, token, bondSize)), @@ -787,9 +778,7 @@ contract BondEscalationModule_Unit_OnDisputeStatusChange is BaseTest { IOracle.DisputeStatus _status = IOracle.DisputeStatus.Won; IOracle.Dispute memory _dispute = _getRandomDispute(_requestId, _status); - uint256 _bondSize = 1000; - - _setRequestData(_requestId, _bondSize, maxEscalations, bondEscalationDeadline, tyingBuffer, disputeWindow); + _setRequestData(_requestId, bondSize, maxEscalations, bondEscalationDeadline, tyingBuffer, disputeWindow); uint256 _numForPledgers = 2; uint256 _numAgainstPledgers = 2; @@ -808,14 +797,14 @@ contract BondEscalationModule_Unit_OnDisputeStatusChange is BaseTest { // Mock and expect IAccountingExtension.pay to be called _mockAndExpect( address(accounting), - abi.encodeCall(IAccountingExtension.pay, (_requestId, _dispute.proposer, _dispute.disputer, token, _bondSize)), + abi.encodeCall(IAccountingExtension.pay, (_requestId, _dispute.proposer, _dispute.disputer, token, bondSize)), abi.encode(true) ); // Mock and expect IAccountingExtension.release to be called _mockAndExpect( address(accounting), - abi.encodeCall(IAccountingExtension.release, (_dispute.disputer, _requestId, token, _bondSize)), + abi.encodeCall(IAccountingExtension.release, (_dispute.disputer, _requestId, token, bondSize)), abi.encode(true) ); @@ -824,7 +813,7 @@ contract BondEscalationModule_Unit_OnDisputeStatusChange is BaseTest { address(accounting), abi.encodeCall( IBondEscalationAccounting.onSettleBondEscalation, - (_requestId, _disputeId, true, token, _bondSize << 1, _numForPledgers) + (_requestId, _disputeId, true, token, bondSize << 1, _numForPledgers) ), abi.encode() ); @@ -879,13 +868,6 @@ contract BondEscalationModule_Unit_OnDisputeStatusChange is BaseTest { abi.encode(true) ); - // Mock and expect IAccountingExtension.release to be called - _mockAndExpect( - address(accounting), - abi.encodeCall(IAccountingExtension.release, (_dispute.proposer, _requestId, token, _bondSize)), - abi.encode(true) - ); - // Mock and expect IBondEscalationAccounting.onSettleBondEscalation to be called vm.mockCall( address(accounting), @@ -938,7 +920,7 @@ contract BondEscalationModule_Unit_PledgeForDispute is BaseTest { _mockAndExpect(address(oracle), abi.encodeCall(IOracle.getDispute, (_disputeId)), abi.encode(_mockDispute)); // Check: does it revert if the dispute is not escalated yet? - vm.expectRevert(IBondEscalationModule.BondEscalationModule_DisputeNotEscalated.selector); + vm.expectRevert(IBondEscalationModule.BondEscalationModule_InvalidDispute.selector); bondEscalationModule.pledgeForDispute(_disputeId); } @@ -1035,7 +1017,7 @@ contract BondEscalationModule_Unit_PledgeForDispute is BaseTest { /** * @notice Tests that pledgeForDispute reverts if the timestamp is within the tying buffer and someone attempts - * to pledge when the funds are tied--effectively breaking the tie + * to pledge when the funds are tied, effectively breaking the tie */ function test_revertIfAttemptToBreakTieDuringTyingBuffer(bytes32 _disputeId, bytes32 _requestId) public { vm.assume(_disputeId > 0); @@ -1062,7 +1044,7 @@ contract BondEscalationModule_Unit_PledgeForDispute is BaseTest { _setBondEscalation(_requestId, _numForPledgers, _numAgainstPledgers); // Check: does it revert if trying to tie outside of the tying buffer? - vm.expectRevert(IBondEscalationModule.BondEscalationModule_CanOnlyTieDuringTyingBuffer.selector); + vm.expectRevert(IBondEscalationModule.BondEscalationModule_CannotBreakTieDuringTyingBuffer.selector); bondEscalationModule.pledgeForDispute(_disputeId); } @@ -1101,12 +1083,10 @@ contract BondEscalationModule_Unit_PledgeForDispute is BaseTest { // Check: is event emitted? vm.expectEmit(true, true, true, true, address(bondEscalationModule)); - emit PledgedInFavorOfDisputer(_disputeId, address(this), _bondSize); + emit PledgedForDispute(_disputeId, address(this), _bondSize); bondEscalationModule.pledgeForDispute(_disputeId); - bondEscalationModule.forTest_setDisputeToRequest(_disputeId, _requestId); - uint256 _pledgesForDispute = bondEscalationModule.getEscalation(_requestId).amountOfPledgesForDispute; // Check: is the number of pledges for the dispute properly updated? assertEq(_pledgesForDispute, _numForPledgers + 1); @@ -1144,7 +1124,7 @@ contract BondEscalationModule_Unit_PledgeAgainstDispute is BaseTest { _mockAndExpect(address(oracle), abi.encodeCall(IOracle.getDispute, (_disputeId)), abi.encode(_mockDispute)); // Check: does it revert if the dispute is not escalated yet? - vm.expectRevert(IBondEscalationModule.BondEscalationModule_DisputeNotEscalated.selector); + vm.expectRevert(IBondEscalationModule.BondEscalationModule_InvalidDispute.selector); bondEscalationModule.pledgeAgainstDispute(_disputeId); } @@ -1244,7 +1224,7 @@ contract BondEscalationModule_Unit_PledgeAgainstDispute is BaseTest { /** * @notice Tests that pledgeAgainstDispute reverts if the timestamp is within the tying buffer and someone attempts - * to pledge when the funds are tied--effectively breaking the tie + * to pledge when the funds are tied, effectively breaking the tie */ function test_revertIfAttemptToBreakTieDuringTyingBuffer(bytes32 _disputeId, bytes32 _requestId) public { vm.assume(_disputeId > 0); @@ -1271,8 +1251,7 @@ contract BondEscalationModule_Unit_PledgeAgainstDispute is BaseTest { _setBondEscalation(_requestId, _numForPledgers, _numAgainstPledgers); // Check: does it revert if trying to tie outside of the tying buffer? - vm.expectRevert(IBondEscalationModule.BondEscalationModule_CanOnlyTieDuringTyingBuffer.selector); - + vm.expectRevert(IBondEscalationModule.BondEscalationModule_CannotBreakTieDuringTyingBuffer.selector); bondEscalationModule.pledgeAgainstDispute(_disputeId); } @@ -1311,12 +1290,10 @@ contract BondEscalationModule_Unit_PledgeAgainstDispute is BaseTest { // Check: is the event emitted? vm.expectEmit(true, true, true, true, address(bondEscalationModule)); - emit PledgedInFavorOfProposer(_disputeId, address(this), _bondSize); + emit PledgedAgainstDispute(_disputeId, address(this), _bondSize); bondEscalationModule.pledgeAgainstDispute(_disputeId); - bondEscalationModule.forTest_setDisputeToRequest(_disputeId, _requestId); - uint256 _pledgesForDispute = bondEscalationModule.getEscalation(_requestId).amountOfPledgesAgainstDispute; // Check: is the number of pledges for the dispute properly updated? assertEq(_pledgesForDispute, _numAgainstPledgers + 1); @@ -1361,7 +1338,7 @@ contract BondEscalationModule_Unit_SettleBondEscalation is BaseTest { } /** - * @notice Tests that settleBondEscalation reverts if someone tries to settle a bondescalated dispute that + * @notice Tests that settleBondEscalation reverts if someone tries to settle a bond-escalated dispute that * has the same number of pledgers. */ function test_revertIfSameNumberOfPledgers(bytes32 _requestId, bytes32 _disputeId) public { @@ -1403,14 +1380,9 @@ contract BondEscalationModule_Unit_SettleBondEscalation is BaseTest { _setBondEscalation(_requestId, _numForPledgers, _numAgainstPledgers); - uint256 _amountToPay = _bondSize + (_numAgainstPledgers * _bondSize) / _numForPledgers; - _mockAndExpect( - address(accounting), - abi.encodeCall( - IBondEscalationAccounting.onSettleBondEscalation, - (_requestId, _disputeId, true, token, _amountToPay, _numForPledgers) - ), + address(oracle), + abi.encodeCall(IOracle.updateDisputeStatus, (_disputeId, IOracle.DisputeStatus.Won)), abi.encode(true) ); @@ -1445,15 +1417,10 @@ contract BondEscalationModule_Unit_SettleBondEscalation is BaseTest { _setBondEscalation(_requestId, _numForPledgers, _numAgainstPledgers); - uint256 _amountToPay = _bondSize + (_numForPledgers * _bondSize) / _numAgainstPledgers; - _mockAndExpect( - address(accounting), - abi.encodeCall( - IBondEscalationAccounting.onSettleBondEscalation, - (_requestId, _disputeId, false, token, _amountToPay, _numAgainstPledgers) - ), - abi.encode() + address(oracle), + abi.encodeCall(IOracle.updateDisputeStatus, (_disputeId, IOracle.DisputeStatus.Lost)), + abi.encode(true) ); // Check: is the event emitted? diff --git a/solidity/test/utils/Helpers.sol b/solidity/test/utils/Helpers.sol index 2eb7cfec..cd60ad9c 100644 --- a/solidity/test/utils/Helpers.sol +++ b/solidity/test/utils/Helpers.sol @@ -13,7 +13,7 @@ contract Helpers is DSTestPlus { _; } - function _assumeFuzzable(address _address) internal { + function _assumeFuzzable(address _address) internal pure { assumeNotForgeAddress(_address); assumeNotZeroAddress(_address); assumeNotPrecompile(_address); diff --git a/yarn.lock b/yarn.lock index 2a45ac76..3ce6404b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -192,10 +192,10 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@defi-wonderland/prophet-core-contracts@0.0.0-bb56cdd7": - version "0.0.0-bb56cdd7" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-bb56cdd7.tgz#9b54484b923c9252af4d2dac696b17626b600234" - integrity sha512-IJsqBK/9RcvzqsrxFSVNhlTmfO271Bavc9oxzuPr/lKen3IA28zfOJ1CjNIN1gdte/CVRajilyx+WlO0a+wzFw== +"@defi-wonderland/prophet-core-contracts@0.0.0-d6780d39": + version "0.0.0-d6780d39" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-d6780d39.tgz#6faa1771f3aa59bd98d17271a878710c1db0686b" + integrity sha512-WYTqODoqsQ34J2bvrg5NNA5Gzungf47X0z5cTxdn3cOnWfOfXToTHSJUUqQ41nGMXRvjbXEC1d0+rWufeNfxbg== dependencies: "@defi-wonderland/solidity-utils" "0.0.0-3e9c8e8b" "@openzeppelin/contracts" "^4.9.3"