Merge pull request #9 from status-im/controlled-delegation

Make Delegation controlled when a defaultDelegate is set.
This commit is contained in:
Ricardo Guilherme Schmidt 2019-03-28 19:17:15 -03:00 committed by GitHub
commit 03adb4bb5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 15 deletions

View File

@ -1,13 +1,14 @@
pragma solidity >=0.5.0 <0.6.0; pragma solidity >=0.5.0 <0.6.0;
import "../../deploy/InstanceAbstract.sol"; import "../../deploy/InstanceAbstract.sol";
import "../../common/Controlled.sol";
import "./Delegation.sol"; import "./Delegation.sol";
/** /**
* @title DelegationAbstract * @title DelegationAbstract
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH). * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH).
*/ */
contract DelegationAbstract is InstanceAbstract, Delegation { contract DelegationAbstract is InstanceAbstract, Controlled, Delegation {
struct DelegateSet { struct DelegateSet {
uint96 fromBlock; //when this was updated uint96 fromBlock; //when this was updated
address to; //who recieved this delegaton address to; //who recieved this delegaton

View File

@ -17,7 +17,7 @@ contract DelegationBase is DelegationAbstract {
} }
/** /**
* @notice Changes the delegation of `msg.sender` to `_to`. if _to 0x00: delegate to self. * @notice Changes the delegation of `msg.sender` to `_to`.
* In case of having a parent proxy, if never defined, fall back to parent proxy. * 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. * 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.
@ -26,6 +26,16 @@ contract DelegationBase is DelegationAbstract {
updateDelegate(msg.sender, _to); updateDelegate(msg.sender, _to);
} }
/**
* @notice Changes the delegation of `address(0)` to `_to`.
* By default accounts delegate to `address(0)`.
* Therefore the delegate of `address(0)` is the default delegate of all accounts.
* @param _defaultDelegate default delegate address
*/
function setDefaultDelegate(address _defaultDelegate) external onlyController {
updateDelegate(address(0), _defaultDelegate);
}
/** /**
* @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.

View File

@ -27,7 +27,8 @@ contract DelegationFactory is InstanceFactory {
function createDelegation( function createDelegation(
Delegation /*_parent*/, Delegation /*_parent*/,
address /*defaultDelegate*/ address /*_controller*/,
address /*_defaultDelegate*/
) )
external external
returns (DelegationAbstract instance) returns (DelegationAbstract instance)

View File

@ -5,35 +5,50 @@ import "./DelegationAbstract.sol";
/** /**
* @title DelegationInit * @title DelegationInit
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
* @notice Initialization Model for Delegation. Is library of functions to initialize instance as Delegation.
*/ */
contract DelegationInit is DelegationAbstract { contract DelegationInit is DelegationAbstract {
modifier notInModel { //avoids control of Init contract
require(address(parentDelegation) == address(0), "Bad call");
_;
}
modifier notImplemented {
revert("Wrong model");
_;
}
/** /**
* @notice Constructor of the model - only knows about watchdog that can trigger upgrade * @notice Constructor of the model
*/ */
constructor() public { constructor() public {
parentDelegation = Delegation(address(-1)); //avoids calling create delegation within the Init contract. parentDelegation = Delegation(address(-1)); //avoids calling create delegation within the Init contract.
} }
/** /**
* @notice Creates a new Delegation with `_parentDelegation` as default delegation. * @notice Creates a new Delegation with parent as `_parentDelegation`
* @param _parentDelegation lookup delegation of unset users
*/ */
function createDelegation(Delegation _parentDelegation) external { function createDelegation(Delegation _parentDelegation) external notInModel {
require(address(parentDelegation) == address(0), "Bad call"); //avoids control of Init contract
parentDelegation = _parentDelegation; parentDelegation = _parentDelegation;
} }
/** /**
* @notice Creates a new Delegation with `_parentDelegation` as default delegation. * @notice Creates a new Delegation with `_parentDelegation` as default delegation.
*/ */
function createDelegation(Delegation _parentDelegation, address defaultDelegate) external { function createDelegation(
require(address(parentDelegation) == address(0), "Bad call"); //avoids control of Init contract Delegation _parentDelegation,
address payable _controller,
address _defaultDelegate
) external notInModel {
controller = _controller;
parentDelegation = _parentDelegation; parentDelegation = _parentDelegation;
updateDelegate(address(0), defaultDelegate); updateDelegate(address(0), _defaultDelegate);
} }
function delegate(address) external {} function delegate(address) external notImplemented {}
function delegatedTo(address) external view returns (address) {} function delegatedTo(address) external view notImplemented returns (address) {}
function delegatedToAt(address,uint) external view returns (address) {} function delegatedToAt(address,uint) external view notImplemented returns (address) {}
} }

View File

@ -54,7 +54,7 @@ contract("DelegationBase", function() {
it("creates headless delegation", async function () { it("creates headless delegation", async function () {
let result = await DelegationFactory.methods.createDelegation(utils.zeroAddress,utils.zeroAddress).send(); let result = await DelegationFactory.methods.createDelegation(utils.zeroAddress).send();
var NoDefaultDelegation = new web3.eth.Contract(DelegationBase._jsonInterface, result.events.InstanceCreated.returnValues[0]); var NoDefaultDelegation = new web3.eth.Contract(DelegationBase._jsonInterface, result.events.InstanceCreated.returnValues[0]);
result = await NoDefaultDelegation.methods.delegatedTo(accounts[0]).call() result = await NoDefaultDelegation.methods.delegatedTo(accounts[0]).call()
assert.equal(result, utils.zeroAddress) assert.equal(result, utils.zeroAddress)
@ -63,7 +63,7 @@ contract("DelegationBase", function() {
}) })
it("creates root delegation", async function () { it("creates root delegation", async function () {
let result = await DelegationFactory.methods.createDelegation(utils.zeroAddress,defaultDelegate).send(); let result = await DelegationFactory.methods.createDelegation(utils.zeroAddress,defaultDelegate,defaultDelegate).send();
RootDelegation = new web3.eth.Contract(DelegationBase._jsonInterface, result.events.InstanceCreated.returnValues[0]); RootDelegation = new web3.eth.Contract(DelegationBase._jsonInterface, result.events.InstanceCreated.returnValues[0]);
result = await RootDelegation.methods.delegatedTo(utils.zeroAddress).call() result = await RootDelegation.methods.delegatedTo(utils.zeroAddress).call()
assert.equal(result, defaultDelegate) assert.equal(result, defaultDelegate)