update to latest solc, update to new instance model, democracy acl

This commit is contained in:
Ricardo Guilherme Schmidt 2019-02-14 10:41:11 -02:00
parent bd491164f6
commit 729f9d0e59
No known key found for this signature in database
GPG Key ID: BFB3F5C8ED618A94
17 changed files with 363 additions and 390 deletions

View File

@ -31,6 +31,17 @@ module.exports = {
"await MiniMeToken.methods.changeController(StatusRoot.address).send()", "await MiniMeToken.methods.changeController(StatusRoot.address).send()",
"await StatusRoot.methods.setOpen(true).send()", "await StatusRoot.methods.setOpen(true).send()",
] ]
},
"DelegationView": {
"args": [ "0x0" ]
},
"DelegationInit": {
},
"DelegationFactory": {
"args": ["$DelegationView", "$DelegationInit", "0x0"]
},
"Democracy": {
"args": ["$MiniMeToken", "$DelegationFactory"]
} }
} }
}, },

View File

@ -1,28 +1,8 @@
pragma solidity >=0.5.0 <0.6.0; pragma solidity >=0.5.0 <0.6.0;
/** interface Delegation {
* @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
}
/** 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. * @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. * 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. * @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, * @notice Reads `_who` configured delegation in this level,
* or from parent level if `_who` never defined/defined to parent address. * or from parent level if `_who` never defined/defined to parent address.
* @param _who What address to lookup. * @param _who What address to lookup.
* @return The address `_who` choosen delegate to. * @return The address `_who` choosen delegate to.
*/ */
function delegatedTo(address _who) function delegatedTo(address _who)
public external
view view
returns (address) returns (address directDelegate);
{
return delegatedToAt(_who, block.number);
}
/** /**
* @notice Reads the final delegate of `_who` at block number `_block`. * @notice Reads the final delegate of `_who` at block number `_block`.
* @param _who Address to lookup. * @param _who Address to lookup.
* @return Final delegate address. * @return Final delegate address.
*/ */
function delegationOf(address _who) function delegationOf(address _who)
public external
view view
returns(address) returns(address finalDelegate);
{
return delegationOfAt(_who, block.number);
}
/** /**
* @notice Reads `_who` configured delegation at block number `_block` in this level, * @notice Reads `_who` configured delegation at block number `_block` in this level,
@ -72,28 +44,10 @@ contract Delegation {
address _who, address _who,
uint _block uint _block
) )
public external
view view
returns (address directDelegate) 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;
}
/** /**
* @notice Reads the final delegate of `_who` at block number `_block`. * @notice Reads the final delegate of `_who` at block number `_block`.
* @param _who Address to lookup. * @param _who Address to lookup.
@ -104,62 +58,8 @@ contract Delegation {
address _who, address _who,
uint _block uint _block
) )
public external
view view
returns(address finalDelegate) 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
}
}
/**
* @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];
}
}
} }

View File

@ -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
}
}
}

View File

@ -1,11 +1,20 @@
pragma solidity >=0.5.0 <0.6.0; 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. * @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. * 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. * @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, * @notice Reads `_who` configured delegation in this level,
* or from parent level if `_who` never defined/defined to parent address. * or from parent level if `_who` never defined/defined to parent address.
* @param _who What address to lookup. * @param _who What address to lookup.
* @return The address `_who` choosen delegate to. * @return The address `_who` choosen delegate to.
*/ */
function delegatedTo(address _who) function delegatedTo(address _who)
public external
view view
returns (address directDelegate); returns (address)
{
return findDelegatedToAt(_who, block.number);
}
/** /**
* @notice Reads the final delegate of `_who` at block number `_block`. * @notice Reads the final delegate of `_who` at block number `_block`.
* @param _who Address to lookup. * @param _who Address to lookup.
* @return Final delegate address. * @return Final delegate address.
*/ */
function delegationOf(address _who) function delegationOf(address _who)
public external
view view
returns(address finalDelegate); returns(address)
{
return findDelegationOfAt(_who, block.number);
}
/** /**
* @notice Reads `_who` configured delegation at block number `_block` in this level, * @notice Reads `_who` configured delegation at block number `_block` in this level,
@ -47,10 +64,13 @@ contract DelegationInterface {
address _who, address _who,
uint _block uint _block
) )
public external
view view
returns (address directDelegate); returns (address directDelegate)
{
return findDelegatedToAt(_who, _block);
}
/** /**
* @notice Reads the final delegate of `_who` at block number `_block`. * @notice Reads the final delegate of `_who` at block number `_block`.
* @param _who Address to lookup. * @param _who Address to lookup.
@ -61,8 +81,11 @@ contract DelegationInterface {
address _who, address _who,
uint _block uint _block
) )
public external
view view
returns(address finalDelegate); returns(address finalDelegate)
{
return findDelegationOfAt(_who, _block);
}
} }

View File

@ -1,8 +1,6 @@
pragma solidity >=0.5.0 <0.6.0; pragma solidity >=0.5.0 <0.6.0;
import "./DelegationInterface.sol"; import "../deploy/InstanceFactory.sol";
import "./DelegationKernel.sol";
import "../deploy/Factory.sol";
import "../deploy/Instance.sol"; import "../deploy/Instance.sol";
/** /**
@ -10,20 +8,21 @@ import "../deploy/Instance.sol";
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
* @dev Upgradable delegation proxy factory * @dev Upgradable delegation proxy factory
*/ */
contract DelegationFactory is Factory { contract DelegationFactory is InstanceFactory {
constructor() constructor(InstanceAbstract _base, InstanceAbstract _init, InstanceAbstract _emergency)
Factory(new DelegationKernel()) InstanceFactory(_base, _init, _emergency)
public public
{ } { }
function createDelegation(address _parent) function createDelegation(
address
)
external external
returns (DelegationInterface) returns (InstanceAbstract instance)
{ {
DelegationKernel instance = DelegationKernel(address(new Instance(latestKernel))); instance = new Instance(base, prototypes[address(base)].init, msg.data);
instance.initializeDelegation(_parent); emit InstanceCreated(instance);
return DelegationInterface(address(instance));
} }
} }

