Import/Migrate existing kredits contracts

This brings in the current state of the kredits contracts incl. the
Contributors, Operator and Token contract.
This commit is contained in:
bumi 2018-03-31 16:18:17 +02:00
parent f0caa1208d
commit 85ae154860
9 changed files with 278 additions and 6 deletions

108
contracts/Contributors.sol Normal file
View File

@ -0,0 +1,108 @@
pragma solidity ^0.4.18;
import './upgradeable/Upgradeable.sol';
contract Contributors is Upgradeable {
struct Contributor {
address account;
bytes32 profileHash;
uint8 hashFunction;
uint8 hashSize;
bool isCore;
bool exists;
}
mapping (address => uint) public contributorIds;
mapping (uint => Contributor) public contributors;
uint256 public contributorsCount;
event ContributorProfileUpdated(uint id, bytes32 oldProfileHash, bytes32 newProfileHash);
event ContributorAddressUpdated(uint id, address oldAddress, address newAddress);
event ContributorAdded(uint id, address _address);
function initialize(address sender) public payable {
require(msg.sender == address(registry));
uint _id = 1;
Contributor c = contributors[_id];
c.exists = true;
c.isCore = true;
c.account = sender;
contributorIds[sender] = _id;
contributorsCount += 1;
}
function coreContributorsCount() constant public returns (uint) {
uint count = 0;
for (uint256 i = 1; i <= contributorsCount; i++) {
if (contributors[i].isCore) {
count += 1;
}
}
return count;
}
function updateContributorAddress(uint _id, address _oldAddress, address _newAddress) public onlyRegistryContractFor('Operator') {
contributorIds[_oldAddress] = 0;
contributorIds[_newAddress] = _id;
contributors[_id].account = _newAddress;
ContributorAddressUpdated(_id, _oldAddress, _newAddress);
}
function updateContributorProfileHash(uint _id, uint8 _hashFunction, uint8 _hashSize, bytes32 _profileHash) public onlyRegistryContractFor('Operator') {
Contributor c = contributors[_id];
bytes32 _oldProfileHash = c.profileHash;
c.profileHash = _profileHash;
c.hashFunction = _hashFunction;
c.hashSize = _hashSize;
ContributorProfileUpdated(_id, _oldProfileHash, c.profileHash);
}
function addContributor(address _address, uint8 _hashFunction, uint8 _hashSize, bytes32 _profileHash, bool isCore) public onlyRegistryContractFor('Operator') {
uint _id = contributorsCount + 1;
if (contributors[_id].exists != true) {
Contributor c = contributors[_id];
c.exists = true;
c.isCore = isCore;
c.hashFunction = _hashFunction;
c.hashSize = _hashSize;
c.profileHash = _profileHash;
c.account = _address;
contributorIds[_address] = _id;
contributorsCount += 1;
ContributorAdded(_id, _address);
}
}
function isCore(uint _id) constant public returns (bool) {
return contributors[_id].isCore;
}
function exists(uint _id) constant public returns (bool) {
return contributors[_id].exists;
}
function addressIsCore(address _address) constant public returns (bool) {
return getContributorByAddress(_address).isCore;
}
function addressExists(address _address) constant public returns (bool) {
return getContributorByAddress(_address).exists;
}
function getContributorIdByAddress(address _address) constant public returns (uint) {
return contributorIds[_address];
}
function getContributorAddressById(uint _id) constant public returns (address) {
return contributors[_id].account;
}
function getContributorByAddress(address _address) internal returns (Contributor) {
uint id = contributorIds[_address];
return contributors[id];
}
}

126
contracts/Operator.sol Normal file
View File

