From 940f1259c3ec6a2317c6df18bab8ae02d1cf2f29 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 13:20:14 -0400 Subject: [PATCH 01/20] moved arbiter and min fee into the whitelisting struct --- contracts/DelphiStake.sol | 108 +++++++++++++++++++------------ contracts/DelphiStakeFactory.sol | 6 +- 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index 22fb3c3..bf13aa3 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -5,8 +5,8 @@ import "tokens/eip20/EIP20.sol"; contract DelphiStake { - event ClaimantWhitelisted(address _claimant); - event ClaimOpened(address _claimant, uint _claimId); + event ClaimantWhitelisted(address _claimant, uint _whitelistId, uint _deadline); + event ClaimOpened(address _claimant, uint _whitelistId, uint _claimId); event FeeIncreased(address _increasedBy, uint _claimId, uint _amount); event SettlementProposed(address _proposedBy, uint _claimId, uint _settlementId); event SettlementAccepted(address _acceptedBy, uint _claimId, uint _settlementId); @@ -18,6 +18,7 @@ contract DelphiStake { struct Claim { + uint whitelistId; address claimant; uint amount; uint fee; @@ -34,9 +35,14 @@ contract DelphiStake { bool claimantAgrees; } - address public masterCopy; // THIS MUST ALWAYS BE IN THE FIRST STORAGE SLOT + struct Whitelist { + address claimant; + address arbiter; + uint minimumFee; + uint deadline; + } - uint public minimumFee; + address public masterCopy; // THIS MUST ALWAYS BE IN THE FIRST STORAGE SLOT uint public claimableStake; EIP20 public token; @@ -44,7 +50,6 @@ contract DelphiStake { string public data; address public staker; - address public arbiter; uint public stakeReleaseTime; @@ -52,7 +57,7 @@ contract DelphiStake { uint public openClaims; mapping(uint => Settlement[]) public settlements; - mapping(address => uint) public whitelistedDeadlines; + Whitelist[] public whitelists; modifier onlyStaker(){ require(msg.sender == staker); @@ -69,13 +74,13 @@ contract DelphiStake { _; } - modifier notStakerOrArbiter(){ - require(msg.sender != staker && msg.sender != arbiter); + modifier validWhitelistId(uint _whitelistId){ + require(_whitelistId < whitelists.length); _; } - modifier onlyArbiter(){ - require(msg.sender == arbiter); + modifier onlyArbiter(uint _claimId){ + require(msg.sender == whitelists[claims[_claimId].whitelistId].arbiter); _; } @@ -84,8 +89,13 @@ contract DelphiStake { _; } - modifier largeEnoughFee(uint _newFee){ - require(_newFee >= minimumFee); + modifier isBeforeDeadline(uint _whitelistId){ + require(now <= whitelists[_whitelistId].deadline); + _; + } + + modifier largeEnoughFee(uint _whitelistId, uint _newFee){ + require(_newFee >= whitelists[_whitelistId].minimumFee); _; } @@ -114,8 +124,8 @@ contract DelphiStake { _; } - modifier onlyWhitelistedClaimant(){ - require(whitelistedDeadlines[msg.sender] >= now); + modifier onlyWhitelistedClaimant(uint _whitelistId){ + require(msg.sender == whitelists[_whitelistId].claimant); _; } @@ -135,13 +145,11 @@ contract DelphiStake { @param _staker the address which is creating the stake through the proxy contract @param _value the value of the stake in token units @param _token the address of the token being deposited - @param _minimumFee the minimum fee which must be deposited by both parties for each claim @param _data a content hash of the relevant associated data describing the stake @param _claimDeadline the deadline for opening new cliams; the earliest moment that a stake can be withdrawn by the staker - @param _arbiter the address which is able to rule on open claims */ - function initDelphiStake(address _staker, uint _value, EIP20 _token, uint _minimumFee, string _data, uint _stakeReleaseTime, address _arbiter) + function initDelphiStake(address _staker, uint _value, EIP20 _token, string _data, uint _stakeReleaseTime) public { require(_stakeReleaseTime > now); @@ -150,19 +158,14 @@ contract DelphiStake { // set to 0 when it was called previously. require(token == address(0)); - // Require reasonable inputs - require(_arbiter != address(0)); - // Revert if the specified value to stake cannot be transferred in require(_token.transferFrom(msg.sender, this, _value)); // Initialize contract storage. claimableStake = _value; token = _token; - minimumFee = _minimumFee; data = _data; stakeReleaseTime = _stakeReleaseTime; - arbiter = _arbiter; staker = _staker; } @@ -171,26 +174,29 @@ contract DelphiStake { "whitelisted for claims" such that a clear path exists for the adjudication of disputes should one arise in the course of events. @param _claimant an address which, once whitelisted, can make claims against this stake + @param _arbiter an address which will rule on any claims this whitelisted claimant will open + @param _minimumFee the minum fee the new claimant must deposit when opening a claim @param _deadline the timestamp before which the whitelisted individual may open a claim */ - function whitelistClaimant(address _claimant, uint _deadline) + function whitelistClaimant(address _claimant, address _arbiter, uint _minimumFee, uint _deadline) public onlyStaker { - // the new deadline should be greater than the existing one - require(_deadline >= whitelistedDeadlines[_claimant]); + // the new claimant cannot be the same address as the staker or arbiter + require(_claimant != staker && _claimant != _arbiter); - // Whitelist the claimant by setting their entry in the whitelistedDeadlines mapping to their deadline - whitelistedDeadlines[_claimant] = _deadline; + // Whitelist the claimant by adding their entry in the whitelists array + whitelists.push(Whitelist(_claimant, _arbiter, _minimumFee, _deadline)); // Emit an event noting that this claimant was whitelisted - ClaimantWhitelisted(_claimant); + ClaimantWhitelisted(_claimant, whitelists.length - 1, _deadline); } /* @dev a whitelisted claimant can use this function to make a claim for remuneration. Once opened, an opportunity for pre-arbitration settlement will commence, but claims cannot be unilaterally cancelled. + @param _whitelistId the index of the whitelisting corresponding to the claim @param _amount the size of the claim being made, denominated in the stake's token. Must be less than or equal to the current amount of stake not locked up in other disputes, minus the fee deposited. @param _fee the size of the fee, denominated in the stake's token, to be offered to the arbiter @@ -199,12 +205,13 @@ contract DelphiStake { @param _data an arbitrary string, perhaps an IPFS hash, containing data substantiating the basis for the claim. */ - function openClaim(uint _amount, uint _fee, string _data) + function openClaim(uint _whitelistId, uint _amount, uint _fee, string _data) public - notStakerOrArbiter + validWhitelistId(_whitelistId) stakerCanPay(_amount, _fee) - onlyWhitelistedClaimant - largeEnoughFee(_fee) + onlyWhitelistedClaimant(_whitelistId) + isBeforeDeadline(_whitelistId) + largeEnoughFee(_whitelistId, _fee) { // Transfer the fee into the DelphiStake require(token.transferFrom(msg.sender, this, _fee)); @@ -212,7 +219,7 @@ contract DelphiStake { // Add a new claim to the claims array and increment the openClaims counter. Because there // is necessarily at least one open claim now, pause any active withdrawal (lockup) // countdown. - claims.push(Claim(msg.sender, _amount, _fee, 0, _data, 0, false, false)); + claims.push(Claim(_whitelistId, msg.sender, _amount, _fee, 0, _data, 0, false, false)); openClaims ++; // The claim amount and claim fee are reserved for this particular claim until the arbiter @@ -221,12 +228,13 @@ contract DelphiStake { // Emit an event that a claim was opened by the message sender (not the claimant), and // include the claim's ID. - ClaimOpened(msg.sender, claims.length - 1); + ClaimOpened(msg.sender, _whitelistId, claims.length - 1); } /* @dev a whitelisted claimant can use this function to make a claim for remuneration. Opened claims will proceed directly to full arbitration, when their claims can be ruled upon. + @param _whitelistId the index of the whitelist corresponding to the new claim @param _claimant the entity which will act as the claimant in the course of the adjudication. @param _amount the size of the claim being made, denominated in the stake's token. Must be less than or equal to the current amount of stake not locked up in other disputes, minus the fee deposited. @@ -236,15 +244,16 @@ contract DelphiStake { @param _data an arbitrary string, perhaps an IPFS hash, containing data substantiating the basis for the claim. */ - function openClaimWithoutSettlement(uint _amount, uint _fee, string _data) + function openClaimWithoutSettlement(uint _whitelistId, uint _amount, uint _fee, string _data) public - notStakerOrArbiter + validWhitelistId(_whitelistId) stakerCanPay(_amount, _fee) - onlyWhitelistedClaimant - largeEnoughFee(_fee) + onlyWhitelistedClaimant(_whitelistId) + isBeforeDeadline(_whitelistId) + largeEnoughFee(_whitelistId, _fee) { require(token.transferFrom(msg.sender, this, _fee)); - claims.push(Claim(msg.sender, _amount, _fee, 0, _data, 0, false, true)); + claims.push(Claim(_whitelistId, msg.sender, _amount, _fee, 0, _data, 0, false, true)); openClaims ++; // The claim amount and claim fee are reserved for this particular claim until the arbiter @@ -252,7 +261,7 @@ contract DelphiStake { claimableStake -= (_amount + _fee); // the claim amount and claim fee are locked up in this contract until the arbiter rules - ClaimOpened(msg.sender, claims.length - 1); + ClaimOpened(msg.sender, _whitelistId, claims.length - 1); } /* @@ -387,12 +396,13 @@ contract DelphiStake { */ function ruleOnClaim(uint _claimId, uint _ruling) public - onlyArbiter + onlyArbiter(_claimId) validClaimID(_claimId) claimNotRuled(_claimId) settlementDidFail(_claimId) { Claim storage claim = claims[_claimId]; + address arbiter = msg.sender; // Set the claim's ruled flag to true, and record the ruling. claim.ruled = true; @@ -416,7 +426,7 @@ contract DelphiStake { } else if (_ruling == 3){ // The claim cannot be ruled. Free up the claim amount and fee. claimableStake += (claim.amount + claim.fee); - require(token.transfer(claim.claimant, (claim.amount + claim.fee))); + require(token.transfer(claim.claimant, (claim.fee))); // TODO: send fsurplus to arbiters } else { revert(); @@ -487,6 +497,20 @@ contract DelphiStake { return claims.length; } + /* + @dev Getter function to return the total number of whitelists which have ever been made against + this stake. + */ + function getNumWhitelists() + public + view + returns (uint) + { + // Return the length of the claims array. Claims are never removed from this array, no matter + // if or how they are resolved. + return whitelists.length; + } + /* @dev Getter function to return the total available fee for any historical claim */ diff --git a/contracts/DelphiStakeFactory.sol b/contracts/DelphiStakeFactory.sol index 7235a56..06c4057 100644 --- a/contracts/DelphiStakeFactory.sol +++ b/contracts/DelphiStakeFactory.sol @@ -23,13 +23,11 @@ contract DelphiStakeFactory { initialialize their stake, depositing their tokens @param _value the value of the stake in token units @param _token the address of the token being deposited - @param _minimumFee the minimum fee which must be deposited by both parties for each claim @param _data a content hash of the relevant associated data describing the stake @param _claimDeadline the deadline for opening new cliams; the earliest moment that a stake can be withdrawn by the staker - @param _arbiter the address which is able to rule on open claims */ - function createDelphiStake(uint _value, EIP20 _token, uint _minimumFee, string _data, uint _stakeReleaseTime, address _arbiter) + function createDelphiStake(uint _value, EIP20 _token, string _data, uint _stakeReleaseTime) public { // Revert if the specified value to stake cannot be transferred in @@ -42,7 +40,7 @@ contract DelphiStakeFactory { _token.approve(newStake, _value); // Initialize the stake and set the staker address as the msg.sender - stakes[stakes.length - 1].initDelphiStake(msg.sender, _value, _token, _minimumFee, _data, _stakeReleaseTime, _arbiter); + stakes[stakes.length - 1].initDelphiStake(msg.sender, _value, _token, _data, _stakeReleaseTime); StakeCreated(stakes.length - 1, stakes[stakes.length - 1]); } From afe116487255e9a14124bc8c6ed31b4578e9534b Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 13:22:46 -0400 Subject: [PATCH 02/20] forces the party rejecting settlement to submit a string with their reasoning for rejection --- contracts/DelphiStake.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index bf13aa3..9dc139d 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -10,7 +10,7 @@ contract DelphiStake { event FeeIncreased(address _increasedBy, uint _claimId, uint _amount); event SettlementProposed(address _proposedBy, uint _claimId, uint _settlementId); event SettlementAccepted(address _acceptedBy, uint _claimId, uint _settlementId); - event SettlementFailed(address _failedBy, uint _claimId); + event SettlementFailed(address _failedBy, uint _claimId, string _data); event ClaimRuled(uint _claimId); event ReleaseTimeIncreased(uint _stakeReleaseTime); event StakeWithdrawn(); @@ -370,8 +370,9 @@ contract DelphiStake { @dev Either party in a claim can call settlementFailed at any time to move the claim from settlement to arbitration. @param _claimId the ID of the claim to reject settlement for + @param _data the IPFS hash of a json object detailing the reason for rejecting settlements */ - function settlementFailed(uint _claimId) + function settlementFailed(uint _claimId, string _data) public validClaimID(_claimId) onlyStakerOrClaimant(_claimId) @@ -383,7 +384,7 @@ contract DelphiStake { // Emit an event stating who rejected the settlement, and for which claim settlement was // rejected. - SettlementFailed(msg.sender, _claimId); + SettlementFailed(msg.sender, _claimId, _data); } /* From 1b77295015e21da6622721e27c55b07e38c545cb Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 13:24:10 -0400 Subject: [PATCH 03/20] adds a new openClaimWithoutSettlement event --- contracts/DelphiStake.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index 9dc139d..1746578 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -7,6 +7,7 @@ contract DelphiStake { event ClaimantWhitelisted(address _claimant, uint _whitelistId, uint _deadline); event ClaimOpened(address _claimant, uint _whitelistId, uint _claimId); + event ClaimOpenedWithoutSettlement(address _claimant, uint _whitelistId, uint _claimId); event FeeIncreased(address _increasedBy, uint _claimId, uint _amount); event SettlementProposed(address _proposedBy, uint _claimId, uint _settlementId); event SettlementAccepted(address _acceptedBy, uint _claimId, uint _settlementId); @@ -261,7 +262,7 @@ contract DelphiStake { claimableStake -= (_amount + _fee); // the claim amount and claim fee are locked up in this contract until the arbiter rules - ClaimOpened(msg.sender, _whitelistId, claims.length - 1); + ClaimOpenedWithoutSettlement(msg.sender, _whitelistId, claims.length - 1); } /* From 0e1df3c5804a4e568f1ac38584cff8be9edc0fad Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 13:31:01 -0400 Subject: [PATCH 04/20] adds whitelist deadline extension, string submission --- contracts/DelphiStake.sol | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index 1746578..d36ef75 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -5,7 +5,8 @@ import "tokens/eip20/EIP20.sol"; contract DelphiStake { - event ClaimantWhitelisted(address _claimant, uint _whitelistId, uint _deadline); + event ClaimantWhitelisted(address _claimant, uint _whitelistId, uint _deadline, string _data); + event WhitelistDeadlineExtended(uint _whitelistId, uint _newDeadline); event ClaimOpened(address _claimant, uint _whitelistId, uint _claimId); event ClaimOpenedWithoutSettlement(address _claimant, uint _whitelistId, uint _claimId); event FeeIncreased(address _increasedBy, uint _claimId, uint _amount); @@ -178,8 +179,9 @@ contract DelphiStake { @param _arbiter an address which will rule on any claims this whitelisted claimant will open @param _minimumFee the minum fee the new claimant must deposit when opening a claim @param _deadline the timestamp before which the whitelisted individual may open a claim + @param _data an IPFS hash representing the scope and terms of the whitelisting */ - function whitelistClaimant(address _claimant, address _arbiter, uint _minimumFee, uint _deadline) + function whitelistClaimant(address _claimant, address _arbiter, uint _minimumFee, uint _deadline, string _data) public onlyStaker { @@ -190,9 +192,29 @@ contract DelphiStake { whitelists.push(Whitelist(_claimant, _arbiter, _minimumFee, _deadline)); // Emit an event noting that this claimant was whitelisted - ClaimantWhitelisted(_claimant, whitelists.length - 1, _deadline); + ClaimantWhitelisted(_claimant, whitelists.length - 1, _deadline, _data); } + /* + @dev if a staker desires, they may extend the deadline before which a particular claimant may open a claim + @param _whitelistId the index of the whitelisting whose deadline is being extended + @param _newDeadline the new deadline for opening claims + */ + function extendClaimDeadline(uint _whitelistId, uint _newDeadline) + public + onlyStaker + { + // the new deadline must be greater than the existing deadline + require(_newDeadline > whitelists[_whitelistId].deadline); + + whitelists[_whitelistId].deadline = _newDeadline; + + // Emit an event noting that this whitelisting's deadline was extended + WhitelistDeadlineExtended(_whitelistId, _newDeadline); + } + + + /* @dev a whitelisted claimant can use this function to make a claim for remuneration. Once opened, an opportunity for pre-arbitration settlement will commence, but claims cannot be From fac129cf1943752086ff22011d9be0619f5a351a Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 13:43:08 -0400 Subject: [PATCH 05/20] removes possible re-entrancy attacks from token transfers --- contracts/DelphiStake.sol | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index d36ef75..4f2e34c 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -160,15 +160,15 @@ contract DelphiStake { // set to 0 when it was called previously. require(token == address(0)); - // Revert if the specified value to stake cannot be transferred in - require(_token.transferFrom(msg.sender, this, _value)); - // Initialize contract storage. claimableStake = _value; token = _token; data = _data; stakeReleaseTime = _stakeReleaseTime; staker = _staker; + + // Revert if the specified value to stake cannot be transferred in + require(_token.transferFrom(msg.sender, this, _value)); } /* @@ -236,9 +236,6 @@ contract DelphiStake { isBeforeDeadline(_whitelistId) largeEnoughFee(_whitelistId, _fee) { - // Transfer the fee into the DelphiStake - require(token.transferFrom(msg.sender, this, _fee)); - // Add a new claim to the claims array and increment the openClaims counter. Because there // is necessarily at least one open claim now, pause any active withdrawal (lockup) // countdown. @@ -249,6 +246,9 @@ contract DelphiStake { // rules claimableStake -= (_amount + _fee); + // Transfer the fee into the DelphiStake + require(token.transferFrom(msg.sender, this, _fee)); + // Emit an event that a claim was opened by the message sender (not the claimant), and // include the claim's ID. ClaimOpened(msg.sender, _whitelistId, claims.length - 1); @@ -275,7 +275,6 @@ contract DelphiStake { isBeforeDeadline(_whitelistId) largeEnoughFee(_whitelistId, _fee) { - require(token.transferFrom(msg.sender, this, _fee)); claims.push(Claim(_whitelistId, msg.sender, _amount, _fee, 0, _data, 0, false, true)); openClaims ++; @@ -284,6 +283,8 @@ contract DelphiStake { claimableStake -= (_amount + _fee); // the claim amount and claim fee are locked up in this contract until the arbiter rules + require(token.transferFrom(msg.sender, this, _fee)); + ClaimOpenedWithoutSettlement(msg.sender, _whitelistId, claims.length - 1); } @@ -300,11 +301,12 @@ contract DelphiStake { claimNotRuled(_claimId) settlementDidFail(_claimId) { - // Transfer tokens from the message sender to this contract and increment the surplusFee // record for this claim by the amount transferred. - require(token.transferFrom(msg.sender, this, _amount)); claims[_claimId].surplusFee += _amount; + // Transfer tokens from the message sender to this contract and increment the surplusFee + require(token.transferFrom(msg.sender, this, _amount)); + // Emit a FeeIncreased event including data on who increased the fee, which claim the fee was // increased for, and by what amount. FeeIncreased(msg.sender, _claimId, _amount); @@ -471,10 +473,12 @@ contract DelphiStake { public onlyStaker { - // Transfer _value tokens from the message sender into this contract, and increment the // claimableStake by _value. - require(token.transferFrom(msg.sender, this, _value)); claimableStake += _value; + + // Transfer _value tokens from the message sender into this contract, and increment the + require(token.transferFrom(msg.sender, this, _value)); + StakeIncreased(msg.sender, _value); } From 5217bb184fb71b396d58c54cd6bce8cd2036e16a Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 13:56:16 -0400 Subject: [PATCH 06/20] removed the ruled bool --- contracts/DelphiStake.sol | 32 +++++++++++++++----------------- contracts/DelphiVoting.sol | 16 ++++++++-------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index 4f2e34c..f5d2ff7 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -27,7 +27,6 @@ contract DelphiStake { uint surplusFee; string data; uint ruling; - bool ruled; bool settlementFailed; } @@ -102,7 +101,7 @@ contract DelphiStake { } modifier claimNotRuled(uint _claimId){ - require(!claims[_claimId].ruled); + require(claims[_claimId].ruling == 0); _; } @@ -239,7 +238,7 @@ contract DelphiStake { // Add a new claim to the claims array and increment the openClaims counter. Because there // is necessarily at least one open claim now, pause any active withdrawal (lockup) // countdown. - claims.push(Claim(_whitelistId, msg.sender, _amount, _fee, 0, _data, 0, false, false)); + claims.push(Claim(_whitelistId, msg.sender, _amount, _fee, 0, _data, 0, false)); openClaims ++; // The claim amount and claim fee are reserved for this particular claim until the arbiter @@ -275,7 +274,7 @@ contract DelphiStake { isBeforeDeadline(_whitelistId) largeEnoughFee(_whitelistId, _fee) { - claims.push(Claim(_whitelistId, msg.sender, _amount, _fee, 0, _data, 0, false, true)); + claims.push(Claim(_whitelistId, msg.sender, _amount, _fee, 0, _data, 0, true)); openClaims ++; // The claim amount and claim fee are reserved for this particular claim until the arbiter @@ -373,11 +372,11 @@ contract DelphiStake { require (settlement.claimantAgrees && settlement.stakerAgrees && !claim.settlementFailed && - !claim.ruled); + claim.ruling == 0); - // Set this claim's ruled flag to true to prevent further actions (settlements or + // Set this claim's ruling to 5 to prevent further actions (settlements or // arbitration) being taken against this claim. - claim.ruled = true; + claim.ruling = 5; // Increase the stake's claimable stake by the claim amount and fee, minus the agreed // settlement amount. Then decrement the openClaims counter, since this claim is resolved. @@ -430,32 +429,31 @@ contract DelphiStake { Claim storage claim = claims[_claimId]; address arbiter = msg.sender; - // Set the claim's ruled flag to true, and record the ruling. - claim.ruled = true; - claim.ruling = _ruling; - - if (_ruling == 0){ + if (_ruling == 1){ + claim.ruling = 1; // The claim is justified. Transfer to the arbiter their fee. require(token.transfer(arbiter, (claim.fee + claim.surplusFee))); require(token.transfer(claim.claimant, (claim.amount + claim.fee))); - } else if (_ruling == 1){ + } else if (_ruling == 2){ + claim.ruling = 2; + // The claim is not justified. Free up the claim amount and fee for future claims, and // transfer to the arbiter their fee. claimableStake += (claim.amount + claim.fee); require(token.transfer(arbiter, (claim.fee + claim.surplusFee))); - } else if (_ruling == 2){ + } else if (_ruling == 3){ + claim.ruling = 3; + // The claim is collusive. Transfer to the arbiter both the staker and claimant fees, and // burn the claim amount. require(token.transfer(arbiter, (claim.fee + claim.fee + claim.surplusFee))); require(token.transfer(address(0), claim.amount)); // burns the claim amount in the event of collusion - } else if (_ruling == 3){ + } else { // The claim cannot be ruled. Free up the claim amount and fee. claimableStake += (claim.amount + claim.fee); require(token.transfer(claim.claimant, (claim.fee))); // TODO: send fsurplus to arbiters - } else { - revert(); } // The claim is ruled. Decrement the total number of open claims. diff --git a/contracts/DelphiVoting.sol b/contracts/DelphiVoting.sol index 24a0a83..1571061 100644 --- a/contracts/DelphiVoting.sol +++ b/contracts/DelphiVoting.sol @@ -255,10 +255,10 @@ contract DelphiVoting { // (totalFee * percentageOfFeeNotReservedForGuaranteedPayouts) * // (winningFactionSize / totalReveals) / // winningFactionSize - // + // // Now an explanation of the above mapped the to the actual equation below. I've identified // each line in the actual equation with a letter. - // + // // On the first line we compute the guaranteed fee. (A + B). // On the second line we compute the number of tokens not reserved in this fee for // guaranteed payouts. (C + D) @@ -281,7 +281,7 @@ contract DelphiVoting { ((claim.tallies[_vote] * 100) / // E (claim.tallies[0] + claim.tallies[1] + claim.tallies[2] + claim.tallies[3])) / // F claim.tallies[_vote]; // G - + // Transfer the arbiter their owed fee require(ds.token().transfer(msg.sender, arbiterFee)); @@ -351,7 +351,7 @@ contract DelphiVoting { } /* - @dev utility function for determining whether a claim has been ruled. Used by claimFee to + @dev utility function for determining whether a claim has been ruled. Used by claimFee to determine whether fees should be disbured. @param _stake the DelphiStake whose storage is to be inspected. @param _claimNumber the unique claim number we are determining if a ruling has been submitted @@ -360,13 +360,13 @@ contract DelphiVoting { */ function claimIsRuled(address _stake, uint _claimNumber) public view returns (bool) { DelphiStake ds = DelphiStake(_stake); - bool ruled; + uint ruling; bool settlementFailed; // Tuple destructuring. settlementFailed is a throwaway value, but is needed by the compiler. - (, ruled, settlementFailed) = ds.claims(_claimNumber); + (, ruling, settlementFailed) = ds.claims(_claimNumber); - return ruled; + return (ruling > 0 && ruling < 5); } /* @@ -392,7 +392,7 @@ contract DelphiVoting { // previousArbiter is the null node. The _arbiter was the first to commit. Its rank is 0. if(previousArbiter == address(0)) { return 0; - } + } // The previous arbiter's previous arbiter is the null node, meaning the previous arbiter // was the first to commit From 00db72a91ead30f5ef8f963a46e68de2b61983e1 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 13:58:24 -0400 Subject: [PATCH 07/20] fixed comment --- contracts/DelphiStake.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index f5d2ff7..9270a76 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -235,9 +235,7 @@ contract DelphiStake { isBeforeDeadline(_whitelistId) largeEnoughFee(_whitelistId, _fee) { - // Add a new claim to the claims array and increment the openClaims counter. Because there - // is necessarily at least one open claim now, pause any active withdrawal (lockup) - // countdown. + // Add a new claim to the claims array and increment the openClaims counter claims.push(Claim(_whitelistId, msg.sender, _amount, _fee, 0, _data, 0, false)); openClaims ++; From b006dab25c6fcbe81c04d3a395d6d9a01a4ab0a7 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 14:02:29 -0400 Subject: [PATCH 08/20] transfers surplus fee to arbiters in the event of ruling 4 --- contracts/DelphiStake.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index 9270a76..7b03151 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -451,7 +451,11 @@ contract DelphiStake { // The claim cannot be ruled. Free up the claim amount and fee. claimableStake += (claim.amount + claim.fee); require(token.transfer(claim.claimant, (claim.fee))); - // TODO: send fsurplus to arbiters + + // transfers of 0 tokens will throw automatically + if (claim.surplusFee > 0){ + require(token.transfer(arbiter, (claim.surplusFee))); + } } // The claim is ruled. Decrement the total number of open claims. From 714f58f46db70e0253a22bd4d93793e8ba0550dd Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 14:05:37 -0400 Subject: [PATCH 09/20] removes onlyStakerOrClaimant modifier, moves into body logic --- contracts/DelphiStake.sol | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index 7b03151..b6f095a 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -120,11 +120,6 @@ contract DelphiStake { _; } - modifier onlyStakerOrClaimant(uint _claimId){ - require(msg.sender == staker || msg.sender == claims[_claimId].claimant); - _; - } - modifier onlyWhitelistedClaimant(uint _whitelistId){ require(msg.sender == whitelists[_whitelistId].claimant); _; @@ -319,7 +314,6 @@ contract DelphiStake { function proposeSettlement(uint _claimId, uint _amount) public validClaimID(_claimId) - onlyStakerOrClaimant(_claimId) settlementDidNotFail(_claimId) { // Only allow settlements for up to the amount that has been reserved (locked) for this claim @@ -329,8 +323,10 @@ contract DelphiStake { // settlement, set their "agrees" flag to true upon proposal. if (msg.sender == staker){ settlements[_claimId].push(Settlement(_amount, true, false)); - } else { + } else if (msg.sender == claims[_claimId].claimant){ settlements[_claimId].push(Settlement(_amount, false, true)); + } else { + revert(); } // Emit an event including the settlement proposed, the claimID the settlement is proposed @@ -349,7 +345,6 @@ contract DelphiStake { public validClaimID(_claimId) validSettlementId(_claimId, _settlementId) - onlyStakerOrClaimant(_claimId) settlementDidNotFail(_claimId) { Settlement storage settlement = settlements[_claimId][_settlementId]; @@ -358,8 +353,10 @@ contract DelphiStake { // Depending on who sent this message, set their agreement flag in the settlement to true if (msg.sender == staker){ settlement.stakerAgrees = true; - } else { + } else if (msg.sender == claims[_claimId].claimant){ settlement.claimantAgrees = true; + } else { + revert(); } // Check if all conditions are met for the settlement to be agreed, and revert otherwise. @@ -397,9 +394,10 @@ contract DelphiStake { function settlementFailed(uint _claimId, string _data) public validClaimID(_claimId) - onlyStakerOrClaimant(_claimId) settlementDidNotFail(_claimId) { + require(msg.sender == staker || msg.sender == claims[_claimId].claimant); + // Set the claim's settlementFailed flag to true, preventing further settlement proposals // and settlement agreements. claims[_claimId].settlementFailed = true; From 317584c6ac720b12f8ca3e3590ca6f9c29df65b8 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 14:08:06 -0400 Subject: [PATCH 10/20] adds getNumSettlements function --- contracts/DelphiStake.sol | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index b6f095a..c985960 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -537,6 +537,21 @@ contract DelphiStake { return whitelists.length; } + /* + @dev Getter function to return the total number of settlements which have ever been made for + this claim. + @param _claimId the index of the claim + */ + function getNumSettlements(uint _claimId) + public + view + returns (uint) + { + // Return the length of the settlements array. Settlements are never removed from this array, no matter + // if or how they are resolved. + return settlements[_claimId].length; + } + /* @dev Getter function to return the total available fee for any historical claim */ From 38cff3a0369b7a6c08ae93b0db66ea79cac8043c Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 14:09:59 -0400 Subject: [PATCH 11/20] removes settlementdidnotfail from acceptSettlement function --- contracts/DelphiStake.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index c985960..cd05d70 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -345,7 +345,6 @@ contract DelphiStake { public validClaimID(_claimId) validSettlementId(_claimId, _settlementId) - settlementDidNotFail(_claimId) { Settlement storage settlement = settlements[_claimId][_settlementId]; Claim storage claim = claims[_claimId]; From d55822e2e9ea69cebe7a8e595d4880c3c053813f Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 14:12:03 -0400 Subject: [PATCH 12/20] fixes faulty comments --- contracts/DelphiStake.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index cd05d70..b4f158d 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -13,7 +13,7 @@ contract DelphiStake { event SettlementProposed(address _proposedBy, uint _claimId, uint _settlementId); event SettlementAccepted(address _acceptedBy, uint _claimId, uint _settlementId); event SettlementFailed(address _failedBy, uint _claimId, string _data); - event ClaimRuled(uint _claimId); + event ClaimRuled(uint _claimId, uint _ruling); event ReleaseTimeIncreased(uint _stakeReleaseTime); event StakeWithdrawn(); event StakeIncreased(address _increasedBy, uint _value); @@ -459,7 +459,7 @@ contract DelphiStake { openClaims--; // Emit an event stating which claim was ruled. - ClaimRuled(_claimId); + ClaimRuled(_claimId, _ruling); } /* @@ -480,8 +480,8 @@ contract DelphiStake { } /* - @dev Increases the deadline for opening claims - @param _newClaimDeadline the unix time stamp (in seconds) before which claims may be opened + @dev Increases the stake release time + @param _stakeReleaseTime the new stake release time */ function extendStakeReleaseTime(uint _stakeReleaseTime) public From b81c53c5d0a6209e9d0e15dc198389782b6055f5 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Sun, 29 Jul 2018 14:19:30 -0400 Subject: [PATCH 13/20] lets stakers withdraw a custom amount --- contracts/DelphiStake.sol | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index b4f158d..fc6cb16 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -15,7 +15,7 @@ contract DelphiStake { event SettlementFailed(address _failedBy, uint _claimId, string _data); event ClaimRuled(uint _claimId, uint _ruling); event ReleaseTimeIncreased(uint _stakeReleaseTime); - event StakeWithdrawn(); + event StakeWithdrawn(uint _amount); event StakeIncreased(address _increasedBy, uint _value); @@ -494,18 +494,17 @@ contract DelphiStake { /* @dev Returns the stake to the staker, if the claim deadline has elapsed and no open claims remain - @param _newClaimDeadline the unix time stamp (in seconds) before which claims may be opened + @param _amount the number of tokens that the staker wishes to withdraw */ - function withdrawStake() + function withdrawStake(uint _amount) public onlyStaker stakeIsReleased noOpenClaims { - uint oldStake = claimableStake; - claimableStake = 0; - require(token.transfer(staker, oldStake)); - StakeWithdrawn(); + claimableStake -= _amount; + require(token.transfer(staker, _amount)); + StakeWithdrawn(_amount); } /* From 027931e69c0cadc8fccbe92b2c70fe0b42f7e403 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Mon, 30 Jul 2018 17:16:43 -0400 Subject: [PATCH 14/20] fixing tests v0 --- test/js/DelphiStake/DelphiStake.js | 29 +++++++---------------------- test/js/DelphiVoting/claimFee.js | 2 +- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/test/js/DelphiStake/DelphiStake.js b/test/js/DelphiStake/DelphiStake.js index 9e20a71..ab7d1dc 100644 --- a/test/js/DelphiStake/DelphiStake.js +++ b/test/js/DelphiStake/DelphiStake.js @@ -23,8 +23,8 @@ contract('DelphiStake', (accounts) => { }); it('should instantiate the contract with the expected values', async () => { - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); const stake = await ds.claimableStake.call(); assert.strictEqual(stake.toString(10), conf.initialStake, @@ -41,9 +41,6 @@ contract('DelphiStake', (accounts) => { assert.strictEqual(deadline.toString(10), conf.deadline, 'the deadline was initialized improperly'); - const storedArbiter = await ds.arbiter.call(); - assert.strictEqual(arbiter, storedArbiter, 'the arbiter was initialized improperly'); - const balance = await token.balanceOf(ds.address); assert.strictEqual(balance.toString(10), stake.toString(10), 'the contract\'s balance and stake did not match'); }); @@ -51,7 +48,7 @@ contract('DelphiStake', (accounts) => { it('should revert when _value does not equal the amount of tokens sent', async () => { try { await utils.as(staker, ds.initDelphiStake, staker, conf.initialStake + 100, token.address, - conf.minFee, conf.data, conf.deadline, arbiter); + conf.data, conf.deadline); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -61,12 +58,12 @@ contract('DelphiStake', (accounts) => { }); it('should revert when trying to call the initialize function more than once', async () => { - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); try { await utils.as(staker, ds.initDelphiStake, staker, conf.initialStake, token.address, - conf.minFee, conf.data, conf.deadline, arbiter); + conf.data, conf.deadline); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -78,7 +75,7 @@ contract('DelphiStake', (accounts) => { it('should revert when trying to call the initialize function with a deadline that is before now', async () => { try { await utils.as(staker, ds.initDelphiStake, staker, conf.initialStake, token.address, - conf.minFee, conf.data, '1', arbiter); + conf.data, '1'); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -86,17 +83,5 @@ contract('DelphiStake', (accounts) => { } assert(false, 'did not revert after trying to call the initialize function with a deadline that is before now'); }); - - it('should revert when trying to initialize with an arbiter of address(0)', async () => { - try { - await utils.as(staker, ds.initDelphiStake, staker, conf.initialStake, token.address, - conf.minFee, conf.data, conf.deadline, '0x0'); - } catch (err) { - assert(utils.isEVMRevert(err), err.toString()); - - return; - } - assert(false, 'did not revert after trying to initialize with an arbiter of address(0)'); - }); }); }); diff --git a/test/js/DelphiVoting/claimFee.js b/test/js/DelphiVoting/claimFee.js index 20ccf8d..e2e41ea 100644 --- a/test/js/DelphiVoting/claimFee.js +++ b/test/js/DelphiVoting/claimFee.js @@ -80,7 +80,7 @@ contract('DelphiVoting', (accounts) => { await registry.updateStatus(solkeccak(arbiterGale)); await registry.updateStatus(solkeccak(arbiterHenry)); - // Create a DelphiVoting with 100 second voting periods, fee decay value of five, + // Create a DelphiVoting with 100 second voting periods, fee decay value of five, // and which uses the registry we just created as its arbiter set const delphiVotingReceipt = await delphiVotingFactory.makeDelphiVoting(registry.address, 5, [solkeccak('parameterizerVotingPeriod'), solkeccak('commitStageLen'), From 0d5ee04486c6742144b2f7eaf29e675acb0e4335 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Mon, 30 Jul 2018 20:26:22 -0400 Subject: [PATCH 15/20] updated all of the tests to pass --- contracts/DelphiStake.sol | 2 +- test/js/DelphiStake/acceptSettlement.js | 16 +-- test/js/DelphiStake/extendStakeReleaseTime.js | 4 +- test/js/DelphiStake/finalizeWithdrawStake.js | 27 ++-- test/js/DelphiStake/increaseClaimFee.js | 20 +-- test/js/DelphiStake/increaseStake.js | 4 +- test/js/DelphiStake/openClaim.js | 121 +++++++--------- .../DelphiStake/openClaimWithoutSettlement.js | 134 ++++++------------ test/js/DelphiStake/proposeSettlement.js | 10 +- test/js/DelphiStake/ruleOnClaim.js | 48 +++---- test/js/DelphiStake/settlementFailed.js | 18 +-- test/js/DelphiStake/whitelistClaimant.js | 33 +++-- .../DelphiStakeFactory/createDelphiStake.js | 26 +--- test/js/DelphiVoting/claimFee.js | 28 ++-- test/js/DelphiVoting/commitVote.js | 14 +- test/js/DelphiVoting/revealVote.js | 14 +- test/js/DelphiVoting/submitRuling.js | 20 +-- test/js/utils.js | 13 +- 18 files changed, 240 insertions(+), 312 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index fc6cb16..5a93432 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -416,8 +416,8 @@ contract DelphiStake { */ function ruleOnClaim(uint _claimId, uint _ruling) public - onlyArbiter(_claimId) validClaimID(_claimId) + onlyArbiter(_claimId) claimNotRuled(_claimId) settlementDidFail(_claimId) { diff --git a/test/js/DelphiStake/acceptSettlement.js b/test/js/DelphiStake/acceptSettlement.js index d7b673a..e682e9b 100644 --- a/test/js/DelphiStake/acceptSettlement.js +++ b/test/js/DelphiStake/acceptSettlement.js @@ -28,15 +28,15 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, conf.initialStake, { from: staker }); await token.transfer(arbiter, 1000, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); const claimAmount = new BN('1', 10); const feeAmount = new BN('10', 10); await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); - await ds.openClaim(claimAmount, feeAmount, '', { from: claimant }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: staker }); + await ds.openClaim(0, claimAmount, feeAmount, '', { from: claimant }); }); it('Should revert if called with an out-of-bounds claimId', async () => { @@ -72,7 +72,7 @@ contract('DelphiStake', (accounts) => { it('Should revert if settlement has failed', async () => { await ds.proposeSettlement(0, 0, { from: staker }); - await ds.settlementFailed(0, { from: claimant }); + await ds.settlementFailed(0, "", { from: claimant }); try { await ds.acceptSettlement(0, 0, { from: claimant }); } catch (err) { @@ -138,7 +138,7 @@ contract('DelphiStake', (accounts) => { await ds.proposeSettlement(0, 0, { from: claimant }); - await ds.settlementFailed(0, { from: staker }); // As other party + await ds.settlementFailed(0, "", { from: staker }); // As other party try { // This function do not entry in {file:DelphiStake.sol,line 342} @@ -159,7 +159,7 @@ contract('DelphiStake', (accounts) => { await ds.acceptSettlement(0, 0, { from: staker }); const claim1 = await ds.claims.call('0'); - assert.strictEqual(claim1[6], true, 'Ruled bool is not correct'); + assert.strictEqual(parseInt(claim1[6], 10), 5, 'Ruling is not correct'); try { await ds.acceptSettlement(0, 0, { from: claimant }); @@ -173,7 +173,7 @@ contract('DelphiStake', (accounts) => { await ds.proposeSettlement(0, 0, { from: claimant }); await ds.acceptSettlement(0, 0, { from: staker }); const claim = await ds.claims.call('0'); - assert.strictEqual(claim[6], true, 'wrong ruled false, Expected true'); + assert.strictEqual(parseInt(claim[6], 10), 5, 'wrong ruled false, Expected true'); }); it('Should return the unused claim funds from the staker back to their stake', async () => { diff --git a/test/js/DelphiStake/extendStakeReleaseTime.js b/test/js/DelphiStake/extendStakeReleaseTime.js index bf4f71d..f7120b7 100644 --- a/test/js/DelphiStake/extendStakeReleaseTime.js +++ b/test/js/DelphiStake/extendStakeReleaseTime.js @@ -27,8 +27,8 @@ contract('DelphiStake', (accounts) => {// eslint-disable-line await token.approve(ds.address, conf.initialStake, { from: staker }); await token.transfer(arbiter, 1000, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); }); it('should revert if called by anyone but the staker', async () => { diff --git a/test/js/DelphiStake/finalizeWithdrawStake.js b/test/js/DelphiStake/finalizeWithdrawStake.js index 3ef4f6f..24b7326 100644 --- a/test/js/DelphiStake/finalizeWithdrawStake.js +++ b/test/js/DelphiStake/finalizeWithdrawStake.js @@ -35,12 +35,12 @@ contract('DelphiStake', (accounts) => { const tims = timeBlock.timestamp + 6; await utils.as(staker, ds.initDelphiStake, staker, conf.initialStake, token.address, - conf.minFee, conf.data, tims, arbiter); + conf.data, tims); }); it('should revert if called by any entity other than the staker', async () => { try { - await utils.as(claimant, ds.withdrawStake); + await utils.as(claimant, ds.withdrawStake, conf.initialStake); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); return; @@ -50,7 +50,7 @@ contract('DelphiStake', (accounts) => { }); it('should revert if called before the release time', async () => { try { - await utils.as(staker, ds.withdrawStake); + await utils.as(staker, ds.withdrawStake, conf.initialStake); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); return; @@ -66,13 +66,13 @@ contract('DelphiStake', (accounts) => { await utils.as(claimant, token.approve, ds.address, feeAmount); - await utils.as(staker, ds.whitelistClaimant, claimant, timeBlock.timestamp + 30); + await utils.as(staker, ds.whitelistClaimant, claimant, arbiter, conf.minFee, timeBlock.timestamp + 30, ""); - await utils.as(claimant, ds.openClaim, claimAmount, feeAmount, ''); + await utils.as(claimant, ds.openClaim, 0, claimAmount, feeAmount, ''); await utils.increaseTime(8000); try { - await utils.as(staker, ds.withdrawStake); + await utils.as(staker, ds.withdrawStake, conf.initialStake); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); return; @@ -83,14 +83,21 @@ contract('DelphiStake', (accounts) => { it('should set claimableStake to zero', async () => { await utils.increaseTime(5000); - await utils.as(staker, ds.withdrawStake); + await utils.as(staker, ds.withdrawStake, conf.initialStake); const claimableStake = await ds.claimableStake(); assert.strictEqual(claimableStake.toString(10), '0', 'claimableStake is not zero'); }); - it('should transfer the old stake amount to the staker', async () => { + it('should set claimableStake to remainder if amount is not full', async () => { + await utils.increaseTime(5000); + await utils.as(staker, ds.withdrawStake, (parseInt(conf.initialStake, 10) - 1)); + const claimableStake = await ds.claimableStake(); + assert.strictEqual(claimableStake.toString(10), '1', 'claimableStake is not 1'); + }); + + it('should transfer the desired amount to the staker', async () => { await utils.increaseTime(10000); - await utils.as(staker, ds.withdrawStake); + await utils.as(staker, ds.withdrawStake, conf.initialStake); const stakerCurrentBalance = await token.balanceOf(staker); assert.strictEqual(stakerCurrentBalance.toString(10), '899000', 'claimableStake doesnt withdraw correctly'); @@ -99,7 +106,7 @@ contract('DelphiStake', (accounts) => { it('should emit a StakeWithdrawn event', async () => { await utils.increaseTime(10000); - await ds.withdrawStake({ from: staker }).then((status) => { + await ds.withdrawStake(conf.initialStake, { from: staker }).then((status) => { assert.strictEqual('StakeWithdrawn', status.logs[0].event, 'did not emit the StakeWithdrawn event'); }); diff --git a/test/js/DelphiStake/increaseClaimFee.js b/test/js/DelphiStake/increaseClaimFee.js index 5f110f9..91eae61 100644 --- a/test/js/DelphiStake/increaseClaimFee.js +++ b/test/js/DelphiStake/increaseClaimFee.js @@ -26,17 +26,17 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, conf.initialStake, { from: staker }); await token.transfer(arbiter, 1000, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); const claimAmount = new BN('1', 10); const feeAmount = new BN('10', 10); await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: staker }); - await ds.openClaim(claimAmount, feeAmount, '', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, '', { from: claimant }); }); it('should revert if called with an out-of-bounds claimId', async () => { @@ -51,8 +51,8 @@ contract('DelphiStake', (accounts) => { }); it('should revert if called on a claim which has already been ruled upon', async () => { - await ds.settlementFailed(0, { from: claimant }); - await ds.ruleOnClaim(0, '0', { from: arbiter }); + await ds.settlementFailed(0, "", { from: claimant }); + await ds.ruleOnClaim(0, '1', { from: arbiter }); try { await utils.as(arbiter, ds.increaseClaimFee, 0, 2); @@ -77,7 +77,7 @@ contract('DelphiStake', (accounts) => { it('should transfer the increase _amount from the sender to the contract', async () => { assert.strictEqual((await token.balanceOf(ds.address)).toString(10), '110', 'claim surplus fee incorrectly'); - await ds.settlementFailed(0, { from: staker }); + await ds.settlementFailed(0, "", { from: staker }); await token.approve(ds.address, 1, { from: staker }); await ds.increaseClaimFee(0, 1, { from: staker }); @@ -86,17 +86,17 @@ contract('DelphiStake', (accounts) => { }); it('should increase the surplus fee by the _amount', async () => { - await ds.settlementFailed(0, { from: staker }); + await ds.settlementFailed(0, "", { from: staker }); await token.approve(ds.address, 1, { from: staker }); await ds.increaseClaimFee(0, 1, { from: staker }); const claim1 = await ds.claims.call('0'); - assert.strictEqual(claim1[3].toString(10), '1', 'claim surplus fee incorrectly'); + assert.strictEqual(claim1[4].toString(10), '1', 'claim surplus fee incorrectly'); }); it('should emit a FeeIncreased event', async () => { - await ds.settlementFailed(0, { from: staker }); + await ds.settlementFailed(0, "", { from: staker }); await token.approve(ds.address, 1, { from: staker }); await ds.increaseClaimFee(0, 1, { from: staker }).then((status) => { diff --git a/test/js/DelphiStake/increaseStake.js b/test/js/DelphiStake/increaseStake.js index b510029..acf6c4a 100644 --- a/test/js/DelphiStake/increaseStake.js +++ b/test/js/DelphiStake/increaseStake.js @@ -28,8 +28,8 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, conf.initialStake, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); // approve the staker and dave to spec incAmount to increase the stake await token.approve(ds.address, incAmount, { from: staker }); diff --git a/test/js/DelphiStake/openClaim.js b/test/js/DelphiStake/openClaim.js index 160f84f..2a1fdda 100644 --- a/test/js/DelphiStake/openClaim.js +++ b/test/js/DelphiStake/openClaim.js @@ -30,61 +30,46 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, conf.initialStake, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); // whitelist the claimant since most tests // use this format. Use 'other' for other situations - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: staker }); }); - it('should not allow the arbiter to open a claim', async () => { - await ds.whitelistClaimant(arbiter, conf.deadline, { from: staker }); - - await token.approve(ds.address, feeAmount, { from: arbiter }); - + it('should not allow the arbiter to be whitelisted', async () => { try { - await ds.openClaim(claimAmount, feeAmount, '', { from: arbiter }); + await ds.whitelistClaimant(arbiter, arbiter, conf.minFee, conf.deadline, "", { from: staker }); + } catch (err) { assert(utils.isEVMRevert(err), err.toString()); - const finalClaims = await ds.getNumClaims.call(); - assert.strictEqual(startingClaims.toString(10), finalClaims.toString(10), - 'claims counter incremented mysteriously'); - return; } - assert(false, 'Expected claim by arbiter to fail'); + assert(false, 'Expected whitelisting of arbiter to fail'); }); - it('should not allow the staker to open a claim', async () => { - await ds.whitelistClaimant(staker, conf.deadline, { from: staker }); - - await token.approve(ds.address, feeAmount, { from: staker }); - + it('should not allow the staker to whitelist themselves', async () => { try { - await ds.openClaim(claimAmount, feeAmount, '', { from: staker }); + await ds.whitelistClaimant(staker, arbiter, conf.minFee, conf.deadline, "", { from: staker }); + } catch (err) { assert(utils.isEVMRevert(err), err.toString()); - - const finalClaims = await ds.getNumClaims.call(); - assert.strictEqual(startingClaims.toString(10), finalClaims.toString(10), - 'claims counter incremented mysteriously'); - return; } - assert(false, 'expected claim by staker to fail'); + assert(false, 'expected whitelisting of staker to fail'); }); it('should not allow a whitelisted individual to open a claim after their deadline', async () => { - await ds.whitelistClaimant(other, '1', { from: staker }); + await ds.whitelistClaimant(other, arbiter, conf.minFee, '1', "", { from: staker }); await token.approve(ds.address, feeAmount, { from: other }); try { - await ds.openClaim(claimAmount, feeAmount, '', { from: other }); + await ds.openClaim(1, claimAmount, feeAmount, '', { from: other }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -102,7 +87,7 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, feeAmount, { from: other }); try { - await ds.openClaim(claimAmount, feeAmount, '', { from: other }); + await ds.openClaim(0, claimAmount, feeAmount, '', { from: other }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -120,7 +105,7 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, parseInt(conf.minFee, 10) - 1, { from: claimant }); try { - await ds.openClaim(claimAmount, conf.minFee - 1, '', { from: claimant }); + await ds.openClaim(0, claimAmount, conf.minFee - 1, '', { from: claimant }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -139,7 +124,7 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, amount, { from: claimant }); try { - await ds.openClaim(claimAmount, amount, '', { from: claimant }); + await ds.openClaim(0, claimAmount, amount, '', { from: claimant }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -155,7 +140,7 @@ contract('DelphiStake', (accounts) => { it('should revert if the fee is not transferred with the transaction', async () => { try { - await ds.openClaim(claimAmount, feeAmount, '', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, '', { from: claimant }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -172,7 +157,7 @@ contract('DelphiStake', (accounts) => { it('should increment the getNumClaims counter', async () => { await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.openClaim(claimAmount, feeAmount, '', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, '', { from: claimant }); const finalClaims = await ds.getNumClaims(); assert.strictEqual(startingClaims.add(new BN('1', 10)).toString(10), @@ -186,24 +171,24 @@ contract('DelphiStake', (accounts) => { const claimId = await ds.getNumClaims(); - await ds.openClaim(claimAmount, feeAmount, 'newclaim', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, 'newclaim', { from: claimant }); const claim = await ds.claims.call(claimId); - assert.strictEqual(claim[0], claimant, 'initialized claimant incorrectly'); - assert.strictEqual(claim[1].toString(10), claimAmount, 'initialized claim amount incorrectly'); - assert.strictEqual(claim[2].toString(10), feeAmount, 'initialized claim fee incorrectly'); - assert.strictEqual(claim[3].toString(10), '0', 'initialized claim surplus fee incorrectly'); - assert.strictEqual(claim[4], 'newclaim', 'initialized claim data incorrectly'); - assert.strictEqual(claim[5].toString(10), '0', 'initialized claim ruling incorrectly'); - assert.strictEqual(claim[6], false, 'initialized ruled bool incorrectly'); + assert.strictEqual(claim[0].toString(10), '0', 'initialized whitelist ID incorrectly'); + assert.strictEqual(claim[1], claimant, 'initialized claimant incorrectly'); + assert.strictEqual(claim[2].toString(10), claimAmount, 'initialized claim amount incorrectly'); + assert.strictEqual(claim[3].toString(10), feeAmount, 'initialized claim fee incorrectly'); + assert.strictEqual(claim[4].toString(10), '0', 'initialized claim surplus fee incorrectly'); + assert.strictEqual(claim[5], 'newclaim', 'initialized claim data incorrectly'); + assert.strictEqual(claim[6].toString(10), '0', 'initialized claim ruling incorrectly'); assert.strictEqual(claim[7], false, 'initialized settlementFailed incorrectly'); }); it('should increment the openClaims.call counter', async () => { await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.openClaim(claimAmount, feeAmount, '', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, '', { from: claimant }); const finalClaims = await ds.openClaims(); assert.strictEqual(startingClaims.add(new BN('1', 10)).toString(10), @@ -216,7 +201,7 @@ contract('DelphiStake', (accounts) => { const startingStake = await ds.claimableStake.call(); - await ds.openClaim(claimAmount, feeAmount, '', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, '', { from: claimant }); const finalStake = await ds.claimableStake(); assert.strictEqual(startingStake.sub(new BN(claimAmount, 10).add(feeAmount)).toString(10), @@ -231,52 +216,52 @@ contract('DelphiStake', (accounts) => { it('should emit a NewClaim event', async () => { await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.openClaim(claimAmount, feeAmount, '', { from: claimant }).then((status) => { + await ds.openClaim(0, claimAmount, feeAmount, '', { from: claimant }).then((status) => { assert.strictEqual('ClaimOpened', status.logs[0].event, 'did not emit the NewClaim event'); }); }); it('should append claims to the end of the claim array, without overwriting earlier claims', async () => { await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.openClaim(claimAmount, feeAmount, 'claim1', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, 'claim1', { from: claimant }); await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.openClaim(claimAmount, feeAmount, 'claim2', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, 'claim2', { from: claimant }); await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.openClaim(claimAmount, feeAmount, 'claim3', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, 'claim3', { from: claimant }); const claim1 = await ds.claims.call('0'); - assert.strictEqual(claim1[0], claimant, 'initialized claimant incorrectly'); - assert.strictEqual(claim1[1].toString(10), claimAmount, 'initialized claim amount incorrectly'); - assert.strictEqual(claim1[2].toString(10), feeAmount, 'initialized claim fee incorrectly'); - assert.strictEqual(claim1[3].toString(10), '0', 'initialized claim surplus fee incorrectly'); - assert.strictEqual(claim1[4], 'claim1', 'initialized claim data incorrectly'); - assert.strictEqual(claim1[5].toString(10), '0', 'initialized claim ruling incorrectly'); - assert.strictEqual(claim1[6], false, 'initialized ruled bool incorrectly'); + assert.strictEqual(claim1[0].toString(10), '0', 'initialized whitelist ID incorrectly'); + assert.strictEqual(claim1[1], claimant, 'initialized claimant incorrectly'); + assert.strictEqual(claim1[2].toString(10), claimAmount, 'initialized claim amount incorrectly'); + assert.strictEqual(claim1[3].toString(10), feeAmount, 'initialized claim fee incorrectly'); + assert.strictEqual(claim1[4].toString(10), '0', 'initialized claim surplus fee incorrectly'); + assert.strictEqual(claim1[5], 'claim1', 'initialized claim data incorrectly'); + assert.strictEqual(claim1[6].toString(10), '0', 'initialized claim ruling incorrectly'); assert.strictEqual(claim1[7], false, 'initialized settlementFailed incorrectly'); const claim2 = await ds.claims.call('1'); - assert.strictEqual(claim2[0], claimant, 'initialized claimant incorrectly'); - assert.strictEqual(claim2[1].toString(10), claimAmount, 'initialized claim amount incorrectly'); - assert.strictEqual(claim2[2].toString(10), feeAmount, 'initialized claim fee incorrectly'); - assert.strictEqual(claim2[3].toString(10), '0', 'initialized claim surplus fee incorrectly'); - assert.strictEqual(claim2[4], 'claim2', 'initialized claim data incorrectly'); - assert.strictEqual(claim2[5].toString(10), '0', 'initialized claim ruling incorrectly'); - assert.strictEqual(claim2[6], false, 'initialized ruled bool incorrectly'); + assert.strictEqual(claim2[0].toString(10), '0', 'initialized whitelist ID incorrectly'); + assert.strictEqual(claim2[1], claimant, 'initialized claimant incorrectly'); + assert.strictEqual(claim2[2].toString(10), claimAmount, 'initialized claim amount incorrectly'); + assert.strictEqual(claim2[3].toString(10), feeAmount, 'initialized claim fee incorrectly'); + assert.strictEqual(claim2[4].toString(10), '0', 'initialized claim surplus fee incorrectly'); + assert.strictEqual(claim2[5], 'claim2', 'initialized claim data incorrectly'); + assert.strictEqual(claim2[6].toString(10), '0', 'initialized claim ruling incorrectly'); assert.strictEqual(claim2[7], false, 'initialized settlementFailed incorrectly'); const claim3 = await ds.claims.call('2'); - assert.strictEqual(claim3[0], claimant, 'initialized claimant incorrectly'); - assert.strictEqual(claim3[1].toString(10), claimAmount, 'initialized claim amount incorrectly'); - assert.strictEqual(claim3[2].toString(10), feeAmount, 'initialized claim fee incorrectly'); - assert.strictEqual(claim3[3].toString(10), '0', 'initialized claim surplus fee incorrectly'); - assert.strictEqual(claim3[4], 'claim3', 'initialized claim data incorrectly'); - assert.strictEqual(claim3[5].toString(10), '0', 'initialized claim ruling incorrectly'); - assert.strictEqual(claim3[6], false, 'initialized ruled bool incorrectly'); + assert.strictEqual(claim3[0].toString(10), '0', 'initialized whitelist ID incorrectly'); + assert.strictEqual(claim3[1], claimant, 'initialized claimant incorrectly'); + assert.strictEqual(claim3[2].toString(10), claimAmount, 'initialized claim amount incorrectly'); + assert.strictEqual(claim3[3].toString(10), feeAmount, 'initialized claim fee incorrectly'); + assert.strictEqual(claim3[4].toString(10), '0', 'initialized claim surplus fee incorrectly'); + assert.strictEqual(claim3[5], 'claim3', 'initialized claim data incorrectly'); + assert.strictEqual(claim3[6].toString(10), '0', 'initialized claim ruling incorrectly'); assert.strictEqual(claim3[7], false, 'initialized settlementFailed incorrectly'); }); }); diff --git a/test/js/DelphiStake/openClaimWithoutSettlement.js b/test/js/DelphiStake/openClaimWithoutSettlement.js index 5270bea..fa7f576 100644 --- a/test/js/DelphiStake/openClaimWithoutSettlement.js +++ b/test/js/DelphiStake/openClaimWithoutSettlement.js @@ -29,57 +29,17 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, conf.initialStake, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); - }); - - it('should not allow the arbiter to open a claim', async () => { - await ds.whitelistClaimant(arbiter, conf.deadline, { from: staker }); - - await token.approve(ds.address, conf.minFee, { from: arbiter }); - - try { - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, '', { from: arbiter }); - } catch (err) { - assert(utils.isEVMRevert(err), err.toString()); - - const finalClaims = await ds.getNumClaims.call(); - assert.strictEqual(startingClaims.toString(10), finalClaims.toString(10), - 'claims counter incremented mysteriously'); - - return; - } - - assert(false, 'Expected claim by arbiter to fail'); - }); - - it('should not allow the staker to open a claim', async () => { - await ds.whitelistClaimant(staker, conf.deadline, { from: staker }); - - await token.approve(ds.address, conf.minFee, { from: staker }); - - try { - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, '', { from: staker }); - } catch (err) { - assert(utils.isEVMRevert(err), err.toString()); - - const finalClaims = await ds.getNumClaims.call(); - assert.strictEqual(startingClaims.toString(10), finalClaims.toString(10), - 'claims counter incremented mysteriously'); - - return; - } - - assert(false, 'expected claim by staker to fail'); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: staker }); }); it('should not allow a non-whitelisted individual to open a claim', async () => { await token.approve(ds.address, conf.minFee, { from: other }); try { - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, '', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, '', { from: claimant }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -94,12 +54,12 @@ contract('DelphiStake', (accounts) => { }); it('should revert if someone is attempting to open a claim after the deadline', async () => { - await ds.whitelistClaimant(other, parseInt(conf.deadline, 10) - 1, { from: staker }); + await ds.whitelistClaimant(other, arbiter, parseInt(conf.deadline, 10) - 1, conf.minFee, '', { from: staker }); await token.approve(ds.address, conf.minFee, { from: claimant }); try { - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, 'claim1', { from: other }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, 'claim1', { from: other }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); return; @@ -109,14 +69,14 @@ contract('DelphiStake', (accounts) => { }); it('should revert if _fee is smaller than the minimum', async () => { - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); + await ds.whitelistClaimant(claimant, arbiter, conf.deadline, conf.minFee, '', { from: staker }); const feeAmount = parseInt(conf.minFee, 10) - 1; await token.approve(ds.address, feeAmount, { from: claimant }); try { - await ds.openClaimWithoutSettlement(claimAmount, feeAmount, '', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, feeAmount, '', { from: claimant }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -136,7 +96,7 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, amount, { from: claimant }); try { - await ds.openClaimWithoutSettlement(claimAmount, amount, '', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, amount, '', { from: claimant }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -152,7 +112,7 @@ contract('DelphiStake', (accounts) => { it('should revert if the fee is not transferred with the transaction', async () => { try { - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, '', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, '', { from: claimant }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -169,7 +129,7 @@ contract('DelphiStake', (accounts) => { it('should increment the getNumClaims counter', async () => { await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, '', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, '', { from: claimant }); const finalClaims = await ds.getNumClaims(); assert.strictEqual(startingClaims.add(new BN('1', 10)).toString(10), @@ -183,24 +143,24 @@ contract('DelphiStake', (accounts) => { const claimId = await ds.getNumClaims(); - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, 'newclaim', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, 'newclaim', { from: claimant }); const claim = await ds.claims.call(claimId); - assert.strictEqual(claim[0], claimant, 'initialized claimant incorrectly'); - assert.strictEqual(claim[1].toString(10), claimAmount, 'initialized claim amount incorrectly'); - assert.strictEqual(claim[2].toString(10), conf.minFee, 'initialized claim fee incorrectly'); - assert.strictEqual(claim[3].toString(10), '0', 'initialized claim surplus fee incorrectly'); - assert.strictEqual(claim[4], 'newclaim', 'initialized claim data incorrectly'); - assert.strictEqual(claim[5].toString(10), '0', 'initialized claim ruling incorrectly'); - assert.strictEqual(claim[6], false, 'initialized ruled bool incorrectly'); + assert.strictEqual(claim[0].toString(10), '0', 'initialized whitelist ID incorrectly'); + assert.strictEqual(claim[1], claimant, 'initialized claimant incorrectly'); + assert.strictEqual(claim[2].toString(10), claimAmount, 'initialized claim amount incorrectly'); + assert.strictEqual(claim[3].toString(10), conf.minFee, 'initialized claim fee incorrectly'); + assert.strictEqual(claim[4].toString(10), '0', 'initialized claim surplus fee incorrectly'); + assert.strictEqual(claim[5], 'newclaim', 'initialized claim data incorrectly'); + assert.strictEqual(claim[6].toString(10), '0', 'initialized claim ruling incorrectly'); assert.strictEqual(claim[7], true, 'initialized settlementFailed incorrectly'); }); it('should increment the openClaims.call counter', async () => { await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, '', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, '', { from: claimant }); const finalClaims = await ds.openClaims(); assert.strictEqual(startingClaims.add(new BN('1', 10)).toString(10), @@ -213,7 +173,7 @@ contract('DelphiStake', (accounts) => { const startingStake = await ds.claimableStake.call(); - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, '', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, '', { from: claimant }); const finalStake = await ds.claimableStake(); assert.strictEqual(startingStake.sub(new BN(claimAmount, 10).add(conf.minFee)).toString(10), @@ -228,52 +188,52 @@ contract('DelphiStake', (accounts) => { it('should emit a NewClaim event', async () => { await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, 'claim1', { from: claimant }).then((status) => { - assert.strictEqual('ClaimOpened', status.logs[0].event, 'did not emit the NewClaim event'); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, 'claim1', { from: claimant }).then((status) => { + assert.strictEqual('ClaimOpenedWithoutSettlement', status.logs[0].event, 'did not emit the NewClaim event'); }); }); it('should append claims to the end of the claim array, without overwriting earlier claims', async () => { await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, 'claim1', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, 'claim1', { from: claimant }); await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, 'claim2', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, 'claim2', { from: claimant }); await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.openClaimWithoutSettlement(claimAmount, conf.minFee, 'claim3', { from: claimant }); + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, 'claim3', { from: claimant }); const claim1 = await ds.claims.call('0'); - assert.strictEqual(claim1[0], claimant, 'initialized claimant incorrectly'); - assert.strictEqual(claim1[1].toString(10), claimAmount, 'initialized claim amount incorrectly'); - assert.strictEqual(claim1[2].toString(10), conf.minFee, 'initialized claim fee incorrectly'); - assert.strictEqual(claim1[3].toString(10), '0', 'initialized claim surplus fee incorrectly'); - assert.strictEqual(claim1[4], 'claim1', 'initialized claim data incorrectly'); - assert.strictEqual(claim1[5].toString(10), '0', 'initialized claim ruling incorrectly'); - assert.strictEqual(claim1[6], false, 'initialized ruled bool incorrectly'); + assert.strictEqual(claim1[0].toString(10), '0', 'initialized whitelist ID incorrectly'); + assert.strictEqual(claim1[1], claimant, 'initialized claimant incorrectly'); + assert.strictEqual(claim1[2].toString(10), claimAmount, 'initialized claim amount incorrectly'); + assert.strictEqual(claim1[3].toString(10), conf.minFee, 'initialized claim fee incorrectly'); + assert.strictEqual(claim1[4].toString(10), '0', 'initialized claim surplus fee incorrectly'); + assert.strictEqual(claim1[5], 'claim1', 'initialized claim data incorrectly'); + assert.strictEqual(claim1[6].toString(10), '0', 'initialized claim ruling incorrectly'); assert.strictEqual(claim1[7], true, 'initialized settlementFailed incorrectly'); const claim2 = await ds.claims.call('1'); - assert.strictEqual(claim2[0], claimant, 'initialized claimant incorrectly'); - assert.strictEqual(claim2[1].toString(10), claimAmount, 'initialized claim amount incorrectly'); - assert.strictEqual(claim2[2].toString(10), conf.minFee, 'initialized claim fee incorrectly'); - assert.strictEqual(claim2[3].toString(10), '0', 'initialized claim surplus fee incorrectly'); - assert.strictEqual(claim2[4], 'claim2', 'initialized claim data incorrectly'); - assert.strictEqual(claim2[5].toString(10), '0', 'initialized claim ruling incorrectly'); - assert.strictEqual(claim2[6], false, 'initialized ruled bool incorrectly'); + assert.strictEqual(claim2[0].toString(10), '0', 'initialized whitelist ID incorrectly'); + assert.strictEqual(claim2[1], claimant, 'initialized claimant incorrectly'); + assert.strictEqual(claim2[2].toString(10), claimAmount, 'initialized claim amount incorrectly'); + assert.strictEqual(claim2[3].toString(10), conf.minFee, 'initialized claim fee incorrectly'); + assert.strictEqual(claim2[4].toString(10), '0', 'initialized claim surplus fee incorrectly'); + assert.strictEqual(claim2[5], 'claim2', 'initialized claim data incorrectly'); + assert.strictEqual(claim2[6].toString(10), '0', 'initialized claim ruling incorrectly'); assert.strictEqual(claim2[7], true, 'initialized settlementFailed incorrectly'); const claim3 = await ds.claims.call('2'); - assert.strictEqual(claim3[0], claimant, 'initialized claimant incorrectly'); - assert.strictEqual(claim3[1].toString(10), claimAmount, 'initialized claim amount incorrectly'); - assert.strictEqual(claim3[2].toString(10), conf.minFee, 'initialized claim fee incorrectly'); - assert.strictEqual(claim3[3].toString(10), '0', 'initialized claim surplus fee incorrectly'); - assert.strictEqual(claim3[4], 'claim3', 'initialized claim data incorrectly'); - assert.strictEqual(claim3[5].toString(10), '0', 'initialized claim ruling incorrectly'); - assert.strictEqual(claim3[6], false, 'initialized ruled bool incorrectly'); + assert.strictEqual(claim3[0].toString(10), '0', 'initialized whitelist ID incorrectly'); + assert.strictEqual(claim3[1], claimant, 'initialized claimant incorrectly'); + assert.strictEqual(claim3[2].toString(10), claimAmount, 'initialized claim amount incorrectly'); + assert.strictEqual(claim3[3].toString(10), conf.minFee, 'initialized claim fee incorrectly'); + assert.strictEqual(claim3[4].toString(10), '0', 'initialized claim surplus fee incorrectly'); + assert.strictEqual(claim3[5], 'claim3', 'initialized claim data incorrectly'); + assert.strictEqual(claim3[6].toString(10), '0', 'initialized claim ruling incorrectly'); assert.strictEqual(claim3[7], true, 'initialized settlementFailed incorrectly'); }); }); diff --git a/test/js/DelphiStake/proposeSettlement.js b/test/js/DelphiStake/proposeSettlement.js index 4751774..3ca1cc4 100644 --- a/test/js/DelphiStake/proposeSettlement.js +++ b/test/js/DelphiStake/proposeSettlement.js @@ -28,14 +28,14 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, conf.initialStake, { from: staker }); await token.transfer(arbiter, 1000, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: staker }); - await ds.openClaim(claimAmount, conf.minFee, '', { from: claimant }); + await ds.openClaim(0, claimAmount, conf.minFee, '', { from: claimant }); }); it('Should revert if called with an out-of-bounds claimId', async () => { @@ -58,7 +58,7 @@ contract('DelphiStake', (accounts) => { }); it('Should revert if settlement has failed', async () => { - await ds.settlementFailed(0, { from: staker }); + await ds.settlementFailed(0, "", { from: staker }); try { await ds.proposeSettlement(0, claimAmount, { from: staker }); } catch (err) { diff --git a/test/js/DelphiStake/ruleOnClaim.js b/test/js/DelphiStake/ruleOnClaim.js index 5853d43..23079e1 100644 --- a/test/js/DelphiStake/ruleOnClaim.js +++ b/test/js/DelphiStake/ruleOnClaim.js @@ -18,7 +18,7 @@ contract('DelphiStake', (accounts) => { const [staker, claimant, arbiter, other] = accounts; const claimAmount = '1'; - const defaultRuling = '1'; + const defaultRuling = '2'; let token; let ds; @@ -39,16 +39,16 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, conf.initialStake, { from: staker }); await token.transfer(arbiter, 1000, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: staker }); - await ds.openClaim(claimAmount, conf.minFee, '', { from: claimant }); + await ds.openClaim(0, claimAmount, conf.minFee, '', { from: claimant }); - await ds.settlementFailed('0', { from: claimant }); + await ds.settlementFailed('0', '', { from: claimant }); originalArbiterBalance = await token.balanceOf(arbiter); originalClaimantBalance = await token.balanceOf(claimant); @@ -74,20 +74,10 @@ contract('DelphiStake', (accounts) => { assert(false, 'expected revert if called on an out-of-bounds claimId'); }); - it('should revert if called on an out-of-bounds ruling', async () => { - try { - await utils.as(arbiter, ds.ruleOnClaim, '0', 6); - } catch (err) { - assert(utils.isEVMRevert(err), err.toString()); - return; - } - - assert(false, 'expected revert if called on an out-of-bounds claimId'); - }); it('should revert if settlement never failed', async () => { await token.approve(ds.address, conf.minFee, { from: claimant }); - await ds.openClaim(claimAmount, conf.minFee, '', { from: claimant }); + await ds.openClaim(0, claimAmount, conf.minFee, '', { from: claimant }); try { await utils.as(arbiter, ds.ruleOnClaim, 1, defaultRuling); @@ -116,7 +106,7 @@ contract('DelphiStake', (accounts) => { const claim = await ds.claims.call('0'); - assert.strictEqual(claim[5].toString(10), defaultRuling, 'initialized claim ruling incorrectly'); + assert.strictEqual(claim[6].toString(10), defaultRuling, 'initialized claim ruling incorrectly'); }); it('should add the claim\'s amount and fee to the stake iff the claim is not accepted', async () => { @@ -135,7 +125,7 @@ contract('DelphiStake', (accounts) => { }); it('should transfer the fee and surplus to the arbiter and the claim amount + fee to the claimant if the ruling is 0', async () => { - const ruling = '0'; + const ruling = '1'; await ds.ruleOnClaim('0', ruling, { from: arbiter }); @@ -147,7 +137,7 @@ contract('DelphiStake', (accounts) => { }); it('should transfer the fee and surplus to the arbiter and return the claim amount + fee to the stakers stake if the ruling is 1', async () => { - const ruling = '1'; + const ruling = '2'; await ds.ruleOnClaim('0', ruling, { from: arbiter }); @@ -159,7 +149,7 @@ contract('DelphiStake', (accounts) => { }); it('should transfer 2 times the fee plus the surplus to the arbiter and should burn the claim amount if the ruling is 2', async () => { - const ruling = '2'; + const ruling = '3'; await ds.ruleOnClaim('0', ruling, { from: arbiter }); @@ -173,7 +163,7 @@ contract('DelphiStake', (accounts) => { }); it('should transfer the fee deposit back to the claimant, transfer the fee surplus to the arbiter, and return the claim amount and fee to the stakers stake', async () => { - const ruling = '3'; + const ruling = '4'; await ds.ruleOnClaim('0', ruling, { from: arbiter }); @@ -183,22 +173,22 @@ contract('DelphiStake', (accounts) => { assert.strictEqual(stake.toString(10), conf.initialStake, 'stake not returned to original amount'); assert.strictEqual(originalClaimantBalance.add( - new BN(parseInt(conf.minFee, 10) + parseInt(claimAmount, 10), 10)) + new BN(parseInt(conf.minFee, 10), 10)) .toString(10), claimantBalance.toString(10), 'Incorrect claimant balance'); }); it('should decrement openClaims', async () => { // Open a new claim - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, '', { from: staker }); await token.approve(ds.address, conf.minFee, { from: claimant }); - const { logs } = await ds.openClaim(claimAmount, conf.minFee, '', { from: claimant }); + const { logs } = await ds.openClaim(0, claimAmount, conf.minFee, '', { from: claimant }); const claimId = utils.getLog(logs, 'ClaimOpened').args._claimId; // eslint-disable-line // Get the initial number of open claims const initialOpenClaims = await ds.openClaims.call(); // Cancel settlement and rule on the claim - await ds.settlementFailed(claimId, { from: claimant }); + await ds.settlementFailed(claimId, "", { from: claimant }); await ds.ruleOnClaim(claimId, defaultRuling, { from: arbiter }); // Since the claim is closed now, expect openClaims to be less than it was before we closed @@ -209,15 +199,15 @@ contract('DelphiStake', (accounts) => { it('should emit a ClaimRuled event', async () => { // Open a new claim - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, '', { from: staker }); await token.approve(ds.address, conf.minFee, { from: claimant }); const openClaimLogs - = (await ds.openClaim(claimAmount, conf.minFee, '', { from: claimant })).logs; + = (await ds.openClaim(1, claimAmount, conf.minFee, '', { from: claimant })).logs; const claimId = utils.getLog(openClaimLogs, 'ClaimOpened').args._claimId; // eslint-disable-line // Cancel settlement and rule on claim. Capture the logs on ruling. - await ds.settlementFailed(claimId, { from: claimant }); + await ds.settlementFailed(claimId, "", { from: claimant }); const ruledLogs = (await ds.ruleOnClaim(claimId, defaultRuling, { from: arbiter })).logs; // Expect utils.getLog to find in the logs returned in openClaim a 'ClaimOpened' event diff --git a/test/js/DelphiStake/settlementFailed.js b/test/js/DelphiStake/settlementFailed.js index 3324742..5f6660b 100644 --- a/test/js/DelphiStake/settlementFailed.js +++ b/test/js/DelphiStake/settlementFailed.js @@ -28,22 +28,22 @@ contract('DelphiStake', (accounts) => { await token.approve(ds.address, conf.initialStake, { from: staker }); await token.transfer(arbiter, 1000, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); const claimAmount = new BN('1', 10); const feeAmount = new BN('10', 10); await token.approve(ds.address, feeAmount, { from: claimant }); - await ds.whitelistClaimant(claimant, conf.deadline, { from: staker }); + await ds.whitelistClaimant(claimant, arbiter, feeAmount, conf.deadline, "", { from: staker }); - await ds.openClaim(claimAmount, feeAmount, '', { from: claimant }); + await ds.openClaim(0, claimAmount, feeAmount, '', { from: claimant }); }); it('should revert if called with an out-of-bounds claimId', async () => { try { - await ds.settlementFailed(1, { from: staker }); + await ds.settlementFailed(1, "", { from: staker }); } catch (err) { return; } @@ -52,7 +52,7 @@ contract('DelphiStake', (accounts) => { it('should revert if called by anyone but the staker or the claimant corresponding to the claimId', async () => { try { - await ds.settlementFailed(0, { from: other }); + await ds.settlementFailed(0, "", { from: other }); } catch (err) { return; } @@ -60,16 +60,16 @@ contract('DelphiStake', (accounts) => { }); it('should revert if settlement has already failed', async () => { - await ds.settlementFailed(0, { from: claimant }); + await ds.settlementFailed(0, "", { from: claimant }); try { - await ds.settlementFailed(0, { from: claimant }); + await ds.settlementFailed(0, "", { from: claimant }); } catch (err) { return; } assert(false, 'expected revert if settlement has already failed '); }); it('should emit the SettlementFailed event', async () => { - await ds.settlementFailed(0, { from: claimant }).then((status) => { + await ds.settlementFailed(0, "", { from: claimant }).then((status) => { assert.strictEqual('SettlementFailed', status.logs[0].event, 'did not emit the SettlementFailed event'); }); }); diff --git a/test/js/DelphiStake/whitelistClaimant.js b/test/js/DelphiStake/whitelistClaimant.js index 80b1ace..1475114 100644 --- a/test/js/DelphiStake/whitelistClaimant.js +++ b/test/js/DelphiStake/whitelistClaimant.js @@ -26,8 +26,8 @@ contract('DelphiStake', (accounts) => {//eslint-disable-line await token.approve(ds.address, conf.initialStake, { from: staker }); await token.transfer(arbiter, 1000, { from: staker }); - await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }); + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); const feeAmount = new BN('10', 10); @@ -36,7 +36,7 @@ contract('DelphiStake', (accounts) => {//eslint-disable-line it('Should revert if called by arbiter', async () => { try { - await ds.whitelistClaimant(claimant, conf.deadline, { from: arbiter }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: arbiter }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); return; @@ -47,7 +47,7 @@ contract('DelphiStake', (accounts) => {//eslint-disable-line it('Should revert if called by anyone other than staker', async () => { try { - await ds.whitelistClaimant(claimant, conf.deadline, { from: other }); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: other }); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); return; @@ -56,27 +56,26 @@ contract('DelphiStake', (accounts) => {//eslint-disable-line assert(false, 'Expected revert if called by anyone but the staker'); }); - it('Should properly set the _claimant address to the given deadline', async () => { - await ds.whitelistClaimant(claimant, '1000', { from: staker }); - const whitelisten = await ds.whitelistedDeadlines(claimant, { from: staker }); - assert.strictEqual(whitelisten.toString(10), '1000', - 'deadline didnt set correctly'); + it('Should properly set the whitelisting to the correct fields', async () => { + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, '1000', '', { from: staker }); + const whitelist = await ds.whitelists(0); + assert.strictEqual(whitelist[0], claimant, 'claimant didnt get set correctly'); + assert.strictEqual(whitelist[1], arbiter, 'arbiter didnt get set correctly'); + assert.strictEqual(whitelist[2].toString(10), conf.minFee, 'minFee didnt set correctly'); + assert.strictEqual(whitelist[3].toString(10), '1000', 'deadline didnt set correctly'); }); it('Should allow staker to extend the deadline for someone who has already been whitelisted', async () => { - await ds.whitelistClaimant(claimant, '1000', { from: staker }); - let whitelisten = await ds.whitelistedDeadlines(claimant, { from: staker }); - assert.strictEqual(whitelisten.toString(10), '1000', - 'deadline didnt set correctly'); + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, '1000', "", { from: staker }); - await ds.whitelistClaimant(claimant, '1001', { from: staker }); - whitelisten = await ds.whitelistedDeadlines(claimant, { from: staker }); - assert.strictEqual(whitelisten.toString(10), '1001', + await ds.extendClaimDeadline(0, '1001', { from: staker }); + whitelist = await ds.whitelists(0); + assert.strictEqual(whitelist[3].toString(10), '1001', 'deadline didnt set correctly'); }); it('Should emit ClaimantWhitelisted event', async () => { - await ds.whitelistClaimant(claimant, '1000', { from: staker }).then((status) => { + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, '1000', '', { from: staker }).then((status) => { assert.strictEqual('ClaimantWhitelisted', status.logs[0].event, 'did not emit the ClaimantWhitelisted event'); }); }); diff --git a/test/js/DelphiStakeFactory/createDelphiStake.js b/test/js/DelphiStakeFactory/createDelphiStake.js index 7a7c04f..14c1d30 100644 --- a/test/js/DelphiStakeFactory/createDelphiStake.js +++ b/test/js/DelphiStakeFactory/createDelphiStake.js @@ -31,7 +31,7 @@ contract('DelphiStakeFactory', (accounts) => { it('should allow the creatation of a single stake', async () => { await token.approve(df.address, conf.initialStake, { from: staker }); await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, - conf.minFee, conf.data, conf.deadline, arbiter); + conf.data, conf.deadline); const numStakes = await df.getNumStakes.call(); @@ -57,7 +57,7 @@ contract('DelphiStakeFactory', (accounts) => { for (let i = 0; i < N; i += 1) { await token.approve(df.address, conf.initialStake, { from: staker }); await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, - conf.minFee, i.toString(10), conf.deadline, arbiter); + i.toString(10), conf.deadline); } const numStakes = await df.getNumStakes.call(); @@ -84,7 +84,7 @@ contract('DelphiStakeFactory', (accounts) => { try { await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, - conf.minFee, conf.data, conf.deadline, arbiter); + conf.data, conf.deadline); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -102,7 +102,7 @@ contract('DelphiStakeFactory', (accounts) => { try { await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, - conf.minFee, conf.data, '1', arbiter); + conf.data, '1'); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -111,25 +111,11 @@ contract('DelphiStakeFactory', (accounts) => { assert(false, 'did not revert after trying to call the initialize function with a deadline that is before now'); }); - it('should revert when trying to initialize with an arbiter of address(0)', async () => { - await token.approve(df.address, conf.initialStake, { from: staker }); - - try { - await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, - conf.minFee, conf.data, conf.deadline, '0x0'); - } catch (err) { - assert(utils.isEVMRevert(err), err.toString()); - - return; - } - assert(false, 'did not revert after trying to initialize with an arbiter of address(0)'); - }); - it('should emit a StakeCreated event', async () => { await token.approve(df.address, conf.initialStake, { from: staker }); - await df.createDelphiStake(conf.initialStake, token.address, conf.minFee, conf.data, - conf.deadline, arbiter, { from: staker }).then((status) => { + await df.createDelphiStake(conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }).then((status) => { assert.strictEqual('StakeCreated', status.logs[0].event, 'did not emit the StakeCreated event'); }); }); diff --git a/test/js/DelphiVoting/claimFee.js b/test/js/DelphiVoting/claimFee.js index e2e41ea..3a500cf 100644 --- a/test/js/DelphiVoting/claimFee.js +++ b/test/js/DelphiVoting/claimFee.js @@ -101,7 +101,7 @@ contract('DelphiVoting', (accounts) => { await token.approve(delphiStakeFactory.address, 90000, { from: staker }); const expirationTime = (await web3.eth.getBlock('latest')).timestamp + 1000; const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(90000, token.address, - 1000, '', expirationTime, delphiVoting.address, { from: staker }); + '', expirationTime, { from: staker }); // eslint-disable-next-line delphiStake = DelphiStake.at(delphiStakeReceipt.logs[0].args._contractAddress); }); @@ -115,7 +115,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and get its claimId const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -160,7 +160,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and get its claimId const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -209,8 +209,8 @@ contract('DelphiVoting', (accounts) => { // Set constants const CLAIM_AMOUNT = '10000'; const FEE_AMOUNT = '1000'; - const PLURALITY_VOTE = '1'; - const NON_PLURALITY_VOTE = '0'; + const PLURALITY_VOTE = '2'; + const NON_PLURALITY_VOTE = '1'; const SALT = '420'; // Compute secret hashes for the plurality and non-plurality vote options @@ -219,7 +219,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and compute its claim ID. const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -286,7 +286,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and compute its claim ID. const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -349,7 +349,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and compute its claim ID. const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -493,7 +493,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and get its claimId const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -538,7 +538,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and get its claimId const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -583,7 +583,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and get its claimId const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); // Get the secret hash for the salted vote @@ -620,8 +620,8 @@ contract('DelphiVoting', (accounts) => { // Set constants const CLAIM_AMOUNT = '50000'; const FEE_AMOUNT = new BN('10000', 10); - const PLURALITY_VOTE = '1'; - const NON_PLURALITY_VOTE = '0'; + const PLURALITY_VOTE = '2'; + const NON_PLURALITY_VOTE = '1'; const SALT = '420'; // Compute secret hashes for the plurality and non-plurality vote options @@ -630,7 +630,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim and compute its claim ID. const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); diff --git a/test/js/DelphiVoting/commitVote.js b/test/js/DelphiVoting/commitVote.js index 7847e11..0c82236 100644 --- a/test/js/DelphiVoting/commitVote.js +++ b/test/js/DelphiVoting/commitVote.js @@ -67,7 +67,7 @@ contract('DelphiVoting', (accounts) => { await registry.updateStatus(solkeccak(arbiterBob)); await registry.updateStatus(solkeccak(arbiterCharlie)); - // Create a DelphiVoting with 100 second voting periods, fee decay value of five, + // Create a DelphiVoting with 100 second voting periods, fee decay value of five, // and which uses the registry we just created as its arbiter set const delphiVotingReceipt = await delphiVotingFactory.makeDelphiVoting(registry.address, 5, [solkeccak('parameterizerVotingPeriod'), solkeccak('commitStageLen'), @@ -84,7 +84,7 @@ contract('DelphiVoting', (accounts) => { await token.approve(delphiStakeFactory.address, 90000, { from: staker }); const expirationTime = (await web3.eth.getBlock('latest')).timestamp + 1000; const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(90000, token.address, - 1000, '', expirationTime, delphiVoting.address, { from: staker }); + '', expirationTime, { from: staker }); // eslint-disable-next-line delphiStake = DelphiStake.at(delphiStakeReceipt.logs[0].args._contractAddress); }); @@ -98,7 +98,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim in the DelphiStake and generate a claim ID const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -132,7 +132,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim in the DelphiStake and generate a claim ID const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); @@ -163,7 +163,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim in the DelphiStake and generate a claim ID const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); // Generate a secret hash and, as a non-arbiter, try to commit it for the claim which @@ -190,7 +190,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim in the DelphiStake and generate a claim ID const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); // Generate a secret hash and, as the arbiter, commit it for the claim which was just @@ -252,7 +252,7 @@ contract('DelphiVoting', (accounts) => { // Make a new claim in the DelphiStake and generate a claim ID const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, 'i love cats', delphiStake); try { diff --git a/test/js/DelphiVoting/revealVote.js b/test/js/DelphiVoting/revealVote.js index 130fe3e..6f3084d 100644 --- a/test/js/DelphiVoting/revealVote.js +++ b/test/js/DelphiVoting/revealVote.js @@ -67,7 +67,7 @@ contract('DelphiVoting', (accounts) => { await registry.updateStatus(solkeccak(arbiterBob)); await registry.updateStatus(solkeccak(arbiterCharlie)); - // Create a DelphiVoting with 100 second voting periods, fee decay value of five, + // Create a DelphiVoting with 100 second voting periods, fee decay value of five, // and which uses the registry we just created as its arbiter set const delphiVotingReceipt = await delphiVotingFactory.makeDelphiVoting(registry.address, 5, [solkeccak('parameterizerVotingPeriod'), solkeccak('commitStageLen'), @@ -84,7 +84,7 @@ contract('DelphiVoting', (accounts) => { await token.approve(delphiStakeFactory.address, 90000, { from: staker }); const expirationTime = (await web3.eth.getBlock('latest')).timestamp + 1000; const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(90000, token.address, - 1000, '', expirationTime, delphiVoting.address, { from: staker }); + '', expirationTime, { from: staker }); // eslint-disable-next-line delphiStake = DelphiStake.at(delphiStakeReceipt.logs[0].args._contractAddress); }); @@ -99,7 +99,7 @@ contract('DelphiVoting', (accounts) => { // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); // Generate a secret hash and commit it as a vote @@ -136,7 +136,7 @@ contract('DelphiVoting', (accounts) => { // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); // Generate a secret hash and commit it as a vote @@ -172,7 +172,7 @@ contract('DelphiVoting', (accounts) => { // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); // Generate a secret hash and commit it as a vote @@ -205,7 +205,7 @@ contract('DelphiVoting', (accounts) => { // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); // Generate a secret hash and commit it as a vote @@ -235,7 +235,7 @@ contract('DelphiVoting', (accounts) => { // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); // Generate a secret hash and commit it as a vote diff --git a/test/js/DelphiVoting/submitRuling.js b/test/js/DelphiVoting/submitRuling.js index 5ec5519..0ad8177 100644 --- a/test/js/DelphiVoting/submitRuling.js +++ b/test/js/DelphiVoting/submitRuling.js @@ -67,7 +67,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line await registry.updateStatus(solkeccak(arbiterBob)); await registry.updateStatus(solkeccak(arbiterCharlie)); - // Create a DelphiVoting with 100 second voting periods, fee decay value of five, + // Create a DelphiVoting with 100 second voting periods, fee decay value of five, // and which uses the registry we just created as its arbiter set const delphiVotingReceipt = await delphiVotingFactory.makeDelphiVoting(registry.address, 5, [solkeccak('parameterizerVotingPeriod'), solkeccak('commitStageLen'), @@ -84,7 +84,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line await token.approve(delphiStakeFactory.address, 90000, { from: staker }); const expirationTime = (await web3.eth.getBlock('latest')).timestamp + 1000; const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(90000, token.address, - 1000, '', expirationTime, delphiVoting.address, { from: staker }); + '', expirationTime, { from: staker }); // eslint-disable-next-line delphiStake = DelphiStake.at(delphiStakeReceipt.logs[0].args._contractAddress); }); @@ -99,7 +99,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); // Generate a secret hash and commit it as a vote const secretHash = utils.getSecretHash(VOTE, SALT); @@ -122,7 +122,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); // Generate a secret hash and commit it as a vote const secretHash = utils.getSecretHash(VOTE, SALT); @@ -152,7 +152,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); // Generate a secret hash and commit it as a vote const secretHash = utils.getSecretHash(VOTE, SALT); @@ -181,7 +181,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); // Generate a secret hash and commit it as a vote const secretHash = utils.getSecretHash(VOTE, SALT); @@ -212,7 +212,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); // Generate a secret hash and commit it as a vote @@ -230,7 +230,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line // Increase time past reveal period await rpc.sendAsync({ method: 'evm_increaseTime', params: [100] }); - // Submit rulling + // Submit rulling await delphiVoting.submitRuling(delphiStake.address, claimNumber); // Check if the result of the ruling was equal to VOTE @@ -242,13 +242,13 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line // Set constants const CLAIM_AMOUNT = '10000'; const FEE_AMOUNT = '1000'; - const VOTE = '1'; // not justified + const VOTE = '2'; // not justified const SALT = '420'; const DATA = 'i love cats'; // Open a new claim on the DS and generate a claim ID for it const claimNumber = - await utils.makeNewClaim(staker, claimant, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); + await utils.makeNewClaim(staker, claimant, delphiVoting.address, CLAIM_AMOUNT, FEE_AMOUNT, DATA, delphiStake); const claimId = utils.getClaimId(delphiStake.address, claimNumber.toString(10)); // Generate a secret hash and commit it as a vote diff --git a/test/js/utils.js b/test/js/utils.js index fb7eddc..ef5a4f3 100644 --- a/test/js/utils.js +++ b/test/js/utils.js @@ -23,21 +23,22 @@ const utils = { await token.approve(ds.address, delphiConfig.initialStake, { from: staker }); await ds.initDelphiStake(delphiConfig.initialStake, token.address, - delphiConfig.minFee, delphiConfig.data, delphiConfig.deadline, - arbiter, { from: staker }); + delphiConfig.data, delphiConfig.deadline, { from: staker }); }, - makeNewClaim: async (staker, claimant, amount, fee, data, ds) => { + makeNewClaim: async (staker, claimant, arbiter, amount, fee, data, ds) => { const token = EIP20.at(await ds.token.call()); - await utils.as(staker, ds.whitelistClaimant, claimant, delphiConfig.deadline); + await utils.as(staker, ds.whitelistClaimant, claimant, arbiter, fee, delphiConfig.deadline, ''); await utils.as(claimant, token.approve, ds.address, new BN(fee, 10)); - await utils.as(claimant, ds.openClaim, amount, fee, data); + const whitelistId = await ds.getNumWhitelists(); + + await utils.as(claimant, ds.openClaim, whitelistId.sub(1), amount, fee, data); const claimId = (await ds.getNumClaims()).sub(1); - await utils.as(claimant, ds.settlementFailed, claimId); + await utils.as(claimant, ds.settlementFailed, claimId, ''); return claimId; }, From 24dbb810827b3f91e1c78f9583c8448d919c5978 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Mon, 30 Jul 2018 20:41:50 -0400 Subject: [PATCH 16/20] added acceptClaim and batch whitelisting functions? --- contracts/DelphiStake.sol | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index 5a93432..119549a 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -1,4 +1,5 @@ pragma solidity ^0.4.18; +pragma experimental ABIEncoderV2; import "tokens/eip20/EIP20.sol"; @@ -10,6 +11,7 @@ contract DelphiStake { event ClaimOpened(address _claimant, uint _whitelistId, uint _claimId); event ClaimOpenedWithoutSettlement(address _claimant, uint _whitelistId, uint _claimId); event FeeIncreased(address _increasedBy, uint _claimId, uint _amount); + event ClaimAccepted(uint _claimId); event SettlementProposed(address _proposedBy, uint _claimId, uint _settlementId); event SettlementAccepted(address _acceptedBy, uint _claimId, uint _settlementId); event SettlementFailed(address _failedBy, uint _claimId, string _data); @@ -189,6 +191,29 @@ contract DelphiStake { ClaimantWhitelisted(_claimant, whitelists.length - 1, _deadline, _data); } + /* + @dev A staker may also whitelist a series of claimants all at once using this batch function call + @param _claimants an address which, once whitelisted, can make claims against this stake + @param _arbiters an address which will rule on any claims this whitelisted claimant will open + @param _minimumFees the minum fee the new claimant must deposit when opening a claim + @param _deadlines the timestamp before which the whitelisted individual may open a claim + @param _datas an IPFS hash representing the scope and terms of the whitelisting + */ + function whitelistClaimants(address[] _claimants, address[] _arbiters, uint[] _minimumFees, uint[] _deadlines, string[] _datas) + public + { + //make sure all of the arrays are the same length + require(_claimants.length == _arbiters.length); + require(_arbiters.length == _minimumFees.length); + require(_minimumFees.length == _deadlines.length); + require(_deadlines.length == _datas.length); + + for(uint i = 0; i < _claimants.length; i++){ + whitelistClaimant(_claimants[i], _arbiters[i], _minimumFees[i], _deadlines[i], _datas[i]); + } + } + + /* @dev if a staker desires, they may extend the deadline before which a particular claimant may open a claim @param _whitelistId the index of the whitelisting whose deadline is being extended @@ -304,6 +329,30 @@ contract DelphiStake { FeeIncreased(msg.sender, _claimId, _amount); } + /* + @dev once a claim has been opened, the staker may simply accept their claim at face value + (to avoid doing so through a settlement) + @param _claimId the claim to be accepted + */ + function acceptClaim(uint _claimId) + public + onlyStaker + validClaimID(_claimId) + settlementDidNotFail(_claimId) + { + Claim storage claim = claims[_claimId]; + + // first set the ruling status to "settled" + claim.ruling = 5; + + claimableStake += claim.fee; + + //transfer the claim amount and return the fee to the claimant + require(token.transfer(claim.claimant, (claim.amount + claim.fee))); + + ClaimAccepted(_claimId); + } + /* @dev once a claim has been opened, either party can propose settlements to resolve the matter without getting the arbiter involved. If a settlement is accepted, both parties recover the fee From 63dbc9cc01ed275b5bc68b8ddad61cf858bdeab9 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Fri, 3 Aug 2018 17:19:21 -0400 Subject: [PATCH 17/20] deleted extraneous modifier and pragma --- contracts/DelphiStake.sol | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/contracts/DelphiStake.sol b/contracts/DelphiStake.sol index 119549a..7fd794a 100644 --- a/contracts/DelphiStake.sol +++ b/contracts/DelphiStake.sol @@ -1,5 +1,4 @@ pragma solidity ^0.4.18; -pragma experimental ABIEncoderV2; import "tokens/eip20/EIP20.sol"; @@ -87,11 +86,6 @@ contract DelphiStake { _; } - modifier onlyClaimant(uint _claimId){ - require(msg.sender == claims[_claimId].claimant); - _; - } - modifier isBeforeDeadline(uint _whitelistId){ require(now <= whitelists[_whitelistId].deadline); _; @@ -191,29 +185,6 @@ contract DelphiStake { ClaimantWhitelisted(_claimant, whitelists.length - 1, _deadline, _data); } - /* - @dev A staker may also whitelist a series of claimants all at once using this batch function call - @param _claimants an address which, once whitelisted, can make claims against this stake - @param _arbiters an address which will rule on any claims this whitelisted claimant will open - @param _minimumFees the minum fee the new claimant must deposit when opening a claim - @param _deadlines the timestamp before which the whitelisted individual may open a claim - @param _datas an IPFS hash representing the scope and terms of the whitelisting - */ - function whitelistClaimants(address[] _claimants, address[] _arbiters, uint[] _minimumFees, uint[] _deadlines, string[] _datas) - public - { - //make sure all of the arrays are the same length - require(_claimants.length == _arbiters.length); - require(_arbiters.length == _minimumFees.length); - require(_minimumFees.length == _deadlines.length); - require(_deadlines.length == _datas.length); - - for(uint i = 0; i < _claimants.length; i++){ - whitelistClaimant(_claimants[i], _arbiters[i], _minimumFees[i], _deadlines[i], _datas[i]); - } - } - - /* @dev if a staker desires, they may extend the deadline before which a particular claimant may open a claim @param _whitelistId the index of the whitelisting whose deadline is being extended From 94576173a7ea907a0cf9602064f99ef1508223e3 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Fri, 3 Aug 2018 19:26:21 -0400 Subject: [PATCH 18/20] added test for acceptClaim, beefed up tests for 100% code cov on delphiStake.sol --- test/js/DelphiStake/acceptClaim.js | 113 +++++++++++++++++++++++ test/js/DelphiStake/increaseClaimFee.js | 3 + test/js/DelphiStake/proposeSettlement.js | 15 +++ 3 files changed, 131 insertions(+) create mode 100644 test/js/DelphiStake/acceptClaim.js diff --git a/test/js/DelphiStake/acceptClaim.js b/test/js/DelphiStake/acceptClaim.js new file mode 100644 index 0000000..6fb56b1 --- /dev/null +++ b/test/js/DelphiStake/acceptClaim.js @@ -0,0 +1,113 @@ +/* eslint-env mocha */ +/* global contract artifacts assert */ + +const DelphiStake = artifacts.require('DelphiStake'); +const EIP20 = artifacts.require('EIP20'); + +const utils = require('../utils.js'); +const BN = require('bignumber.js'); + +const conf = utils.getConfig(); + +contract('DelphiStake', (accounts) => { + describe('Function: acceptClaim', () => { + const [staker, claimant, arbiter, other] = accounts; + + const claimAmount = '1'; + const startingClaims = new BN('0', 10); + + let ds; + let token; + + beforeEach(async () => { + token = await EIP20.new(1000000, 'Delphi Tokens', 18, 'DELPHI', { from: staker }); + await token.transfer(claimant, 100000, { from: staker }); + await token.transfer(arbiter, 100000, { from: staker }); + await token.transfer(other, 100000, { from: staker }); + + ds = await DelphiStake.new(); + + await token.approve(ds.address, conf.initialStake, { from: staker }); + + await ds.initDelphiStake(staker, conf.initialStake, token.address, conf.data, + conf.deadline, { from: staker }); + + await ds.whitelistClaimant(claimant, arbiter, conf.minFee, conf.deadline, "", { from: staker }); + + await token.approve(ds.address, conf.minFee, { from: claimant }); + + await ds.openClaim(0, claimAmount, conf.minFee, '', { from: claimant }); + + }); + + it('should not allow a non-staker to accept a claim', async () => { + try { + await ds.acceptClaim(0, { from: claimant }); + } catch (err) { + assert(utils.isEVMRevert(err), err.toString()); + + let claim = await ds.claims(0); + assert(parseInt(claim[6], 10) == 0, 'allowed claimant to accept their own claim'); + + return; + } + + assert(false, 'expected claim acceptance by non-issuer to fail'); + }); + + it('should not allow a staker to accept a claim outside the length of the claims array', async () => { + try { + await ds.acceptClaim(1, { from: staker }); + } catch (err) { + assert(utils.isEVMRevert(err), err.toString()); + + let claim = await ds.claims(0); + assert(parseInt(claim[6], 10) == 0, 'allowed claimant to accept their own claim'); + + return; + } + + assert(false, 'expected claim acceptance of out of bounds claim to fail'); + }); + + it('should not allow a staker to accept a claim whose settlement has failed', async () => { + await token.approve(ds.address, conf.minFee, { from: claimant }); + + await ds.openClaimWithoutSettlement(0, claimAmount, conf.minFee, '', { from: claimant }); + + try { + await ds.acceptClaim(1, { from: staker }); + } catch (err) { + assert(utils.isEVMRevert(err), err.toString()); + + let claim = await ds.claims(1); + assert(parseInt(claim[6], 10) == 0, 'allowed claimant to accept their own claim'); + + return; + } + + assert(false, 'expected claim acceptance of out of bounds claim to fail'); + }); + + it('should allow a staker to accept a claim', async () => { + + await ds.acceptClaim(0, { from: staker }); + + let balance = await token.balanceOf(claimant); + + assert(parseInt(balance, 10) == 100001); + + let claim = await ds.claims(0); + + assert(parseInt(claim[6], 10) == 5); + + }); + + it('should emit an event for accepting a claim', async () => { + await ds.acceptClaim(0, { from: staker }).then((status) => { + assert.strictEqual('ClaimAccepted', status.logs[0].event, 'did not emit the ClaimAccepted event'); + }); + }); + + }); +}); diff --git a/test/js/DelphiStake/increaseClaimFee.js b/test/js/DelphiStake/increaseClaimFee.js index 91eae61..8b6e7cb 100644 --- a/test/js/DelphiStake/increaseClaimFee.js +++ b/test/js/DelphiStake/increaseClaimFee.js @@ -93,6 +93,9 @@ contract('DelphiStake', (accounts) => { const claim1 = await ds.claims.call('0'); assert.strictEqual(claim1[4].toString(10), '1', 'claim surplus fee incorrectly'); + + await ds.ruleOnClaim(0, 4, { from: arbiter }); + }); it('should emit a FeeIncreased event', async () => { diff --git a/test/js/DelphiStake/proposeSettlement.js b/test/js/DelphiStake/proposeSettlement.js index 3ca1cc4..db6a68b 100644 --- a/test/js/DelphiStake/proposeSettlement.js +++ b/test/js/DelphiStake/proposeSettlement.js @@ -89,6 +89,21 @@ contract('DelphiStake', (accounts) => { assert.strictEqual(settlement[2], true, 'claimant did not agree'); }); + it('Should increment the number of settlements', async () => { + await ds.proposeSettlement(0, claimAmount, { from: claimant }); + + let total = await ds.getNumSettlements(0); + + assert.strictEqual(total.toString(10), '1', 'initialized settlements array length wrong'); + + await ds.proposeSettlement(0, claimAmount, { from: claimant }); + + total = await ds.getNumSettlements(0); + + assert.strictEqual(total.toString(10), '2', 'initialized settlements array length wrong'); + + }); + it('Should create a new settlement by the staker, and have the settlement properly initialize the fields', async () => { await ds.proposeSettlement(0, claimAmount, { from: staker }); From 1c037a4d431147b265eb18d68cdae9adab8d931d Mon Sep 17 00:00:00 2001 From: mbeylin Date: Fri, 3 Aug 2018 22:07:24 -0400 Subject: [PATCH 19/20] parameterized the staker --- contracts/DelphiStakeFactory.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/DelphiStakeFactory.sol b/contracts/DelphiStakeFactory.sol index 06c4057..fb55d8c 100644 --- a/contracts/DelphiStakeFactory.sol +++ b/contracts/DelphiStakeFactory.sol @@ -21,15 +21,19 @@ contract DelphiStakeFactory { /* @dev when creating a new Delphi Stake using a proxy contract architecture, a user must initialialize their stake, depositing their tokens + @param _staker the address of the individual creating the stake @param _value the value of the stake in token units @param _token the address of the token being deposited @param _data a content hash of the relevant associated data describing the stake @param _claimDeadline the deadline for opening new cliams; the earliest moment that a stake can be withdrawn by the staker */ - function createDelphiStake(uint _value, EIP20 _token, string _data, uint _stakeReleaseTime) + function createDelphiStake(address _issuer, uint _value, EIP20 _token, string _data, uint _stakeReleaseTime) public { + // Revert if the issuer is the 0 _contractAddress + require(_issuer != address(0)); + // Revert if the specified value to stake cannot be transferred in require(_token.transferFrom(msg.sender, this, _value)); @@ -40,7 +44,7 @@ contract DelphiStakeFactory { _token.approve(newStake, _value); // Initialize the stake and set the staker address as the msg.sender - stakes[stakes.length - 1].initDelphiStake(msg.sender, _value, _token, _data, _stakeReleaseTime); + stakes[stakes.length - 1].initDelphiStake(_issuer, _value, _token, _data, _stakeReleaseTime); StakeCreated(stakes.length - 1, stakes[stakes.length - 1]); } From 0f58d3a6ecf5224a54e1289de16e9d8538324254 Mon Sep 17 00:00:00 2001 From: mbeylin Date: Fri, 3 Aug 2018 22:07:53 -0400 Subject: [PATCH 20/20] updated tests for new stake parameter --- test/js/DelphiStakeFactory/createDelphiStake.js | 10 +++++----- test/js/DelphiVoting/claimFee.js | 2 +- test/js/DelphiVoting/commitVote.js | 2 +- test/js/DelphiVoting/revealVote.js | 2 +- test/js/DelphiVoting/submitRuling.js | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/js/DelphiStakeFactory/createDelphiStake.js b/test/js/DelphiStakeFactory/createDelphiStake.js index 14c1d30..d0eb178 100644 --- a/test/js/DelphiStakeFactory/createDelphiStake.js +++ b/test/js/DelphiStakeFactory/createDelphiStake.js @@ -30,7 +30,7 @@ contract('DelphiStakeFactory', (accounts) => { it('should allow the creatation of a single stake', async () => { await token.approve(df.address, conf.initialStake, { from: staker }); - await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, + await utils.as(staker, df.createDelphiStake, staker, conf.initialStake, token.address, conf.data, conf.deadline); const numStakes = await df.getNumStakes.call(); @@ -56,7 +56,7 @@ contract('DelphiStakeFactory', (accounts) => { /* eslint-disable no-await-in-loop */ for (let i = 0; i < N; i += 1) { await token.approve(df.address, conf.initialStake, { from: staker }); - await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, + await utils.as(staker, df.createDelphiStake, staker, conf.initialStake, token.address, i.toString(10), conf.deadline); } @@ -83,7 +83,7 @@ contract('DelphiStakeFactory', (accounts) => { await token.approve(df.address, conf.initialStake - 1, { from: staker }); try { - await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, + await utils.as(staker, df.createDelphiStake, staker, conf.initialStake, token.address, conf.data, conf.deadline); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -101,7 +101,7 @@ contract('DelphiStakeFactory', (accounts) => { await token.approve(df.address, conf.initialStake, { from: staker }); try { - await utils.as(staker, df.createDelphiStake, conf.initialStake, token.address, + await utils.as(staker, df.createDelphiStake, staker, conf.initialStake, token.address, conf.data, '1'); } catch (err) { assert(utils.isEVMRevert(err), err.toString()); @@ -114,7 +114,7 @@ contract('DelphiStakeFactory', (accounts) => { it('should emit a StakeCreated event', async () => { await token.approve(df.address, conf.initialStake, { from: staker }); - await df.createDelphiStake(conf.initialStake, token.address, conf.data, + await df.createDelphiStake(staker, conf.initialStake, token.address, conf.data, conf.deadline, { from: staker }).then((status) => { assert.strictEqual('StakeCreated', status.logs[0].event, 'did not emit the StakeCreated event'); }); diff --git a/test/js/DelphiVoting/claimFee.js b/test/js/DelphiVoting/claimFee.js index 3a500cf..2606b68 100644 --- a/test/js/DelphiVoting/claimFee.js +++ b/test/js/DelphiVoting/claimFee.js @@ -100,7 +100,7 @@ contract('DelphiVoting', (accounts) => { // from now await token.approve(delphiStakeFactory.address, 90000, { from: staker }); const expirationTime = (await web3.eth.getBlock('latest')).timestamp + 1000; - const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(90000, token.address, + const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(staker, 90000, token.address, '', expirationTime, { from: staker }); // eslint-disable-next-line delphiStake = DelphiStake.at(delphiStakeReceipt.logs[0].args._contractAddress); diff --git a/test/js/DelphiVoting/commitVote.js b/test/js/DelphiVoting/commitVote.js index 0c82236..844dd2d 100644 --- a/test/js/DelphiVoting/commitVote.js +++ b/test/js/DelphiVoting/commitVote.js @@ -83,7 +83,7 @@ contract('DelphiVoting', (accounts) => { // from now await token.approve(delphiStakeFactory.address, 90000, { from: staker }); const expirationTime = (await web3.eth.getBlock('latest')).timestamp + 1000; - const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(90000, token.address, + const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(staker, 90000, token.address, '', expirationTime, { from: staker }); // eslint-disable-next-line delphiStake = DelphiStake.at(delphiStakeReceipt.logs[0].args._contractAddress); diff --git a/test/js/DelphiVoting/revealVote.js b/test/js/DelphiVoting/revealVote.js index 6f3084d..aa89e67 100644 --- a/test/js/DelphiVoting/revealVote.js +++ b/test/js/DelphiVoting/revealVote.js @@ -83,7 +83,7 @@ contract('DelphiVoting', (accounts) => { // from now await token.approve(delphiStakeFactory.address, 90000, { from: staker }); const expirationTime = (await web3.eth.getBlock('latest')).timestamp + 1000; - const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(90000, token.address, + const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(staker, 90000, token.address, '', expirationTime, { from: staker }); // eslint-disable-next-line delphiStake = DelphiStake.at(delphiStakeReceipt.logs[0].args._contractAddress); diff --git a/test/js/DelphiVoting/submitRuling.js b/test/js/DelphiVoting/submitRuling.js index 0ad8177..560b2bb 100644 --- a/test/js/DelphiVoting/submitRuling.js +++ b/test/js/DelphiVoting/submitRuling.js @@ -83,7 +83,7 @@ contract('DelphiVoting', (accounts) => { //eslint-disable-line // from now await token.approve(delphiStakeFactory.address, 90000, { from: staker }); const expirationTime = (await web3.eth.getBlock('latest')).timestamp + 1000; - const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(90000, token.address, + const delphiStakeReceipt = await delphiStakeFactory.createDelphiStake(staker, 90000, token.address, '', expirationTime, { from: staker }); // eslint-disable-next-line delphiStake = DelphiStake.at(delphiStakeReceipt.logs[0].args._contractAddress);