diff --git a/contracts/democracy/Democracy.sol b/contracts/democracy/Democracy.sol new file mode 100644 index 0000000..ebf9f42 --- /dev/null +++ b/contracts/democracy/Democracy.sol @@ -0,0 +1,82 @@ +pragma solidity ^0.4.21; +import "./DemocracyInterface.sol"; +import "./ProposalManager.sol"; + +contract Democracy is DemocracyInterface { + + mapping (bytes32 => Allowance) topicAllowance; + + 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 allowTopicSpecific(bytes32 _topic, address _destination, bytes4 _allowedCall, bool allowance) + external + { + require(msg.sender == address(this)); + topicAllowance[_topic].calls[keccak256(_destination, _allowedCall)] = allowance; + } + + function allowTopicAnyCall(bytes32 _topic, address _destination, bool allowance) + external + { + require(msg.sender == address(this)); + topicAllowance[_topic].anyCall[_destination] = allowance; + } + + function executeProposal( + uint256 _proposalId, + address _destination, + uint _value, + bytes _data + ) + external + returns (bool success) + { + bytes32 topic; + bytes32 txHash; + bool approved; + bool executed; + (topic, txHash, approved, executed) = proposalManager.getProposal(_proposalId); + require(approved); + require(!executed); + require( + txHash == keccak256( + _destination, + _value, + _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 + bytes memory data = _data; + bytes4 calling; + assembly { + calling := mload(add(data, 4)) + } + delete data; + 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); + } + +} \ No newline at end of file diff --git a/contracts/democracy/DemocracyInterface.sol b/contracts/democracy/DemocracyInterface.sol new file mode 100644 index 0000000..070f3d6 --- /dev/null +++ b/contracts/democracy/DemocracyInterface.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.4.17; + +import "./DemocracyStorage.sol"; + +/** + * @title DemocracyInterface + * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) + */ +contract DemocracyInterface is DemocracyStorage { + + function executeProposal( + uint256 _proposalId, + address _destination, + uint _value, + bytes _data + ) + external + returns(bool success); + + +} \ No newline at end of file diff --git a/contracts/status/ConstitutionStorage.sol b/contracts/democracy/DemocracyStorage.sol similarity index 67% rename from contracts/status/ConstitutionStorage.sol rename to contracts/democracy/DemocracyStorage.sol index cd6e73c..1d10f80 100644 --- a/contracts/status/ConstitutionStorage.sol +++ b/contracts/democracy/DemocracyStorage.sol @@ -1,20 +1,21 @@ pragma solidity ^0.4.17; -import "../deploy/BasicSystemStorage.sol"; +import "../deploy/InstanceStorage.sol"; import "../token/MiniMeTokenInterface.sol"; -import "../democracy/TrustNetworkInterface.sol"; +import "./TrustNetworkInterface.sol"; +import "./ProposalManagerInterface.sol"; /** - * @title InstanceStorage + * @title DemocracyStorage * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) * @dev Defines kernel vars that Kernel contract share with Instance. * Important to avoid overwriting wrong storage pointers is that * InstanceStorage should be always the first contract at heritance. */ -contract ConstitutionStorage is BasicSystemStorage { +contract DemocracyStorage is InstanceStorage { // protected zone start (InstanceStorage vars) MiniMeTokenInterface public token; TrustNetworkInterface public trustNet; - address proposalManager; + ProposalManagerInterface public proposalManager; // protected zone end } \ No newline at end of file diff --git a/contracts/democracy/ProposalManager.sol b/contracts/democracy/ProposalManager.sol index f692a09..5d64584 100644 --- a/contracts/democracy/ProposalManager.sol +++ b/contracts/democracy/ProposalManager.sol @@ -36,9 +36,9 @@ contract ProposalManager is ProposalManagerInterface, Controlled { return pos; } - function getProposal(uint id) public constant returns (bytes32 topic, bytes32 txHash, uint stake, address staker, bool approved, bool executed) { + 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.stake, p.staker, p.approved, p.executed); + return (p.topic, p.txHash, p.approved, p.executed); } function getProposalTxHash(uint id) public constant returns(bytes32) { @@ -106,10 +106,11 @@ contract ProposalManager is ProposalManagerInterface, Controlled { require(token.transferFrom(address(this), proposal.staker, proposal.stake)); } - function setExecuted(uint id) public onlyController { - Proposal memory p = proposals[id]; + 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; + proposals[_id].executed = true; } } \ No newline at end of file diff --git a/contracts/democracy/ProposalManagerInterface.sol b/contracts/democracy/ProposalManagerInterface.sol index 7e849f5..f328ace 100644 --- a/contracts/democracy/ProposalManagerInterface.sol +++ b/contracts/democracy/ProposalManagerInterface.sol @@ -49,11 +49,11 @@ contract ProposalManagerInterface { } function addProposal(bytes32 _topic, bytes32 _txHash, uint _stake) public returns (uint); - function getProposal(uint id) public constant returns (bytes32 topic, bytes32 txHash, uint stake, address staker, bool approved, bool executed); - function getProposalTxHash(uint id) public constant returns(bytes32); + 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 tabulateVote(uint _proposal, address _delegator) public; function tabulateVeto(uint _proposal, address _delegator) public; function approve(uint _proposal) public; - function setExecuted(uint id) public; + function setExecuted(uint _id, bytes32 _txHash) public returns(bool); } \ No newline at end of file diff --git a/contracts/status/ConstitutionModule.sol b/contracts/status/ConstitutionModule.sol deleted file mode 100644 index b460a2f..0000000 --- a/contracts/status/ConstitutionModule.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma solidity ^0.4.17; - -import "./ConstitutionStorage.sol"; - -contract ConstitutionModule is ConstitutionStorage { - - function install() external; - -} \ No newline at end of file diff --git a/contracts/status/StatusConstitution.sol b/contracts/status/StatusConstitution.sol index 9fdce5e..5a77ec2 100644 --- a/contracts/status/StatusConstitution.sol +++ b/contracts/status/StatusConstitution.sol @@ -1,9 +1,6 @@ pragma solidity ^0.4.17; -import "./ConstitutionStorage.sol"; -import "../token/MiniMeToken.sol"; -import "../democracy/TrustNetworkInterface.sol"; -import "../democracy/ProposalManager.sol"; +import "../democracy/Democracy.sol"; import "../registry/TokenRegistry.sol"; @@ -12,44 +9,6 @@ import "../registry/TokenRegistry.sol"; * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) * @dev */ -contract StatusConstitution is ConstitutionStorage { - - function StatusConstitution(address _statusNetworkToken, address _statusNetworkTrust, address _stakeBank) public { - token = MiniMeTokenInterface(_statusNetworkToken); - trustNet = TrustNetworkInterface(_statusNetworkTrust); - proposalManager = new ProposalManager(token, trustNet); - - } - - function installModule(address _module, bytes _data) external { - require(msg.sender == address(this)); - require(_module.delegatecall(_data)); - } - - function executeProposal( - bytes32 _topic, - uint256 _proposalId, - address _destination, - uint _value, - bytes _data - ) - external - returns (bool success) - { - require(msg.sender == address(proposalManager)); - if (_destination == address(this)) { - require(_topic == 0); - } else { - bytes memory data = _data; - bytes4 calling; - assembly { - calling := mload(add(data, 4)) - } - delete data; - require(_topic == keccak256(_destination) || _topic == keccak256(_destination, calling)); - } - - return _destination.call.value(_value)(_data); - } +contract StatusConstitution is Democracy { } \ No newline at end of file diff --git a/contracts/status/StatusRecoverer.sol b/contracts/status/StatusRecoverer.sol deleted file mode 100644 index f521b96..0000000 --- a/contracts/status/StatusRecoverer.sol +++ /dev/null @@ -1,43 +0,0 @@ -pragma solidity ^0.4.17; - -import "../deploy/AbstractRecoverer.sol"; -import "../ens/ENS.sol"; - -/** - * @title GitPivotRecoverer - * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) - * @dev Common Recoverer for GitPivot. - * address resolved from ens recover.gitpivot.eth can set new system. - */ -contract StatusRecoverer is BasicSystemStorage { - - /** - * @dev will be callable in emergency state of RecorverableSystem - */ - function recoverSystem(address newSystem) public { - require(msg.sender == consensusContract()); - system = newSystem; - } - - /** - * @dev resolves recoverer.statusnet.eth -> this method trust that ENS is safe. - */ - function consensusContract() public constant returns(address) { - bytes32 node = 0x0; //recover.statusnet.eth //bytes32 node = keccak256("recoverer", keccak256("gitpivot", keccak256("eth"))); - address ensAddress = 0x314159265dD8dbb310642f98f50C066173C1259b; - if (codeSize(ensAddress) == 0) { - ensAddress = 0x112234455C3a32FD11230C42E7Bccd4A84e02010; - } - return ENS(ensAddress).resolver(node).addr(node); - } - - function codeSize(address _addr) internal constant returns(uint size) { - if (_addr == 0) { - return 0; - } - assembly { - size := extcodesize(_addr) - } - } - -} \ No newline at end of file diff --git a/contracts/status/modules/TokenRegistryModule.sol b/contracts/status/modules/TokenRegistryModule.sol deleted file mode 100644 index f64b91b..0000000 --- a/contracts/status/modules/TokenRegistryModule.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.4.17; - -import "../ConstitutionModule.sol"; -import "../../registry/TokenRegistry.sol"; - -contract TokenRegistryModule is ConstitutionModule { - - function install() external { - TokenRegistry tokenReg = new TokenRegistry(); - bytes32 rootTokenReg = keccak256(address(tokenReg)); - trustNet.addTopic(rootTokenReg, 0x0); - trustNet.addTopic(keccak256(address(tokenReg), bytes4(keccak256("addToken(address,string,string,uint8,bytes,bytes)"))), rootTokenReg); - trustNet.addTopic(keccak256(address(tokenReg), bytes4(keccak256("removeToken(address,uint256)"))), rootTokenReg); - } - - -} \ No newline at end of file