Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Staking bug updates #97

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 182 additions & 99 deletions contracts/DelphiStake.sol

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions contracts/DelphiStakeFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +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 _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(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));

Expand All @@ -42,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, _minimumFee, _data, _stakeReleaseTime, _arbiter);
stakes[stakes.length - 1].initDelphiStake(_issuer, _value, _token, _data, _stakeReleaseTime);

StakeCreated(stakes.length - 1, stakes[stakes.length - 1]);
}
Expand Down
16 changes: 8 additions & 8 deletions contracts/DelphiVoting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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));

Expand Down Expand Up @@ -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
Expand All @@ -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);
}

/*
Expand All @@ -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
Expand Down
29 changes: 7 additions & 22 deletions test/js/DelphiStake/DelphiStake.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -41,17 +41,14 @@ 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');
});

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());

Expand All @@ -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());

Expand All @@ -78,25 +75,13 @@ 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());

return;
}
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)');
});
});
});
113 changes: 113 additions & 0 deletions test/js/DelphiStake/acceptClaim.js
Original file line number Diff line number Diff line change
@@ -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');
});
});

});
});
16 changes: 8 additions & 8 deletions test/js/DelphiStake/acceptSettlement.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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}
Expand All @@ -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 });
Expand All @@ -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 () => {
Expand Down
4 changes: 2 additions & 2 deletions test/js/DelphiStake/extendStakeReleaseTime.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
Loading