mirror of
https://github.com/status-im/visual-identity.git
synced 2025-02-08 18:53:44 +00:00
included fee collector, moved executed flag to democracy and +
This commit is contained in:
parent
f6b2174694
commit
d91bfb7f8e
@ -1,20 +1,23 @@
|
||||
pragma solidity ^0.4.21;
|
||||
import "./DemocracyInterface.sol";
|
||||
import "./ProposalManager.sol";
|
||||
import "./FeeRecycler.sol";
|
||||
|
||||
contract Democracy is DemocracyInterface {
|
||||
|
||||
mapping (bytes32 => Allowance) topicAllowance;
|
||||
mapping (uint256 => bool) executedProposals;
|
||||
|
||||
struct Allowance {
|
||||
mapping(address => bool) anyCall;
|
||||
mapping(bytes32 => bool) calls;
|
||||
}
|
||||
|
||||
function Democracy(address _baseToken, address _trustNetwork) public {
|
||||
token = MiniMeTokenInterface(_baseToken);
|
||||
trustNet = TrustNetworkInterface(_trustNetwork);
|
||||
proposalManager = new ProposalManager(token, trustNet);
|
||||
function Democracy(MiniMeTokenInterface _token, TrustNetworkInterface _trustNetwork) public {
|
||||
token = _token;
|
||||
trustNet = _trustNetwork;
|
||||
feeCollector = new FeeRecycler(_token);
|
||||
proposalManager = new ProposalManager(_token, _trustNetwork, feeCollector);
|
||||
}
|
||||
|
||||
function allowTopicSpecific(bytes32 _topic, address _destination, bytes4 _allowedCall, bool allowance)
|
||||
@ -40,13 +43,14 @@ contract Democracy is DemocracyInterface {
|
||||
external
|
||||
returns (bool success)
|
||||
{
|
||||
require(!executedProposals[_proposalId]);
|
||||
executedProposals[_proposalId] = true;
|
||||
|
||||
bytes32 topic;
|
||||
bytes32 txHash;
|
||||
bool approved;
|
||||
bool executed;
|
||||
(topic, txHash, approved, executed) = proposalManager.getProposal(_proposalId);
|
||||
(topic, txHash, approved) = proposalManager.getProposal(_proposalId);
|
||||
require(approved);
|
||||
require(!executed);
|
||||
require(
|
||||
txHash == keccak256(
|
||||
_destination,
|
||||
@ -54,6 +58,7 @@ contract Democracy is DemocracyInterface {
|
||||
_data
|
||||
)
|
||||
);
|
||||
|
||||
if(topic != 0x0) { //if not root topic
|
||||
Allowance storage allowed = topicAllowance[topic];
|
||||
if(!allowed.anyCall[_destination]){ //if topic not allowed any call to destination
|
||||
@ -66,15 +71,7 @@ contract Democracy is DemocracyInterface {
|
||||
require(allowed.calls[keccak256(_destination, calling)]); //require call allowance
|
||||
}
|
||||
}
|
||||
|
||||
// save that this was executed
|
||||
require(
|
||||
proposalManager.setExecuted(
|
||||
_proposalId,
|
||||
txHash
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
//execute the call
|
||||
return _destination.call.value(_value)(_data);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import "../deploy/InstanceStorage.sol";
|
||||
import "../token/MiniMeTokenInterface.sol";
|
||||
import "./TrustNetworkInterface.sol";
|
||||
import "./ProposalManagerInterface.sol";
|
||||
import "./FeeCollector.sol";
|
||||
|
||||
/**
|
||||
* @title DemocracyStorage
|
||||
@ -17,5 +18,6 @@ contract DemocracyStorage is InstanceStorage {
|
||||
MiniMeTokenInterface public token;
|
||||
TrustNetworkInterface public trustNet;
|
||||
ProposalManagerInterface public proposalManager;
|
||||
FeeCollector public feeCollector;
|
||||
// protected zone end
|
||||
}
|
26
contracts/democracy/FeeCollector.sol
Normal file
26
contracts/democracy/FeeCollector.sol
Normal file
@ -0,0 +1,26 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
/** @notice Interface for fee collector */
|
||||
contract FeeCollector {
|
||||
|
||||
/**
|
||||
* @notice Collect a fee from yourself in your address
|
||||
* @param _amount to be collected
|
||||
*/
|
||||
function collect(uint256 _amount) external;
|
||||
|
||||
/**
|
||||
* @notice Collect a fee from your address in name of someone
|
||||
* @param _from to which address fee will be registered to
|
||||
* @param _amount to be collected
|
||||
*/
|
||||
function collectFor(address _from, uint256 _amount) external;
|
||||
|
||||
/**
|
||||
* @notice Collect a fee from someone
|
||||
* @param _from who allowed collection
|
||||
* @param _amount to be collected
|
||||
*/
|
||||
function collectFrom(address _from, uint256 _amount) external;
|
||||
|
||||
}
|
@ -2,14 +2,14 @@ pragma solidity ^0.4.21;
|
||||
|
||||
import "../common/Controlled.sol";
|
||||
import "../token/ERC20Token.sol";
|
||||
import "../token/MiniMeToken.sol";
|
||||
|
||||
import "../token/MiniMeTokenInterface.sol";
|
||||
import "./FeeCollector.sol";
|
||||
/**
|
||||
* @title FeeRecycler
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmBH)
|
||||
* @dev Allow user selecting predefined destinations to where this fees will be invested
|
||||
*/
|
||||
contract FeeRecycler is Controlled {
|
||||
contract FeeRecycler is Controlled, FeeCollector {
|
||||
|
||||
//allowed democratically choosen destinations
|
||||
mapping (address => bool) public destinations;
|
||||
@ -18,22 +18,43 @@ contract FeeRecycler is Controlled {
|
||||
//used for withdrawing lost tokens
|
||||
uint256 public totalLocked;
|
||||
//base token
|
||||
MiniMeToken public token;
|
||||
MiniMeTokenInterface public token;
|
||||
|
||||
/**
|
||||
* @notice Constructor defines the unchangable (?) baseToken
|
||||
* @param _token base token
|
||||
*/
|
||||
function FeeRecycler(MiniMeToken _token) public {
|
||||
function FeeRecycler(MiniMeTokenInterface _token) public {
|
||||
token = _token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Collect a fee from yourself in your address
|
||||
* @param _amount to be collected
|
||||
*/
|
||||
function collect(uint256 _amount) external {
|
||||
require(token.transferFrom(msg.sender, address(this), _amount));
|
||||
balances[msg.sender] += _amount;
|
||||
totalLocked += _amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Collect a fee from someone
|
||||
* @param _from who allowed collection
|
||||
* @param _amount to be collected
|
||||
*/
|
||||
function collectFrom(address _from, uint256 _amount) external {
|
||||
require(token.transferFrom(_from, address(this), _amount));
|
||||
balances[_from] += _amount;
|
||||
totalLocked += _amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Lock a fee in name of someone
|
||||
* @param _from who would be able to recycle this funds
|
||||
* @param _amount to be locked
|
||||
*/
|
||||
function lock(address _from, uint256 _amount) external {
|
||||
function collectFor(address _from, uint256 _amount) external {
|
||||
require(token.transferFrom(msg.sender, address(this), _amount));
|
||||
balances[_from] += _amount;
|
||||
totalLocked += _amount;
|
||||
@ -77,7 +98,7 @@ contract FeeRecycler is Controlled {
|
||||
if (address(_token) == address(token)) {
|
||||
require(_amount <= _token.balanceOf(address(this)) - totalLocked);
|
||||
} else if (address(_token) == address(0)) {
|
||||
require(this.balance <= _amount);
|
||||
require(address(this).balance <= _amount);
|
||||
}
|
||||
if (address(_token) != address(0)) {
|
||||
_token.transfer(_destination, _amount);
|
||||
|
@ -1,52 +1,107 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../common/Controlled.sol";
|
||||
import "../token/MiniMeTokenInterface.sol";
|
||||
import "./ProposalManagerInterface.sol";
|
||||
import "./TrustNetworkInterface.sol";
|
||||
import "./DelegationProxyInterface.sol";
|
||||
import "../token/MiniMeTokenInterface.sol";
|
||||
import "../common/Controlled.sol";
|
||||
|
||||
/**
|
||||
* @title ProposalManager
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* Store the proposals, votes and results for other smartcontracts
|
||||
* Store the proposals, votes and tabulate results for Democracy
|
||||
*/
|
||||
contract ProposalManager is ProposalManagerInterface, Controlled {
|
||||
|
||||
function ProposalManager(MiniMeTokenInterface _SNT, TrustNetworkInterface _trustNet) public {
|
||||
|
||||
function ProposalManager(
|
||||
MiniMeTokenInterface _SNT,
|
||||
TrustNetworkInterface _trustNet,
|
||||
FeeCollector _feeCollector
|
||||
)
|
||||
public
|
||||
{
|
||||
trustNet = _trustNet;
|
||||
token = _SNT;
|
||||
feeCollector = _feeCollector;
|
||||
}
|
||||
|
||||
function addProposal(bytes32 _topic, bytes32 _txHash, uint _stake) public returns (uint) {
|
||||
require(_stake > 1000);
|
||||
require(token.transferFrom(msg.sender, address(this), _stake));
|
||||
uint pos = proposals.length++;
|
||||
Proposal storage p = proposals[pos];
|
||||
function addProposal(
|
||||
bytes32 _topic,
|
||||
bytes32 _txHash,
|
||||
uint _visibilityFee
|
||||
)
|
||||
public
|
||||
returns (uint proposalId)
|
||||
{
|
||||
require(_visibilityFee > minVisibilityFee);
|
||||
require(
|
||||
token.transferFrom(
|
||||
msg.sender,
|
||||
address(this),
|
||||
_visibilityFee
|
||||
)
|
||||
);
|
||||
token.approve(feeCollector, _visibilityFee);
|
||||
feeCollector.collectFor(msg.sender, _visibilityFee);
|
||||
proposalId = proposals.length++;
|
||||
Proposal storage p = proposals[proposalId];
|
||||
|
||||
p.topic = _topic;
|
||||
p.txHash = _txHash;
|
||||
p.stake = _stake;
|
||||
p.staker = msg.sender;
|
||||
p.visibilityFee = _visibilityFee;
|
||||
|
||||
p.blockStart = block.number + 1000; //will be replaced by configurations
|
||||
p.voteBlockEnd = p.blockStart + 10000; //dummy value
|
||||
p.vetoBlockEnd = p.voteBlockEnd + 5000; //dummy value
|
||||
|
||||
return pos;
|
||||
emit ProposalSet(_topic, proposalId, _txHash, _visibilityFee);
|
||||
}
|
||||
|
||||
function getProposal(uint id) public constant returns (bytes32 topic, bytes32 txHash, bool approved, bool executed) {
|
||||
Proposal memory p = proposals[id];
|
||||
return (p.topic, p.txHash, p.approved, p.executed);
|
||||
function increaseProposalVisibility(
|
||||
uint _proposalId,
|
||||
uint256 _visibilityFee
|
||||
)
|
||||
external
|
||||
{
|
||||
require(_visibilityFee > minVisibilityFee);
|
||||
require(
|
||||
token.transferFrom(
|
||||
msg.sender,
|
||||
address(this),
|
||||
_visibilityFee
|
||||
)
|
||||
);
|
||||
token.approve(feeCollector, _visibilityFee);
|
||||
feeCollector.collectFor(msg.sender, _visibilityFee);
|
||||
proposals[_proposalId].visibilityFee += _visibilityFee;
|
||||
Proposal memory p = proposals[_proposalId];
|
||||
emit ProposalSet(p.topic, _proposalId, p.txHash, p.visibilityFee);
|
||||
}
|
||||
|
||||
function getProposal(uint _proposalId)
|
||||
public
|
||||
constant
|
||||
returns (
|
||||
bytes32 topic,
|
||||
bytes32 txHash,
|
||||
bool approved
|
||||
)
|
||||
{
|
||||
Proposal memory p = proposals[_proposalId];
|
||||
return (p.topic, p.txHash, p.result == Vote.Approve);
|
||||
}
|
||||
|
||||
function getProposalTxHash(uint id) public constant returns(bytes32) {
|
||||
return proposals[id].txHash;
|
||||
function getProposalTxHash(uint _proposalId)
|
||||
public
|
||||
constant
|
||||
returns(bytes32)
|
||||
{
|
||||
return proposals[_proposalId].txHash;
|
||||
}
|
||||
|
||||
function vote(uint _proposal, Vote _vote) public {
|
||||
Proposal storage proposal = proposals[_proposal];
|
||||
function voteProposal(uint _proposalId, Vote _vote)
|
||||
public
|
||||
{
|
||||
Proposal storage proposal = proposals[_proposalId];
|
||||
require(block.number >= proposal.blockStart);
|
||||
if (_vote == Vote.Veto) {
|
||||
require(block.number <= proposal.vetoBlockEnd);
|
||||
@ -58,8 +113,10 @@ contract ProposalManager is ProposalManagerInterface, Controlled {
|
||||
|
||||
}
|
||||
|
||||
function tabulateVote(uint _proposal, address _delegator) public {
|
||||
Proposal storage proposal = proposals[_proposal];
|
||||
function tabulateVote(uint _proposalId, address _delegator)
|
||||
public
|
||||
{
|
||||
Proposal storage proposal = proposals[_proposalId];
|
||||
require(block.number > proposal.voteBlockEnd);
|
||||
require(!proposal.tabulated[_delegator].vote);
|
||||
proposal.tabulated[_delegator].vote = true;
|
||||
@ -74,8 +131,10 @@ contract ProposalManager is ProposalManagerInterface, Controlled {
|
||||
}
|
||||
}
|
||||
|
||||
function tabulateVeto(uint _proposal, address _delegator) public {
|
||||
Proposal storage proposal = proposals[_proposal];
|
||||
function tabulateVeto(uint _proposalId, address _delegator)
|
||||
public
|
||||
{
|
||||
Proposal storage proposal = proposals[_proposalId];
|
||||
require(block.number > proposal.vetoBlockEnd);
|
||||
require(!proposal.tabulated[_delegator].veto);
|
||||
proposal.tabulated[_delegator].veto = true;
|
||||
@ -91,26 +150,25 @@ contract ProposalManager is ProposalManagerInterface, Controlled {
|
||||
|
||||
}
|
||||
|
||||
function approve(uint _proposal) public {
|
||||
Proposal storage proposal = proposals[_proposal];
|
||||
function finalResult(uint _proposalId)
|
||||
public
|
||||
{
|
||||
Proposal storage proposal = proposals[_proposalId];
|
||||
require(proposal.vetoBlockEnd + tabulationBlockDelay > block.number);
|
||||
require(!proposal.approved);
|
||||
require(proposal.result == Vote.Null);
|
||||
uint256 totalTokens = token.totalSupplyAt(proposal.vetoBlockEnd);
|
||||
uint256 approvals = proposal.results[uint8(Vote.Approve)];
|
||||
uint256 veto = proposal.results[uint8(Vote.Veto)];
|
||||
uint256 vetos = proposal.results[uint8(Vote.Veto)];
|
||||
uint256 approvalQuorum = (totalTokens / 2);
|
||||
uint256 vetoQuorum = (totalTokens / 3);
|
||||
require(veto < vetoQuorum);
|
||||
require(approvals >= approvalQuorum);
|
||||
proposal.approved = true;
|
||||
require(token.transferFrom(address(this), proposal.staker, proposal.stake));
|
||||
if (vetos >= vetoQuorum) {
|
||||
proposal.result = Vote.Veto;
|
||||
} else if(approvals >= approvalQuorum) {
|
||||
proposal.result = Vote.Approve;
|
||||
} else {
|
||||
proposal.result = Vote.Reject;
|
||||
}
|
||||
emit ProposalResult(_proposalId, proposal.result);
|
||||
}
|
||||
|
||||
function setExecuted(uint _id, bytes32 _txHash) public onlyController returns(bool){
|
||||
Proposal memory p = proposals[_id];
|
||||
require(p.txHash == _txHash);
|
||||
require(p.approved);
|
||||
require(!p.executed);
|
||||
proposals[_id].executed = true;
|
||||
}
|
||||
}
|
@ -1,28 +1,20 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/MiniMeTokenInterface.sol";
|
||||
import "./TrustNetworkInterface.sol";
|
||||
import "./DelegationProxyInterface.sol";
|
||||
import "../token/MiniMeTokenInterface.sol";
|
||||
|
||||
import "./FeeCollector.sol";
|
||||
/**
|
||||
* @title ProposalManager
|
||||
* @title ProposalManagerInterface
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||
* Store the proposals, votes and results for other smartcontracts
|
||||
*/
|
||||
contract ProposalManagerInterface {
|
||||
|
||||
TrustNetworkInterface public trustNet;
|
||||
MiniMeTokenInterface public token;
|
||||
uint256 public tabulationBlockDelay;
|
||||
|
||||
Proposal[] public proposals;
|
||||
|
||||
struct Proposal {
|
||||
bytes32 topic;
|
||||
bytes32 txHash;
|
||||
|
||||
uint stake;
|
||||
address staker;
|
||||
uint visibilityFee;
|
||||
|
||||
uint blockStart;
|
||||
uint voteBlockEnd;
|
||||
@ -32,8 +24,7 @@ contract ProposalManagerInterface {
|
||||
mapping(address => Tabulations) tabulated;
|
||||
mapping(uint8 => uint256) results;
|
||||
|
||||
bool approved;
|
||||
bool executed;
|
||||
Vote result;
|
||||
}
|
||||
|
||||
struct Tabulations {
|
||||
@ -47,13 +38,21 @@ contract ProposalManagerInterface {
|
||||
Approve,
|
||||
Veto
|
||||
}
|
||||
|
||||
TrustNetworkInterface public trustNet;
|
||||
MiniMeTokenInterface public token;
|
||||
FeeCollector public feeCollector;
|
||||
uint256 public tabulationBlockDelay;
|
||||
uint256 public minVisibilityFee = 1000;
|
||||
Proposal[] public proposals;
|
||||
|
||||
event ProposalSet(bytes32 indexed topic, uint256 _proposalId, bytes32 _txHash, uint256 _visibility);
|
||||
event ProposalResult(uint256 _proposalId, Vote finalResult);
|
||||
|
||||
function addProposal(bytes32 _topic, bytes32 _txHash, uint _stake) public returns (uint);
|
||||
function getProposal(uint _id) public constant returns (bytes32 topic, bytes32 txHash, bool approved, bool executed);
|
||||
function getProposalTxHash(uint _id) public constant returns(bytes32);
|
||||
function vote(uint _proposal, Vote _vote) public;
|
||||
function addProposal(bytes32 _topic, bytes32 _txHash, uint _visibilityFee) public returns (uint);
|
||||
function getProposal(uint _id) public constant returns (bytes32 topic, bytes32 txHash, bool approved);
|
||||
function voteProposal(uint _proposal, Vote _vote) public;
|
||||
function tabulateVote(uint _proposal, address _delegator) public;
|
||||
function tabulateVeto(uint _proposal, address _delegator) public;
|
||||
function approve(uint _proposal) public;
|
||||
function setExecuted(uint _id, bytes32 _txHash) public returns(bool);
|
||||
function finalResult(uint _proposalId) public;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user