mirror of
https://github.com/status-im/visual-identity.git
synced 2025-02-13 04:57:03 +00:00
Created test case to demonstrate how to use contracts
This commit is contained in:
parent
a712cece85
commit
3759522633
7
config/namesystem.js
Normal file
7
config/namesystem.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
default: {
|
||||||
|
enabled: false,
|
||||||
|
available_providers: ["ens"],
|
||||||
|
provider: "ens"
|
||||||
|
}
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.11;
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
import "../common/Controlled.sol";
|
import "../common/Controlled.sol";
|
||||||
import "./LowLevelStringManipulator.sol";
|
import "./LowLevelStringManipulator.sol";
|
||||||
@ -27,6 +27,8 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
address token;
|
address token;
|
||||||
address pollContract;
|
address pollContract;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
|
uint voters;
|
||||||
|
mapping(bytes32 => uint) votersPerBallot;
|
||||||
mapping(address => VoteLog) votes;
|
mapping(address => VoteLog) votes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,10 +64,10 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
Poll p = _polls[ _idPoll ];
|
Poll p = _polls[ _idPoll ];
|
||||||
p.startBlock = _startBlock;
|
p.startBlock = _startBlock;
|
||||||
p.endBlock = _endBlock;
|
p.endBlock = _endBlock;
|
||||||
|
p.voters = 0;
|
||||||
|
|
||||||
|
var (name, symbol) = getTokenNameSymbol(address(token));
|
||||||
var (name,symbol) = getTokenNameSymbol(address(token));
|
string memory proposalName = strConcat(name, "_", uint2str(_idPoll));
|
||||||
string memory proposalName = strConcat(name , "_", uint2str(_idPoll));
|
|
||||||
string memory proposalSymbol = strConcat(symbol, "_", uint2str(_idPoll));
|
string memory proposalSymbol = strConcat(symbol, "_", uint2str(_idPoll));
|
||||||
|
|
||||||
p.token = tokenFactory.createCloneToken(
|
p.token = tokenFactory.createCloneToken(
|
||||||
@ -80,6 +82,8 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
p.pollContract = IPollFactory(_pollFactory).create(_description);
|
p.pollContract = IPollFactory(_pollFactory).create(_description);
|
||||||
|
|
||||||
if (p.pollContract == 0) throw;
|
if (p.pollContract == 0) throw;
|
||||||
|
|
||||||
|
emit PollCreated(_idPoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelPoll(uint _idPoll) onlyController {
|
function cancelPoll(uint _idPoll) onlyController {
|
||||||
@ -90,6 +94,18 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
PollCanceled(_idPoll);
|
PollCanceled(_idPoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function canVote(uint _idPoll) public view returns(bool) {
|
||||||
|
if(_idPoll >= _polls.length) return false;
|
||||||
|
|
||||||
|
Poll storage p = _polls[_idPoll];
|
||||||
|
uint balance = MiniMeToken(p.token).balanceOf(msg.sender);
|
||||||
|
|
||||||
|
return block.number >= p.startBlock &&
|
||||||
|
block.number <= p.endBlock &&
|
||||||
|
!p.canceled &&
|
||||||
|
balance != 0;
|
||||||
|
}
|
||||||
|
|
||||||
function vote(uint _idPoll, bytes32 _ballot) {
|
function vote(uint _idPoll, bytes32 _ballot) {
|
||||||
if (_idPoll >= _polls.length) throw;
|
if (_idPoll >= _polls.length) throw;
|
||||||
Poll p = _polls[_idPoll];
|
Poll p = _polls[_idPoll];
|
||||||
@ -110,6 +126,10 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
|
|
||||||
p.votes[msg.sender].ballot = _ballot;
|
p.votes[msg.sender].ballot = _ballot;
|
||||||
p.votes[msg.sender].amount = amount;
|
p.votes[msg.sender].amount = amount;
|
||||||
|
|
||||||
|
p.voters++;
|
||||||
|
|
||||||
|
p.votersPerBallot[_ballot]++;
|
||||||
|
|
||||||
if (!IPollContract(p.pollContract).deltaVote(int(amount), _ballot)) throw;
|
if (!IPollContract(p.pollContract).deltaVote(int(amount), _ballot)) throw;
|
||||||
|
|
||||||
@ -129,9 +149,11 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
|
|
||||||
if (!IPollContract(p.pollContract).deltaVote(-int(amount), ballot)) throw;
|
if (!IPollContract(p.pollContract).deltaVote(-int(amount), ballot)) throw;
|
||||||
|
|
||||||
|
|
||||||
p.votes[msg.sender].ballot = 0;
|
p.votes[msg.sender].ballot = 0;
|
||||||
p.votes[msg.sender].amount = 0;
|
p.votes[msg.sender].amount = 0;
|
||||||
|
p.votersPerBallot[ballot]--;
|
||||||
|
|
||||||
|
p.voters--;
|
||||||
|
|
||||||
// enableTransfers = true;
|
// enableTransfers = true;
|
||||||
if (!MiniMeToken(p.token).transferFrom(address(this), msg.sender, amount)) throw;
|
if (!MiniMeToken(p.token).transferFrom(address(this), msg.sender, amount)) throw;
|
||||||
@ -155,7 +177,8 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
bytes32 _pollType,
|
bytes32 _pollType,
|
||||||
string _question,
|
string _question,
|
||||||
bool _finalized,
|
bool _finalized,
|
||||||
uint _totalCensus
|
uint _totalCensus,
|
||||||
|
uint _voters
|
||||||
) {
|
) {
|
||||||
if (_idPoll >= _polls.length) throw;
|
if (_idPoll >= _polls.length) throw;
|
||||||
Poll p = _polls[_idPoll];
|
Poll p = _polls[_idPoll];
|
||||||
@ -168,6 +191,7 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
_question = getString(p.pollContract, bytes4(sha3("question()")));
|
_question = getString(p.pollContract, bytes4(sha3("question()")));
|
||||||
_finalized = (!p.canceled) && (getBlockNumber() >= _endBlock);
|
_finalized = (!p.canceled) && (getBlockNumber() >= _endBlock);
|
||||||
_totalCensus = MiniMeToken(p.token).totalSupply();
|
_totalCensus = MiniMeToken(p.token).totalSupply();
|
||||||
|
_voters = p.voters;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVote(uint _idPoll, address _voter) constant returns (bytes32 _ballot, uint _amount) {
|
function getVote(uint _idPoll, address _voter) constant returns (bytes32 _ballot, uint _amount) {
|
||||||
@ -178,6 +202,16 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
_amount = p.votes[_voter].amount;
|
_amount = p.votes[_voter].amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getVotesByBallot(uint _idPoll, bytes32 _ballot)
|
||||||
|
public view returns(uint voters, uint votes) {
|
||||||
|
if (_idPoll >= _polls.length) throw;
|
||||||
|
Poll storage p = _polls[_idPoll];
|
||||||
|
|
||||||
|
voters = p.votersPerBallot[_ballot];
|
||||||
|
votes = p.votersPerBallot[_ballot];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function proxyPayment(address ) payable returns(bool) {
|
function proxyPayment(address ) payable returns(bool) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -199,6 +233,7 @@ contract PollManager is LowLevelStringManipulator, Controlled {
|
|||||||
event Vote(uint indexed idPoll, address indexed _voter, bytes32 ballot, uint amount);
|
event Vote(uint indexed idPoll, address indexed _voter, bytes32 ballot, uint amount);
|
||||||
event Unvote(uint indexed idPoll, address indexed _voter, bytes32 ballot, uint amount);
|
event Unvote(uint indexed idPoll, address indexed _voter, bytes32 ballot, uint amount);
|
||||||
event PollCanceled(uint indexed idPoll);
|
event PollCanceled(uint indexed idPoll);
|
||||||
|
event PollCreated(uint indexed idPoll);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ contract SingleChoice is Controlled {
|
|||||||
using RLP for bytes;
|
using RLP for bytes;
|
||||||
|
|
||||||
string public question;
|
string public question;
|
||||||
string[] public options;
|
string[] public choices;
|
||||||
int[] public result;
|
int[] public result;
|
||||||
bytes32 uid;
|
bytes32 uid;
|
||||||
|
|
||||||
@ -50,11 +50,11 @@ contract SingleChoice is Controlled {
|
|||||||
var itrOptions = itmOptions.iterator();
|
var itrOptions = itmOptions.iterator();
|
||||||
|
|
||||||
while(itrOptions.hasNext()) {
|
while(itrOptions.hasNext()) {
|
||||||
options.length++;
|
choices.length++;
|
||||||
options[options.length-1] = itrOptions.next().toAscii();
|
choices[choices.length-1] = itrOptions.next().toAscii();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.length = options.length;
|
result.length = choices.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pollType() constant returns (bytes32) {
|
function pollType() constant returns (bytes32) {
|
||||||
@ -63,7 +63,7 @@ contract SingleChoice is Controlled {
|
|||||||
|
|
||||||
function isValid(bytes32 _ballot) constant returns(bool) {
|
function isValid(bytes32 _ballot) constant returns(bool) {
|
||||||
uint v = uint(_ballot) / (2**248);
|
uint v = uint(_ballot) / (2**248);
|
||||||
if (v>=options.length) return false;
|
if (v>=choices.length) return false;
|
||||||
if (getBallot(v) != _ballot) return false;
|
if (getBallot(v) != _ballot) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ contract SingleChoice is Controlled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function nOptions() constant returns(uint) {
|
function nOptions() constant returns(uint) {
|
||||||
return options.length;
|
return choices.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBallot(uint _option) constant returns(bytes32) {
|
function getBallot(uint _option) constant returns(bytes32) {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
pragma solidity ^0.4.6;
|
pragma solidity ^0.4.6;
|
||||||
|
|
||||||
import "./SingleChoice.sol";
|
import "./SingleChoice.sol";
|
||||||
|
import "./PollManager.sol";
|
||||||
|
|
||||||
contract SingleChoiceFactory {
|
contract SingleChoiceFactory is IPollFactory {
|
||||||
uint salt;
|
uint salt;
|
||||||
function create(bytes _description) returns(address) {
|
function create(bytes _description) returns(address) {
|
||||||
salt++;
|
salt++;
|
||||||
|
@ -22,10 +22,12 @@
|
|||||||
"bignumber.js": "^5.0.0",
|
"bignumber.js": "^5.0.0",
|
||||||
"formik": "^0.11.11",
|
"formik": "^0.11.11",
|
||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
|
"lodash": "^4.17.10",
|
||||||
"react": "^16.3.2",
|
"react": "^16.3.2",
|
||||||
"react-blockies": "^1.3.0",
|
"react-blockies": "^1.3.0",
|
||||||
"react-bootstrap": "^0.32.1",
|
"react-bootstrap": "^0.32.1",
|
||||||
"react-dom": "^16.3.2",
|
"react-dom": "^16.3.2",
|
||||||
"react-toggle": "^4.0.2"
|
"react-toggle": "^4.0.2",
|
||||||
|
"rlp": "^2.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
168
test/votingdapp.js
Normal file
168
test/votingdapp.js
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
const utils = require('../utils/testUtils')
|
||||||
|
const assert = require('assert');
|
||||||
|
const SingleChoice = require('Embark/contracts/SingleChoice');
|
||||||
|
const BN = web3.utils.BN;
|
||||||
|
var _ = require('lodash');
|
||||||
|
var rlp = require('rlp');
|
||||||
|
|
||||||
|
config({
|
||||||
|
contracts: {
|
||||||
|
"MiniMeTokenFactory": {
|
||||||
|
"gasLimit": 4000000
|
||||||
|
},
|
||||||
|
"MiniMeToken": {
|
||||||
|
"deploy": false,
|
||||||
|
},
|
||||||
|
"SNT":{
|
||||||
|
"instanceOf": "MiniMeToken",
|
||||||
|
"args": [
|
||||||
|
"$MiniMeTokenFactory",
|
||||||
|
utils.zeroAddress,
|
||||||
|
0,
|
||||||
|
"TestMiniMeToken",
|
||||||
|
18,
|
||||||
|
"TST",
|
||||||
|
true
|
||||||
|
],
|
||||||
|
"gasLimit": 4000000
|
||||||
|
},
|
||||||
|
"PollManager": {
|
||||||
|
"deploy": true,
|
||||||
|
"args": ["$MiniMeTokenFactory", "$SNT"]
|
||||||
|
},
|
||||||
|
"SingleChoiceFactory": {
|
||||||
|
"deploy": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
singleChoiceDef = (question, options) => {
|
||||||
|
var d = [
|
||||||
|
new Buffer(question),
|
||||||
|
_.map(options, function(o) {
|
||||||
|
return new Buffer(o);
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
var b= rlp.encode(d);
|
||||||
|
var rlpDefinition = '0x' + b.toString('hex');
|
||||||
|
|
||||||
|
return rlpDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("VotingDapp", function () {
|
||||||
|
this.timeout(0);
|
||||||
|
|
||||||
|
let accounts;
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
|
||||||
|
web3.eth.getAccounts().then((acc) => {
|
||||||
|
accounts = acc;
|
||||||
|
return SNT.methods.generateTokens(accounts[0], 123456).send()
|
||||||
|
}).then((receipt) => {
|
||||||
|
return SNT.methods.generateTokens(accounts[1], 789012).send()
|
||||||
|
}).then((receipt) => {
|
||||||
|
return SNT.methods.generateTokens(accounts[2], 345678).send()
|
||||||
|
}).then((receipt) => {
|
||||||
|
return SNT.methods.generateTokens(accounts[3], 901234).send()
|
||||||
|
}).then((receipt) => {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Test", async () => {
|
||||||
|
|
||||||
|
const blockNumber = await web3.eth.getBlockNumber();
|
||||||
|
const question = singleChoiceDef("Move from Slack to Status Desktop", [ "Yes", "No" ]);
|
||||||
|
let receipt;
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Creating a proposal without holding SNT SHOULD FAIL!
|
||||||
|
try {
|
||||||
|
receipt = await PollManager.methods.addPoll(
|
||||||
|
blockNumber,
|
||||||
|
blockNumber + 10,
|
||||||
|
SingleChoiceFactory.options.address,
|
||||||
|
question)
|
||||||
|
.send({from: accounts[8]});
|
||||||
|
assert.fail('should have reverted before');
|
||||||
|
} catch(error) {
|
||||||
|
utils.assertJump(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Creating a proposal as a SNT holder
|
||||||
|
|
||||||
|
receipt = await PollManager.methods.addPoll(
|
||||||
|
blockNumber,
|
||||||
|
blockNumber + 10,
|
||||||
|
SingleChoiceFactory.options.address,
|
||||||
|
question)
|
||||||
|
.send({from: accounts[0]});
|
||||||
|
|
||||||
|
assert.equal(!!receipt.events.PollCreated, true, "PollCreated not triggered");
|
||||||
|
|
||||||
|
const pollId = receipt.events.PollCreated.returnValues.idPoll;
|
||||||
|
let poll = await PollManager.methods.poll(pollId).call();
|
||||||
|
|
||||||
|
SingleChoice.options.address = poll._pollContract;
|
||||||
|
const pollContract = SingleChoice;
|
||||||
|
|
||||||
|
// Options are represented as a hex value
|
||||||
|
const Yes = await SingleChoice.methods.getBallot(0).call();
|
||||||
|
const No = await SingleChoice.methods.getBallot(1).call();
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Determining if I can vote por a proposal
|
||||||
|
let canVote = await PollManager.methods.canVote(pollId).call({from: accounts[0]});
|
||||||
|
assert.equal(canVote, true, "User should be able to vote");
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Voting
|
||||||
|
receipt = await PollManager.methods.vote(pollId, Yes).send({from: accounts[0]});
|
||||||
|
assert.equal(!!receipt.events.Vote, true, "Vote not triggered");
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Getting what option the voter selected
|
||||||
|
let myVote = await PollManager.methods.getVote(pollId, accounts[0]).call();
|
||||||
|
assert.equal(myVote._ballot, Yes, "Vote is different from selected");
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Voting when you're not a SNT holder SHOULD FAIL!
|
||||||
|
try {
|
||||||
|
receipt = await PollManager.methods.vote(pollId, Yes)
|
||||||
|
.send({from: accounts[8]});
|
||||||
|
assert.fail('should have reverted before');
|
||||||
|
} catch(error) {
|
||||||
|
utils.assertJump(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Getting proposal information
|
||||||
|
poll = await PollManager.methods.poll(pollId).call();
|
||||||
|
let votersByBallotYES = await PollManager.methods.getVotesByBallot(pollId, Yes).call();
|
||||||
|
let tokenVotesByBallotYES = await pollContract.methods.result(0).call(); // 0 == Yes (because it is the initial option )
|
||||||
|
|
||||||
|
// console.dir(poll); // Will contain state of the poll
|
||||||
|
// console.log(tokenVotesByBallotYES); // Contains how many votes has a ballot
|
||||||
|
// console.log(votersByBallotYES); // Contains how many voters voted for that option
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Unvote
|
||||||
|
receipt = await PollManager.methods.unvote(pollId).send({from: accounts[0]});
|
||||||
|
assert.equal(!!receipt.events.Unvote, true, "Unvote not triggered");
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user