Permissions

This commit is contained in:
bumi 2021-09-26 19:25:43 +02:00
parent 623cf6d6da
commit ffd4a5aeaf
5 changed files with 95 additions and 42 deletions

View File

@ -9,6 +9,7 @@ interface IToken {
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);
}
@ -17,11 +18,6 @@ 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;
@ -52,17 +48,22 @@ contract Contribution is Initializable {
event ContributionClaimed(uint32 id, uint32 indexed contributorId, uint32 amount);
event ContributionVetoed(uint32 id, address vetoedByAccount);
modifier onlyCore {
require(contributorContract.addressIsCore(msg.sender), "Core only");
_;
}
function initialize(uint32 blocksToWait_) public initializer {
blocksToWait = blocksToWait_;
}
// TODO who can call this when?
function setTokenContract(address token) public {
require(address(tokenContract) == address(0) || contributorContract.addressIsCore(msg.sender), "Core only");
tokenContract = IToken(token);
}
// TODO who can call this when?
function setContributorContract(address contributor) public {
require(address(contributorContract) == address(0) || contributorContract.addressIsCore(msg.sender), "Core only");
contributorContract = ContributorInterface(contributor);
}
@ -151,6 +152,7 @@ contract Contribution is Initializable {
function add(uint32 amount, uint32 contributorId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public{
//require(canPerform(msg.sender, ADD_CONTRIBUTION_ROLE, new uint32[](0)), 'nope');
require(balanceOf(msg.sender) > 0, "Must have Kredits");
uint32 contributionId = contributionsCount + 1;
ContributionData storage c = contributions[contributionId];
c.exists = true;
@ -174,7 +176,8 @@ contract Contribution is Initializable {
emit ContributionAdded(contributionId, contributorId, amount);
}
function veto(uint32 contributionId) public {
function veto(uint32 contributionId) public onlyCore {
ContributionData storage c = contributions[contributionId];
require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED');
@ -201,4 +204,5 @@ contract Contribution is Initializable {
function exists(uint32 contributionId) public view returns (bool) {
return contributions[contributionId].exists;
}
}

View File

@ -11,6 +11,7 @@ interface IContributionBalance {
}
contract Contributor is Initializable {
address deployer;
IContributionBalance public contributionContract;
ITokenBalance public tokenContract;
@ -30,18 +31,22 @@ contract Contributor is Initializable {
event ContributorAccountUpdated(uint32 id, address oldAccount, address newAccount);
event ContributorAdded(uint32 id, address account);
function initialize() public initializer {
modifier onlyCore {
require(addressIsCore(msg.sender), "Core only");
_;
}
// TODO who can call this when?
function setContributionContract(address contribution) public {
function initialize() public initializer {
deployer = msg.sender;
}
function setContributionContract(address contribution) public onlyCore {
require(address(contributionContract) == address(0) || addressIsCore(msg.sender), "Core only");
contributionContract = IContributionBalance(contribution);
}
// TODO who can call this when?
function setTokenContract(address token) public {
function setTokenContract(address token) public onlyCore {
require(address(tokenContract) == address(0) || addressIsCore(msg.sender), "Core only");
tokenContract = ITokenBalance(token);
}
@ -55,7 +60,7 @@ contract Contributor is Initializable {
return count;
}
function updateContributorAccount(uint32 id, address oldAccount, address newAccount) public {
function updateContributorAccount(uint32 id, address oldAccount, address newAccount) public onlyCore {
require(newAccount != address(0), "invalid new account address");
require(getContributorAddressById(id) == oldAccount, "contributor does not exist");
@ -65,7 +70,7 @@ contract Contributor is Initializable {
emit ContributorAccountUpdated(id, oldAccount, newAccount);
}
function updateContributorProfileHash(uint32 id, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public {
function updateContributorProfileHash(uint32 id, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public onlyCore {
Contributor storage c = contributors[id];
bytes32 oldHashDigest = c.hashDigest;
c.hashDigest = hashDigest;
@ -75,7 +80,7 @@ contract Contributor is Initializable {
ContributorProfileUpdated(id, oldHashDigest, c.hashDigest);
}
function addContributor(address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public {
function addContributor(address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public onlyCore {
require(!addressExists(account));
uint32 _id = contributorsCount + 1;
assert(!contributors[_id].exists); // this can not be acually
@ -94,7 +99,7 @@ contract Contributor is Initializable {
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;
return id > 1 && id < 7 || msg.sender == deployer;
}
function exists(uint32 id) view public returns (bool) {
@ -137,16 +142,4 @@ contract Contributor is Initializable {
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

@ -2,10 +2,16 @@ pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
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 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");
ContributorInterface public contributorContract;
struct ReimbursementData {
uint32 recipientId;
@ -31,6 +37,24 @@ contract Reimbursement is Initializable {
blocksToWait = 40320; // 7 days; 15 seconds block time
}
modifier onlyCore {
require(contributorContract.addressIsCore(msg.sender), "Core only");
_;
}
function setContributorContract(address contributor) public {
require(address(contributorContract) == address(0) || contributorContract.addressIsCore(msg.sender), "Core only");
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);
}
function totalAmount(bool confirmedOnly) public view returns (uint256 amount) {
for (uint32 i = 1; i <= reimbursementsCount; i++) {
ReimbursementData memory r = reimbursements[i];
@ -57,7 +81,7 @@ contract Reimbursement is Initializable {
);
}
function add(uint256 amount, address token, uint32 recipientId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public {
function add(uint256 amount, address token, uint32 recipientId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public onlyCore {
uint32 reimbursementId = reimbursementsCount + 1;
ReimbursementData storage r = reimbursements[reimbursementId];
r.exists = true;
@ -74,7 +98,7 @@ contract Reimbursement is Initializable {
emit ReimbursementAdded(reimbursementId, msg.sender, amount);
}
function veto(uint32 reimbursementId) public {
function veto(uint32 reimbursementId) public onlyCore {
ReimbursementData storage r = reimbursements[reimbursementId];
require(r.exists, 'NOT_FOUND');
require(block.number < r.confirmedAtBlock, 'VETO_PERIOD_ENDED');

View File

@ -3,10 +3,19 @@ pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol";
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;
bytes32 public constant MINT_TOKEN_ROLE = keccak256("MINT_TOKEN_ROLE");
address public contributionContract;
event LogMint(address indexed recipient, uint256 amount, uint32 contributionId);
@ -14,7 +23,17 @@ contract Token is Initializable, ERC20Upgradeable {
__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);
}
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public {
require(contributionContract == msg.sender, "Only Contribution");
require(amount > 0, "INVALID_AMOUNT");
uint256 amountInWei = amount.mul(1 ether);

View File

@ -1,7 +1,7 @@
const { ethers, upgrades } = require("hardhat");
const path = require('path');
const fileInject = require('./helpers/file_inject.js');
const path = require("path");
const fileInject = require("./helpers/file_inject.js");
async function main() {
const network = await hre.ethers.provider.getNetwork();
@ -16,19 +16,27 @@ async function main() {
const contributor = await upgrades.deployProxy(Contributor, []);
await contributor.deployed();
console.log("Contributor deployed to:", contributor.address);
console.log("...waiting for 1 confirmation");
await contributor.deployTransaction.wait();
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);
console.log("...waiting for 1 confirmation");
await contribution.deployTransaction.wait();
const token = await upgrades.deployProxy(Token, []);
await token.deployed();
console.log("Token deployed to:", token.address);
console.log("...waiting for 1 confirmation");
await token.deployTransaction.wait();
const reimbursement = await upgrades.deployProxy(Reimbursement, []);
await reimbursement.deployed();
console.log("Reimbursement deployed to:", reimbursement.address);
console.log("...waiting for 1 confirmation");
await reimbursement.deployTransaction.wait();
await contributor.setTokenContract(token.address);
await contributor.setContributionContract(contribution.address);
@ -36,6 +44,11 @@ async function main() {
await contribution.setTokenContract(token.address);
await contribution.setContributorContract(contributor.address);
await token.setContributionContract(contribution.address);
await token.setContributorContract(contributor.address);
await reimbursement.setContributorContract(contributor.address);
const c = await contributor.contributionContract();
console.log(c);
@ -43,11 +56,11 @@ async function main() {
Contributor: contributor.address,
Contribution: contribution.address,
Token: token.address,
Reimbursement: reimbursement.address
Reimbursement: reimbursement.address,
};
const libPath = path.join(__dirname, '..', 'lib');
fileInject(path.join(libPath, 'addresses.json'), networkId, addresses);
const libPath = path.join(__dirname, "..", "lib");
fileInject(path.join(libPath, "addresses.json"), networkId, addresses);
}
main();