Move contracts to root level for hardhart usage

byebye aragon apps
This commit is contained in:
bumi 2021-06-08 15:45:23 +02:00
parent 1425c3664a
commit a626409221
19 changed files with 12793 additions and 4158 deletions

4
.gitignore vendored
View File

@ -6,3 +6,7 @@ node_modules
.tm_properties
yarn-error.log
.DS_Store
cache
artifacts
.openzeppelin

204
contracts/Contribution.sol Normal file
View File

@ -0,0 +1,204 @@
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
interface IToken {
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) external;
}
interface ContributorInterface {
function getContributorAddressById(uint32 contributorId) external view returns (address);
function getContributorIdByAddress(address contributorAccount) external view returns (uint32);
// TODO Maybe use for validation
// function exists(uint32 contributorId) public view returns (bool);
}
contract Contribution is Initializable {
ContributorInterface public contributorContract;
IToken public tokenContract;
bytes32 public constant ADD_CONTRIBUTION_ROLE = keccak256("ADD_CONTRIBUTION_ROLE");
bytes32 public constant VETO_CONTRIBUTION_ROLE = keccak256("VETO_CONTRIBUTION_ROLE");
bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
struct ContributionData {
uint32 contributorId;
uint32 amount;
bool claimed;
bytes32 hashDigest;
uint8 hashFunction;
uint8 hashSize;
string tokenMetadataURL;
uint256 confirmedAtBlock;
bool vetoed;
bool exists;
}
string internal name_;
string internal symbol_;
// map contribution ID to contributor
mapping(uint32 => uint32) public contributionOwner;
// map contributor to contribution IDs
mapping(uint32 => uint32[]) public ownedContributions;
mapping(uint32 => ContributionData) public contributions;
uint32 public contributionsCount;
uint32 public blocksToWait;
event ContributionAdded(uint32 id, uint32 indexed contributorId, uint32 amount);
event ContributionClaimed(uint32 id, uint32 indexed contributorId, uint32 amount);
event ContributionVetoed(uint32 id, address vetoedByAccount);
function initialize(uint32 blocksToWait_) public initializer {
blocksToWait = blocksToWait_;
}
// TODO who can call this when?
function setTokenContract(address token) public {
tokenContract = IToken(token);
}
// TODO who can call this when?
function setContributorContract(address contributor) public {
contributorContract = ContributorInterface(contributor);
}
function getContributorIdByAddress(address contributorAccount) public view returns (uint32) {
return contributorContract.getContributorIdByAddress(contributorAccount);
}
function getContributorAddressById(uint32 contributorId) public view returns (address) {
return contributorContract.getContributorAddressById(contributorId);
}
//
// Token standard functions (ERC 721)
//
function name() external view returns (string memory) {
return name_;
}
function symbol() external view returns (string memory) {
return symbol_;
}
// Balance is amount of ERC271 tokens, not amount of kredits
function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0));
uint32 contributorId = getContributorIdByAddress(owner);
return ownedContributions[contributorId].length;
}
function ownerOf(uint32 contributionId) public view returns (address) {
require(exists(contributionId));
uint32 contributorId = contributions[contributionId].contributorId;
return getContributorAddressById(contributorId);
}
function tokenOfOwnerByIndex(address owner, uint32 index) public view returns (uint32) {
uint32 contributorId = getContributorIdByAddress(owner);
return ownedContributions[contributorId][index];
}
function tokenMetadata(uint32 contributionId) public view returns (string memory) {
return contributions[contributionId].tokenMetadataURL;
}
//
// Custom functions
//
function totalKreditsEarned(bool confirmedOnly) public view returns (uint32 amount) {
for (uint32 i = 1; i <= contributionsCount; i++) {
ContributionData memory c = contributions[i];
if (!c.vetoed && (block.number >= c.confirmedAtBlock || !confirmedOnly)) {
amount += c.amount; // should use safemath
}
}
}
function totalKreditsEarnedByContributor(uint32 contributorId, bool confirmedOnly) public view returns (uint32 amount) {
uint256 tokenCount = ownedContributions[contributorId].length;
for (uint256 i = 0; i < tokenCount; i++) {
uint32 cId = ownedContributions[contributorId][i];
ContributionData memory c = contributions[cId];
if (!c.vetoed && (block.number >= c.confirmedAtBlock || !confirmedOnly)) {
amount += c.amount; // should use safemath
}
}
}
function getContribution(uint32 contributionId) public view returns (uint32 id, uint32 contributorId, uint32 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint256 confirmedAtBlock, bool exists, bool vetoed) {
id = contributionId;
ContributionData storage c = contributions[id];
return (
id,
c.contributorId,
c.amount,
c.claimed,
c.hashDigest,
c.hashFunction,
c.hashSize,
c.confirmedAtBlock,
c.exists,
c.vetoed
);
}
function add(uint32 amount, uint32 contributorId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public{
//require(canPerform(msg.sender, ADD_CONTRIBUTION_ROLE, new uint32[](0)), 'nope');
uint32 contributionId = contributionsCount + 1;
ContributionData storage c = contributions[contributionId];
c.exists = true;
c.amount = amount;
c.claimed = false;
c.contributorId = contributorId;
c.hashDigest = hashDigest;
c.hashFunction = hashFunction;
c.hashSize = hashSize;
if (contributionId < 10) {
c.confirmedAtBlock = block.number;
} else {
c.confirmedAtBlock = block.number + 1 + blocksToWait;
}
contributionsCount++;
contributionOwner[contributionId] = contributorId;
ownedContributions[contributorId].push(contributionId);
emit ContributionAdded(contributionId, contributorId, amount);
}
function veto(uint32 contributionId) public {
ContributionData storage c = contributions[contributionId];
require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED');
require(block.number < c.confirmedAtBlock, 'VETO_PERIOD_ENDED');
c.vetoed = true;
emit ContributionVetoed(contributionId, msg.sender);
}
function claim(uint32 contributionId) public {
ContributionData storage c = contributions[contributionId];
require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED');
require(!c.vetoed, 'VETOED');
require(block.number >= c.confirmedAtBlock, 'NOT_CLAIMABLE');
c.claimed = true;
address contributorAccount = getContributorAddressById(c.contributorId);
uint256 amount = uint256(c.amount);
tokenContract.mintFor(contributorAccount, amount, contributionId);
emit ContributionClaimed(contributionId, c.contributorId, c.amount);
}
function exists(uint32 contributionId) public view returns (bool) {
return contributions[contributionId].exists;
}
}

