update to latest solc, update to new instance model, democracy acl
This commit is contained in:
parent
bd491164f6
commit
729f9d0e59
|
@ -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"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,28 +1,8 @@
|
|||
pragma solidity >=0.5.0 <0.6.0;
|
||||
|
||||
/**
|
||||
* @title Delegation
|
||||
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH).
|
||||
*/
|
||||
contract Delegation {
|
||||
interface 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
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calls Constructor
|
||||
*/
|
||||
constructor(address _parentDelegation) public {
|
||||
parentDelegation = _parentDelegation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Changes the delegation of `msg.sender` to `_to`. if _to 0x00: delegate to self.
|
||||
|
@ -30,9 +10,7 @@ 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,
|
||||
|
@ -41,12 +19,9 @@ contract Delegation {
|
|||
* @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`.
|
||||
|
@ -54,12 +29,9 @@ contract Delegation {
|
|||
* @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,27 +44,9 @@ 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`.
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @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];
|
||||
}
|
||||
}
|
||||
returns(address finalDelegate);
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,11 +1,20 @@
|
|||
pragma solidity >=0.5.0 <0.6.0;
|
||||
|
||||
import "../token/MiniMeTokenInterface.sol";
|
||||
import "./DelegationAbstract.sol";
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
|
||||
contract DelegationInterface {
|
||||
|
||||
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,7 +22,9 @@ 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,
|
||||
|
@ -22,9 +33,12 @@ contract DelegationInterface {
|
|||
* @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`.
|
||||
|
@ -32,9 +46,12 @@ contract DelegationInterface {
|
|||
* @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,9 +64,12 @@ 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`.
|
||||
|
@ -61,8 +81,11 @@ contract DelegationInterface {
|
|||
address _who,
|
||||
uint _block
|
||||
)
|
||||
public
|
||||
external
|
||||
view
|
||||
returns(address finalDelegate);
|
||||
returns(address finalDelegate)
|
||||
{
|
||||
return findDelegationOfAt(_who, _block);
|
||||
}
|
||||
|
||||
}
|
|
@ -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())
|
||||
constructor(InstanceAbstract _base, InstanceAbstract _init, InstanceAbstract _emergency)
|
||||
InstanceFactory(_base, _init, _emergency)
|
||||
public
|
||||
{ }
|
||||
|
||||
function createDelegation(address _parent)
|
||||
function createDelegation(
|
||||
address
|
||||
)
|
||||
external
|
||||
returns (DelegationInterface)
|
||||
returns (InstanceAbstract instance)
|
||||
{
|
||||
DelegationKernel instance = DelegationKernel(address(new Instance(latestKernel)));
|
||||
instance.initializeDelegation(_parent);
|
||||
return DelegationInterface(address(instance));
|
||||
instance = new Instance(base, prototypes[address(base)].init, msg.data);
|
||||
emit InstanceCreated(instance);
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
abi.encodePacked(
|
||||
_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
|
||||
if(topic != bytes32(0)) { //if not root topic
|
||||
bytes memory data = _data;
|
||||
bytes4 calling;
|
||||
bytes4 sig;
|
||||
assembly {
|
||||
calling := mload(add(data, 4))
|
||||
}
|
||||
delete data;
|
||||
require(allowed.calls[keccak256(_destination, calling)]); //require call allowance
|
||||
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)];
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
emit Transfer(_from, _to, _value);
|
||||
return true;
|
||||
} else {
|
||||
|
|
|
@ -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])
|
||||
|
||||
|
Loading…
Reference in New Issue