From 55afd31001928e7075c506bf985911b7b79c8bcb Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Mon, 8 Jul 2024 19:26:53 -0300 Subject: [PATCH 1/5] fix: adding escalated status --- .../resolution/PrivateERC20ResolutionModule.sol | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/solidity/contracts/modules/resolution/PrivateERC20ResolutionModule.sol b/solidity/contracts/modules/resolution/PrivateERC20ResolutionModule.sol index 4019f307..eb5a5be7 100644 --- a/solidity/contracts/modules/resolution/PrivateERC20ResolutionModule.sol +++ b/solidity/contracts/modules/resolution/PrivateERC20ResolutionModule.sol @@ -54,7 +54,10 @@ contract PrivateERC20ResolutionModule is Module, IPrivateERC20ResolutionModule { function commitVote(IOracle.Request calldata _request, IOracle.Dispute calldata _dispute, bytes32 _commitment) public { bytes32 _disputeId = _getId(_dispute); if (ORACLE.createdAt(_disputeId) == 0) revert PrivateERC20ResolutionModule_NonExistentDispute(); - if (ORACLE.disputeStatus(_disputeId) != IOracle.DisputeStatus.None) { + if ( + ORACLE.disputeStatus(_disputeId) != IOracle.DisputeStatus.None + && ORACLE.disputeStatus(_disputeId) != IOracle.DisputeStatus.Escalated + ) { revert PrivateERC20ResolutionModule_AlreadyResolved(); } @@ -114,7 +117,10 @@ contract PrivateERC20ResolutionModule is Module, IPrivateERC20ResolutionModule { IOracle.Dispute calldata _dispute ) external onlyOracle { if (ORACLE.createdAt(_disputeId) == 0) revert PrivateERC20ResolutionModule_NonExistentDispute(); - if (ORACLE.disputeStatus(_disputeId) != IOracle.DisputeStatus.None) { + if ( + ORACLE.disputeStatus(_disputeId) != IOracle.DisputeStatus.None + && ORACLE.disputeStatus(_disputeId) != IOracle.DisputeStatus.Escalated + ) { revert PrivateERC20ResolutionModule_AlreadyResolved(); } From 82a20f945bb5281a6f107adae47b87008bf5265a Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Mon, 8 Jul 2024 19:52:36 -0300 Subject: [PATCH 2/5] fix: issue anyone can steal pledge --- .../extensions/BondEscalationAccounting.sol | 8 +++++++- .../extensions/IBondEscalationAccounting.sol | 14 ++++++++++++++ .../dispute/BondEscalationAccounting.t.sol | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/solidity/contracts/extensions/BondEscalationAccounting.sol b/solidity/contracts/extensions/BondEscalationAccounting.sol index 294d57c9..b4b8e9f9 100644 --- a/solidity/contracts/extensions/BondEscalationAccounting.sol +++ b/solidity/contracts/extensions/BondEscalationAccounting.sol @@ -17,7 +17,9 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount mapping(bytes32 _disputeId => EscalationResult _result) public escalationResults; /// @inheritdoc IBondEscalationAccounting - mapping(bytes32 _requestId => mapping(address _pledger => bool)) public pledgerClaimed; + mapping(bytes32 _requestId => mapping(address _pledger => bool _claimed)) public pledgerClaimed; + + mapping(bytes32 _disputeId => mapping(address _pledger => bool _pledged)) public pledgerHasPledged; constructor(IOracle _oracle) AccountingExtension(_oracle) {} @@ -33,6 +35,8 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount pledges[_disputeId][_token] += _amount; + pledgerHasPledged[_disputeId][_pledger] = true; + unchecked { balanceOf[_pledger][_token] -= _amount; } @@ -78,6 +82,7 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount if (_result.token == IERC20(address(0))) revert BondEscalationAccounting_NoEscalationResult(); bytes32 _requestId = _result.requestId; if (pledgerClaimed[_requestId][_pledger]) revert BondEscalationAccounting_AlreadyClaimed(); + if (!pledgerHasPledged[_disputeId][_pledger]) revert BondEscalationAccounting_NotPledged(); IOracle.DisputeStatus _status = ORACLE.disputeStatus(_disputeId); uint256 _amountPerPledger = _result.amountPerPledger; @@ -95,6 +100,7 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount uint256 _claimAmount = _amountPerPledger * _numberOfPledges; pledgerClaimed[_requestId][_pledger] = true; + pledgerHasPledged[_disputeId][_pledger] = false; balanceOf[_pledger][_token] += _claimAmount; unchecked { diff --git a/solidity/interfaces/extensions/IBondEscalationAccounting.sol b/solidity/interfaces/extensions/IBondEscalationAccounting.sol index dead0586..e315bcc6 100644 --- a/solidity/interfaces/extensions/IBondEscalationAccounting.sol +++ b/solidity/interfaces/extensions/IBondEscalationAccounting.sol @@ -107,6 +107,11 @@ interface IBondEscalationAccounting is IAccountingExtension { */ error BondEscalationAccounting_AlreadySettled(); + /** + * @notice Thrown when an user tries to claim their pledge for an escalation which wasn't pledged + */ + error BondEscalationAccounting_NotPledged(); + /*/////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ @@ -160,6 +165,15 @@ interface IBondEscalationAccounting is IAccountingExtension { */ function pledgerClaimed(bytes32 _requestId, address _pledger) external returns (bool _claimed); + /** + * @notice True if the given pledger has pledged for the given dispute + * + * @param _disputeId The ID of the bond-escalated dispute + * @param _pledger Address of the pledger + * @return _pledged True if the pledger has pledged + */ + function pledgerHasPledged(bytes32 _disputeId, address _pledger) external returns (bool _pledged); + /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ diff --git a/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol b/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol index 7030d4ab..30d2e4e7 100644 --- a/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol +++ b/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol @@ -19,6 +19,10 @@ import {Strings} from '@openzeppelin/contracts/utils/Strings.sol'; contract ForTest_BondEscalationAccounting is BondEscalationAccounting { constructor(IOracle _oracle) BondEscalationAccounting(_oracle) {} + function forTest_setPledgerHasPledged(bytes32 _disputeId, address _pledger, bool _pledged) public { + pledgerHasPledged[_disputeId][_pledger] = _pledged; + } + function forTest_setPledge(bytes32 _disputeId, IERC20 _token, uint256 _amount) public { pledges[_disputeId][_token] = _amount; } @@ -445,6 +449,16 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { bondEscalationAccounting.claimEscalationReward(_disputeId, pledger); } + function test_revertIfNotPledged(bytes32 _disputeId, bytes32 _requestId) public { + bondEscalationAccounting.forTest_setEscalationResult( + _disputeId, _requestId, token, 0, IBondEscalationModule(address(this)) + ); + + vm.expectRevert(IBondEscalationAccounting.BondEscalationAccounting_NotPledged.selector); + + bondEscalationAccounting.claimEscalationReward(_disputeId, pledger); + } + function test_forVotesWon( bytes32 _disputeId, bytes32 _requestId, @@ -462,6 +476,8 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { bondEscalationAccounting.forTest_setPledge(_disputeId, token, _amount * _pledges); + bondEscalationAccounting.forTest_setPledgerHasPledged(_disputeId, pledger, true); + // Mock and expect to call the oracle getting the dispute status _mockAndExpect( address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.Won) @@ -507,6 +523,8 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { bondEscalationAccounting.forTest_setPledge(_disputeId, token, _amount * _pledges); + bondEscalationAccounting.forTest_setPledgerHasPledged(_disputeId, pledger, true); + // Mock and expect to call the oracle getting the dispute status _mockAndExpect( address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.Lost) From 2ecae943af6b75b5adfd09e14ba51c3b498592fa Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Fri, 19 Jul 2024 13:57:58 -0300 Subject: [PATCH 3/5] fix: tests --- solidity/test/integration/BondEscalation.t.sol | 4 ++-- solidity/test/integration/IntegrationBase.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/solidity/test/integration/BondEscalation.t.sol b/solidity/test/integration/BondEscalation.t.sol index 26cbdc9b..f9ad10cc 100644 --- a/solidity/test/integration/BondEscalation.t.sol +++ b/solidity/test/integration/BondEscalation.t.sol @@ -356,8 +356,8 @@ contract Integration_BondEscalation is IntegrationBase { // 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'); + // _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); diff --git a/solidity/test/integration/IntegrationBase.sol b/solidity/test/integration/IntegrationBase.sol index 728cbde3..f5ce3e33 100644 --- a/solidity/test/integration/IntegrationBase.sol +++ b/solidity/test/integration/IntegrationBase.sol @@ -42,7 +42,7 @@ import {TestConstants} from '../utils/TestConstants.sol'; // solhint-enable no-unused-import contract IntegrationBase is DSTestPlus, TestConstants, Helpers { - uint256 public constant FORK_BLOCK = 100_000_000; + uint256 public constant FORK_BLOCK = 122_612_760; uint256 internal _initialBalance = 100_000 ether; From b4478440520ab15e9b85a4643a26fb6fb73ba6fe Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Mon, 22 Jul 2024 03:13:28 -0300 Subject: [PATCH 4/5] feat: no resolution --- .../extensions/BondEscalationAccounting.sol | 9 +-- .../extensions/IBondEscalationAccounting.sol | 14 ---- .../dispute/BondEscalationAccounting.t.sol | 73 ++++++++++++++----- 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/solidity/contracts/extensions/BondEscalationAccounting.sol b/solidity/contracts/extensions/BondEscalationAccounting.sol index b4b8e9f9..851ce760 100644 --- a/solidity/contracts/extensions/BondEscalationAccounting.sol +++ b/solidity/contracts/extensions/BondEscalationAccounting.sol @@ -19,8 +19,6 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount /// @inheritdoc IBondEscalationAccounting mapping(bytes32 _requestId => mapping(address _pledger => bool _claimed)) public pledgerClaimed; - mapping(bytes32 _disputeId => mapping(address _pledger => bool _pledged)) public pledgerHasPledged; - constructor(IOracle _oracle) AccountingExtension(_oracle) {} /// @inheritdoc IBondEscalationAccounting @@ -35,8 +33,6 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount pledges[_disputeId][_token] += _amount; - pledgerHasPledged[_disputeId][_pledger] = true; - unchecked { balanceOf[_pledger][_token] -= _amount; } @@ -82,14 +78,14 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount if (_result.token == IERC20(address(0))) revert BondEscalationAccounting_NoEscalationResult(); bytes32 _requestId = _result.requestId; if (pledgerClaimed[_requestId][_pledger]) revert BondEscalationAccounting_AlreadyClaimed(); - if (!pledgerHasPledged[_disputeId][_pledger]) revert BondEscalationAccounting_NotPledged(); IOracle.DisputeStatus _status = ORACLE.disputeStatus(_disputeId); uint256 _amountPerPledger = _result.amountPerPledger; uint256 _numberOfPledges; if (_status == IOracle.DisputeStatus.NoResolution) { - _numberOfPledges = 1; + _numberOfPledges = _result.bondEscalationModule.pledgesForDispute(_requestId, _pledger) + + _result.bondEscalationModule.pledgesAgainstDispute(_requestId, _pledger); } else { _numberOfPledges = _status == IOracle.DisputeStatus.Won ? _result.bondEscalationModule.pledgesForDispute(_requestId, _pledger) @@ -100,7 +96,6 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount uint256 _claimAmount = _amountPerPledger * _numberOfPledges; pledgerClaimed[_requestId][_pledger] = true; - pledgerHasPledged[_disputeId][_pledger] = false; balanceOf[_pledger][_token] += _claimAmount; unchecked { diff --git a/solidity/interfaces/extensions/IBondEscalationAccounting.sol b/solidity/interfaces/extensions/IBondEscalationAccounting.sol index e315bcc6..dead0586 100644 --- a/solidity/interfaces/extensions/IBondEscalationAccounting.sol +++ b/solidity/interfaces/extensions/IBondEscalationAccounting.sol @@ -107,11 +107,6 @@ interface IBondEscalationAccounting is IAccountingExtension { */ error BondEscalationAccounting_AlreadySettled(); - /** - * @notice Thrown when an user tries to claim their pledge for an escalation which wasn't pledged - */ - error BondEscalationAccounting_NotPledged(); - /*/////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ @@ -165,15 +160,6 @@ interface IBondEscalationAccounting is IAccountingExtension { */ function pledgerClaimed(bytes32 _requestId, address _pledger) external returns (bool _claimed); - /** - * @notice True if the given pledger has pledged for the given dispute - * - * @param _disputeId The ID of the bond-escalated dispute - * @param _pledger Address of the pledger - * @return _pledged True if the pledger has pledged - */ - function pledgerHasPledged(bytes32 _disputeId, address _pledger) external returns (bool _pledged); - /*/////////////////////////////////////////////////////////////// LOGIC //////////////////////////////////////////////////////////////*/ diff --git a/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol b/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol index 30d2e4e7..f5f39cd7 100644 --- a/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol +++ b/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol @@ -19,10 +19,6 @@ import {Strings} from '@openzeppelin/contracts/utils/Strings.sol'; contract ForTest_BondEscalationAccounting is BondEscalationAccounting { constructor(IOracle _oracle) BondEscalationAccounting(_oracle) {} - function forTest_setPledgerHasPledged(bytes32 _disputeId, address _pledger, bool _pledged) public { - pledgerHasPledged[_disputeId][_pledger] = _pledged; - } - function forTest_setPledge(bytes32 _disputeId, IERC20 _token, uint256 _amount) public { pledges[_disputeId][_token] = _amount; } @@ -449,16 +445,6 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { bondEscalationAccounting.claimEscalationReward(_disputeId, pledger); } - function test_revertIfNotPledged(bytes32 _disputeId, bytes32 _requestId) public { - bondEscalationAccounting.forTest_setEscalationResult( - _disputeId, _requestId, token, 0, IBondEscalationModule(address(this)) - ); - - vm.expectRevert(IBondEscalationAccounting.BondEscalationAccounting_NotPledged.selector); - - bondEscalationAccounting.claimEscalationReward(_disputeId, pledger); - } - function test_forVotesWon( bytes32 _disputeId, bytes32 _requestId, @@ -476,8 +462,6 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { bondEscalationAccounting.forTest_setPledge(_disputeId, token, _amount * _pledges); - bondEscalationAccounting.forTest_setPledgerHasPledged(_disputeId, pledger, true); - // Mock and expect to call the oracle getting the dispute status _mockAndExpect( address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.Won) @@ -523,8 +507,6 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { bondEscalationAccounting.forTest_setPledge(_disputeId, token, _amount * _pledges); - bondEscalationAccounting.forTest_setPledgerHasPledged(_disputeId, pledger, true); - // Mock and expect to call the oracle getting the dispute status _mockAndExpect( address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.Lost) @@ -551,4 +533,59 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { // Check: are the pledges updated? assertEq(bondEscalationAccounting.pledges(_disputeId, token), 0); } + + function test_noResolution( + bytes32 _disputeId, + bytes32 _requestId, + uint256 _amount, + uint256 _pledges, + address _bondEscalationModule + ) public assumeFuzzable(_bondEscalationModule) { + vm.assume(_amount > 0); + vm.assume(_pledges > 0 && _pledges < 30); + + _amount = bound(_amount, 0, type(uint128).max / _pledges); + + bondEscalationAccounting.forTest_setEscalationResult( + _disputeId, _requestId, token, _amount, IBondEscalationModule(_bondEscalationModule) + ); + + bondEscalationAccounting.forTest_setPledge(_disputeId, token, _amount * _pledges * 2); + + // Mock and expect to call the oracle getting the dispute status + _mockAndExpect( + address(oracle), + abi.encodeCall(IOracle.disputeStatus, (_disputeId)), + abi.encode(IOracle.DisputeStatus.NoResolution) + ); + + // Mock and expect to call the escalation module asking for pledges + _mockAndExpect( + _bondEscalationModule, + abi.encodeCall(IBondEscalationModule.pledgesAgainstDispute, (_requestId, pledger)), + abi.encode(_pledges) + ); + + // Mock and expect the call to the escalation module asking for pledges + _mockAndExpect( + _bondEscalationModule, + abi.encodeCall(IBondEscalationModule.pledgesForDispute, (_requestId, pledger)), + abi.encode(_pledges) + ); + + // Check: is the event emitted? + vm.expectEmit(true, true, true, true, address(bondEscalationAccounting)); + emit EscalationRewardClaimed(_requestId, _disputeId, pledger, token, _amount * _pledges * 2); + + vm.prank(_bondEscalationModule); + bondEscalationAccounting.claimEscalationReward(_disputeId, pledger); + + // Check: is the balance of the pledger properly updated? + assertEq(bondEscalationAccounting.balanceOf(pledger, token), _amount * _pledges * 2); + // Check: is the reward marked as claimed for the pledger? + assertTrue(bondEscalationAccounting.pledgerClaimed(_requestId, pledger)); + + // Check: are the pledges updated? + assertEq(bondEscalationAccounting.pledges(_disputeId, token), 0); + } } From 5161792dd425b461db54f157e1cda5e7a0c76891 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Tue, 23 Jul 2024 23:05:03 -0300 Subject: [PATCH 5/5] feat: tests --- solidity/test/integration/BondEscalation.t.sol | 4 ++-- .../dispute/BondEscalationAccounting.t.sol | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/solidity/test/integration/BondEscalation.t.sol b/solidity/test/integration/BondEscalation.t.sol index f9ad10cc..26cbdc9b 100644 --- a/solidity/test/integration/BondEscalation.t.sol +++ b/solidity/test/integration/BondEscalation.t.sol @@ -356,8 +356,8 @@ contract Integration_BondEscalation is IntegrationBase { // 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'); + _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); diff --git a/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol b/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol index f5f39cd7..3c71e321 100644 --- a/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol +++ b/solidity/test/unit/modules/dispute/BondEscalationAccounting.t.sol @@ -538,19 +538,21 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { bytes32 _disputeId, bytes32 _requestId, uint256 _amount, - uint256 _pledges, + uint256 _pledgesAgainst, + uint256 _pledgesFor, address _bondEscalationModule ) public assumeFuzzable(_bondEscalationModule) { vm.assume(_amount > 0); - vm.assume(_pledges > 0 && _pledges < 30); + vm.assume(_pledgesAgainst > 0 && _pledgesAgainst < 10_000); + vm.assume(_pledgesFor > 0 && _pledgesFor < 10_000); - _amount = bound(_amount, 0, type(uint128).max / _pledges); + _amount = bound(_amount, 0, type(uint128).max / (_pledgesAgainst + _pledgesFor)); bondEscalationAccounting.forTest_setEscalationResult( _disputeId, _requestId, token, _amount, IBondEscalationModule(_bondEscalationModule) ); - bondEscalationAccounting.forTest_setPledge(_disputeId, token, _amount * _pledges * 2); + bondEscalationAccounting.forTest_setPledge(_disputeId, token, _amount * (_pledgesAgainst + _pledgesFor)); // Mock and expect to call the oracle getting the dispute status _mockAndExpect( @@ -563,25 +565,25 @@ contract BondEscalationAccounting_Unit_ClaimEscalationReward is BaseTest { _mockAndExpect( _bondEscalationModule, abi.encodeCall(IBondEscalationModule.pledgesAgainstDispute, (_requestId, pledger)), - abi.encode(_pledges) + abi.encode(_pledgesAgainst) ); // Mock and expect the call to the escalation module asking for pledges _mockAndExpect( _bondEscalationModule, abi.encodeCall(IBondEscalationModule.pledgesForDispute, (_requestId, pledger)), - abi.encode(_pledges) + abi.encode(_pledgesFor) ); // Check: is the event emitted? vm.expectEmit(true, true, true, true, address(bondEscalationAccounting)); - emit EscalationRewardClaimed(_requestId, _disputeId, pledger, token, _amount * _pledges * 2); + emit EscalationRewardClaimed(_requestId, _disputeId, pledger, token, _amount * (_pledgesAgainst + _pledgesFor)); vm.prank(_bondEscalationModule); bondEscalationAccounting.claimEscalationReward(_disputeId, pledger); // Check: is the balance of the pledger properly updated? - assertEq(bondEscalationAccounting.balanceOf(pledger, token), _amount * _pledges * 2); + assertEq(bondEscalationAccounting.balanceOf(pledger, token), _amount * (_pledgesAgainst + _pledgesFor)); // Check: is the reward marked as claimed for the pledger? assertTrue(bondEscalationAccounting.pledgerClaimed(_requestId, pledger));