152
contracts/Contributor.sol Normal file
View File

@ -0,0 +1,152 @@
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
interface ITokenBalance {
function balanceOf(address contributorAccount) external view returns (uint256);
}
interface IContributionBalance {
function totalKreditsEarnedByContributor(uint32 contributorId, bool confirmedOnly) external view returns (uint32 amount);
function balanceOf(address owner) external view returns (uint256);
}
contract Contributor is Initializable {
IContributionBalance public contributionContract;
ITokenBalance public tokenContract;
struct Contributor {
address account;
bytes32 hashDigest;
uint8 hashFunction;
uint8 hashSize;
bool exists;
}
mapping (address => uint32) public contributorIds;
mapping (uint32 => Contributor) public contributors;
uint32 public contributorsCount;
event ContributorProfileUpdated(uint32 id, bytes32 oldHashDigest, bytes32 newHashDigest); // what should be logged
event ContributorAccountUpdated(uint32 id, address oldAccount, address newAccount);
event ContributorAdded(uint32 id, address account);
function initialize() public initializer {
}
// TODO who can call this when?
function setContributionContract(address contribution) public {
contributionContract = IContributionBalance(contribution);
}
// TODO who can call this when?
function setTokenContract(address token) public {
tokenContract = ITokenBalance(token);
}
function coreContributorsCount() public view returns (uint32) {
uint32 count = 0;
for (uint32 i = 1; i <= contributorsCount; i++) {
if (isCoreTeam(i)) {
count += 1;
}
}
return count;
}
function updateContributorAccount(uint32 id, address oldAccount, address newAccount) public {
require(newAccount != address(0), "invalid new account address");
require(getContributorAddressById(id) == oldAccount, "contributor does not exist");
contributorIds[oldAccount] = 0;
contributorIds[newAccount] = id;
contributors[id].account = newAccount;
emit ContributorAccountUpdated(id, oldAccount, newAccount);
}
function updateContributorProfileHash(uint32 id, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public {
Contributor storage c = contributors[id];
bytes32 oldHashDigest = c.hashDigest;
c.hashDigest = hashDigest;
c.hashFunction = hashFunction;
c.hashSize = hashSize;
ContributorProfileUpdated(id, oldHashDigest, c.hashDigest);
}
function addContributor(address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public {
require(!addressExists(account));
uint32 _id = contributorsCount + 1;
assert(!contributors[_id].exists); // this can not be acually
Contributor storage c = contributors[_id];
c.exists = true;
c.hashDigest = hashDigest;
c.hashFunction = hashFunction;
c.hashSize = hashSize;
c.account = account;
contributorIds[account] = _id;
contributorsCount += 1;
emit ContributorAdded(_id, account);
}
function isCoreTeam(uint32 id) view public returns (bool) {
// TODO: for simplicity we simply define the first contributors as core
// later this needs to be changed to something more dynamic
return id < 7;
}
function exists(uint32 id) view public returns (bool) {
return contributors[id].exists;
}
function addressIsCore(address account) view public returns (bool) {
uint32 id = getContributorIdByAddress(account);
return isCoreTeam(id);
}
function addressExists(address account) view public returns (bool) {
return getContributorByAddress(account).exists;
}
function getContributorIdByAddress(address account) view public returns (uint32) {
return contributorIds[account];
}
function getContributorAddressById(uint32 id) view public returns (address) {
return contributors[id].account;
}
function getContributorByAddress(address account) internal view returns (Contributor memory) {
uint32 id = contributorIds[account];
return contributors[id];
}
function getContributorById(uint32 _id) public view returns (uint32 id, address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, uint32 totalKreditsEarned, uint256 contributionsCount, bool exists ) {
id = _id;
Contributor storage c = contributors[_id];
account = c.account;
hashDigest = c.hashDigest;
hashFunction = c.hashFunction;
hashSize = c.hashSize;
isCore = isCoreTeam(id);
balance = tokenContract.balanceOf(c.account);
totalKreditsEarned = contributionContract.totalKreditsEarnedByContributor(_id, true);
contributionsCount = contributionContract.balanceOf(c.account);
exists = c.exists;
}
function canPerform(address _who, address _where, bytes32 _what, uint256[] memory _how) public returns (bool) {
address sender = _who;
if (sender == address(0)) {
sender = tx.origin;
}
// _what == keccak256('VOTE_PROPOSAL_ROLE')
if (_what == 0xd61216798314d2fc33e42ff2021d66707b1e38517d3f7166798a9d3a196a9c96) {
return contributorIds[sender] != uint256(0);
}
return addressIsCore(sender);
}
}

View File

@ -1,99 +0,0 @@
pragma solidity 0.4.24;
import "@aragon/os/contracts/apps/AragonApp.sol";
import "@aragon/os/contracts/kernel/Kernel.sol";
import "@aragon/os/contracts/acl/ACL.sol";
import "@aragon/kits-base/contracts/KitBase.sol";
import "../apps/contribution/contracts/Contribution.sol";
import "../apps/contributor/contracts/Contributor.sol";
import "../apps/token/contracts/Token.sol";
import "../apps/proposal/contracts/Proposal.sol";
import "../apps/reimbursement/contracts/Reimbursement.sol";
contract KreditsKit is KitBase {
// ensure alphabetic order
enum Apps { Contribution, Contributor, Proposal, Reimbursement, Token }
bytes32[5] public appIds;
event DeployInstance(address dao);
event InstalledApp(address dao, address appProxy, bytes32 appId);
constructor (DAOFactory _fac, ENS _ens, bytes32[5] _appIds) public KitBase(_fac, _ens) {
appIds = _appIds;
}
function newInstance() public returns (Kernel dao) {
address root = msg.sender;
dao = fac.newDAO(this);
ACL acl = ACL(dao.acl());
acl.createPermission(this, dao, dao.APP_MANAGER_ROLE(), this);
Contributor contributor = Contributor(_installApp(dao, appIds[uint8(Apps.Contributor)]));
contributor.initialize(root, appIds);
acl.createPermission(root, contributor, contributor.MANAGE_CONTRIBUTORS_ROLE(), this);
Token token = Token(_installApp(dao, appIds[uint8(Apps.Token)]));
token.initialize(appIds);
Contribution contribution = Contribution(_installApp(dao, appIds[uint8(Apps.Contribution)]));
contribution.initialize(appIds);
acl.createPermission(root, contribution, contribution.ADD_CONTRIBUTION_ROLE(), this);
acl.createPermission(root, contribution, contribution.VETO_CONTRIBUTION_ROLE(), this);
acl.grantPermission(proposal, contribution, contribution.ADD_CONTRIBUTION_ROLE());
Proposal proposal = Proposal(_installApp(dao, appIds[uint8(Apps.Proposal)]));
proposal.initialize(appIds);
Reimbursement reimbursement = Reimbursement(_installApp(dao, appIds[uint8(Apps.Reimbursement)]));
reimbursement.initialize();
acl.createPermission(root, reimbursement, reimbursement.ADD_REIMBURSEMENT_ROLE(), this);
acl.createPermission(root, reimbursement, reimbursement.VETO_REIMBURSEMENT_ROLE(), this);
uint256[] memory params = new uint256[](1);
params[0] = uint256(203) << 248 | uint256(1) << 240 | uint240(contributor);
acl.grantPermissionP(acl.ANY_ENTITY(), contribution, contribution.ADD_CONTRIBUTION_ROLE(), params);
acl.grantPermissionP(acl.ANY_ENTITY(), contribution, contribution.VETO_CONTRIBUTION_ROLE(), params);
acl.grantPermissionP(acl.ANY_ENTITY(), contributor, contributor.MANAGE_CONTRIBUTORS_ROLE(), params);
acl.grantPermissionP(acl.ANY_ENTITY(), reimbursement, reimbursement.ADD_REIMBURSEMENT_ROLE(), params);
//acl.setPermissionManager(this, proposal, proposal.VOTE_PROPOSAL_ROLE();
acl.createPermission(root, proposal, proposal.VOTE_PROPOSAL_ROLE(), this);
acl.grantPermissionP(acl.ANY_ENTITY(), proposal, proposal.VOTE_PROPOSAL_ROLE(), params);
acl.createPermission(root, proposal, proposal.ADD_PROPOSAL_ROLE(), this);
//acl.grantPermissionP(address(-1), proposal, proposal.ADD_PROPOSAL_ROLE(), params);
acl.grantPermission(acl.ANY_ENTITY(), proposal, proposal.ADD_PROPOSAL_ROLE());
acl.setPermissionManager(root, proposal, proposal.VOTE_PROPOSAL_ROLE());
acl.setPermissionManager(root, proposal, proposal.ADD_PROPOSAL_ROLE());
acl.setPermissionManager(root, contribution, contribution.ADD_CONTRIBUTION_ROLE());
acl.setPermissionManager(root, contribution, contribution.VETO_CONTRIBUTION_ROLE());
acl.setPermissionManager(root, contributor, contributor.MANAGE_CONTRIBUTORS_ROLE());
acl.setPermissionManager(root, reimbursement, reimbursement.ADD_REIMBURSEMENT_ROLE());
acl.setPermissionManager(root, reimbursement, reimbursement.VETO_REIMBURSEMENT_ROLE());
acl.createPermission(root, token, token.MINT_TOKEN_ROLE(), this);
acl.grantPermission(contribution, token, token.MINT_TOKEN_ROLE());
acl.setPermissionManager(root, token, token.MINT_TOKEN_ROLE());
cleanupDAOPermissions(dao, acl, root);
emit DeployInstance(dao);
return dao;
}
function _installApp(Kernel _dao, bytes32 _appId) internal returns (AragonApp) {
address baseAppAddress = latestVersionAppBase(_appId);
require(baseAppAddress != address(0), "App should be deployed");
AragonApp appProxy = AragonApp(_dao.newAppInstance(_appId, baseAppAddress, new bytes(0), true));
emit InstalledApp(_dao, appProxy, _appId);
return appProxy;
}
}

View File

@ -0,0 +1,89 @@
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract Reimbursement is Initializable {
bytes32 public constant ADD_REIMBURSEMENT_ROLE = keccak256("ADD_REIMBURSEMENT_ROLE");
bytes32 public constant VETO_REIMBURSEMENT_ROLE = keccak256("VETO_REIMBURSEMENT_ROLE");
// bytes32 public constant MANAGE_APPS_ROLE = keccak256("MANAGE_APPS_ROLE");
struct ReimbursementData {
uint32 recipientId;
uint256 amount;
address token;
bytes32 hashDigest;
uint8 hashFunction;
uint8 hashSize;
uint256 confirmedAtBlock;
bool vetoed;
bool exists;
}
mapping(uint32 => ReimbursementData) public reimbursements;
uint32 public reimbursementsCount;
uint32 public blocksToWait;
event ReimbursementAdded(uint32 id, address indexed addedByAccount, uint256 amount);
event ReimbursementVetoed(uint32 id, address vetoedByAccount);
function initialize() public initializer {
blocksToWait = 40320; // 7 days; 15 seconds block time
}
function totalAmount(bool confirmedOnly) public view returns (uint256 amount) {
for (uint32 i = 1; i <= reimbursementsCount; i++) {
ReimbursementData memory r = reimbursements[i];
if (!r.vetoed && (block.number >= r.confirmedAtBlock || !confirmedOnly)) {
amount += r.amount; // should use safemath
}
}
}
function get(uint32 reimbursementId) public view returns (uint32 id, uint32 recipientId, uint256 amount, address token, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint256 confirmedAtBlock, bool exists, bool vetoed) {
id = reimbursementId;
ReimbursementData storage r = reimbursements[id];
return (
id,
r.recipientId,
r.amount,
r.token,
r.hashDigest,
r.hashFunction,
r.hashSize,
r.confirmedAtBlock,
r.exists,
r.vetoed
);
}
function add(uint256 amount, address token, uint32 recipientId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public {
uint32 reimbursementId = reimbursementsCount + 1;
ReimbursementData storage r = reimbursements[reimbursementId];
r.exists = true;
r.amount = amount;
r.token = token;
r.recipientId = recipientId;
r.hashDigest = hashDigest;
r.hashFunction = hashFunction;
r.hashSize = hashSize;
r.confirmedAtBlock = block.number + blocksToWait;
reimbursementsCount++;
emit ReimbursementAdded(reimbursementId, msg.sender, amount);
}
function veto(uint32 reimbursementId) public {
ReimbursementData storage r = reimbursements[reimbursementId];
require(r.exists, 'NOT_FOUND');
require(block.number < r.confirmedAtBlock, 'VETO_PERIOD_ENDED');
r.vetoed = true;
emit ReimbursementVetoed(reimbursementId, msg.sender);
}
function exists(uint32 reimbursementId) public view returns (bool) {
return reimbursements[reimbursementId].exists;
}
}

25
contracts/Token.sol Normal file
View File

@ -0,0 +1,25 @@
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol";
contract Token is Initializable, ERC20Upgradeable {
using SafeMathUpgradeable for uint256;
bytes32 public constant MINT_TOKEN_ROLE = keccak256("MINT_TOKEN_ROLE");
event LogMint(address indexed recipient, uint256 amount, uint32 contributionId);
function initialize() public virtual initializer {
__ERC20_init('Kredits', 'KS');
}
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public {
require(amount > 0, "INVALID_AMOUNT");
uint256 amountInWei = amount.mul(1 ether);
_mint(contributorAccount, amountInWei);
emit LogMint(contributorAccount, amount, contributionId);
}
}

View File

@ -1,13 +0,0 @@
pragma solidity 0.4.24;
import "@aragon/os/contracts/apm/APMNamehash.sol";
contract APMNamehashOpen is APMNamehash {
bytes32 public constant OPEN_TITLE = keccak256("open");
bytes32 public constant OPEN_APM_NODE = keccak256(abi.encodePacked(APM_NODE, OPEN_TITLE));
function apmNamehashOpen(string name) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(OPEN_APM_NODE, keccak256(name)));
}
}

View File

@ -1,16 +0,0 @@
pragma solidity 0.4.24;
import "@aragon/os/contracts/apps/AragonApp.sol";
// This is a "Dummy" app which's only purpose to exist is because
// Aragon's CLI still doesn't support running a Kit inside a project
// which isn't considered to be a "valid" Aragon project.
// It requires us to have an arrap.json file pointing to the contract
// and a manifest.json file which describes the front-end structure.
contract DummyApp is AragonApp {
function initialize() public onlyInit {
initialized();
}
}

View File

@ -1,23 +0,0 @@
pragma solidity ^0.4.4;
contract Migrations {
address public owner;
uint public last_completed_migration;
modifier restricted() {
if (msg.sender == owner) _;
}
function constructor() public {
owner = msg.sender;
}
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}

63
hardhat.config.js Normal file
View File

@ -0,0 +1,63 @@
require("@nomiclabs/hardhat-waffle");
require('hardhat-deploy');
require("hardhat-deploy-ethers");
require('@openzeppelin/hardhat-upgrades');
const promptly = require('promptly');
// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async () => {
const accounts = await ethers.getSigners();
for (const account of accounts) {
console.log(account.address);
}
});
task('fund', "Send eth to an address", async () => {
const to = await promptly.prompt('Address:');
const value = await promptly.prompt('Value:');
const signer = await ethers.getSigners();
const fundTransaction = await signer[0].sendTransaction({to: to, value: ethers.utils.parseEther(value)});
console.log(fundTransaction);
});
task("create-wallet", "Creates a new wallet json", async () => {
const wallet = ethers.Wallet.createRandom();
console.log('New wallet:');
console.log(`Address: ${wallet.address}`);
console.log(`Public key: ${wallet.publicKey}`);
console.log(`Private key: ${wallet.privateKey}`);
console.log(`Mnemonic: ${JSON.stringify(wallet.mnemonic)}`);
const password = await promptly.prompt('Encryption password: ')
const encryptedJSON = await wallet.encrypt(password);
console.log('Encrypted wallet JSON:');
console.log(encryptedJSON);
});
// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more
/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.8.0",
// defaultNetwork: 'localhost',
networks: {
hardhat: {
chainId: 1337
}
},
namedAccounts: {
deployer: {
default: 0
}
}
};

