From 729f9d0e595ae0dd119289237de105d53c217e02 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt Date: Thu, 14 Feb 2019 10:41:11 -0200 Subject: [PATCH] update to latest solc, update to new instance model, democracy acl --- config/contracts.js | 11 ++ contracts/democracy/Delegation.sol | 128 ++---------------- contracts/democracy/DelegationAbstract.sol | 126 +++++++++++++++++ ...gationInterface.sol => DelegationBase.sol} | 57 +++++--- contracts/democracy/DelegationFactory.sol | 25 ++-- contracts/democracy/DelegationInit.sol | 32 +++++ contracts/democracy/DelegationKernel.sol | 30 ---- contracts/democracy/DelegationView.sol | 26 ++-- contracts/democracy/Democracy.sol | 98 ++++++++------ contracts/democracy/ProposalCuration.sol | 12 +- contracts/democracy/ProposalManager.sol | 12 +- contracts/democracy/TrustNetwork.sol | 32 ++--- contracts/democracy/TrustNetworkInterface.sol | 8 +- contracts/status/TestStatusNetwork.sol | 1 + contracts/token/MiniMeTokenInterface.sol | 108 --------------- contracts/token/StandardToken.sol | 6 +- test/{delegation_spec.js => delegation.js} | 41 +++--- 17 files changed, 363 insertions(+), 390 deletions(-) create mode 100644 contracts/democracy/DelegationAbstract.sol rename contracts/democracy/{DelegationInterface.sol => DelegationBase.sol} (63%) create mode 100644 contracts/democracy/DelegationInit.sol delete mode 100644 contracts/democracy/DelegationKernel.sol delete mode 100644 contracts/token/MiniMeTokenInterface.sol rename test/{delegation_spec.js => delegation.js} (68%) diff --git a/config/contracts.js b/config/contracts.js index 3840741..69e7006 100644 --- a/config/contracts.js +++ b/config/contracts.js @@ -31,6 +31,17 @@ module.exports = { "await MiniMeToken.methods.changeController(StatusRoot.address).send()", "await StatusRoot.methods.setOpen(true).send()", ] + }, + "DelegationView": { + "args": [ "0x0" ] + }, + "DelegationInit": { + }, + "DelegationFactory": { + "args": ["$DelegationView", "$DelegationInit", "0x0"] + }, + "Democracy": { + "args": ["$MiniMeToken", "$DelegationFactory"] } } }, diff --git a/contracts/democracy/Delegation.sol b/contracts/democracy/Delegation.sol index 0423c25..7751e06 100644 --- a/contracts/democracy/Delegation.sol +++ b/contracts/democracy/Delegation.sol @@ -1,28 +1,8 @@ pragma solidity >=0.5.0 <0.6.0; -/** - * @title Delegation - * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH). - */ -contract Delegation { - event Delegate(address who, address to); - //default delegation proxy, being used when user didn't set any delegation at this level. - address public parentDelegation; - - //snapshots of changes, allow delegation changes be done at any time without compromising vote results. - mapping (address => DelegateSet[]) public delegations; - - struct DelegateSet { - uint128 fromBlock; //when this was updated - address to; //who recieved this delegaton - } +interface Delegation { - /** - * @notice Calls Constructor - */ - constructor(address _parentDelegation) public { - parentDelegation = _parentDelegation; - } + event Delegate(address who, address to); /** * @notice Changes the delegation of `msg.sender` to `_to`. if _to 0x00: delegate to self. @@ -30,36 +10,28 @@ contract Delegation { * If once defined and want to delegate to parent proxy, set `_to` as parent address. * @param _to To what address the caller address will delegate to. */ - function delegate(address _to) external { - _updateDelegate(msg.sender, _to); - } + function delegate(address _to) external; /** * @notice Reads `_who` configured delegation in this level, * or from parent level if `_who` never defined/defined to parent address. * @param _who What address to lookup. * @return The address `_who` choosen delegate to. - */ + */ function delegatedTo(address _who) - public + external view - returns (address) - { - return delegatedToAt(_who, block.number); - } - + returns (address directDelegate); + /** * @notice Reads the final delegate of `_who` at block number `_block`. * @param _who Address to lookup. * @return Final delegate address. */ function delegationOf(address _who) - public + external view - returns(address) - { - return delegationOfAt(_who, block.number); - } + returns(address finalDelegate); /** * @notice Reads `_who` configured delegation at block number `_block` in this level, @@ -72,28 +44,10 @@ contract Delegation { address _who, uint _block ) - public + external view - returns (address directDelegate) - { - DelegateSet[] storage checkpoints = delegations[_who]; - - //In case there is no registry - if (checkpoints.length == 0) { - if (parentDelegation != 0x0) { - return Delegation(parentDelegation).delegatedToAt(_who, _block); - } else { - return 0x0; - } - } - DelegateSet memory d = _getMemoryAt(checkpoints, _block); - // Case user set delegate to parentDelegation address - if (d.to == parentDelegation && d.to != 0x0) { - return Delegation(parentDelegation).delegatedToAt(_who, _block); - } - return d.to; - } - + returns (address directDelegate); + /** * @notice Reads the final delegate of `_who` at block number `_block`. * @param _who Address to lookup. @@ -104,62 +58,8 @@ contract Delegation { address _who, uint _block ) - public + external view - returns(address finalDelegate) - { - finalDelegate = delegatedToAt(_who, _block); - if (finalDelegate != 0x0) { //_who is delegating? - return delegationOfAt(finalDelegate, _block); //load the delegation of _who delegation - } else { - return _who; //reached the endpoint of delegation - } - - } + returns(address finalDelegate); - /** - * @dev Changes the delegation of `_from` to `_to`. if _to 0x00: delegate to self. - * In case of having a parent proxy, if never defined, fall back to parent proxy. - * If once defined and want to delegate to parent proxy, set `_to` as parent address. - * @param _from Address delegating. - * @param _to Address delegated. - */ - function _updateDelegate(address _from, address _to) internal { - emit Delegate(_from, _to); - DelegateSet memory _newFrom; //allocate memory - DelegateSet[] storage fromHistory = delegations[_from]; - - //Add the new delegation - _newFrom.fromBlock = uint128(block.number); - _newFrom.to = _to; //delegate address - - fromHistory.push(_newFrom); //register `from` delegation update; - } - - /** - * @dev `_getDelegationAt` retrieves the delegation at a given block number. - * @param checkpoints The memory being queried. - * @param _block The block number to retrieve the value at. - * @return The delegation being queried. - */ - function _getMemoryAt(DelegateSet[] storage checkpoints, uint _block) internal view returns (DelegateSet d) { - // Case last checkpoint is the one; - if (_block >= checkpoints[checkpoints.length-1].fromBlock) { - d = checkpoints[checkpoints.length-1]; - } else { - // Lookup in array; - uint min = 0; - uint max = checkpoints.length-1; - while (max > min) { - uint mid = (max + min + 1) / 2; - if (checkpoints[mid].fromBlock <= _block) { - min = mid; - } else { - max = mid-1; - } - } - d = checkpoints[min]; - } - } - } \ No newline at end of file diff --git a/contracts/democracy/DelegationAbstract.sol b/contracts/democracy/DelegationAbstract.sol new file mode 100644 index 0000000..f55a9bb --- /dev/null +++ b/contracts/democracy/DelegationAbstract.sol @@ -0,0 +1,126 @@ +pragma solidity >=0.5.0 <0.6.0; + +import "../deploy/InstanceAbstract.sol"; +import "./Delegation.sol"; + +/** + * @title DelegationAbstract + * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH). + */ +contract DelegationAbstract is InstanceAbstract, Delegation { + struct DelegateSet { + uint128 fromBlock; //when this was updated + address to; //who recieved this delegaton + } + //default delegation proxy, being used when user didn't set any delegation at this level. + address public parentDelegation; + + //snapshots of changes, allow delegation changes be done at any time without compromising vote results. + mapping (address => DelegateSet[]) public delegations; + + + constructor() internal { + + } + + /** + * @dev Changes the delegation of `_from` to `_to`. if _to 0x00: delegate to self. + * In case of having a parent proxy, if never defined, fall back to parent proxy. + * If once defined and want to delegate to parent proxy, set `_to` as parent address. + * @param _from Address delegating. + * @param _to Address delegated. + */ + function updateDelegate(address _from, address _to) internal { + emit Delegate(_from, _to); + DelegateSet memory _newFrom; //allocate memory + DelegateSet[] storage fromHistory = delegations[_from]; + + //Add the new delegation + _newFrom.fromBlock = uint128(block.number); + _newFrom.to = _to; //delegate address + + fromHistory.push(_newFrom); //register `from` delegation update; + } + + /** + * @dev `_getDelegationAt` retrieves the delegation at a given block number. + * @param checkpoints The memory being queried. + * @param _block The block number to retrieve the value at. + * @return The delegation being queried. + */ + function getMemoryAt(DelegateSet[] storage checkpoints, uint _block) internal view returns (DelegateSet memory d) { + // Case last checkpoint is the one; + if (_block >= checkpoints[checkpoints.length-1].fromBlock) { + d = checkpoints[checkpoints.length-1]; + } else { + // Lookup in array; + uint min = 0; + uint max = checkpoints.length-1; + while (max > min) { + uint mid = (max + min + 1) / 2; + if (checkpoints[mid].fromBlock <= _block) { + min = mid; + } else { + max = mid-1; + } + } + d = checkpoints[min]; + } + } + + /** + * @notice Reads `_who` configured delegation at block number `_block` in this level, + * or from parent level if `_who` never defined/defined to parent address. + * @param _who What address to lookup. + * @param _block Block number of what height in history. + * @return The address `_who` choosen delegate to. + */ + function findDelegatedToAt( + address _who, + uint _block + ) + internal + view + returns (address directDelegate) + { + DelegateSet[] storage checkpoints = delegations[_who]; + + //In case there is no registry + if (checkpoints.length == 0) { + if (parentDelegation != address(0)) { + return Delegation(parentDelegation).delegatedToAt(_who, _block); + } else { + return address(0); + } + } + DelegateSet memory d = getMemoryAt(checkpoints, _block); + // Case user set delegate to parentDelegation address + if (d.to == parentDelegation && d.to != address(0x0)) { + return Delegation(parentDelegation).delegatedToAt(_who, _block); + } + return d.to; + } + + /** + * @notice Reads the final delegate of `_who` at block number `_block`. + * @param _who Address to lookup. + * @param _block From what block. + * @return Final delegate address. + */ + function findDelegationOfAt( + address _who, + uint _block + ) + internal + view + returns(address finalDelegate) + { + finalDelegate = findDelegatedToAt(_who, _block); + if (finalDelegate != address(0)) { //_who is delegating? + return findDelegationOfAt(finalDelegate, _block); //load the delegation of _who delegation + } else { + return _who; //reached the endpoint of delegation + } + + } +} \ No newline at end of file diff --git a/contracts/democracy/DelegationInterface.sol b/contracts/democracy/DelegationBase.sol similarity index 63% rename from contracts/democracy/DelegationInterface.sol rename to contracts/democracy/DelegationBase.sol index aac924f..37a195e 100644 --- a/contracts/democracy/DelegationInterface.sol +++ b/contracts/democracy/DelegationBase.sol @@ -1,11 +1,20 @@ pragma solidity >=0.5.0 <0.6.0; -import "../token/MiniMeTokenInterface.sol"; +import "./DelegationAbstract.sol"; - -contract DelegationInterface { +/** + * @title DelegationBase + * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) + * @dev Creates a delegation proxy killable model for cheap redeploy and upgradability. + */ +contract DelegationBase is DelegationAbstract { - event Delegate(address who, address to); + /** + * @notice Calls Constructor + */ + constructor(address _parentDelegation) public { + parentDelegation = _parentDelegation; + } /** * @notice Changes the delegation of `msg.sender` to `_to`. if _to 0x00: delegate to self. @@ -13,28 +22,36 @@ contract DelegationInterface { * If once defined and want to delegate to parent proxy, set `_to` as parent address. * @param _to To what address the caller address will delegate to. */ - function delegate(address _to) external; + function delegate(address _to) external { + updateDelegate(msg.sender, _to); + } /** * @notice Reads `_who` configured delegation in this level, * or from parent level if `_who` never defined/defined to parent address. * @param _who What address to lookup. * @return The address `_who` choosen delegate to. - */ + */ function delegatedTo(address _who) - public + external view - returns (address directDelegate); - + returns (address) + { + return findDelegatedToAt(_who, block.number); + } + /** * @notice Reads the final delegate of `_who` at block number `_block`. * @param _who Address to lookup. * @return Final delegate address. */ function delegationOf(address _who) - public + external view - returns(address finalDelegate); + returns(address) + { + return findDelegationOfAt(_who, block.number); + } /** * @notice Reads `_who` configured delegation at block number `_block` in this level, @@ -47,10 +64,13 @@ contract DelegationInterface { address _who, uint _block ) - public + external view - returns (address directDelegate); - + returns (address directDelegate) + { + return findDelegatedToAt(_who, _block); + } + /** * @notice Reads the final delegate of `_who` at block number `_block`. * @param _who Address to lookup. @@ -61,8 +81,11 @@ contract DelegationInterface { address _who, uint _block ) - public + external view - returns(address finalDelegate); - + returns(address finalDelegate) + { + return findDelegationOfAt(_who, _block); + } + } \ No newline at end of file diff --git a/contracts/democracy/DelegationFactory.sol b/contracts/democracy/DelegationFactory.sol index 77e1d66..98e0449 100644 --- a/contracts/democracy/DelegationFactory.sol +++ b/contracts/democracy/DelegationFactory.sol @@ -1,8 +1,6 @@ pragma solidity >=0.5.0 <0.6.0; -import "./DelegationInterface.sol"; -import "./DelegationKernel.sol"; -import "../deploy/Factory.sol"; +import "../deploy/InstanceFactory.sol"; import "../deploy/Instance.sol"; /** @@ -10,20 +8,21 @@ import "../deploy/Instance.sol"; * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) * @dev Upgradable delegation proxy factory */ -contract DelegationFactory is Factory { +contract DelegationFactory is InstanceFactory { - constructor() - Factory(new DelegationKernel()) - public + constructor(InstanceAbstract _base, InstanceAbstract _init, InstanceAbstract _emergency) + InstanceFactory(_base, _init, _emergency) + public { } - function createDelegation(address _parent) + function createDelegation( + address + ) external - returns (DelegationInterface) - { - DelegationKernel instance = DelegationKernel(address(new Instance(latestKernel))); - instance.initializeDelegation(_parent); - return DelegationInterface(address(instance)); + returns (InstanceAbstract instance) + { + instance = new Instance(base, prototypes[address(base)].init, msg.data); + emit InstanceCreated(instance); } } \ No newline at end of file diff --git a/contracts/democracy/DelegationInit.sol b/contracts/democracy/DelegationInit.sol new file mode 100644 index 0000000..d0e3b1a --- /dev/null +++ b/contracts/democracy/DelegationInit.sol @@ -0,0 +1,32 @@ +pragma solidity >=0.5.0 <0.6.0; + +import "./DelegationAbstract.sol"; + +/** + * @title DelegationInit + * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) + */ +contract DelegationInit is DelegationAbstract { + + /** + * @notice Constructor of the model - only knows about watchdog that can trigger upgrade + */ + constructor() public { + parentDelegation = address(-1); //avoids calling create delegation within the Init contract. + } + + /** + * @notice Creates a new Delegation with `_parentDelegation` as default delegation. + */ + function createDelegation(address _parentDelegation) external { + require(parentDelegation == address(0), "Bad call"); //avoids control of Init contract + parentDelegation = _parentDelegation; + } + + function delegate(address) external {} + function delegatedTo(address) external view returns (address) {} + function delegationOf(address) external view returns (address) {} + function delegatedToAt(address,uint) external view returns (address) {} + function delegationOfAt(address,uint) external view returns (address) {} + +} \ No newline at end of file diff --git a/contracts/democracy/DelegationKernel.sol b/contracts/democracy/DelegationKernel.sol deleted file mode 100644 index 5180c22..0000000 --- a/contracts/democracy/DelegationKernel.sol +++ /dev/null @@ -1,30 +0,0 @@ -pragma solidity >=0.5.0 <0.6.0; - -import "../deploy/InstanceStorage.sol"; -import "./DelegationView.sol"; - -/** - * @title DelegationKernel - * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) - * @dev Creates a delegation proxy killable model for cheap redeploy and upgradability. - */ -contract DelegationKernel is InstanceStorage, DelegationView { - bool private ready = false; //TODO: abstract initialized flag - - /** - * @notice Constructor of the model - only knows about watchdog that can trigger upgrade - */ - constructor() DelegationView(0x0) public { - ready = true; - } - - /** - * @notice Creates a new Delegation with `_parentDelegation` as default delegation. - */ - function initializeDelegation(address _parentDelegation) public { - require(!ready); - ready = true; - parentDelegation = _parentDelegation; - } - -} \ No newline at end of file diff --git a/contracts/democracy/DelegationView.sol b/contracts/democracy/DelegationView.sol index 4862672..54d00b2 100644 --- a/contracts/democracy/DelegationView.sol +++ b/contracts/democracy/DelegationView.sol @@ -1,14 +1,14 @@ pragma solidity >=0.5.0 <0.6.0; -import "./Delegation.sol"; +import "./DelegationBase.sol"; /** - * @title Delegation + * @title DelegationView * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) - * @dev Creates a delegation proxy layer for MiniMeTokenInterface. + * @dev Creates a delegation proxy layer for MiniMeToken. */ -contract DelegationView is Delegation { +contract DelegationView is DelegationBase { //storage of preprocessed view of FinalDelegate mapping(bytes32 => FinalDelegate) public delegationView; @@ -18,7 +18,7 @@ contract DelegationView is Delegation { bool found; } - constructor(address _parentDelegation) Delegation(_parentDelegation) public { + constructor(address _parentDelegation) DelegationBase(_parentDelegation) public { } @@ -28,20 +28,20 @@ contract DelegationView is Delegation { * @param _block From what block. * @return Final delegate address. */ - function delegationOfAt( + function findDelegationOfAt( address _who, uint _block ) - public + internal view returns(address finalDelegate) { - bytes32 searchIndex = keccak256(_who, _block); + bytes32 searchIndex = keccak256(abi.encodePacked(_who, _block)); FinalDelegate memory search = delegationView[searchIndex]; if (search.found) { return search.delegate; } else { - return super.delegationOfAt(_who, _block); + return super.findDelegationOfAt(_who, _block); } } @@ -61,14 +61,14 @@ contract DelegationView is Delegation { external returns (bool) { - bytes32 searchIndex = keccak256(_delegator,_block); + bytes32 searchIndex = keccak256(abi.encodePacked(_delegator,_block)); FinalDelegate memory search = delegationView[searchIndex]; require(!search.found); for (uint i = 0; i < loopLimit; i++) { if (search.delegate == address(0)) { search.delegate = _delegator; } - address delegateFrom = delegatedToAt(search.delegate, _block); + address delegateFrom = findDelegatedToAt(search.delegate, _block); if (delegateFrom == address(0)) { // search.delegate demonsted this address didnt delegated, search.found = true; // so its the final delegate @@ -100,11 +100,11 @@ contract DelegationView is Delegation { returns (address lastDelegate, bool found) { require(_block > block.number); //cannot renderize current state view ? - bytes32 searchIndex = keccak256(_delegator, _block); + bytes32 searchIndex = keccak256(abi.encodePacked(_delegator, _block)); FinalDelegate memory search = delegationView[searchIndex]; if (!search.found) { if (search.delegate == address(0)) { - lastDelegate = delegatedToAt(_delegator, _block); + lastDelegate = findDelegatedToAt(_delegator, _block); if (lastDelegate == address(0)) { //`_delegator` FinalDelegate is itself lastDelegate = _delegator; diff --git a/contracts/democracy/Democracy.sol b/contracts/democracy/Democracy.sol index c68216f..dbe2b23 100644 --- a/contracts/democracy/Democracy.sol +++ b/contracts/democracy/Democracy.sol @@ -1,6 +1,6 @@ pragma solidity >=0.5.0 <0.6.0; -import "../token/MiniMeTokenInterface.sol"; +import "../token/MiniMeToken.sol"; import "./DelegationFactory.sol"; import "./TrustNetwork.sol"; import "./ProposalCuration.sol"; @@ -9,46 +9,31 @@ import "./ProposalManager.sol"; contract Democracy { - MiniMeTokenInterface public token; + MiniMeToken public token; TrustNetwork public trustNet; ProposalManager public proposalManager; - mapping (bytes32 => Allowance) topicAllowance; + mapping (bytes32 => mapping (address => mapping (bytes32 => bool))) allowance; mapping (uint256 => bool) executedProposals; - struct Allowance { - mapping(address => bool) anyCall; - mapping(bytes32 => bool) calls; + modifier selfOnly { + require(msg.sender == address(this), "Unauthorized"); + _; } - constructor(MiniMeTokenInterface _token, DelegationFactory _DelegationFactory) public { + constructor(MiniMeToken _token, DelegationFactory _DelegationFactory) public { token = _token; trustNet = new TrustNetwork(_DelegationFactory); proposalManager = new ProposalCuration(_token, trustNet).proposalManager(); } - 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 + bytes calldata _data ) external - returns (bool success) + returns (bool success, bytes memory r) { require(!executedProposals[_proposalId]); executedProposals[_proposalId] = true; @@ -60,27 +45,64 @@ contract Democracy { require(approved); require( txHash == keccak256( - _destination, - _value, - _data + abi.encodePacked( + _destination, + _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 + 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 - return _destination.call.value(_value)(_data); + (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)]; + } } \ No newline at end of file diff --git a/contracts/democracy/ProposalCuration.sol b/contracts/democracy/ProposalCuration.sol index 26bc559..3e2dd17 100644 --- a/contracts/democracy/ProposalCuration.sol +++ b/contracts/democracy/ProposalCuration.sol @@ -1,7 +1,7 @@ pragma solidity >=0.5.0 <0.6.0; import "../common/Controlled.sol"; -import "../token/MiniMeTokenInterface.sol"; +import "../token/MiniMeToken.sol"; import "./ProposalManager.sol"; contract ProposalCuration is Controlled { @@ -15,7 +15,7 @@ contract ProposalCuration is Controlled { ProposalManager public proposalManager; uint256 public approvalTimeLimit; - MiniMeTokenInterface token; + MiniMeToken token; mapping (address => SubmitPrice) submitAllowances; @@ -34,7 +34,7 @@ contract ProposalCuration is Controlled { } constructor( - MiniMeTokenInterface _token, + MiniMeToken _token, TrustNetworkInterface _trustNet ) public @@ -47,8 +47,8 @@ contract ProposalCuration is Controlled { bytes32 _topic, address _to, uint256 _value, - bytes _data, - bytes _description + bytes calldata _data, + bytes calldata _description ) external returns (uint256 proposalId) @@ -56,7 +56,7 @@ contract ProposalCuration is Controlled { uint256 submitPrice = getSubmitPrice(msg.sender); require(token.allowance(msg.sender, address(this)) >= submitPrice); require(token.transferFrom(msg.sender, address(this), submitPrice)); - proposalId = proposalManager.addProposal(_topic,keccak256(_to,_value,_data)); + proposalId = proposalManager.addProposal(_topic,keccak256(abi.encodePacked(_to,_value,_data))); proposals[proposalId] = ProposalData( msg.sender, _to, diff --git a/contracts/democracy/ProposalManager.sol b/contracts/democracy/ProposalManager.sol index 44d63bc..5a69d7c 100644 --- a/contracts/democracy/ProposalManager.sol +++ b/contracts/democracy/ProposalManager.sol @@ -2,8 +2,8 @@ pragma solidity >=0.5.0 <0.6.0; import "../common/Controlled.sol"; import "../common/MessageSigned.sol"; -import "../token/MiniMeTokenInterface.sol"; -import "./DelegationInterface.sol"; +import "../token/MiniMeToken.sol"; +import "./Delegation.sol"; import "./TrustNetworkInterface.sol"; /** @@ -15,7 +15,7 @@ contract ProposalManager is Controlled, MessageSigned { event ProposalSet(bytes32 indexed topic, uint256 proposalId, bytes32 txHash); event ProposalResult(uint256 proposalId, uint8 finalResult); - MiniMeTokenInterface public token; + MiniMeToken public token; TrustNetworkInterface public trustNet; uint256 public tabulationBlockDelay; Proposal[] public proposals; @@ -43,7 +43,7 @@ contract ProposalManager is Controlled, MessageSigned { } constructor( - MiniMeTokenInterface _token, + MiniMeToken _token, TrustNetworkInterface _trustNet ) public @@ -91,8 +91,8 @@ contract ProposalManager is Controlled, MessageSigned { } - function tabulateVote(uint _proposalId, Vote _vote, uint256 _position, bytes32[] _proof, bytes _signature) - public + function tabulateVote(uint _proposalId, Vote _vote, uint256 _position, bytes32[] calldata _proof, bytes calldata _signature) + external { Proposal storage proposal = proposals[_proposalId]; require(block.number > proposal.voteBlockEnd, "Voting running"); diff --git a/contracts/democracy/TrustNetwork.sol b/contracts/democracy/TrustNetwork.sol index 00585a1..d801968 100644 --- a/contracts/democracy/TrustNetwork.sol +++ b/contracts/democracy/TrustNetwork.sol @@ -2,7 +2,7 @@ pragma solidity >=0.5.0 <0.6.0; import "../common/Controlled.sol"; import "./TrustNetworkInterface.sol"; -import "./DelegationInterface.sol"; +import "./Delegation.sol"; import "./DelegationFactory.sol"; @@ -17,30 +17,30 @@ contract TrustNetwork is TrustNetworkInterface, Controlled { DelegationFactory delegationFactory; struct Topic { - DelegationInterface voteDelegation; - DelegationInterface vetoDelegation; + Delegation voteDelegation; + Delegation vetoDelegation; } - constructor(address _delegationFactory) public { - delegationFactory = DelegationFactory(_delegationFactory); - topics[0x0] = newTopic(0x0, 0x0); + constructor(DelegationFactory _delegationFactory) public { + delegationFactory = _delegationFactory; + topics[bytes32(0)] = newTopic(address(0), address(0)); } function addTopic(bytes32 topicId, bytes32 parentTopic) public onlyController { Topic memory parent = topics[parentTopic]; address vote = address(parent.voteDelegation); address veto = address(parent.vetoDelegation); - require(vote != 0x0); - require(veto != 0x0); + require(vote != address(0)); + require(veto != address(0)); Topic storage topic = topics[topicId]; - require(address(topic.voteDelegation) == 0x0); - require(address(topic.vetoDelegation) == 0x0); + require(address(topic.voteDelegation) == address(0)); + require(address(topic.vetoDelegation) == address(0)); topics[topicId] = newTopic(vote, veto); } - function getTopic(bytes32 _topicId) public view returns (DelegationInterface vote, DelegationInterface veto) { + function getTopic(bytes32 _topicId) public view returns (Delegation vote, Delegation veto) { Topic memory topic = topics[_topicId]; vote = topic.voteDelegation; veto = topic.vetoDelegation; @@ -51,7 +51,7 @@ contract TrustNetwork is TrustNetworkInterface, Controlled { ) public view - returns (DelegationInterface voteDelegation) + returns (Delegation voteDelegation) { return topics[_topicId].voteDelegation; } @@ -61,16 +61,16 @@ contract TrustNetwork is TrustNetworkInterface, Controlled { ) public view - returns (DelegationInterface vetoDelegation) + returns (Delegation vetoDelegation) { return topics[_topicId].vetoDelegation; } - function newTopic(address _vote, address _veto) internal returns (Topic topic) { + function newTopic(address _vote, address _veto) internal returns (Topic memory topic) { topic = Topic ({ - voteDelegation: delegationFactory.createDelegation(_vote), - vetoDelegation: delegationFactory.createDelegation(_veto) + voteDelegation: Delegation(address(delegationFactory.createDelegation(_vote))), + vetoDelegation: Delegation(address(delegationFactory.createDelegation(_veto))) }); } diff --git a/contracts/democracy/TrustNetworkInterface.sol b/contracts/democracy/TrustNetworkInterface.sol index cc11a48..ad6bf07 100644 --- a/contracts/democracy/TrustNetworkInterface.sol +++ b/contracts/democracy/TrustNetworkInterface.sol @@ -1,11 +1,11 @@ pragma solidity >=0.5.0 <0.6.0; -import "./DelegationInterface.sol"; +import "./Delegation.sol"; contract TrustNetworkInterface { function addTopic(bytes32 topicId, bytes32 parentTopic) public; - function getTopic(bytes32 _topicId) public view returns (DelegationInterface vote, DelegationInterface veto); - function getVoteDelegation(bytes32 _topicId) public view returns (DelegationInterface voteDelegation); - function getVetoDelegation(bytes32 _topicId) public view returns (DelegationInterface vetoDelegation); + function getTopic(bytes32 _topicId) public view returns (Delegation vote, Delegation veto); + function getVoteDelegation(bytes32 _topicId) public view returns (Delegation voteDelegation); + function getVetoDelegation(bytes32 _topicId) public view returns (Delegation vetoDelegation); } \ No newline at end of file diff --git a/contracts/status/TestStatusNetwork.sol b/contracts/status/TestStatusNetwork.sol index da32ead..64a7227 100644 --- a/contracts/status/TestStatusNetwork.sol +++ b/contracts/status/TestStatusNetwork.sol @@ -43,6 +43,7 @@ contract TestStatusNetwork is StatusNetwork { function _generateTokens(address _who, uint _amount) private { require(msg.sender == owner || open, "Test Mint Disabled"); address statusNetwork = snt.controller(); + if(statusNetwork == address(this)){ snt.generateTokens(_who, _amount); } else { diff --git a/contracts/token/MiniMeTokenInterface.sol b/contracts/token/MiniMeTokenInterface.sol deleted file mode 100644 index 8e7b3d0..0000000 --- a/contracts/token/MiniMeTokenInterface.sol +++ /dev/null @@ -1,108 +0,0 @@ -pragma solidity ^0.4.23; - -import "./ERC20Token.sol"; - - -contract MiniMeTokenInterface is ERC20Token { - - /** - * @notice `msg.sender` approves `_spender` to send `_amount` tokens on - * its behalf, and then a function is triggered in the contract that is - * being approved, `_spender`. This allows users to use their tokens to - * interact with contracts in one function call instead of two - * @param _spender The address of the contract able to transfer the tokens - * @param _amount The amount of tokens to be approved for transfer - * @return True if the function call was successful - */ - function approveAndCall( - address _spender, - uint256 _amount, - bytes _extraData - ) - external - returns (bool success); - - /** - * @notice Creates a new clone token with the initial distribution being - * this token at `_snapshotBlock` - * @param _cloneTokenName Name of the clone token - * @param _cloneDecimalUnits Number of decimals of the smallest unit - * @param _cloneTokenSymbol Symbol of the clone token - * @param _snapshotBlock Block when the distribution of the parent token is - * copied to set the initial distribution of the new clone token; - * if the block is zero than the actual block, the current block is used - * @param _transfersEnabled True if transfers are allowed in the clone - * @return The address of the new MiniMeToken Contract - */ - function createCloneToken( - string _cloneTokenName, - uint8 _cloneDecimalUnits, - string _cloneTokenSymbol, - uint _snapshotBlock, - bool _transfersEnabled - ) - public - returns(address); - - /** - * @notice Generates `_amount` tokens that are assigned to `_owner` - * @param _owner The address that will be assigned the new tokens - * @param _amount The quantity of tokens generated - * @return True if the tokens are generated correctly - */ - function generateTokens( - address _owner, - uint _amount - ) - public - returns (bool); - - /** - * @notice Burns `_amount` tokens from `_owner` - * @param _owner The address that will lose the tokens - * @param _amount The quantity of tokens to burn - * @return True if the tokens are burned correctly - */ - function destroyTokens( - address _owner, - uint _amount - ) - public - returns (bool); - - /** - * @notice Enables token holders to transfer their tokens freely if true - * @param _transfersEnabled True if transfers are allowed in the clone - */ - function enableTransfers(bool _transfersEnabled) public; - - /** - * @notice This method can be used by the controller to extract mistakenly - * sent tokens to this contract. - * @param _token The address of the token contract that you want to recover - * set to 0 in case you want to extract ether. - */ - function claimTokens(address _token) public; - - /** - * @dev Queries the balance of `_owner` at a specific `_blockNumber` - * @param _owner The address from which the balance will be retrieved - * @param _blockNumber The block number when the balance is queried - * @return The balance at `_blockNumber` - */ - function balanceOfAt( - address _owner, - uint _blockNumber - ) - public - constant - returns (uint); - - /** - * @notice Total amount of tokens at a specific `_blockNumber`. - * @param _blockNumber The block number when the totalSupply is queried - * @return The total amount of tokens at `_blockNumber` - */ - function totalSupplyAt(uint _blockNumber) public view returns(uint); - -} \ No newline at end of file diff --git a/contracts/token/StandardToken.sol b/contracts/token/StandardToken.sol index 91ca055..484f5a8 100644 --- a/contracts/token/StandardToken.sol +++ b/contracts/token/StandardToken.sol @@ -84,11 +84,7 @@ contract StandardToken is ERC20Token { { if (balances[_from] >= _value && _value > 0) { balances[_from] -= _value; - if(_to == address(0)) { - supply -= _value; - } else { - balances[_to] += _value; - } + balances[_to] += _value; emit Transfer(_from, _to, _value); return true; } else { diff --git a/test/delegation_spec.js b/test/delegation.js similarity index 68% rename from test/delegation_spec.js rename to test/delegation.js index e7f108c..b2253a2 100644 --- a/test/delegation_spec.js +++ b/test/delegation.js @@ -1,23 +1,24 @@ const utils = require("../utils/testUtils") -const Delegation = require('Embark/contracts/Delegation'); +const DelegationView = require('Embark/contracts/DelegationView'); +const ChildDelegation = require('Embark/contracts/ChildDelegation'); config({ contracts: { - "Delegation": { - "args": [ 0 ] + "DelegationView": { + "args": [ "0x0" ] }, "ChildDelegation": { - "instanceOf": "Delegation", + "instanceOf": "DelegationView", "args": [ - "$Delegation" + "$DelegationView" ] } } }); -contract("Delegation", function() { +contract("DelegationView", function() { this.timeout(0); var accounts; @@ -30,41 +31,41 @@ contract("Delegation", function() { it("starts with no delegate", async function () { - let result = await Delegation.methods.delegatedTo(accounts[0]).call() + let result = await DelegationView.methods.delegatedTo(accounts[0]).call() assert.equal(result, utils.zeroAddress) }) it("starts with delegation to self", async function () { - result = await Delegation.methods.delegationOf(accounts[0]).call() + result = await DelegationView.methods.delegationOf(accounts[0]).call() assert.equal(result, accounts[0]) }) it("a0 delegate to a1", async function () { - result = await Delegation.methods.delegate(accounts[1]).send({from: accounts[0]}) + result = await DelegationView.methods.delegate(accounts[1]).send({from: accounts[0]}) const delegateArgs = result.events.Delegate.returnValues; assert.equal(delegateArgs.who, accounts[0]) assert.equal(delegateArgs.to, accounts[1]) - result = await Delegation.methods.delegatedTo(accounts[0]).call() + result = await DelegationView.methods.delegatedTo(accounts[0]).call() assert.equal(result, accounts[1]) - result = await Delegation.methods.delegationOf(accounts[0]).call() + result = await DelegationView.methods.delegationOf(accounts[0]).call() assert.equal(result, accounts[1]) }) it("a1 delegate to a2", async function () { - result = await Delegation.methods.delegate(accounts[2]).send({from: accounts[1]}) + result = await DelegationView.methods.delegate(accounts[2]).send({from: accounts[1]}) const delegateArgs = result.events.Delegate.returnValues; assert.equal(delegateArgs.who, accounts[1]) assert.equal(delegateArgs.to, accounts[2]) - result = await Delegation.methods.delegatedTo(accounts[1]).call() + result = await DelegationView.methods.delegatedTo(accounts[1]).call() assert.equal(result, accounts[2]) - result = await Delegation.methods.delegationOf(accounts[0]).call() + result = await DelegationView.methods.delegationOf(accounts[0]).call() assert.equal(result, accounts[2]) - result = await Delegation.methods.delegationOf(accounts[1]).call() + result = await DelegationView.methods.delegationOf(accounts[1]).call() assert.equal(result, accounts[2]) @@ -72,20 +73,20 @@ contract("Delegation", function() { it("a2 delegate to a3", async function () { - result = await Delegation.methods.delegate(accounts[3]).send({from: accounts[2]}) + result = await DelegationView.methods.delegate(accounts[3]).send({from: accounts[2]}) const delegateArgs = result.events.Delegate.returnValues; assert.equal(delegateArgs.who, accounts[2]) assert.equal(delegateArgs.to, accounts[3]) - result = await Delegation.methods.delegatedTo(accounts[2]).call() + result = await DelegationView.methods.delegatedTo(accounts[2]).call() assert.equal(result, accounts[3]) - result = await Delegation.methods.delegationOf(accounts[0]).call() + result = await DelegationView.methods.delegationOf(accounts[0]).call() assert.equal(result, accounts[3]) - result = await Delegation.methods.delegationOf(accounts[1]).call() + result = await DelegationView.methods.delegationOf(accounts[1]).call() assert.equal(result, accounts[3]) - result = await Delegation.methods.delegationOf(accounts[2]).call() + result = await DelegationView.methods.delegationOf(accounts[2]).call() assert.equal(result, accounts[3])