@ -0,0 +1,126 @@
pragma solidity ^0.4.18;
// ToDo: only load interfaces
import './Token.sol';
import './Contributors.sol';
contract Operator is Upgradeable {
struct Proposal {
address creator;
uint recipientId;
uint votesCount;
uint votesNeeded;
uint256 amount;
bool executed;
string ipfsHash;
mapping (address => bool) votes;
bool exists;
}
Proposal[] public proposals;
event ProposalCreated(uint256 id, address creator, uint recipient, uint256 amount, string ipfsHash);
event ProposalVoted(uint256 id, address voter);
event ProposalVoted(uint256 id, address voter, uint256 totalVotes);
event ProposalExecuted(uint256 id, uint recipient, uint256 amount, string ipfsHash);
modifier coreOnly() {
require(contributorsContract().addressIsCore(msg.sender));
_;
}
modifier contributorOnly() {
require(contributorsContract().addressExists(msg.sender));
_;
}
modifier noEther() {
require(msg.value == 0);
_;
}
function contributorsContract() constant public returns (Contributors) {
return Contributors(registry.getProxyFor('Contributors'));
}
function tokenContract() constant public returns (Token) {
return Token(registry.getProxyFor('Token'));
}
function contributorsCount() constant public returns (uint) {
return contributorsContract().contributorsCount();
}
function coreContributorsCount() constant public returns (uint) {
return contributorsContract().coreContributorsCount();
}
function addContributor(address _address, bytes32 _profileHash, uint8 _hashFunction, uint8 _hashSize, bool _isCore) public coreOnly {
contributorsContract().addContributor(_address, _hashFunction, _hashSize, _profileHash, _isCore);
}
function updateContributorProfileHash(uint _id, bytes32 _profileHash, uint8 _hashFunction, uint8 _hashSize) public coreOnly {
contributorsContract().updateContributorProfileHash(_id, _hashFunction, _hashSize, _profileHash);
}
function getContributor(uint _id) constant public returns (address account, uint8 hashFunction, uint8 hashSize, bytes32 profileHash, bool isCore) {
bool exists;
(account, profileHash, hashFunction, hashSize, isCore, exists) = contributorsContract().contributors(_id);
if (!exists) { throw; }
}
function proposalsCount() constant public returns (uint) {
return proposals.length;
}
function addProposal(uint _recipient, uint256 _amount, string _ipfsHash) public returns (uint256 proposalId) {
require(contributorsContract().exists(_recipient));
proposalId = proposals.length;
uint _votesNeeded = contributorsContract().coreContributorsCount() / 100 * 75;
var p = Proposal({
creator: msg.sender,
recipientId: _recipient,
amount: _amount,
ipfsHash: _ipfsHash,
votesCount: 0,
votesNeeded: _votesNeeded,
executed: false,
exists: true
});
proposals.push(p);
ProposalCreated(proposalId, msg.sender, p.recipientId, p.amount, p.ipfsHash);
}
function vote(uint256 _proposalId) public coreOnly returns (uint _pId, bool _executed) {
var p = proposals[_proposalId];
if (p.executed) { throw; }
if (p.votes[msg.sender] == true) { throw; }
p.votes[msg.sender] = true;
p.votesCount++;
_executed = false;
_pId = _proposalId;
if (p.votesCount >= p.votesNeeded) {
executeProposal(_proposalId);
_executed = true;
}
ProposalVoted(_pId, msg.sender, p.votesCount);
}
function hasVotedFor(address _sender, uint256 _proposalId) public constant returns (bool) {
Proposal p = proposals[_proposalId];
return p.exists && p.votes[_sender];
}
function executeProposal(uint proposalId) private returns (bool) {
var p = proposals[proposalId];
if (p.executed) { throw; }
if (p.votesCount < p.votesNeeded) { throw; }
address recipientAddress = contributorsContract().getContributorAddressById(p.recipientId);
tokenContract().mintFor(recipientAddress, p.amount, p.ipfsHash);
p.executed = true;
ProposalExecuted(proposalId, p.recipientId, p.amount, p.ipfsHash);
return true;
}
}

View File

@ -10,11 +10,6 @@ contract Token is Upgradeable, BasicToken {
event LogMint(address indexed recipient, uint256 amount, string reference);
modifier requireRegistry() {
require(address(registry) != 0x0);
_;
}
function initialize(address sender) public payable {
require(msg.sender == address(registry));
name = 'Kredits';
@ -22,7 +17,7 @@ contract Token is Upgradeable, BasicToken {
decimals = 18;
}
function mintFor(address _recipient, uint256 _amount, string _reference) requireRegistry returns (bool success) {
function mintFor(address _recipient, uint256 _amount, string _reference) onlyRegistryContractFor('Operator') public returns (bool success) {
totalSupply_ = totalSupply_.add(_amount);
balances[_recipient] = balances[_recipient].add(_amount);

View File

@ -49,4 +49,5 @@ interface IRegistry {
*/
function getLatestVersion(bytes32 name) public view returns (address);
function getProxyFor(bytes32 name) public view returns (address);
}

View File

@ -47,6 +47,10 @@ contract Registry is IRegistry {
return getVersion(name, current);
}
function getProxyFor(bytes32 name) public view returns (address) {
return proxies[name];
}
function upgrade(bytes32 name, uint version) public {
UpgradeabilityProxy(proxies[name]).upgradeTo(version);
ProxyImplementationUpgraded(name, version);

View File

@ -16,6 +16,17 @@ contract UpgradeabilityStorage {
// contract name
bytes32 public _proxiedContractName;
modifier requireRegistry() {
require(address(registry) != 0x0);
_;
}
modifier onlyRegistryContractFor(bytes32 name) {
require(address(registry) != 0x0);
require(msg.sender == registry.getProxyFor(name));
_;
}
/**
* @dev Tells the address of the current implementation
* @return address of the current implementation

View File

@ -7,6 +7,7 @@ module.exports = function(deployer) {
console.log('Token address: ', Token.address);
Registry.deployed().then(function(registry) {
registry.addVersion('Token', Token.address);
registry.createProxy('Token', 1);
});
});
};

View File

@ -0,0 +1,13 @@
var Registry = artifacts.require('./Registry.sol');
var Contributors = artifacts.require('./Contributors.sol');
module.exports = function(deployer) {
deployer.deploy(Contributors).then(function(contributors) {
console.log('Registry address: ', Registry.address);
console.log('Contributors address: ', Contributors.address);
Registry.deployed().then(function(registry) {
registry.addVersion('Contributors', Contributors.address);
registry.createProxy('Contributors', 1);
});
});
};

View File

@ -0,0 +1,13 @@
var Registry = artifacts.require('./Registry.sol');
var Operator = artifacts.require('./Operator.sol');
module.exports = function(deployer) {
deployer.deploy(Operator).then(function(operator) {
console.log('Registry address: ', Registry.address);
console.log('Operator address: ', Operator.address);
Registry.deployed().then(function(registry) {
registry.addVersion('Operator', Operator.address);
registry.createProxy('Operator', 1);
});
});
};