View File

@ -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) {}
}

View File

@ -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;
}
}

View File

@ -1,14 +1,14 @@
pragma solidity >=0.5.0 <0.6.0; 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) * @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 //storage of preprocessed view of FinalDelegate
mapping(bytes32 => FinalDelegate) public delegationView; mapping(bytes32 => FinalDelegate) public delegationView;
@ -18,7 +18,7 @@ contract DelegationView is Delegation {
bool found; 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. * @param _block From what block.
* @return Final delegate address. * @return Final delegate address.
*/ */
function delegationOfAt( function findDelegationOfAt(
address _who, address _who,
uint _block uint _block
) )
public internal
view view
returns(address finalDelegate) returns(address finalDelegate)
{ {
bytes32 searchIndex = keccak256(_who, _block); bytes32 searchIndex = keccak256(abi.encodePacked(_who, _block));
FinalDelegate memory search = delegationView[searchIndex]; FinalDelegate memory search = delegationView[searchIndex];
if (search.found) { if (search.found) {
return search.delegate; return search.delegate;
} else { } else {
return super.delegationOfAt(_who, _block); return super.findDelegationOfAt(_who, _block);
} }
} }
@ -61,14 +61,14 @@ contract DelegationView is Delegation {
external external
returns (bool) returns (bool)
{ {
bytes32 searchIndex = keccak256(_delegator,_block); bytes32 searchIndex = keccak256(abi.encodePacked(_delegator,_block));
FinalDelegate memory search = delegationView[searchIndex]; FinalDelegate memory search = delegationView[searchIndex];
require(!search.found); require(!search.found);
for (uint i = 0; i < loopLimit; i++) { for (uint i = 0; i < loopLimit; i++) {
if (search.delegate == address(0)) { if (search.delegate == address(0)) {
search.delegate = _delegator; search.delegate = _delegator;
} }
address delegateFrom = delegatedToAt(search.delegate, _block); address delegateFrom = findDelegatedToAt(search.delegate, _block);
if (delegateFrom == address(0)) { if (delegateFrom == address(0)) {
// search.delegate demonsted this address didnt delegated, // search.delegate demonsted this address didnt delegated,
search.found = true; // so its the final delegate search.found = true; // so its the final delegate
@ -100,11 +100,11 @@ contract DelegationView is Delegation {
returns (address lastDelegate, bool found) returns (address lastDelegate, bool found)
{ {
require(_block > block.number); //cannot renderize current state view ? 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]; FinalDelegate memory search = delegationView[searchIndex];
if (!search.found) { if (!search.found) {
if (search.delegate == address(0)) { if (search.delegate == address(0)) {
lastDelegate = delegatedToAt(_delegator, _block); lastDelegate = findDelegatedToAt(_delegator, _block);
if (lastDelegate == address(0)) { if (lastDelegate == address(0)) {
//`_delegator` FinalDelegate is itself //`_delegator` FinalDelegate is itself
lastDelegate = _delegator; lastDelegate = _delegator;

View File

@ -1,6 +1,6 @@
pragma solidity >=0.5.0 <0.6.0; pragma solidity >=0.5.0 <0.6.0;
import "../token/MiniMeTokenInterface.sol"; import "../token/MiniMeToken.sol";
import "./DelegationFactory.sol"; import "./DelegationFactory.sol";
import "./TrustNetwork.sol"; import "./TrustNetwork.sol";
import "./ProposalCuration.sol"; import "./ProposalCuration.sol";
@ -9,46 +9,31 @@ import "./ProposalManager.sol";
contract Democracy { contract Democracy {
MiniMeTokenInterface public token; MiniMeToken public token;
TrustNetwork public trustNet; TrustNetwork public trustNet;
ProposalManager public proposalManager; ProposalManager public proposalManager;
mapping (bytes32 => Allowance) topicAllowance; mapping (bytes32 => mapping (address => mapping (bytes32 => bool))) allowance;
mapping (uint256 => bool) executedProposals; mapping (uint256 => bool) executedProposals;
struct Allowance { modifier selfOnly {
mapping(address => bool) anyCall; require(msg.sender == address(this), "Unauthorized");
mapping(bytes32 => bool) calls; _;
} }
constructor(MiniMeTokenInterface _token, DelegationFactory _DelegationFactory) public { constructor(MiniMeToken _token, DelegationFactory _DelegationFactory) public {
token = _token; token = _token;
trustNet = new TrustNetwork(_DelegationFactory); trustNet = new TrustNetwork(_DelegationFactory);
proposalManager = new ProposalCuration(_token, trustNet).proposalManager(); 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( function executeProposal(
uint256 _proposalId, uint256 _proposalId,
address _destination, address _destination,
uint _value, bytes calldata _data
bytes _data
) )
external external
returns (bool success) returns (bool success, bytes memory r)
{ {
require(!executedProposals[_proposalId]); require(!executedProposals[_proposalId]);
executedProposals[_proposalId] = true; executedProposals[_proposalId] = true;
@ -60,27 +45,64 @@ contract Democracy {
require(approved); require(approved);
require( require(
txHash == keccak256( txHash == keccak256(
_destination, abi.encodePacked(
_value, _destination,
_data _data
)
) )
); );
if(topic != 0x0) { //if not root topic if(topic != bytes32(0)) { //if not root topic
Allowance storage allowed = topicAllowance[topic]; bytes memory data = _data;
if(!allowed.anyCall[_destination]){ //if topic not allowed any call to destination bytes4 sig;
bytes memory data = _data; assembly {
bytes4 calling; sig := mload(add(data, 4))
assembly {
calling := mload(add(data, 4))
}
delete data;
require(allowed.calls[keccak256(_destination, calling)]); //require call allowance
} }
delete sig;
require(isTopicAllowed(topic, _destination, sig)); //require call allowance
} }
//execute the call //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)];
}
} }

View File

@ -1,7 +1,7 @@
pragma solidity >=0.5.0 <0.6.0; pragma solidity >=0.5.0 <0.6.0;
import "../common/Controlled.sol"; import "../common/Controlled.sol";
import "../token/MiniMeTokenInterface.sol"; import "../token/MiniMeToken.sol";
import "./ProposalManager.sol"; import "./ProposalManager.sol";
contract ProposalCuration is Controlled { contract ProposalCuration is Controlled {
@ -15,7 +15,7 @@ contract ProposalCuration is Controlled {
ProposalManager public proposalManager; ProposalManager public proposalManager;
uint256 public approvalTimeLimit; uint256 public approvalTimeLimit;
MiniMeTokenInterface token; MiniMeToken token;
mapping (address => SubmitPrice) submitAllowances; mapping (address => SubmitPrice) submitAllowances;
@ -34,7 +34,7 @@ contract ProposalCuration is Controlled {
} }
constructor( constructor(
MiniMeTokenInterface _token, MiniMeToken _token,
TrustNetworkInterface _trustNet TrustNetworkInterface _trustNet
) )
public public
@ -47,8 +47,8 @@ contract ProposalCuration is Controlled {
bytes32 _topic, bytes32 _topic,
address _to, address _to,
uint256 _value, uint256 _value,
bytes _data, bytes calldata _data,
bytes _description bytes calldata _description
) )
external external
returns (uint256 proposalId) returns (uint256 proposalId)
@ -56,7 +56,7 @@ contract ProposalCuration is Controlled {
uint256 submitPrice = getSubmitPrice(msg.sender); uint256 submitPrice = getSubmitPrice(msg.sender);
require(token.allowance(msg.sender, address(this)) >= submitPrice); require(token.allowance(msg.sender, address(this)) >= submitPrice);
require(token.transferFrom(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( proposals[proposalId] = ProposalData(
msg.sender, msg.sender,
_to, _to,

View File

@ -2,8 +2,8 @@ pragma solidity >=0.5.0 <0.6.0;
import "../common/Controlled.sol"; import "../common/Controlled.sol";
import "../common/MessageSigned.sol"; import "../common/MessageSigned.sol";
import "../token/MiniMeTokenInterface.sol"; import "../token/MiniMeToken.sol";
import "./DelegationInterface.sol"; import "./Delegation.sol";
import "./TrustNetworkInterface.sol"; import "./TrustNetworkInterface.sol";
/** /**
@ -15,7 +15,7 @@ contract ProposalManager is Controlled, MessageSigned {
event ProposalSet(bytes32 indexed topic, uint256 proposalId, bytes32 txHash); event ProposalSet(bytes32 indexed topic, uint256 proposalId, bytes32 txHash);
event ProposalResult(uint256 proposalId, uint8 finalResult); event ProposalResult(uint256 proposalId, uint8 finalResult);
MiniMeTokenInterface public token; MiniMeToken public token;
TrustNetworkInterface public trustNet; TrustNetworkInterface public trustNet;
uint256 public tabulationBlockDelay; uint256 public tabulationBlockDelay;
Proposal[] public proposals; Proposal[] public proposals;
@ -43,7 +43,7 @@ contract ProposalManager is Controlled, MessageSigned {
} }
constructor( constructor(
MiniMeTokenInterface _token, MiniMeToken _token,
TrustNetworkInterface _trustNet TrustNetworkInterface _trustNet
) )
public public
@ -91,8 +91,8 @@ contract ProposalManager is Controlled, MessageSigned {
} }
function tabulateVote(uint _proposalId, Vote _vote, uint256 _position, bytes32[] _proof, bytes _signature) function tabulateVote(uint _proposalId, Vote _vote, uint256 _position, bytes32[] calldata _proof, bytes calldata _signature)
public external
{ {
Proposal storage proposal = proposals[_proposalId]; Proposal storage proposal = proposals[_proposalId];
require(block.number > proposal.voteBlockEnd, "Voting running"); require(block.number > proposal.voteBlockEnd, "Voting running");

View File

@ -2,7 +2,7 @@ pragma solidity >=0.5.0 <0.6.0;
import "../common/Controlled.sol"; import "../common/Controlled.sol";
import "./TrustNetworkInterface.sol"; import "./TrustNetworkInterface.sol";
import "./DelegationInterface.sol"; import "./Delegation.sol";
import "./DelegationFactory.sol"; import "./DelegationFactory.sol";
@ -17,30 +17,30 @@ contract TrustNetwork is TrustNetworkInterface, Controlled {
DelegationFactory delegationFactory; DelegationFactory delegationFactory;
struct Topic { struct Topic {
DelegationInterface voteDelegation; Delegation voteDelegation;
DelegationInterface vetoDelegation; Delegation vetoDelegation;
} }
constructor(address _delegationFactory) public { constructor(DelegationFactory _delegationFactory) public {
delegationFactory = DelegationFactory(_delegationFactory); delegationFactory = _delegationFactory;
topics[0x0] = newTopic(0x0, 0x0); topics[bytes32(0)] = newTopic(address(0), address(0));
} }
function addTopic(bytes32 topicId, bytes32 parentTopic) public onlyController { function addTopic(bytes32 topicId, bytes32 parentTopic) public onlyController {
Topic memory parent = topics[parentTopic]; Topic memory parent = topics[parentTopic];
address vote = address(parent.voteDelegation); address vote = address(parent.voteDelegation);
address veto = address(parent.vetoDelegation); address veto = address(parent.vetoDelegation);
require(vote != 0x0); require(vote != address(0));
require(veto != 0x0); require(veto != address(0));
Topic storage topic = topics[topicId]; Topic storage topic = topics[topicId];
require(address(topic.voteDelegation) == 0x0); require(address(topic.voteDelegation) == address(0));
require(address(topic.vetoDelegation) == 0x0); require(address(topic.vetoDelegation) == address(0));
topics[topicId] = newTopic(vote, veto); 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]; Topic memory topic = topics[_topicId];
vote = topic.voteDelegation; vote = topic.voteDelegation;
veto = topic.vetoDelegation; veto = topic.vetoDelegation;
@ -51,7 +51,7 @@ contract TrustNetwork is TrustNetworkInterface, Controlled {
) )
public public
view view
returns (DelegationInterface voteDelegation) returns (Delegation voteDelegation)
{ {
return topics[_topicId].voteDelegation; return topics[_topicId].voteDelegation;
} }
@ -61,16 +61,16 @@ contract TrustNetwork is TrustNetworkInterface, Controlled {
) )
public public
view view
returns (DelegationInterface vetoDelegation) returns (Delegation vetoDelegation)
{ {
return topics[_topicId].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 ({ topic = Topic ({
voteDelegation: delegationFactory.createDelegation(_vote), voteDelegation: Delegation(address(delegationFactory.createDelegation(_vote))),
vetoDelegation: delegationFactory.createDelegation(_veto) vetoDelegation: Delegation(address(delegationFactory.createDelegation(_veto)))
}); });
} }

View File

@ -1,11 +1,11 @@
pragma solidity >=0.5.0 <0.6.0; pragma solidity >=0.5.0 <0.6.0;
import "./DelegationInterface.sol"; import "./Delegation.sol";
contract TrustNetworkInterface { contract TrustNetworkInterface {
function addTopic(bytes32 topicId, bytes32 parentTopic) public; function addTopic(bytes32 topicId, bytes32 parentTopic) public;
function getTopic(bytes32 _topicId) public view returns (DelegationInterface vote, DelegationInterface veto); function getTopic(bytes32 _topicId) public view returns (Delegation vote, Delegation veto);
function getVoteDelegation(bytes32 _topicId) public view returns (DelegationInterface voteDelegation); function getVoteDelegation(bytes32 _topicId) public view returns (Delegation voteDelegation);
function getVetoDelegation(bytes32 _topicId) public view returns (DelegationInterface vetoDelegation); function getVetoDelegation(bytes32 _topicId) public view returns (Delegation vetoDelegation);
} }

View File

@ -43,6 +43,7 @@ contract TestStatusNetwork is StatusNetwork {
function _generateTokens(address _who, uint _amount) private { function _generateTokens(address _who, uint _amount) private {
require(msg.sender == owner || open, "Test Mint Disabled"); require(msg.sender == owner || open, "Test Mint Disabled");
address statusNetwork = snt.controller(); address statusNetwork = snt.controller();
if(statusNetwork == address(this)){ if(statusNetwork == address(this)){
snt.generateTokens(_who, _amount); snt.generateTokens(_who, _amount);
} else { } else {

View File

@ -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);
}

View File

@ -84,11 +84,7 @@ contract StandardToken is ERC20Token {
{ {
if (balances[_from] >= _value && _value > 0) { if (balances[_from] >= _value && _value > 0) {
balances[_from] -= _value; balances[_from] -= _value;
if(_to == address(0)) { balances[_to] += _value;
supply -= _value;
} else {
balances[_to] += _value;
}
emit Transfer(_from, _to, _value); emit Transfer(_from, _to, _value);
return true; return true;
} else { } else {

View File

@ -1,23 +1,24 @@
const utils = require("../utils/testUtils") const utils = require("../utils/testUtils")
const Delegation = require('Embark/contracts/Delegation'); const DelegationView = require('Embark/contracts/DelegationView');
const ChildDelegation = require('Embark/contracts/ChildDelegation');
config({ config({
contracts: { contracts: {
"Delegation": { "DelegationView": {
"args": [ 0 ] "args": [ "0x0" ]
}, },
"ChildDelegation": { "ChildDelegation": {
"instanceOf": "Delegation", "instanceOf": "DelegationView",
"args": [ "args": [
"$Delegation" "$DelegationView"
] ]
} }
} }
}); });
contract("Delegation", function() { contract("DelegationView", function() {
this.timeout(0); this.timeout(0);
var accounts; var accounts;
@ -30,41 +31,41 @@ contract("Delegation", function() {
it("starts with no delegate", async 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) assert.equal(result, utils.zeroAddress)
}) })
it("starts with delegation to self", async function () { 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]) assert.equal(result, accounts[0])
}) })
it("a0 delegate to a1", async function () { 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; const delegateArgs = result.events.Delegate.returnValues;
assert.equal(delegateArgs.who, accounts[0]) assert.equal(delegateArgs.who, accounts[0])
assert.equal(delegateArgs.to, accounts[1]) 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]) 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]) assert.equal(result, accounts[1])
}) })
it("a1 delegate to a2", async function () { 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; const delegateArgs = result.events.Delegate.returnValues;
assert.equal(delegateArgs.who, accounts[1]) assert.equal(delegateArgs.who, accounts[1])
assert.equal(delegateArgs.to, accounts[2]) 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]) 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]) 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]) assert.equal(result, accounts[2])
@ -72,20 +73,20 @@ contract("Delegation", function() {
it("a2 delegate to a3", async 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; const delegateArgs = result.events.Delegate.returnValues;
assert.equal(delegateArgs.who, accounts[2]) assert.equal(delegateArgs.who, accounts[2])
assert.equal(delegateArgs.to, accounts[3]) 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]) 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]) 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]) 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]) assert.equal(result, accounts[3])