Skip to content

Commit

Permalink
test: bond escalation integration tests (#11)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
gas1cent authored Oct 19, 2023
1 parent 0a18c9b commit 004c369
Show file tree
Hide file tree
Showing 11 changed files with 570 additions and 129 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 0 additions & 1 deletion solidity/contracts/extensions/BondEscalationAccounting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
117 changes: 62 additions & 55 deletions solidity/contracts/modules/dispute/BondEscalationModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
);
}

/**
Expand All @@ -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);
Expand All @@ -287,7 +294,7 @@ contract BondEscalationModule is Module, IBondEscalationModule {
}

if (block.timestamp > _params.bondEscalationDeadline && _numPledgersForDispute == _numPledgersAgainstDispute) {
revert BondEscalationModule_CanOnlyTieDuringTyingBuffer();
revert BondEscalationModule_CannotBreakTieDuringTyingBuffer();
}
}

Expand Down
10 changes: 5 additions & 5 deletions solidity/interfaces/modules/dispute/IBondEscalationModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.
*/
Expand All @@ -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.
*/
Expand Down
2 changes: 1 addition & 1 deletion solidity/scripts/Deploy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 004c369

Please sign in to comment.