Merge pull request #73 from 67P/feature/contribution_owner

Convert contribution owner to ID, use smaller number formats
This commit is contained in:
bumi 2019-04-04 21:40:16 +00:00 committed by GitHub
commit 99394e7f14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 159 additions and 128 deletions

View File

@ -4,7 +4,14 @@ import "@aragon/os/contracts/apps/AragonApp.sol";
import "@aragon/os/contracts/kernel/IKernel.sol"; import "@aragon/os/contracts/kernel/IKernel.sol";
interface IToken { interface IToken {
function mintFor(address contributorAccount, uint256 amount, uint256 contributionId) public; function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public;
}
interface ContributorInterface {
function getContributorAddressById(uint32 contributorId) public view returns (address);
function getContributorIdByAddress(address contributorAccount) public view returns (uint32);
// TODO Maybe use for validation
// function exists(uint32 contributorId) public view returns (bool);
} }
contract Contribution is AragonApp { contract Contribution is AragonApp {
@ -12,13 +19,14 @@ contract Contribution is AragonApp {
bytes32 public constant VETO_CONTRIBUTION_ROLE = keccak256("VETO_CONTRIBUTION_ROLE"); bytes32 public constant VETO_CONTRIBUTION_ROLE = keccak256("VETO_CONTRIBUTION_ROLE");
bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb; bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
// ensure alphabetic order // ensure alphabetic order
enum Apps { Contribution, Contributor, Proposal, Token } enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds; bytes32[4] public appIds;
struct ContributionData { struct ContributionData {
address contributor; uint32 contributorId;
uint256 amount; uint32 amount;
bool claimed; bool claimed;
bytes32 hashDigest; bytes32 hashDigest;
uint8 hashFunction; uint8 hashFunction;
@ -28,31 +36,52 @@ contract Contribution is AragonApp {
bool vetoed; bool vetoed;
bool exists; bool exists;
} }
string internal name_; string internal name_;
string internal symbol_; string internal symbol_;
mapping(uint256 => address) contributionOwner; // map contribution ID to contributor
mapping(address => uint256[]) ownedContributions; mapping(uint32 => uint32) public contributionOwner;
// map contributor to contribution IDs
mapping(uint32 => uint32[]) public ownedContributions;
mapping(uint256 => ContributionData) public contributions; mapping(uint32 => ContributionData) public contributions;
uint256 public contributionsCount; uint32 public contributionsCount;
uint256 public blocksToWait = 0; uint32 public blocksToWait = 0;
event ContributionAdded(uint256 id, address indexed contributor, uint256 amount); event ContributionAdded(uint32 id, uint32 indexed contributorId, uint32 amount);
event ContributionClaimed(uint256 id, address indexed contributor, uint256 amount); event ContributionClaimed(uint32 id, uint32 indexed contributorId, uint32 amount);
event ContributionVetoed(uint256 id, address vetoedByAccount); event ContributionVetoed(uint32 id, address vetoedByAccount);
function initialize(bytes32[4] _appIds) public onlyInit { function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds; appIds = _appIds;
initialized(); initialized();
} }
// TODO refactor into a single function
function getTokenContract() public view returns (address) { function getTokenContract() public view returns (address) {
IKernel k = IKernel(kernel()); IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]); return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
} }
function getContributorContract() public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contributor)]);
}
function getContributorIdByAddress(address contributorAccount) public view returns (uint32) {
address contributor = getContributorContract();
return ContributorInterface(contributor).getContributorIdByAddress(contributorAccount);
}
function getContributorAddressById(uint32 contributorId) public view returns (address) {
address contributor = getContributorContract();
return ContributorInterface(contributor).getContributorAddressById(contributorId);
}
//
// Token standard functions (ERC 721)
//
function name() external view returns (string) { function name() external view returns (string) {
return name_; return name_;
@ -62,30 +91,38 @@ contract Contribution is AragonApp {
return symbol_; return symbol_;
} }
// Balance is amount of ERC271 tokens, not amount of kredits
function balanceOf(address owner) public view returns (uint256) { function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0)); require(owner != address(0));
return ownedContributions[owner].length; uint32 contributorId = getContributorIdByAddress(owner);
return ownedContributions[contributorId].length;
} }
function ownerOf(uint256 contributionId) public view returns (address) { function ownerOf(uint32 contributionId) public view returns (address) {
require(exists(contributionId)); require(exists(contributionId));
return contributions[contributionId].contributor; uint32 contributorId = contributions[contributionId].contributorId;
return getContributorAddressById(contributorId);
} }
function tokenOfOwnerByIndex(address contributor, uint256 index) public view returns (uint256) { function tokenOfOwnerByIndex(address owner, uint32 index) public view returns (uint32) {
return ownedContributions[contributor][index]; uint32 contributorId = getContributorIdByAddress(owner);
return ownedContributions[contributorId][index];
} }
function tokenMetadata(uint256 contributionId) public view returns (string) { function tokenMetadata(uint32 contributionId) public view returns (string) {
return contributions[contributionId].tokenMetadataURL; return contributions[contributionId].tokenMetadataURL;
} }
function getContribution(uint256 contributionId) public view returns (uint256 id, address contributor, uint256 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint claimAfterBlock, bool exists, bool vetoed) { //
// Custom functions
//
function getContribution(uint32 contributionId) public view returns (uint32 id, uint32 contributorId, uint32 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint claimAfterBlock, bool exists, bool vetoed) {
id = contributionId; id = contributionId;
ContributionData storage c = contributions[id]; ContributionData storage c = contributions[id];
return ( return (
id, id,
c.contributor, c.contributorId,
c.amount, c.amount,
c.claimed, c.claimed,
c.hashDigest, c.hashDigest,
@ -97,14 +134,14 @@ contract Contribution is AragonApp {
); );
} }
function add(uint256 amount, address contributorAccount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_CONTRIBUTION_ROLE) { function add(uint32 amount, uint32 contributorId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_CONTRIBUTION_ROLE) {
//require(canPerform(msg.sender, ADD_CONTRIBUTION_ROLE, new uint256[](0)), 'nope'); //require(canPerform(msg.sender, ADD_CONTRIBUTION_ROLE, new uint32[](0)), 'nope');
uint256 contributionId = contributionsCount + 1; uint32 contributionId = contributionsCount + 1;
ContributionData storage c = contributions[contributionId]; ContributionData storage c = contributions[contributionId];
c.exists = true; c.exists = true;
c.amount = amount; c.amount = amount;
c.claimed = false; c.claimed = false;
c.contributor = contributorAccount; c.contributorId = contributorId;
c.hashDigest = hashDigest; c.hashDigest = hashDigest;
c.hashFunction = hashFunction; c.hashFunction = hashFunction;
c.hashSize = hashSize; c.hashSize = hashSize;
@ -112,13 +149,13 @@ contract Contribution is AragonApp {
contributionsCount++; contributionsCount++;
contributionOwner[contributionId] = contributorAccount; contributionOwner[contributionId] = contributorId;
ownedContributions[contributorAccount].push(contributionId); ownedContributions[contributorId].push(contributionId);
emit ContributionAdded(contributionId, contributorAccount, amount); emit ContributionAdded(contributionId, contributorId, amount);
} }
function veto(uint256 contributionId) public isInitialized auth(VETO_CONTRIBUTION_ROLE) { function veto(uint32 contributionId) public isInitialized auth(VETO_CONTRIBUTION_ROLE) {
ContributionData storage c = contributions[contributionId]; ContributionData storage c = contributions[contributionId];
require(c.exists, 'NOT_FOUND'); require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED'); require(!c.claimed, 'ALREADY_CLAIMED');
@ -127,7 +164,7 @@ contract Contribution is AragonApp {
emit ContributionVetoed(contributionId, msg.sender); emit ContributionVetoed(contributionId, msg.sender);
} }
function claim(uint256 contributionId) public isInitialized { function claim(uint32 contributionId) public isInitialized {
ContributionData storage c = contributions[contributionId]; ContributionData storage c = contributions[contributionId];
require(c.exists, 'NOT_FOUND'); require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED'); require(!c.claimed, 'ALREADY_CLAIMED');
@ -136,11 +173,13 @@ contract Contribution is AragonApp {
c.claimed = true; c.claimed = true;
address token = getTokenContract(); address token = getTokenContract();
IToken(token).mintFor(c.contributor, c.amount, contributionId); address contributorAccount = getContributorAddressById(c.contributorId);
emit ContributionClaimed(contributionId, c.contributor, c.amount); uint256 amount = uint256(c.amount);
IToken(token).mintFor(contributorAccount, amount, contributionId);
emit ContributionClaimed(contributionId, c.contributorId, c.amount);
} }
function exists(uint256 contributionId) view public returns (bool) { function exists(uint32 contributionId) view public returns (bool) {
return contributions[contributionId].exists; return contributions[contributionId].exists;
} }
} }

View File

@ -20,20 +20,20 @@ contract Contributor is AragonApp {
bool exists; bool exists;
} }
mapping (address => uint256) public contributorIds; mapping (address => uint32) public contributorIds;
mapping (uint256 => Contributor) public contributors; mapping (uint32 => Contributor) public contributors;
uint256 public contributorsCount; uint32 public contributorsCount;
// ensure alphabetic order // ensure alphabetic order
enum Apps { Contribution, Contributor, Proposal, Token } enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds; bytes32[4] public appIds;
event ContributorProfileUpdated(uint256 id, bytes32 oldIpfsHash, bytes32 newIpfsHash); event ContributorProfileUpdated(uint32 id, bytes32 oldIpfsHash, bytes32 newIpfsHash);
event ContributorAccountUpdated(uint256 id, address oldAccount, address newAccount); event ContributorAccountUpdated(uint32 id, address oldAccount, address newAccount);
event ContributorAdded(uint256 id, address account); event ContributorAdded(uint32 id, address account);
function initialize(address root,bytes32[4] _appIds) public onlyInit { function initialize(address root,bytes32[4] _appIds) public onlyInit {
uint256 _id = contributorsCount + 1; uint32 _id = contributorsCount + 1;
Contributor storage c = contributors[_id]; Contributor storage c = contributors[_id];
c.exists = true; c.exists = true;
c.isCore = true; c.isCore = true;
@ -52,9 +52,9 @@ contract Contributor is AragonApp {
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]); return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
} }
function coreContributorsCount() view public returns (uint256) { function coreContributorsCount() view public returns (uint32) {
uint256 count = 0; uint32 count = 0;
for (uint256 i = 1; i <= contributorsCount; i++) { for (uint32 i = 1; i <= contributorsCount; i++) {
if (contributors[i].isCore) { if (contributors[i].isCore) {
count += 1; count += 1;
} }
@ -62,14 +62,14 @@ contract Contributor is AragonApp {
return count; return count;
} }
function updateContributorAccount(uint256 id, address oldAccount, address newAccount) public auth(MANAGE_CONTRIBUTORS_ROLE) { function updateContributorAccount(uint32 id, address oldAccount, address newAccount) public auth(MANAGE_CONTRIBUTORS_ROLE) {
contributorIds[oldAccount] = 0; contributorIds[oldAccount] = 0;
contributorIds[newAccount] = id; contributorIds[newAccount] = id;
contributors[id].account = newAccount; contributors[id].account = newAccount;
ContributorAccountUpdated(id, oldAccount, newAccount); ContributorAccountUpdated(id, oldAccount, newAccount);
} }
function updateContributorIpfsHash(uint256 id, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) { function updateContributorIpfsHash(uint32 id, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
Contributor storage c = contributors[id]; Contributor storage c = contributors[id];
bytes32 oldIpfsHash = c.ipfsHash; bytes32 oldIpfsHash = c.ipfsHash;
c.ipfsHash = ipfsHash; c.ipfsHash = ipfsHash;
@ -81,7 +81,7 @@ contract Contributor is AragonApp {
function addContributor(address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) { function addContributor(address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
require(!addressExists(account)); require(!addressExists(account));
uint256 _id = contributorsCount + 1; uint32 _id = contributorsCount + 1;
assert(!contributors[_id].exists); // this can not be acually assert(!contributors[_id].exists); // this can not be acually
Contributor storage c = contributors[_id]; Contributor storage c = contributors[_id];
c.exists = true; c.exists = true;
@ -96,11 +96,11 @@ contract Contributor is AragonApp {
emit ContributorAdded(_id, account); emit ContributorAdded(_id, account);
} }
function isCore(uint256 id) view public returns (bool) { function isCore(uint32 id) view public returns (bool) {
return contributors[id].isCore; return contributors[id].isCore;
} }
function exists(uint256 id) view public returns (bool) { function exists(uint32 id) view public returns (bool) {
return contributors[id].exists; return contributors[id].exists;
} }
@ -112,20 +112,20 @@ contract Contributor is AragonApp {
return getContributorByAddress(account).exists; return getContributorByAddress(account).exists;
} }
function getContributorIdByAddress(address account) view public returns (uint256) { function getContributorIdByAddress(address account) view public returns (uint32) {
return contributorIds[account]; return contributorIds[account];
} }
function getContributorAddressById(uint256 id) view public returns (address) { function getContributorAddressById(uint32 id) view public returns (address) {
return contributors[id].account; return contributors[id].account;
} }
function getContributorByAddress(address account) internal view returns (Contributor) { function getContributorByAddress(address account) internal view returns (Contributor) {
uint256 id = contributorIds[account]; uint32 id = contributorIds[account];
return contributors[id]; return contributors[id];
} }
function getContributorById(uint256 _id) public view returns (uint256 id, address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, bool exists ) { function getContributorById(uint32 _id) public view returns (uint32 id, address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, bool exists ) {
id = _id; id = _id;
Contributor storage c = contributors[_id]; Contributor storage c = contributors[_id];
account = c.account; account = c.account;
@ -138,7 +138,7 @@ contract Contributor is AragonApp {
exists = c.exists; exists = c.exists;
} }
function canPerform(address _who, address _where, bytes32 _what, uint256[] memory _how) public returns (bool) { function canPerform(address _who, address _where, bytes32 _what/*, uint256[] memory _how*/) public returns (bool) {
address sender = _who; address sender = _who;
if (sender == address(-1)) { if (sender == address(-1)) {
sender = tx.origin; sender = tx.origin;

View File

@ -4,13 +4,13 @@ import "@aragon/os/contracts/apps/AragonApp.sol";
import "@aragon/os/contracts/kernel/IKernel.sol"; import "@aragon/os/contracts/kernel/IKernel.sol";
interface IContributor { interface IContributor {
function getContributorAddressById(uint256 contributorId) public view returns (address); function getContributorAddressById(uint32 contributorId) public view returns (address);
function getContributorIdByAddress(address contributorAccount) public view returns (uint256); function getContributorIdByAddress(address contributorAccount) public view returns (uint32);
function exists(uint256 contributorId) public view returns (bool); function exists(uint32 contributorId) public view returns (bool);
} }
interface IContribution { interface IContribution {
function add(uint256 amount, address contributor, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public; function add(uint32 amount, uint32 contributorId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public;
} }
contract Proposal is AragonApp { contract Proposal is AragonApp {
@ -25,26 +25,26 @@ contract Proposal is AragonApp {
struct Proposal { struct Proposal {
address creatorAccount; address creatorAccount;
uint contributorId; uint32 contributorId;
uint votesCount; uint16 votesCount;
uint votesNeeded; uint16 votesNeeded;
uint256 amount; uint32 amount;
bool executed; bool executed;
bytes32 hashDigest; bytes32 hashDigest;
uint8 hashFunction; uint8 hashFunction;
uint8 hashSize; uint8 hashSize;
uint256[] voterIds; uint32[] voterIds;
mapping (uint256 => bool) votes; mapping (uint32 => bool) votes;
bool exists; bool exists;
} }
mapping(uint256 => Proposal) public proposals; mapping(uint32 => Proposal) public proposals;
uint256 public proposalsCount; uint32 public proposalsCount;
event ProposalCreated(uint256 id, address creatorAccount, uint256 contributorId, uint256 amount); event ProposalCreated(uint32 id, address creatorAccount, uint32 contributorId, uint32 amount);
event ProposalVoted(uint256 id, uint256 voterId, uint256 totalVotes); event ProposalVoted(uint32 id, uint32 voterId, uint16 totalVotes);
event ProposalExecuted(uint256 id, uint256 contributorId, uint256 amount); event ProposalExecuted(uint32 id, uint32 contributorId, uint32 amount);
function initialize(bytes32[4] _appIds) public onlyInit { function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds; appIds = _appIds;
@ -59,11 +59,11 @@ contract Proposal is AragonApp {
return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contribution)]); return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contribution)]);
} }
function addProposal(uint contributorId, uint256 amount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_PROPOSAL_ROLE) { function addProposal(uint32 contributorId, uint32 amount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_PROPOSAL_ROLE) {
require(IContributor(getContributorContract()).exists(contributorId), 'CONTRIBUTOR_NOT_FOUND'); require(IContributor(getContributorContract()).exists(contributorId), 'CONTRIBUTOR_NOT_FOUND');
uint256 proposalId = proposalsCount + 1; uint32 proposalId = proposalsCount + 1;
uint256 _votesNeeded = 1; //contributorsContract().coreContributorsCount() / 100 * 75; uint16 _votesNeeded = 1; //contributorsContract().coreContributorsCount() / 100 * 75;
Proposal storage p = proposals[proposalId]; Proposal storage p = proposals[proposalId];
p.creatorAccount = msg.sender; p.creatorAccount = msg.sender;
@ -80,7 +80,7 @@ contract Proposal is AragonApp {
emit ProposalCreated(proposalId, msg.sender, p.contributorId, p.amount); emit ProposalCreated(proposalId, msg.sender, p.contributorId, p.amount);
} }
function getProposal(uint proposalId) public view returns (uint256 id, address creatorAccount, uint256 contributorId, uint256 votesCount, uint256 votesNeeded, uint256 amount, bool executed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint256[] voterIds, bool exists) { function getProposal(uint32 proposalId) public view returns (uint32 id, address creatorAccount, uint32 contributorId, uint16 votesCount, uint16 votesNeeded, uint32 amount, bool executed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint32[] voterIds, bool exists) {
id = proposalId; id = proposalId;
Proposal storage p = proposals[id]; Proposal storage p = proposals[id];
return ( return (
@ -99,10 +99,10 @@ contract Proposal is AragonApp {
); );
} }
function vote(uint256 proposalId) public isInitialized auth(VOTE_PROPOSAL_ROLE) { function vote(uint32 proposalId) public isInitialized auth(VOTE_PROPOSAL_ROLE) {
Proposal storage p = proposals[proposalId]; Proposal storage p = proposals[proposalId];
require(!p.executed, 'ALREADY_EXECUTED'); require(!p.executed, 'ALREADY_EXECUTED');
uint256 voterId = IContributor(getContributorContract()).getContributorIdByAddress(msg.sender); uint32 voterId = IContributor(getContributorContract()).getContributorIdByAddress(msg.sender);
require(p.votes[voterId] != true, 'ALREADY_VOTED'); require(p.votes[voterId] != true, 'ALREADY_VOTED');
p.voterIds.push(voterId); p.voterIds.push(voterId);
p.votes[voterId] = true; p.votes[voterId] = true;
@ -114,20 +114,19 @@ contract Proposal is AragonApp {
emit ProposalVoted(proposalId, voterId, p.votesCount); emit ProposalVoted(proposalId, voterId, p.votesCount);
} }
function batchVote(uint256[] _proposalIds) public isInitialized auth(VOTE_PROPOSAL_ROLE) { function batchVote(uint32[] _proposalIds) public isInitialized auth(VOTE_PROPOSAL_ROLE) {
for (uint256 i = 0; i < _proposalIds.length; i++) { for (uint32 i = 0; i < _proposalIds.length; i++) {
vote(_proposalIds[i]); vote(_proposalIds[i]);
} }
} }
function executeProposal(uint proposalId) private { function executeProposal(uint32 proposalId) private {
Proposal storage p = proposals[proposalId]; Proposal storage p = proposals[proposalId];
require(!p.executed, 'ALREADY_EXECUTED'); require(!p.executed, 'ALREADY_EXECUTED');
require(p.votesCount >= p.votesNeeded, 'MISSING_VOTES'); require(p.votesCount >= p.votesNeeded, 'MISSING_VOTES');
p.executed = true; p.executed = true;
address contributorAccount = IContributor(getContributorContract()).getContributorAddressById(p.contributorId); IContribution(getContributionContract()).add(p.amount, p.contributorId, p.hashDigest, p.hashFunction, p.hashSize);
IContribution(getContributionContract()).add(p.amount, contributorAccount, p.hashDigest, p.hashFunction, p.hashSize);
emit ProposalExecuted(proposalId, p.contributorId, p.amount); emit ProposalExecuted(proposalId, p.contributorId, p.amount);
} }

View File

@ -10,14 +10,14 @@ contract Token is ERC20Token, AragonApp {
enum Apps { Contribution, Contributor, Proposal, Token } enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds; bytes32[4] public appIds;
event LogMint(address indexed recipient, uint256 amount, uint256 contributionId); event LogMint(address indexed recipient, uint256 amount, uint32 contributionId);
function initialize(bytes32[4] _appIds) public onlyInit { function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds; appIds = _appIds;
initialized(); initialized();
} }
function mintFor(address contributorAccount, uint256 amount, uint256 contributionId) public isInitialized auth(MINT_TOKEN_ROLE) { function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public isInitialized auth(MINT_TOKEN_ROLE) {
_mint(contributorAccount, amount); _mint(contributorAccount, amount);
emit LogMint(contributorAccount, amount, contributionId); emit LogMint(contributorAccount, amount, contributionId);
} }

View File

@ -5,8 +5,8 @@ const contractCalls = [
['Proposal', 'addProposal', [{ contributorId: 3, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]], ['Proposal', 'addProposal', [{ contributorId: 3, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]],
['Proposal', 'addProposal', [{ contributorId: 3, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Hacked on kredits', url: '' }, { gasLimit: 350000 }]], ['Proposal', 'addProposal', [{ contributorId: 3, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Hacked on kredits', url: '' }, { gasLimit: 350000 }]],
['Proposal', 'vote', [1, { gasLimit: 550000 }]], ['Proposal', 'vote', [1, { gasLimit: 550000 }]],
['Contribution', 'addContribution', [{ contributorAccount: '0x49575f3DD9a0d60aE661BC992f72D837A77f05Bc', amount: 5000, kind: 'dev', description: '[67P/kredits-contracts] Introduce contribution token', url: '' }, { gasLimit: 350000 }]], ['Contribution', 'addContribution', [{ contributorId: 2, amount: 5000, kind: 'dev', description: '[67P/kredits-contracts] Introduce contribution token', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'addContribution', [{ contributorAccount: '0x7e8f313c56f809188313aa274fa67ee58c31515d', amount: 1500, kind: 'dev', description: '[67P/kredits-web] Reviewed stuff', url: '' }, { gasLimit: 350000 }]], ['Contribution', 'addContribution', [{ contributorId: 3, amount: 1500, kind: 'dev', description: '[67P/kredits-web] Reviewed stuff', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'claim', [1, { gasLimit: 300000 }]] ['Contribution', 'claim', [1, { gasLimit: 300000 }]]
]; ];
const funds = [ const funds = [

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,4 @@
const ethers = require('ethers'); const ethers = require('ethers');
const RSVP = require('rsvp');
const ContributionSerializer = require('../serializers/contribution'); const ContributionSerializer = require('../serializers/contribution');
const Base = require('./base'); const Base = require('./base');
@ -7,43 +6,44 @@ const Base = require('./base');
class Contribution extends Base { class Contribution extends Base {
all() { all() {
return this.functions.contributionsCount() return this.functions.contributionsCount()
.then((count) => { .then(async (count) => {
count = count.toNumber();
let contributions = []; let contributions = [];
for (let id = 1; id <= count; id++) { for (let id = 1; id <= count; id++) {
contributions.push(this.getById(id)); const contribution = await this.getById(id)
contributions.push(contribution);
} }
return RSVP.all(contributions); return contributions;
}); });
} }
getById(id) { getById(id) {
id = ethers.utils.bigNumberify(id);
return this.functions.getContribution(id) return this.functions.getContribution(id)
.then((data) => { .then(data => {
return this.ipfs.catAndMerge(data, ContributionSerializer.deserialize); return this.ipfs.catAndMerge(data, ContributionSerializer.deserialize);
}); });
} }
getByContributor(contributor) { getByContributorId(contributorId) {
return this.functions.balanceOf(contributor) return this.functions.getContributorAddressById(contributorId)
then((balance) => { .then(address => this.getByContributorAddress(address));
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); getByContributorAddress(address) {
return this.functions.balanceOf(address)
.then(async (balance) => {
const count = balance.toNumber();
const contributions = [];
for (let index = 0; index < count; index++) {
const id = await this.functions.tokenOfOwnerByIndex(address, index);
const contribution = await this.getById(id);
contributions.push(contribution);
}
return contributions;
}); });
} }
@ -56,7 +56,7 @@ class Contribution extends Base {
.then((ipfsHashAttr) => { .then((ipfsHashAttr) => {
let contribution = [ let contribution = [
contributionAttr.amount, contributionAttr.amount,
contributionAttr.contributorAccount, contributionAttr.contributorId,
ipfsHashAttr.hashDigest, ipfsHashAttr.hashDigest,
ipfsHashAttr.hashFunction, ipfsHashAttr.hashFunction,
ipfsHashAttr.hashSize, ipfsHashAttr.hashSize,

View File

@ -7,8 +7,7 @@ const Base = require('./base');
class Contributor extends Base { class Contributor extends Base {
all() { all() {
return this.functions.contributorsCount() return this.functions.contributorsCount()
.then((count) => { .then(count => {
count = count.toNumber();
let contributors = []; let contributors = [];
for (let id = 1; id <= count; id++) { for (let id = 1; id <= count; id++) {
@ -20,8 +19,6 @@ class Contributor extends Base {
} }
getById(id) { getById(id) {
id = ethers.utils.bigNumberify(id);
return this.functions.getContributorById(id) return this.functions.getContributorById(id)
.then((data) => { .then((data) => {
// TODO: remove when naming updated on the contract // TODO: remove when naming updated on the contract

View File

@ -7,8 +7,7 @@ const Base = require('./base');
class Proposal extends Base { class Proposal extends Base {
all() { all() {
return this.functions.proposalsCount() return this.functions.proposalsCount()
.then((count) => { .then(count => {
count = count.toNumber();
let proposals = []; let proposals = [];
for (let id = 1; id <= count; id++) { for (let id = 1; id <= count; id++) {
@ -20,10 +19,8 @@ class Proposal extends Base {
} }
getById(id) { getById(id) {
id = ethers.utils.bigNumberify(id);
return this.functions.getProposal(id) return this.functions.getProposal(id)
.then((data) => { .then(data => {
return this.ipfs.catAndMerge(data, ContributionSerializer.deserialize); return this.ipfs.catAndMerge(data, ContributionSerializer.deserialize);
}); });
} }

View File

@ -27,7 +27,7 @@ module.exports = async function(callback) {
console.log(`Creating a contribution for contributor account ${contributorAccount} ID: ${contributorId}`); console.log(`Creating a contribution for contributor account ${contributorAccount} ID: ${contributorId}`);
let contributionAttributes = { let contributionAttributes = {
contributorAccount, contributorId,
amount: await promptly.prompt('Amount: '), amount: await promptly.prompt('Amount: '),
description: await promptly.prompt('Description: '), description: await promptly.prompt('Description: '),
kind: await promptly.prompt('Kind: ', { default: 'dev' }), kind: await promptly.prompt('Kind: ', { default: 'dev' }),

View File

@ -14,7 +14,6 @@ module.exports = async function(callback) {
console.log(`Using Contribution at: ${kredits.Contribution.contract.address}`); console.log(`Using Contribution at: ${kredits.Contribution.contract.address}`);
const table = new Table({ const table = new Table({
head: ['ID', 'Contributor account', 'Amount', 'Claimed?', 'Vetoed?', 'Description'] head: ['ID', 'Contributor account', 'Amount', 'Claimed?', 'Vetoed?', 'Description']
}) })
@ -24,7 +23,7 @@ module.exports = async function(callback) {
contributions.forEach((c) => { contributions.forEach((c) => {
table.push([ table.push([
c.id.toString(), c.id.toString(),
c.contributor, c.contributorId,
c.amount.toString(), c.amount.toString(),
c.claimed, c.claimed,
c.vetoed, c.vetoed,

View File

@ -14,7 +14,6 @@ module.exports = async function(callback) {
console.log(`Using Proposal at: ${kredits.Proposal.contract.address}`); console.log(`Using Proposal at: ${kredits.Proposal.contract.address}`);
const table = new Table({ const table = new Table({
head: ['ID', 'Contributor ID', 'Amount', 'Votes', 'Executed?', 'Description'] head: ['ID', 'Contributor ID', 'Amount', 'Votes', 'Executed?', 'Description']
}) })

View File

@ -40,6 +40,7 @@ module.exports = async function(callback) {
next(); next();
}).catch((error) => { }).catch((error) => {
console.log(`[FAILED] kredits.${contractName}.${method}(${JSON.stringify(args)})`); console.log(`[FAILED] kredits.${contractName}.${method}(${JSON.stringify(args)})`);
console.log(`Error: ${error.message}`);
next(); next();
}); });
}, () => { console.log("\nDone!") }); }, () => { console.log("\nDone!") });