2019-02-14 10:41:11 -02:00

108 lines
3.2 KiB
Solidity

pragma solidity >=0.5.0 <0.6.0;
import "../token/MiniMeToken.sol";
import "./DelegationFactory.sol";
import "./TrustNetwork.sol";
import "./ProposalCuration.sol";
import "./ProposalManager.sol";
contract Democracy {
MiniMeToken public token;
TrustNetwork public trustNet;
ProposalManager public proposalManager;
mapping (bytes32 => mapping (address => mapping (bytes32 => bool))) allowance;
mapping (uint256 => bool) executedProposals;
modifier selfOnly {
require(msg.sender == address(this), "Unauthorized");
_;
}
constructor(MiniMeToken _token, DelegationFactory _DelegationFactory) public {
token = _token;
trustNet = new TrustNetwork(_DelegationFactory);
proposalManager = new ProposalCuration(_token, trustNet).proposalManager();
}
function executeProposal(
uint256 _proposalId,
address _destination,
bytes calldata _data
)
external
returns (bool success, bytes memory r)
{
require(!executedProposals[_proposalId]);
executedProposals[_proposalId] = true;
bytes32 topic;
bytes32 txHash;
bool approved;
(topic, txHash, approved) = proposalManager.getProposal(_proposalId);
require(approved);
require(
txHash == keccak256(
abi.encodePacked(
_destination,
_data
)
)
);
if(topic != bytes32(0)) { //if not root topic
bytes memory data = _data;
bytes4 sig;
assembly {
sig := mload(add(data, 4))
}
delete sig;
require(isTopicAllowed(topic, _destination, sig)); //require call allowance
}
//execute the call
(success, r) = _destination.call(_data);
}
function setTopicAllowance(bytes32 _topic, address _destination, bytes4 _callSig, bool _allowed) external selfOnly {
require(_topic != bytes32(0), "Cannot change root topic");
allowance[_topic][_destination][_callSig] = _allowed;
}
function setProposalManager(ProposalManager _proposalManager) external selfOnly {
require(address(_proposalManager) != address(0), "Bad call");
proposalManager = _proposalManager;
}
function setTrustNetwork(TrustNetwork _trustNet) external selfOnly {
require(address(_trustNet) != address(0), "Bad call");
trustNet = _trustNet;
}
function setToken(MiniMeToken _token) external selfOnly {
require(address(_token) != address(0), "Bad call");
token = _token;
}
function isTopicAllowed(
bytes32 topic,
address destinAddr,
bytes4 calledSig
)
public
view
returns (bool)
{
return allowance[topic][destinAddr][calledSig]
|| allowance[topic][destinAddr][bytes4(0)]
|| allowance[topic][address(0)][calledSig]
|| allowance[topic][address(0)][bytes4(0)]
|| allowance[topic][destinAddr][calledSig]
|| allowance[topic][destinAddr][bytes4(0)]
|| allowance[topic][address(0)][calledSig]
|| allowance[topic][address(0)][bytes4(0)];
}
}