Continue Contribution contract and JS wrapper
This commit is contained in:
parent
6b8f718051
commit
dae44cac70
@ -1,34 +1,49 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
import "zeppelin-solidity/contracts/token/ERC721/ERC721Token.sol";
|
||||
import './upgradeable/Upgradeable.sol';
|
||||
|
||||
// ToDo: only load interfaces
|
||||
import './Token.sol';
|
||||
import './Contributors.sol';
|
||||
|
||||
contract Contribution is Upgradeable, ERC721Token {
|
||||
|
||||
struct Contribution {
|
||||
struct ContributionData {
|
||||
address contributor;
|
||||
uint amount;
|
||||
bool issued;
|
||||
uint proposalId;
|
||||
string url;
|
||||
uint256 claimAfterBlock;
|
||||
bool claimed;
|
||||
bytes32 hashDigest;
|
||||
uint8 hashFunction;
|
||||
uint8 hashSize;
|
||||
string tokenMetadataURL;
|
||||
uint claimAfterBlock;
|
||||
bool exists;
|
||||
}
|
||||
string internal name_;
|
||||
string internal symbol_;
|
||||
|
||||
mapping(uint256 => string) contributionURIs;
|
||||
|
||||
mapping(uint256 => address) contributionOwner;
|
||||
mapping(address => uint256[]) ownedContributions;
|
||||
|
||||
mapping(uint256 => Contribution) public contributions;
|
||||
mapping(uint256 => ContributionData) public contributions;
|
||||
uint256 public contributionsCount;
|
||||
|
||||
event ContributionAdded(uint256 id, address indexed contributor, uint256 amount);
|
||||
event ContributionClaimed(uint256 id, address indexed contributor, uint256 amount);
|
||||
|
||||
modifier coreOnly() {
|
||||
require(contributorsContract().addressIsCore(msg.sender));
|
||||
_;
|
||||
}
|
||||
modifier contributorOnly() {
|
||||
require(contributorsContract().addressExists(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
function contributorsContract() view public returns (Contributors) {
|
||||
return Contributors(registry.getProxyFor('Contributors'));
|
||||
}
|
||||
|
||||
function tokenContract() view public returns (Token) {
|
||||
return Token(registry.getProxyFor('Token'));
|
||||
@ -42,11 +57,6 @@ contract Contribution is Upgradeable, ERC721Token {
|
||||
return symbol_;
|
||||
}
|
||||
|
||||
function contributionURI(uint256 contributionId) public view returns (string) {
|
||||
require(exists(contributionId));
|
||||
return contributions[contributionId].url;
|
||||
}
|
||||
|
||||
function ownerOf(uint256 contributionId) public view returns (address) {
|
||||
require(exists(contributionId));
|
||||
return contributions[contributionId].contributor;
|
||||
@ -56,14 +66,36 @@ contract Contribution is Upgradeable, ERC721Token {
|
||||
return ownedContributions[contributor].length;
|
||||
}
|
||||
|
||||
function add(uint256 amount, uint256 proposalId, address contributor, uint256 blocksToWait, string url) public {
|
||||
function tokenOfOwnerByIndex(address contributor, uint index) public view returns (uint) {
|
||||
return ownedContributions[contributor][index];
|
||||
}
|
||||
|
||||
function tokenMetadata(uint contributionId) public view returns (string) {
|
||||
return contributions[contributionId].tokenMetadataURL;
|
||||
}
|
||||
|
||||
function getContribution(uint contributionId) public view returns (uint256 id, address contributor, uint256 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint claimAfterBlock, bool exists) {
|
||||
id = contributionId;
|
||||
ContributionData storage c = contributions[id];
|
||||
return (
|
||||
id,
|
||||
c.contributor,
|
||||
c.amount,
|
||||
c.claimed,
|
||||
c.hashDigest,
|
||||
c.hashFunction,
|
||||
c.hashSize,
|
||||
c.claimAfterBlock,
|
||||
c.exists
|
||||
);
|
||||
}
|
||||
|
||||
function add(uint256 amount, address contributor, uint256 blocksToWait) public coreOnly {
|
||||
uint contributionId = contributionsCount + 1;
|
||||
var c = contributions[contributionId];
|
||||
ContributionData storage c = contributions[contributionId];
|
||||
c.exists = true;
|
||||
c.amount = amount;
|
||||
c.issued = false;
|
||||
c.proposalId = proposalId;
|
||||
c.url = url;
|
||||
c.claimed = false;
|
||||
c.contributor = contributor;
|
||||
c.claimAfterBlock = block.number + blocksToWait;
|
||||
|
||||
@ -71,17 +103,19 @@ contract Contribution is Upgradeable, ERC721Token {
|
||||
|
||||
contributionOwner[contributionId] = contributor;
|
||||
ownedContributions[contributor].push(contributionId);
|
||||
|
||||
|
||||
ContributionAdded(contributionId, contributor, amount);
|
||||
}
|
||||
|
||||
function claim(uint256 contributionId) public {
|
||||
var c = contributions[contributionId];
|
||||
ContributionData storage c = contributions[contributionId];
|
||||
require(c.exists);
|
||||
require(!c.issued);
|
||||
require(!c.claimed);
|
||||
require(block.number > c.claimAfterBlock);
|
||||
c.claimed = true;
|
||||
tokenContract().mintFor(c.contributor, c.amount, contributionId);
|
||||
c.issued = true;
|
||||
|
||||
ContributionClaimed(contributionId, c.contributor, c.amount);
|
||||
}
|
||||
|
||||
function exists(uint256 contributionId) view public returns (bool) {
|
||||
|
@ -121,12 +121,11 @@ contract Operator is Upgradeable {
|
||||
}
|
||||
|
||||
function executeProposal(uint proposalId) private {
|
||||
|
||||
var p = proposals[proposalId];
|
||||
require(!p.executed);
|
||||
require(p.votesCount >= p.votesNeeded);
|
||||
address recipientAddress = contributorsContract().getContributorAddressById(p.contributorId);
|
||||
contributionContract().add(p.amount, proposalId, recipientAddress, 0, '');
|
||||
contributionContract().add(p.amount, recipientAddress, 0);
|
||||
p.executed = true;
|
||||
ProposalExecuted(proposalId, p.contributorId, p.amount);
|
||||
}
|
||||
|
1
lib/abis/Contribution.json
Normal file
1
lib/abis/Contribution.json
Normal file
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"creatorAccount","type":"address"},{"name":"contributorId","type":"uint256"},{"name":"votesCount","type":"uint256"},{"name":"votesNeeded","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"executed","type":"bool"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"proposalsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_proxiedContractName","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"creatorAccount","type":"address"},{"indexed":false,"name":"contributorId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"voterId","type":"uint256"},{"indexed":false,"name":"totalVotes","type":"uint256"}],"name":"ProposalVoted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"contributorId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"constant":true,"inputs":[],"name":"contributorsContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"contributorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"coreContributorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"contributorId","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"}],"name":"addProposal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"proposalId","type":"uint256"}],"name":"getProposal","outputs":[{"name":"id","type":"uint256"},{"name":"creatorAccount","type":"address"},{"name":"contributorId","type":"uint256"},{"name":"votesCount","type":"uint256"},{"name":"votesNeeded","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"executed","type":"bool"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"voterIds","type":"uint256[]"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"proposalId","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_proposalIds","type":"uint256[]"}],"name":"batchVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
|
||||
[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"creatorAccount","type":"address"},{"name":"contributorId","type":"uint256"},{"name":"votesCount","type":"uint256"},{"name":"votesNeeded","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"executed","type":"bool"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"proposalsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_proxiedContractName","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"creatorAccount","type":"address"},{"indexed":false,"name":"contributorId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"voterId","type":"uint256"},{"indexed":false,"name":"totalVotes","type":"uint256"}],"name":"ProposalVoted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"contributorId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"constant":true,"inputs":[],"name":"contributorsContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"contributionContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"contributorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"coreContributorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"contributorId","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"}],"name":"addProposal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"proposalId","type":"uint256"}],"name":"getProposal","outputs":[{"name":"id","type":"uint256"},{"name":"creatorAccount","type":"address"},{"name":"contributorId","type":"uint256"},{"name":"votesCount","type":"uint256"},{"name":"votesNeeded","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"executed","type":"bool"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"voterIds","type":"uint256[]"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"proposalId","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_proposalIds","type":"uint256[]"}],"name":"batchVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
|
51
lib/contracts/contribution.js
Normal file
51
lib/contracts/contribution.js
Normal file
@ -0,0 +1,51 @@
|
||||
const ethers = require('ethers');
|
||||
const RSVP = require('rsvp');
|
||||
|
||||
const ContributionSerializer = require('../serializers/contribution');
|
||||
const Base = require('./base');
|
||||
|
||||
class Contribution extends Base {
|
||||
all() {
|
||||
return this.functions.contributionsCount()
|
||||
.then((count) => {
|
||||
count = count.toNumber();
|
||||
let contributions = [];
|
||||
|
||||
for (let id = 1; id <= count; id++) {
|
||||
contributions.push(this.getById(id));
|
||||
}
|
||||
|
||||
return RSVP.all(contributions);
|
||||
});
|
||||
}
|
||||
|
||||
getById(id) {
|
||||
id = ethers.utils.bigNumberify(id);
|
||||
|
||||
return this.functions.getContribution(id)
|
||||
.then((data) => {
|
||||
return this.ipfs.catAndMerge(data, ContributionSerializer.deserialize);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
getByContributor(contributor) {
|
||||
return this.functions.balanceOf(contributor)
|
||||
then((balance) => {
|
||||
count = balance.toNumber();
|
||||
|
||||
let contributions = [];
|
||||
|
||||
for (let index = 0; index <= count; index++) {
|
||||
this.functions.tokenOfOwnerByIndex(contributor, index)
|
||||
.then((id) => {
|
||||
contributions.push(this.getById(id));
|
||||
});
|
||||
}
|
||||
|
||||
return RSVP.all(contributions);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Contribution;
|
@ -1,5 +1,6 @@
|
||||
module.exports = {
|
||||
Contributors: require('./contributor'),
|
||||
Contribution: require('./contribution'),
|
||||
Operator: require('./operator'),
|
||||
Token: require('./token'),
|
||||
Registry: require('./registry')
|
||||
|
@ -5,6 +5,7 @@ const Preflight = require('./utils/preflight');
|
||||
|
||||
const ABIS = {
|
||||
Contributors: require('./abis/Contributors.json'),
|
||||
Contribution: require('./abis/Contribution.json'),
|
||||
Operator: require('./abis/Operator.json'),
|
||||
Registry: require('./abis/Registry.json'),
|
||||
Token: require('./abis/Token.json')
|
||||
@ -76,6 +77,10 @@ class Kredits {
|
||||
return this.contractFor('token');
|
||||
}
|
||||
|
||||
get Contribution() {
|
||||
return this.contractFor('contribution');
|
||||
}
|
||||
|
||||
// Should be private
|
||||
contractFor(name) {
|
||||
if (this.contracts[name]) {
|
||||
|
@ -8,6 +8,7 @@ const addressesPath = path.join(libPath, 'addresses');
|
||||
|
||||
const files = [
|
||||
'Contributors',
|
||||
'Contribution',
|
||||
'Operator',
|
||||
'Registry',
|
||||
'Token'
|
||||
|
Loading…
x
Reference in New Issue
Block a user