Merge pull request 'Remove claims, add withdrawals' (#225) from feature/184-remove_kredits_claims into feature/export-import
Reviewed-on: #225
This commit is contained in:
commit
fd012d5359
@ -2,10 +2,6 @@ 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);
|
||||
@ -16,12 +12,10 @@ interface ContributorInterface {
|
||||
|
||||
contract Contribution is Initializable {
|
||||
ContributorInterface public contributorContract;
|
||||
IToken public tokenContract;
|
||||
|
||||
struct ContributionData {
|
||||
uint32 contributorId;
|
||||
uint32 amount;
|
||||
bool claimed;
|
||||
bytes32 hashDigest;
|
||||
uint8 hashFunction;
|
||||
uint8 hashSize;
|
||||
@ -52,7 +46,6 @@ contract Contribution is Initializable {
|
||||
bool public migrationDone;
|
||||
|
||||
event ContributionAdded(uint32 id, uint32 indexed contributorId, uint32 amount);
|
||||
event ContributionClaimed(uint32 id, uint32 indexed contributorId, uint32 amount);
|
||||
event ContributionVetoed(uint32 id, address vetoedByAccount);
|
||||
|
||||
modifier onlyCore {
|
||||
@ -75,11 +68,6 @@ contract Contribution is Initializable {
|
||||
migrationDone = true;
|
||||
}
|
||||
|
||||
function setTokenContract(address token) public {
|
||||
require(address(tokenContract) == address(0) || contributorContract.addressIsCore(msg.sender), "Core only");
|
||||
tokenContract = IToken(token);
|
||||
}
|
||||
|
||||
function setContributorContract(address contributor) public {
|
||||
require(address(contributorContract) == address(0) || contributorContract.addressIsCore(msg.sender), "Core only");
|
||||
contributorContract = ContributorInterface(contributor);
|
||||
@ -151,14 +139,13 @@ contract Contribution is Initializable {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
function getContribution(uint32 contributionId) public view returns (uint32 id, uint32 contributorId, uint32 amount, 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,
|
||||
@ -178,7 +165,6 @@ contract Contribution is Initializable {
|
||||
ContributionData storage c = contributions[contributionId];
|
||||
c.exists = true;
|
||||
c.amount = amount;
|
||||
c.claimed = false;
|
||||
c.contributorId = contributorId;
|
||||
c.hashDigest = hashDigest;
|
||||
c.hashFunction = hashFunction;
|
||||
@ -203,29 +189,13 @@ contract Contribution is Initializable {
|
||||
function veto(uint32 contributionId) public onlyCore {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ pragma solidity ^0.8.0;
|
||||
|
||||
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
||||
|
||||
interface ITokenBalance {
|
||||
interface IToken {
|
||||
function mintFor(address contributorAccount, uint256 amount) external;
|
||||
function balanceOf(address contributorAccount) external view returns (uint256);
|
||||
}
|
||||
interface IContributionBalance {
|
||||
@ -11,9 +12,9 @@ interface IContributionBalance {
|
||||
}
|
||||
|
||||
contract Contributor is Initializable {
|
||||
address deployer;
|
||||
address public deployer;
|
||||
IContributionBalance public contributionContract;
|
||||
ITokenBalance public tokenContract;
|
||||
IToken public tokenContract;
|
||||
|
||||
struct Contributor {
|
||||
address account;
|
||||
@ -21,6 +22,7 @@ contract Contributor is Initializable {
|
||||
uint8 hashFunction;
|
||||
uint8 hashSize;
|
||||
bool exists;
|
||||
uint32 kreditsWithdrawn;
|
||||
}
|
||||
|
||||
mapping (address => uint32) public contributorIds;
|
||||
@ -36,6 +38,11 @@ contract Contributor is Initializable {
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyContributors {
|
||||
require(addressExists(msg.sender) && contributionContract.balanceOf(msg.sender) > 0, "Contributors only");
|
||||
_;
|
||||
}
|
||||
|
||||
function initialize() public initializer {
|
||||
deployer = msg.sender;
|
||||
}
|
||||
@ -47,7 +54,7 @@ contract Contributor is Initializable {
|
||||
|
||||
function setTokenContract(address token) public onlyCore {
|
||||
require(address(tokenContract) == address(0) || addressIsCore(msg.sender), "Core only");
|
||||
tokenContract = ITokenBalance(token);
|
||||
tokenContract = IToken(token);
|
||||
}
|
||||
|
||||
function coreContributorsCount() public view returns (uint32) {
|
||||
@ -81,7 +88,7 @@ contract Contributor is Initializable {
|
||||
}
|
||||
|
||||
function addContributor(address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public onlyCore {
|
||||
require(!addressExists(account));
|
||||
require(!addressExists(account), "Address already in use");
|
||||
uint32 _id = contributorsCount + 1;
|
||||
assert(!contributors[_id].exists); // this can not be acually
|
||||
Contributor storage c = contributors[_id];
|
||||
@ -90,6 +97,7 @@ contract Contributor is Initializable {
|
||||
c.hashFunction = hashFunction;
|
||||
c.hashSize = hashSize;
|
||||
c.account = account;
|
||||
c.kreditsWithdrawn = 0;
|
||||
contributorIds[account] = _id;
|
||||
|
||||
contributorsCount += 1;
|
||||
@ -132,7 +140,7 @@ contract Contributor is Initializable {
|
||||
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 ) {
|
||||
function getContributorById(uint32 _id) view public returns (uint32 id, address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, uint32 totalKreditsEarned, uint256 contributionsCount, bool exists, uint256 kreditsWithdrawn) {
|
||||
id = _id;
|
||||
Contributor storage c = contributors[_id];
|
||||
account = c.account;
|
||||
@ -144,6 +152,19 @@ contract Contributor is Initializable {
|
||||
totalKreditsEarned = contributionContract.totalKreditsEarnedByContributor(_id, true);
|
||||
contributionsCount = contributionContract.balanceOf(c.account);
|
||||
exists = c.exists;
|
||||
kreditsWithdrawn = c.kreditsWithdrawn;
|
||||
}
|
||||
|
||||
function withdraw() public onlyContributors {
|
||||
uint32 id = getContributorIdByAddress(msg.sender);
|
||||
Contributor storage c = contributors[id];
|
||||
|
||||
// TODO check if we need a failsafe for unconfirmed or malicious txs
|
||||
uint32 confirmedKredits = contributionContract.totalKreditsEarnedByContributor(id, true);
|
||||
uint32 amountWithdrawable = confirmedKredits - c.kreditsWithdrawn;
|
||||
require (amountWithdrawable > 0, "No kredits available");
|
||||
|
||||
c.kreditsWithdrawn += amountWithdrawable;
|
||||
tokenContract.mintFor(msg.sender, amountWithdrawable);
|
||||
}
|
||||
}
|
||||
|
@ -7,38 +7,32 @@ interface ContributorInterface {
|
||||
function getContributorAddressById(uint32 contributorId) external view returns (address);
|
||||
function getContributorIdByAddress(address contributorAccount) external view returns (uint32);
|
||||
function addressIsCore(address sender) external view returns (bool);
|
||||
// TODO Maybe use for validation
|
||||
// function exists(uint32 contributorId) public view returns (bool);
|
||||
}
|
||||
|
||||
contract Token is Initializable, ERC20Upgradeable {
|
||||
ContributorInterface public contributorContract;
|
||||
using SafeMathUpgradeable for uint256;
|
||||
|
||||
address public contributionContract;
|
||||
address public contributorContractAddress;
|
||||
|
||||
event LogMint(address indexed recipient, uint256 amount, uint32 contributionId);
|
||||
event KreditsMinted(address indexed recipient, uint256 amount);
|
||||
|
||||
function initialize() public virtual initializer {
|
||||
__ERC20_init('Kredits', 'KS');
|
||||
}
|
||||
|
||||
function setContributionContract(address contribution) public {
|
||||
require(address(contributionContract) == address(0) || contributorContract.addressIsCore(msg.sender), "Core only");
|
||||
contributionContract = contribution;
|
||||
}
|
||||
function setContributorContract(address contributor) public {
|
||||
require(address(contributorContract) == address(0) || contributorContract.addressIsCore(msg.sender), "Core only");
|
||||
contributorContract = ContributorInterface(contributor);
|
||||
contributorContractAddress = contributor;
|
||||
}
|
||||
|
||||
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public {
|
||||
require(contributionContract == msg.sender, "Only Contribution");
|
||||
function mintFor(address contributorAccount, uint256 amount) public {
|
||||
require(contributorContractAddress == msg.sender, "Only Contributor");
|
||||
require(amount > 0, "INVALID_AMOUNT");
|
||||
|
||||
uint256 amountInWei = amount.mul(1 ether);
|
||||
_mint(contributorAccount, amountInWei);
|
||||
emit LogMint(contributorAccount, amount, contributionId);
|
||||
emit KreditsMinted(contributorAccount, amount);
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"contributionId","type":"uint32"}],"name":"LogMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributionContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContract","outputs":[{"internalType":"contract ContributorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contributorAccount","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32","name":"contributionId","type":"uint32"}],"name":"mintFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contribution","type":"address"}],"name":"setContributionContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contributor","type":"address"}],"name":"setContributorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
|
||||
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"KreditsMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContract","outputs":[{"internalType":"contract ContributorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contributorAccount","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contributor","type":"address"}],"name":"setContributorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
|
@ -57,16 +57,6 @@ async function main() {
|
||||
return res.wait();
|
||||
}).catch(handleError);
|
||||
|
||||
|
||||
console.log('Calling Contribution#setTokenContract')
|
||||
await contracts.Contribution.functions
|
||||
.setTokenContract(contracts.Token.address)
|
||||
.then(res => {
|
||||
console.log(`...transaction published: ${res.hash}`);
|
||||
return res.wait();
|
||||
}).catch(handleError);
|
||||
|
||||
|
||||
console.log('Calling Contribution#setContributorContract')
|
||||
await contracts.Contribution.functions
|
||||
.setContributorContract(contracts.Contributor.address)
|
||||
@ -75,14 +65,6 @@ async function main() {
|
||||
return res.wait();
|
||||
}).catch(handleError);
|
||||
|
||||
console.log('Calling Token#setContributionContract')
|
||||
await contracts.Token.functions
|
||||
.setContributionContract(contracts.Contribution.address)
|
||||
.then(res => {
|
||||
console.log(`...transaction published: ${res.hash}`);
|
||||
return res.wait();
|
||||
}).catch(handleError);
|
||||
|
||||
console.log('Calling Token#setContributorContract')
|
||||
await contracts.Token.functions
|
||||
.setContributorContract(contracts.Contributor.address)
|
||||
|
@ -12,7 +12,7 @@ async function main() {
|
||||
console.log(`Using Contribution at: ${kredits.Contribution.contract.address}`);
|
||||
|
||||
const table = new Table({
|
||||
head: ['ID', 'Contributor ID', 'Description', 'Amount', 'Confirmed?', 'Vetoed?', 'Claimed?', 'IPFS']
|
||||
head: ['ID', 'Contributor ID', 'Description', 'Amount', 'Confirmed?', 'Vetoed?', 'IPFS']
|
||||
})
|
||||
|
||||
try {
|
||||
@ -31,7 +31,6 @@ async function main() {
|
||||
c.amount.toString(),
|
||||
`${confirmed} (${c.confirmedAtBlock})`,
|
||||
c.vetoed,
|
||||
c.claimed,
|
||||
c.ipfsHash
|
||||
])
|
||||
});
|
||||
|
@ -128,7 +128,7 @@ describe("Contribution contract", async function () {
|
||||
before(async function () {
|
||||
const contributionFactory = await ethers.getContractFactory("Contribution");
|
||||
Contribution = await upgrades.deployProxy(contributionFactory, [40321]);
|
||||
await Contribution.setContributorContract(Contributor.address).then(res => res.wait())
|
||||
await Contribution.setContributorContract(Contributor.address);
|
||||
});
|
||||
|
||||
it("allows to add a contribution with custom confirmedAtBlock", async function () {
|
||||
|
@ -1,30 +1,106 @@
|
||||
const { expect } = require("chai");
|
||||
const { ethers, upgrades } = require("hardhat");
|
||||
// const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs");
|
||||
let owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7;
|
||||
let Contribution, Contributor;
|
||||
let Contribution, Contributor, Token;
|
||||
|
||||
describe("Contributor contract", async function () {
|
||||
before(async function () {
|
||||
[owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7] = await ethers.getSigners();
|
||||
// let accounts = [owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7];
|
||||
// const contributorFactory = await ethers.getContractFactory("Contributor");
|
||||
// Contributor = await upgrades.deployProxy(contributorFactory);
|
||||
// for (const account of accounts) {
|
||||
// await Contributor.addContributor(account.address, "0x99b8afd7b266e19990924a8be9099e81054b70c36b20937228a77a5cf75723b8", 18, 32);
|
||||
// }
|
||||
|
||||
const contributorFactory = await ethers.getContractFactory("Contributor");
|
||||
Contributor = await upgrades.deployProxy(contributorFactory);
|
||||
const contributionFactory = await ethers.getContractFactory("Contribution");
|
||||
Contribution = await upgrades.deployProxy(contributionFactory, [40321]);
|
||||
const tokenFactory = await ethers.getContractFactory("Token");
|
||||
Token = await upgrades.deployProxy(tokenFactory);
|
||||
|
||||
await Contributor.setTokenContract(Token.address);
|
||||
await Contributor.setContributionContract(Contribution.address);
|
||||
await Contribution.setContributorContract(Contributor.address);
|
||||
await Token.setContributorContract(Contributor.address);
|
||||
|
||||
let accounts = [owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7];
|
||||
for (const account of accounts) {
|
||||
await Contributor.addContributor(account.address, "0x99b8afd7b266e19990924a8be9099e81054b70c36b20937228a77a5cf75723b8", 18, 32);
|
||||
}
|
||||
});
|
||||
|
||||
describe("initialize()", function () {
|
||||
before(async function () {
|
||||
// const [owner] = await ethers.getSigners();
|
||||
const contributorFactory = await ethers.getContractFactory("Contributor");
|
||||
Contributor = await upgrades.deployProxy(contributorFactory);
|
||||
});
|
||||
|
||||
it("sets the deployer address", async function () {
|
||||
expect(await Contributor.deployer()).to.equal(owner.address);
|
||||
expect(await Contributor.deployer()).to.not.equal(addr1.address);
|
||||
});
|
||||
});
|
||||
|
||||
describe("add()", function () {
|
||||
it("does not allow random accounts to create a contributor profile", async function () {
|
||||
await expect(Contributor.connect(addr7).addContributor(
|
||||
"0x608FD4b95116Ea616990Aaeb1d4f1ce07612f261",
|
||||
"0x1d9de6de5c72eedca6d7a5e8a9159e2f5fe676506aece3000acefcc821723429",
|
||||
18, 32
|
||||
)).to.be.revertedWith("Core only");
|
||||
expect(await Contributor.contributorsCount()).to.equal(8);
|
||||
});
|
||||
|
||||
it("allows core contributors to create a contributor profile", async function () {
|
||||
await Contributor.connect(addr1).addContributor(
|
||||
"0x608FD4b95116Ea616990Aaeb1d4f1ce07612f261",
|
||||
"0x1d9de6de5c72eedca6d7a5e8a9159e2f5fe676506aece3000acefcc821723429",
|
||||
18, 32
|
||||
);
|
||||
expect(await Contributor.contributorsCount()).to.equal(9);
|
||||
const c = await Contributor.getContributorById(9);
|
||||
expect(c['account']).to.equal("0x608FD4b95116Ea616990Aaeb1d4f1ce07612f261");
|
||||
expect(c['kreditsWithdrawn']).to.equal(0);
|
||||
});
|
||||
|
||||
it("does not allow to create accounts with an existing address", async function () {
|
||||
await expect(Contributor.connect(addr1).addContributor(
|
||||
"0x608FD4b95116Ea616990Aaeb1d4f1ce07612f261",
|
||||
"0x1d9de6de5c72eedca6d7a5e8a9159e2f5fe676506aece3000acefcc821723429",
|
||||
18, 32
|
||||
)).to.be.revertedWith("Address already in use");
|
||||
expect(await Contributor.contributorsCount()).to.equal(9);
|
||||
});
|
||||
|
||||
it("emits a ContributorAdded event", async function () {
|
||||
await expect(Contributor.connect(addr1).addContributor(
|
||||
"0x765E88b4F9a59C3a3b300C6eFF9E6E9fDDf9FbD9",
|
||||
"0xcfbeeadc244dfdc55bbad50d431871439df067970db84c73023956c96a6f5df2",
|
||||
18, 32
|
||||
)).to.emit(Contributor, "ContributorAdded").withArgs(10, "0x765E88b4F9a59C3a3b300C6eFF9E6E9fDDf9FbD9");
|
||||
});
|
||||
});
|
||||
|
||||
describe("withdraw()", function () {
|
||||
before(async function () {
|
||||
// Add some pre-confirmed contributions (confirmedAtBlock 1)
|
||||
await Contribution.add(
|
||||
1500, 2, "0xe794f010e617449719c64076546254129f63a6d16cf200031afa646aeb35777f",
|
||||
18, 32, 1, false
|
||||
);
|
||||
await Contribution.add(
|
||||
5000, 2, "0xe794f010e617449719c64076546254129f63a6d16cf200031afa646aeb35777f",
|
||||
18, 32, 1, false
|
||||
);
|
||||
await Contribution.finishMigration();
|
||||
});
|
||||
|
||||
it("requires the transaction sender to be a contributor", async function () {
|
||||
await expect(Contributor.withdraw()).to.be.revertedWith("Contributors only");
|
||||
});
|
||||
|
||||
it("executes a withdrawal of all available ERC20 kredits", async function () {
|
||||
let c = await Contributor.getContributorById(2);
|
||||
expect(c['balance']).to.equal(0);
|
||||
await Contributor.connect(addr1).withdraw();
|
||||
c = await Contributor.getContributorById(2);
|
||||
expect(c['balance'].toString()).to.equal("6500000000000000000000");
|
||||
expect(c['kreditsWithdrawn']).to.equal(6500);
|
||||
});
|
||||
|
||||
it("requires the withdrawable amount to be larger than 0", async function () {
|
||||
await expect(Contributor.connect(addr1).withdraw()).to.be.revertedWith("No kredits available");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user