8
lib/addresses.json Normal file
View File

@ -0,0 +1,8 @@
{
"1337": {
"Contributor": "0xB0D4afd8879eD9F52b28595d31B441D079B2Ca07",
"Contribution": "0x922D6956C99E12DFeB3224DEA977D0939758A1Fe",
"Token": "0x5081a39b8A5f0E35a8D959395a630b68B74Dd30f",
"Reimbursement": "0x1fA02b2d6A771842690194Cf62D91bdd92BfE28d"
}
}

View File

@ -7,20 +7,15 @@ const ABIS = {
Contributor: require('./abis/Contributor.json'),
Contribution: require('./abis/Contribution.json'),
Reimbursement: require('./abis/Reimbursement.json'),
Token: require('./abis/Token.json'),
Proposal: require('./abis/Proposal.json'),
Kernel: require('./abis/Kernel.json'),
Acl: require('./abis/ACL.json'),
Token: require('./abis/Token.json')
};
const APP_CONTRACTS = [
'Contributor',
'Contribution',
'Token',
'Proposal',
'Reimbursement',
'Acl',
'Reimbursement'
];
const DaoAddresses = require('./addresses/dao.json');
const Addresses = require('./addresses.json');
const Contracts = require('./contracts');
const IPFS = require('./utils/ipfs');
@ -48,18 +43,9 @@ class Kredits {
init (names) {
let contractsToLoad = names || APP_CONTRACTS;
return this.provider.getNetwork().then(network => {
this.addresses['Kernel'] = this.addresses['Kernel'] || DaoAddresses[network.chainId.toString()];
let addressPromises = contractsToLoad.map((contractName) => {
return this.Kernel.getApp(contractName).then((address) => {
this.addresses[contractName] = address;
}).catch((error) => {
throw new Error(`Failed to get address for ${contractName} from DAO at ${this.Kernel.contract.address}
- ${error.message}`
);
});
});
return Promise.all(addressPromises).then(() => { return this; });
if (Object.keys(this.addresses).length === 0) {
this.addresses = Addresses[network.chainId.toString()];
}
});
}
@ -86,16 +72,7 @@ class Kredits {
}
static availableNetworks () {
return Object.keys(DaoAddresses);
}
get Kernel () {
let k = this.contractFor('Kernel');
// in case we want to use a special apm (e.g. development vs. production)
if (this.options.apm) {
k.apm = this.options.apm;
}
return k;
return Object.keys(Addresses);
}
get Contributor () {
@ -107,10 +84,6 @@ class Kredits {
return this.Contributor;
}
get Proposal () {
return this.contractFor('Proposal');
}
get Operator () {
return this.Proposal;
}
@ -127,10 +100,6 @@ class Kredits {
return this.contractFor('Reimbursement');
}
get Acl () {
return this.contractFor('Acl');
}
// Should be private
contractFor (name) {
if (this.contracts[name]) {

15922
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -42,8 +42,10 @@
},
"homepage": "https://github.com/67P/truffle-kredits#readme",
"devDependencies": {
"@aragon/kits-base": "^1.0.0",
"@aragon/os": "^4.4.0",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.0",
"@openzeppelin/contracts-upgradeable": "^4.1.0",
"@openzeppelin/hardhat-upgrades": "^1.8.2",
"async-each-series": "^1.1.0",
"cli-table": "^0.3.1",
"eslint": "^7.1.0",
@ -52,12 +54,14 @@
"eslint-plugin-promise": "^4.2.1",
"eth-provider": "^0.2.5",
"ethereum-block-by-date": "^1.4.0",
"ethereum-waffle": "^3.3.0",
"hardhat": "^2.0.3",
"hardhat-deploy": "^0.7.0-beta.35",
"hardhat-deploy-ethers": "^0.3.0-beta.7",
"homedir": "^0.6.0",
"promptly": "^3.0.3",
"solc": "^0.6.8",
"solhint": "^2.3.1",
"truffle-hdwallet-provider": "^1.0.17",
"truffle-hdwallet-provider-privkey": "^0.3.0",
"yargs": "^15.0.0"
},
"dependencies": {

View File

@ -1,16 +1,12 @@
const promptly = require('promptly');
const { inspect } = require('util');
const initKredits = require('./helpers/init_kredits.js');
const { ethers } = require("hardhat");
const Kredits = require('../lib/kredits');
module.exports = async function(callback) {
let kredits;
try {
kredits = await initKredits(web3);
} catch(e) {
callback(e);
return;
}
async function main() {
kredits = new Kredits(hre.ethers.provider, hre.ethers.provider.getSigner())
await kredits.init();
console.log(`Using Contributions at: ${kredits.Contribution.contract.address}`);
@ -49,10 +45,11 @@ module.exports = async function(callback) {
.then(result => {
console.log("\n\nResult:");
console.log(result);
callback();
})
.catch(error => {
console.log('Failed to create contribution');
callback(inspect(error));
console.log(error);
});
}
main();

View File

@ -1,6 +1,7 @@
const promptly = require('promptly');
const initKredits = require('./helpers/init_kredits.js');
const { ethers } = require("hardhat");
const Kredits = require('../lib/kredits');
async function prompt(message, options) {
if (!options) {
@ -8,15 +9,9 @@ async function prompt(message, options) {
}
return await promptly.prompt(message, options);
}
module.exports = async function(callback) {
let kredits;
try {
kredits = await initKredits(web3);
} catch(e) {
callback(e);
return;
}
async function main() {
kredits = new Kredits(hre.ethers.provider, hre.ethers.provider.getSigner())
await kredits.init();
console.log(`Using contributors at: ${kredits.Contributor.contract.address}`);
@ -36,9 +31,10 @@ module.exports = async function(callback) {
kredits.Contributor.add(contributorAttributes, { gasLimit: 350000 }).then((result) => {
console.log("\n\nResult:");
console.log(result);
callback();
}).catch((error) => {
console.log('Failed to create contributor');
callback(error);
console.log(error);
});
}
main();

53
scripts/create-proxy.js Normal file
View File

@ -0,0 +1,53 @@
const { ethers, upgrades } = require("hardhat");
const path = require('path');
const fileInject = require('./helpers/file_inject.js');
async function main() {
const network = await hre.ethers.provider.getNetwork();
const networkId = network.chainId;
console.log(`Deploying to network #${networkId}`);
const Contributor = await ethers.getContractFactory("Contributor");
const Contribution = await ethers.getContractFactory("Contribution");
const Token = await ethers.getContractFactory("Token");
const Reimbursement = await ethers.getContractFactory("Reimbursement");
const contributor = await upgrades.deployProxy(Contributor, []);
await contributor.deployed();
console.log("Contributor deployed to:", contributor.address);
const blocksToWait = 40320; // 7 days; 15 seconds block time
const contribution = await upgrades.deployProxy(Contribution, [blocksToWait]);
await contribution.deployed();
console.log("Contribution deployed to:", contribution.address);
const token = await upgrades.deployProxy(Token, []);
await token.deployed();
console.log("Token deployed to:", token.address);
const reimbursement = await upgrades.deployProxy(Reimbursement, []);
await reimbursement.deployed();
console.log("Reimbursement deployed to:", reimbursement.address);
await contributor.setTokenContract(token.address);
await contributor.setContributionContract(contribution.address);
await contribution.setTokenContract(token.address);
await contribution.setContributorContract(contributor.address);
const c = await contributor.contributionContract();
console.log(c);
const addresses = {
Contributor: contributor.address,
Contribution: contribution.address,
Token: token.address,
Reimbursement: reimbursement.address
};
const libPath = path.join(__dirname, '..', 'lib');
fileInject(path.join(libPath, 'addresses.json'), networkId, addresses);
}
main();

View File

@ -1,16 +1,13 @@
const promptly = require('promptly');
const Table = require('cli-table');
const initKredits = require('./helpers/init_kredits.js');
const { ethers } = require("hardhat");
const Kredits = require('../lib/kredits');
module.exports = async function(callback) {
async function main() {
let kredits;
try {
kredits = await initKredits(web3);
} catch(e) {
callback(e);
return;
}
kredits = new Kredits(hre.ethers.provider, hre.ethers.provider.getSigner())
await kredits.init();
console.log(`Using Contribution at: ${kredits.Contribution.contract.address}`);
@ -47,6 +44,6 @@ module.exports = async function(callback) {
} catch (err) {
console.log(err);
}
callback();
}
main();

View File

@ -1,17 +1,13 @@
const promptly = require('promptly');
const Table = require('cli-table');
const ethers = require('ethers');
const initKredits = require('./helpers/init_kredits.js');
const { ethers } = require("hardhat");
const Kredits = require('../lib/kredits');
module.exports = async function(callback) {
async function main() {
let kredits;
try {
kredits = await initKredits(web3);
} catch(e) {
callback(e);
return;
}
kredits = new Kredits(hre.ethers.provider, hre.ethers.provider.getSigner())
await kredits.init();
console.log(`Using Contributor at: ${kredits.Contributor.contract.address}`);
@ -19,7 +15,6 @@ module.exports = async function(callback) {
head: ['ID', 'Account', 'Name', 'Core?', 'Balance', 'Kredits earned', 'Contributions count', 'IPFS']
})
try {
const contributors = await kredits.Contributor.all()
contributors.forEach((c) => {
@ -33,13 +28,9 @@ module.exports = async function(callback) {
c.contributionsCount.toString(),
c.ipfsHash
])
})
});
console.log(table.toString())
} catch(e) {
callback(e);
return;
}
callback()
console.log(table.toString());
}
main();