From 8a609f4f965344845a4bf10a7cd971084e06efb6 Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Wed, 20 Nov 2019 07:50:07 +0200 Subject: [PATCH 1/2] remove universal genericscheme --- contracts/universalSchemes/UGenericScheme.sol | 184 ------------- test/ugenericscheme.js | 257 ------------------ 2 files changed, 441 deletions(-) delete mode 100644 contracts/universalSchemes/UGenericScheme.sol delete mode 100644 test/ugenericscheme.js diff --git a/contracts/universalSchemes/UGenericScheme.sol b/contracts/universalSchemes/UGenericScheme.sol deleted file mode 100644 index 637f4f40..00000000 --- a/contracts/universalSchemes/UGenericScheme.sol +++ /dev/null @@ -1,184 +0,0 @@ -pragma solidity ^0.5.11; - -import "@daostack/infra/contracts/votingMachines/IntVoteInterface.sol"; -import "@daostack/infra/contracts/votingMachines/VotingMachineCallbacksInterface.sol"; -import "./UniversalScheme.sol"; -import "../votingMachines/VotingMachineCallbacks.sol"; - - -/** - * @title UGenericScheme. - * @dev A scheme for proposing and executing calls to an arbitrary function - * on a specific contract on behalf of the organization avatar. - */ -contract UGenericScheme is UniversalScheme, VotingMachineCallbacks, ProposalExecuteInterface { - event NewCallProposal( - address indexed _avatar, - bytes32 indexed _proposalId, - bytes _callData, - uint256 _value, - string _descriptionHash - ); - - event ProposalExecuted( - address indexed _avatar, - bytes32 indexed _proposalId, - bytes _genericCallReturnValue - ); - - event ProposalExecutedByVotingMachine( - address indexed _avatar, - bytes32 indexed _proposalId, - int256 _param - ); - - event ProposalDeleted(address indexed _avatar, bytes32 indexed _proposalId); - - // Details of a voting proposal: - struct CallProposal { - bytes callData; - uint256 value; - bool exist; - bool passed; - } - - // A mapping from the organization (Avatar) address to the saved data of the organization: - mapping(address=>mapping(bytes32=>CallProposal)) public organizationsProposals; - - struct Parameters { - IntVoteInterface intVote; - bytes32 voteParams; - address contractToCall; - } - - // A mapping from hashes to parameters (use to store a particular configuration on the controller) - mapping(bytes32=>Parameters) public parameters; - - /** - * @dev execution of proposals, can only be called by the voting machine in which the vote is held. - * @param _proposalId the ID of the voting in the voting machine - * @param _decision a parameter of the voting result, 1 yes and 2 is no. - * @return bool success - */ - function executeProposal(bytes32 _proposalId, int256 _decision) - external - onlyVotingMachine(_proposalId) - returns(bool) { - Avatar avatar = proposalsInfo[msg.sender][_proposalId].avatar; - CallProposal storage proposal = organizationsProposals[address(avatar)][_proposalId]; - require(proposal.exist, "must be a live proposal"); - require(proposal.passed == false, "cannot execute twice"); - - if (_decision == 1) { - proposal.passed = true; - execute(avatar, _proposalId); - } else { - delete organizationsProposals[address(avatar)][_proposalId]; - emit ProposalDeleted(address(avatar), _proposalId); - } - - emit ProposalExecutedByVotingMachine(address(avatar), _proposalId, _decision); - return true; - } - - /** - * @dev execution of proposals after it has been decided by the voting machine - * @param _proposalId the ID of the voting in the voting machine - */ - function execute(Avatar _avatar, bytes32 _proposalId) public { - Parameters memory params = parameters[getParametersFromController(_avatar)]; - CallProposal storage proposal = organizationsProposals[address(_avatar)][_proposalId]; - require(proposal.exist, "must be a live proposal"); - require(proposal.passed, "proposal must passed by voting machine"); - proposal.exist = false; - bytes memory genericCallReturnValue; - bool success; - ControllerInterface controller = ControllerInterface(_avatar.owner()); - (success, genericCallReturnValue) = - controller.genericCall(params.contractToCall, proposal.callData, _avatar, proposal.value); - if (success) { - delete organizationsProposals[address(_avatar)][_proposalId]; - emit ProposalDeleted(address(_avatar), _proposalId); - emit ProposalExecuted(address(_avatar), _proposalId, genericCallReturnValue); - } else { - proposal.exist = true; - } - } - - /** - * @dev Hash the parameters, save them if necessary, and return the hash value - * @param _voteParams - voting parameters - * @param _intVote - voting machine contract. - * @return bytes32 -the parameters hash - */ - function setParameters( - bytes32 _voteParams, - IntVoteInterface _intVote, - address _contractToCall - ) public returns(bytes32) - { - bytes32 paramsHash = getParametersHash(_voteParams, _intVote, _contractToCall); - parameters[paramsHash].voteParams = _voteParams; - parameters[paramsHash].intVote = _intVote; - parameters[paramsHash].contractToCall = _contractToCall; - return paramsHash; - } - - /** - * @dev propose to call on behalf of the _avatar - * The function trigger NewCallProposal event - * @param _avatar avatar of the organization - * @param _callData - The abi encode data for the call - * @param _value value(ETH) to transfer with the call - * @param _descriptionHash proposal description hash - * @return an id which represents the proposal - */ - function proposeCall(Avatar _avatar, bytes memory _callData, uint256 _value, string memory _descriptionHash) - public - returns(bytes32) - { - Parameters memory params = parameters[getParametersFromController(_avatar)]; - IntVoteInterface intVote = params.intVote; - - bytes32 proposalId = intVote.propose(2, params.voteParams, msg.sender, address(_avatar)); - - organizationsProposals[address(_avatar)][proposalId] = CallProposal({ - callData: _callData, - value: _value, - exist: true, - passed: false - }); - proposalsInfo[address(params.intVote)][proposalId] = ProposalInfo({ - blockNumber:block.number, - avatar:_avatar - }); - emit NewCallProposal(address(_avatar), proposalId, _callData, _value, _descriptionHash); - return proposalId; - } - - /** - * @dev getContractToCall return the contract this scheme is calling - * @param _avatar address of the organization's avatar - * @return address the address of the contract this scheme is calling to - * on behalf of the avatar - */ - function getContractToCall(Avatar _avatar) public view returns(address) { - return parameters[getParametersFromController(_avatar)].contractToCall; - } - - /** - * @dev Hash the parameters, and return the hash value - * @param _voteParams - voting parameters - * @param _intVote - voting machine contract. - * @return bytes32 -the parameters hash - */ - function getParametersHash( - bytes32 _voteParams, - IntVoteInterface _intVote, - address _contractToCall - ) public pure returns(bytes32) - { - return keccak256(abi.encodePacked(_voteParams, _intVote, _contractToCall)); - } - -} diff --git a/test/ugenericscheme.js b/test/ugenericscheme.js deleted file mode 100644 index e1509bb0..00000000 --- a/test/ugenericscheme.js +++ /dev/null @@ -1,257 +0,0 @@ -import * as helpers from './helpers'; -const constants = require('./constants'); -const AbsoluteVote = artifacts.require('./AbsoluteVote.sol'); -const GenericScheme = artifacts.require('./UGenericScheme.sol'); -const DaoCreator = artifacts.require("./DaoCreator.sol"); -const DAOTracker = artifacts.require("./DAOTracker.sol"); -const ControllerCreator = artifacts.require("./ControllerCreator.sol"); -const ERC20Mock = artifacts.require("./ERC20Mock.sol"); -const ActionMock = artifacts.require("./ActionMock.sol"); -const Wallet = artifacts.require("./Wallet.sol"); - -export class GenericSchemeParams { - constructor() { - } -} - -const setupGenericSchemeParams = async function( - genericScheme, - accounts, - contractToCall, - genesisProtocol = false, - tokenAddress = 0 - ) { - var genericSchemeParams = new GenericSchemeParams(); - if (genesisProtocol === true){ - genericSchemeParams.votingMachine = await helpers.setupGenesisProtocol(accounts,tokenAddress,0,helpers.NULL_ADDRESS); - await genericScheme.setParameters(genericSchemeParams.votingMachine.params,genericSchemeParams.votingMachine.genesisProtocol.address,contractToCall); - genericSchemeParams.paramsHash = await genericScheme.getParametersHash(genericSchemeParams.votingMachine.params,genericSchemeParams.votingMachine.genesisProtocol.address,contractToCall); - } - else { - genericSchemeParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50,genericScheme.address); - await genericScheme.setParameters(genericSchemeParams.votingMachine.params,genericSchemeParams.votingMachine.absoluteVote.address,contractToCall); - genericSchemeParams.paramsHash = await genericScheme.getParametersHash(genericSchemeParams.votingMachine.params,genericSchemeParams.votingMachine.absoluteVote.address,contractToCall); - } - - return genericSchemeParams; -}; - -const setup = async function (accounts,contractToCall = 0,reputationAccount=0,genesisProtocol = false,tokenAddress=0) { - var testSetup = new helpers.TestSetup(); - testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100); - testSetup.genericScheme = await GenericScheme.new(); - var controllerCreator = await ControllerCreator.new({gas: constants.ARC_GAS_LIMIT}); - var daoTracker = await DAOTracker.new({gas: constants.ARC_GAS_LIMIT}); - testSetup.daoCreator = await DaoCreator.new(controllerCreator.address,daoTracker.address,{gas:constants.ARC_GAS_LIMIT}); - testSetup.reputationArray = [20,10,70]; - - if (reputationAccount === 0) { - testSetup.org = await helpers.setupOrganizationWithArrays(testSetup.daoCreator,[accounts[0],accounts[1],accounts[2]],[1000,1000,1000],testSetup.reputationArray); - } else { - testSetup.org = await helpers.setupOrganizationWithArrays(testSetup.daoCreator,[accounts[0],accounts[1],reputationAccount],[1000,1000,1000],testSetup.reputationArray); - } - testSetup.genericSchemeParams= await setupGenericSchemeParams(testSetup.genericScheme,accounts,contractToCall,genesisProtocol,tokenAddress); - var permissions = "0x00000010"; - - - await testSetup.daoCreator.setSchemes(testSetup.org.avatar.address, - [testSetup.genericScheme.address], - [testSetup.genericSchemeParams.paramsHash],[permissions],"metaData"); - - return testSetup; -}; - -const createCallToActionMock = async function(_avatar,_actionMock) { - return await new web3.eth.Contract(_actionMock.abi).methods.test2(_avatar).encodeABI(); -}; - -contract('UGenericScheme', function(accounts) { - before(function() { - helpers.etherForEveryone(accounts); - }); - it("setParameters", async function() { - var genericScheme = await GenericScheme.new(); - var absoluteVote = await AbsoluteVote.new(); - await genericScheme.setParameters("0x1234",absoluteVote.address,accounts[0]); - var paramHash = await genericScheme.getParametersHash("0x1234",absoluteVote.address,accounts[0]); - var parameters = await genericScheme.parameters(paramHash); - assert.equal(parameters[0],absoluteVote.address); - assert.equal(parameters[2],accounts[0]); - }); - - - it("proposeCall log", async function() { - - var actionMock =await ActionMock.new(); - var testSetup = await setup(accounts,actionMock.address); - var callData = await createCallToActionMock(testSetup.org.avatar.address,actionMock); - - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address, - callData,0,helpers.NULL_HASH); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "NewCallProposal"); - }); - - it("execute proposeCall -no decision - proposal data delete", async function() { - var actionMock =await ActionMock.new(); - var testSetup = await setup(accounts,actionMock.address); - var callData = await createCallToActionMock(testSetup.org.avatar.address,actionMock); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,callData,0,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - await testSetup.genericSchemeParams.votingMachine.absoluteVote.vote(proposalId,0,0,helpers.NULL_ADDRESS,{from:accounts[2]}); - //check organizationsProposals after execution - var organizationProposal = await testSetup.genericScheme.organizationsProposals(testSetup.org.avatar.address,proposalId); - assert.equal(organizationProposal.passed,false); - assert.equal(organizationProposal.callData,null); - }); - - it("execute proposeVote -positive decision - proposal data delete", async function() { - var actionMock =await ActionMock.new(); - var testSetup = await setup(accounts,actionMock.address); - var callData = await createCallToActionMock(testSetup.org.avatar.address,actionMock); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,callData,0,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - var organizationProposal = await testSetup.genericScheme.organizationsProposals(testSetup.org.avatar.address,proposalId); - assert.equal(organizationProposal[0],callData,helpers.NULL_HASH); - await testSetup.genericSchemeParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); - //check organizationsProposals after execution - organizationProposal = await testSetup.genericScheme.organizationsProposals(testSetup.org.avatar.address,proposalId); - assert.equal(organizationProposal.callData,null);//new contract address - }); - - it("execute proposeVote -positive decision - destination reverts", async function() { - var actionMock =await ActionMock.new(); - var testSetup = await setup(accounts,actionMock.address); - var callData = await createCallToActionMock(helpers.NULL_ADDRESS,actionMock); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,callData,0,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - - await testSetup.genericSchemeParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); - //actionMock revert because msg.sender is not the _addr param at actionMock thpugh the generic scheme not . - var organizationProposal = await testSetup.genericScheme.organizationsProposals(testSetup.org.avatar.address,proposalId); - assert.equal(organizationProposal.exist,true);//new contract address - assert.equal(organizationProposal.passed,true);//new contract address - //can call execute - await testSetup.genericScheme.execute(testSetup.org.avatar.address, proposalId); - - }); - - - it("execute proposeVote -positive decision - destination reverts and then active", async function() { - var actionMock =await ActionMock.new(); - var testSetup = await setup(accounts,actionMock.address); - var activationTime = (await web3.eth.getBlock("latest")).timestamp + 1000; - await actionMock.setActivationTime(activationTime); - var callData = await new web3.eth.Contract(actionMock.abi).methods.test3().encodeABI(); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,callData,0,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - - await testSetup.genericSchemeParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); - //actionMock revert because msg.sender is not the _addr param at actionMock thpugh the generic scheme not . - var organizationProposal = await testSetup.genericScheme.organizationsProposals(testSetup.org.avatar.address,proposalId); - assert.equal(organizationProposal.exist,true);//new contract address - assert.equal(organizationProposal.passed,true);//new contract address - //can call execute - await testSetup.genericScheme.execute(testSetup.org.avatar.address, proposalId); - await helpers.increaseTime(1001); - await testSetup.genericScheme.execute(testSetup.org.avatar.address, proposalId); - - organizationProposal = await testSetup.genericScheme.organizationsProposals(testSetup.org.avatar.address,proposalId); - assert.equal(organizationProposal.exist,false);//new contract address - assert.equal(organizationProposal.passed,false);//new contract address - try { - await testSetup.genericScheme.execute(testSetup.org.avatar.address, proposalId); - assert(false, "cannot call execute after it been executed"); - } catch(error) { - helpers.assertVMException(error); - } - }); - - - - it("execute proposeVote without return value-positive decision - check action", async function() { - var actionMock =await ActionMock.new(); - var testSetup = await setup(accounts,actionMock.address); - const encodeABI = await new web3.eth.Contract(actionMock.abi).methods.withoutReturnValue(testSetup.org.avatar.address).encodeABI(); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,encodeABI,0,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - - await testSetup.genericSchemeParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); - - }); - - it("execute should fail if not executed from votingMachine", async function() { - var actionMock =await ActionMock.new(); - var testSetup = await setup(accounts,actionMock.address); - const encodeABI = await new web3.eth.Contract(actionMock.abi).methods.withoutReturnValue(testSetup.org.avatar.address).encodeABI(); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,encodeABI,0,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - - try { - await testSetup.genericScheme.execute(testSetup.org.avatar.address, proposalId); - assert(false, "execute should fail if not executed from votingMachine"); - } catch(error) { - helpers.assertVMException(error); - } - - }); - - it("execute proposeVote -positive decision - check action - with GenesisProtocol", async function() { - var actionMock =await ActionMock.new(); - var standardTokenMock = await ERC20Mock.new(accounts[0],1000); - var testSetup = await setup(accounts,actionMock.address,0,true,standardTokenMock.address); - var value = 123; - var callData = await createCallToActionMock(testSetup.org.avatar.address,actionMock); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,callData,value,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - //transfer some eth to avatar - await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value: web3.utils.toWei('1', "ether")}); - assert.equal(await web3.eth.getBalance(actionMock.address),0); - tx = await testSetup.genericSchemeParams.votingMachine.genesisProtocol.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); - await testSetup.genericScheme.getPastEvents('ProposalExecutedByVotingMachine', { - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"ProposalExecutedByVotingMachine"); - assert.equal(events[0].args._param,1); - }); - assert.equal(await web3.eth.getBalance(actionMock.address),value); - }); - - it("execute proposeVote -negative decision - check action - with GenesisProtocol", async function() { - var actionMock =await ActionMock.new(); - var standardTokenMock = await ERC20Mock.new(accounts[0],1000); - var testSetup = await setup(accounts,actionMock.address,0,true,standardTokenMock.address); - - var callData = await createCallToActionMock(testSetup.org.avatar.address,actionMock); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,callData,0,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - tx = await testSetup.genericSchemeParams.votingMachine.genesisProtocol.vote(proposalId,2,0,helpers.NULL_ADDRESS,{from:accounts[2]}); - await testSetup.genericScheme.getPastEvents('ProposalExecutedByVotingMachine', { - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"ProposalExecutedByVotingMachine"); - assert.equal(events[0].args._param,2); - }); - }); - - it("Wallet - execute proposeVote -positive decision - check action - with GenesisProtocol", async function() { - var wallet =await Wallet.new(); - await web3.eth.sendTransaction({from:accounts[0],to:wallet.address, value: web3.utils.toWei('1', "ether")}); - var standardTokenMock = await ERC20Mock.new(accounts[0],1000); - var testSetup = await setup(accounts,wallet.address,0,true,standardTokenMock.address); - var callData = await new web3.eth.Contract(wallet.abi).methods.pay(accounts[1]).encodeABI(); - var tx = await testSetup.genericScheme.proposeCall(testSetup.org.avatar.address,callData,0,helpers.NULL_HASH); - var proposalId = await helpers.getValueFromLogs(tx, '_proposalId'); - assert.equal(await web3.eth.getBalance(wallet.address),web3.utils.toWei('1', "ether")); - await testSetup.genericSchemeParams.votingMachine.genesisProtocol.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); - assert.equal(await web3.eth.getBalance(wallet.address),web3.utils.toWei('1', "ether")); - await wallet.transferOwnership(testSetup.org.avatar.address); - await testSetup.genericScheme.execute(testSetup.org.avatar.address, proposalId); - assert.equal(await web3.eth.getBalance(wallet.address),0); - }); - -}); From 544b8536bcbbdc045fedc27d2cc6589afd29f799 Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Thu, 21 Nov 2019 09:48:50 +0200 Subject: [PATCH 2/2] remove universal controller --- contracts/controller/Controller.sol | 4 +- contracts/controller/ControllerInterface.sol | 204 ----- contracts/controller/UController.sol | 590 --------------- contracts/schemes/Auction4Reputation.sol | 4 +- .../ContinuousLockingToken4Reputation.sol | 4 +- .../schemes/FixedReputationAllocation.sol | 4 +- contracts/schemes/Forwarder.sol | 4 +- contracts/schemes/GenericScheme.sol | 2 +- contracts/schemes/Locking4Reputation.sol | 4 +- contracts/schemes/ReputationFromToken.sol | 4 +- contracts/schemes/SignalScheme.sol | 2 +- contracts/test/UniversalSchemeMock.sol | 4 +- .../universalSchemes/ContributionReward.sol | 10 +- contracts/universalSchemes/DaoCreator.sol | 33 +- .../GlobalConstraintRegistrar.sol | 4 +- .../universalSchemes/SchemeRegistrar.sol | 2 +- .../universalSchemes/UniversalScheme.sol | 6 +- contracts/universalSchemes/UpgradeScheme.sol | 2 +- .../VoteInOrganizationScheme.sol | 2 +- contracts/utils/DAOTracker.sol | 6 +- .../votingMachines/VotingMachineCallbacks.sol | 6 +- migrations/2_deploy_organization.js | 15 +- test/daocreator.js | 136 +--- test/daotracker.js | 6 +- test/forwarder.js | 16 +- test/helpers.js | 8 +- test/ucontroller.js | 700 ------------------ 27 files changed, 65 insertions(+), 1717 deletions(-) delete mode 100644 contracts/controller/ControllerInterface.sol delete mode 100644 contracts/controller/UController.sol delete mode 100644 test/ucontroller.js diff --git a/contracts/controller/Controller.sol b/contracts/controller/Controller.sol index 784d35f6..f7ce3d76 100644 --- a/contracts/controller/Controller.sol +++ b/contracts/controller/Controller.sol @@ -2,8 +2,6 @@ pragma solidity ^0.5.11; import "./Avatar.sol"; import "../globalConstraints/GlobalConstraintInterface.sol"; -import "./ControllerInterface.sol"; - /** * @title Controller contract @@ -11,7 +9,7 @@ import "./ControllerInterface.sol"; * It is subject to a set of schemes and constraints that determine its behavior. * Each scheme has it own parameters and operation permissions. */ -contract Controller is ControllerInterface { +contract Controller { struct Scheme { bytes32 paramsHash; // a hash "configuration" of the scheme diff --git a/contracts/controller/ControllerInterface.sol b/contracts/controller/ControllerInterface.sol deleted file mode 100644 index 9790ec27..00000000 --- a/contracts/controller/ControllerInterface.sol +++ /dev/null @@ -1,204 +0,0 @@ -pragma solidity ^0.5.11; - -import "./Avatar.sol"; -import "../globalConstraints/GlobalConstraintInterface.sol"; - -/** - * @title Controller contract - * @dev A controller controls the organizations tokens ,reputation and avatar. - * It is subject to a set of schemes and constraints that determine its behavior. - * Each scheme has it own parameters and operation permissions. - */ -interface ControllerInterface { - - /** - * @dev Mint `_amount` of reputation that are assigned to `_to` . - * @param _amount amount of reputation to mint - * @param _to beneficiary address - * @return bool which represents a success - */ - function mintReputation(uint256 _amount, address _to, address _avatar) - external - returns(bool); - - /** - * @dev Burns `_amount` of reputation from `_from` - * @param _amount amount of reputation to burn - * @param _from The address that will lose the reputation - * @return bool which represents a success - */ - function burnReputation(uint256 _amount, address _from, address _avatar) - external - returns(bool); - - /** - * @dev mint tokens . - * @param _amount amount of token to mint - * @param _beneficiary beneficiary address - * @param _avatar address - * @return bool which represents a success - */ - function mintTokens(uint256 _amount, address _beneficiary, address _avatar) - external - returns(bool); - - /** - * @dev register or update a scheme - * @param _scheme the address of the scheme - * @param _paramsHash a hashed configuration of the usage of the scheme - * @param _permissions the permissions the new scheme will have - * @param _avatar address - * @return bool which represents a success - */ - function registerScheme(address _scheme, bytes32 _paramsHash, bytes4 _permissions, address _avatar) - external - returns(bool); - - /** - * @dev unregister a scheme - * @param _avatar address - * @param _scheme the address of the scheme - * @return bool which represents a success - */ - function unregisterScheme(address _scheme, address _avatar) - external - returns(bool); - - /** - * @dev unregister the caller's scheme - * @param _avatar address - * @return bool which represents a success - */ - function unregisterSelf(address _avatar) external returns(bool); - - /** - * @dev add or update Global Constraint - * @param _globalConstraint the address of the global constraint to be added. - * @param _params the constraint parameters hash. - * @param _avatar the avatar of the organization - * @return bool which represents a success - */ - function addGlobalConstraint(address _globalConstraint, bytes32 _params, address _avatar) - external returns(bool); - - /** - * @dev remove Global Constraint - * @param _globalConstraint the address of the global constraint to be remove. - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function removeGlobalConstraint (address _globalConstraint, address _avatar) - external returns(bool); - - /** - * @dev upgrade the Controller - * The function will trigger an event 'UpgradeController'. - * @param _newController the address of the new controller. - * @param _avatar address - * @return bool which represents a success - */ - function upgradeController(address _newController, Avatar _avatar) - external returns(bool); - - /** - * @dev perform a generic call to an arbitrary contract - * @param _contract the contract's address to call - * @param _data ABI-encoded contract call to call `_contract` address. - * @param _avatar the controller's avatar address - * @param _value value (ETH) to transfer with the transaction - * @return bool -success - * bytes - the return value of the called _contract's function. - */ - function genericCall(address _contract, bytes calldata _data, Avatar _avatar, uint256 _value) - external - returns(bool, bytes memory); - - /** - * @dev send some ether - * @param _amountInWei the amount of ether (in Wei) to send - * @param _to address of the beneficiary - * @param _avatar address - * @return bool which represents a success - */ - function sendEther(uint256 _amountInWei, address payable _to, Avatar _avatar) - external returns(bool); - - /** - * @dev send some amount of arbitrary ERC20 Tokens - * @param _externalToken the address of the Token Contract - * @param _to address of the beneficiary - * @param _value the amount of ether (in Wei) to send - * @param _avatar address - * @return bool which represents a success - */ - function externalTokenTransfer(IERC20 _externalToken, address _to, uint256 _value, Avatar _avatar) - external - returns(bool); - - /** - * @dev transfer token "from" address "to" address - * One must to approve the amount of tokens which can be spend from the - * "from" account.This can be done using externalTokenApprove. - * @param _externalToken the address of the Token Contract - * @param _from address of the account to send from - * @param _to address of the beneficiary - * @param _value the amount of ether (in Wei) to send - * @param _avatar address - * @return bool which represents a success - */ - function externalTokenTransferFrom( - IERC20 _externalToken, - address _from, - address _to, - uint256 _value, - Avatar _avatar) - external - returns(bool); - - /** - * @dev externalTokenApproval approve the spender address to spend a specified amount of tokens - * on behalf of msg.sender. - * @param _externalToken the address of the Token Contract - * @param _spender address - * @param _value the amount of ether (in Wei) which the approval is referring to. - * @return bool which represents a success - */ - function externalTokenApproval(IERC20 _externalToken, address _spender, uint256 _value, Avatar _avatar) - external - returns(bool); - - /** - * @dev metaData emits an event with a string, should contain the hash of some meta data. - * @param _metaData a string representing a hash of the meta data - * @param _avatar Avatar - * @return bool which represents a success - */ - function metaData(string calldata _metaData, Avatar _avatar) external returns(bool); - - /** - * @dev getNativeReputation - * @param _avatar the organization avatar. - * @return organization native reputation - */ - function getNativeReputation(address _avatar) - external - view - returns(address); - - function isSchemeRegistered( address _scheme, address _avatar) external view returns(bool); - - function getSchemeParameters(address _scheme, address _avatar) external view returns(bytes32); - - function getGlobalConstraintParameters(address _globalConstraint, address _avatar) external view returns(bytes32); - - function getSchemePermissions(address _scheme, address _avatar) external view returns(bytes4); - - /** - * @dev globalConstraintsCount return the global constraint pre and post count - * @return uint256 globalConstraintsPre count. - * @return uint256 globalConstraintsPost count. - */ - function globalConstraintsCount(address _avatar) external view returns(uint, uint); - - function isGlobalConstraintRegistered(address _globalConstraint, address _avatar) external view returns(bool); -} diff --git a/contracts/controller/UController.sol b/contracts/controller/UController.sol deleted file mode 100644 index 3f53ad05..00000000 --- a/contracts/controller/UController.sol +++ /dev/null @@ -1,590 +0,0 @@ -pragma solidity ^0.5.11; - -import "./Avatar.sol"; -import "../globalConstraints/GlobalConstraintInterface.sol"; -import "./ControllerInterface.sol"; - - -/** - * @title Universal Controller contract - * @dev A universal controller hold organizations and controls their tokens ,reputations - * and avatar. - * It is subject to a set of schemes and constraints that determine its behavior. - * Each scheme has it own parameters and operation permissions. - */ -contract UController is ControllerInterface { - - struct Scheme { - bytes32 paramsHash; // a hash "configuration" of the scheme - bytes4 permissions; // A bitwise flags of permissions, - // All 0: Not registered, - // 1st bit: Flag if the scheme is registered, - // 2nd bit: Scheme can register other schemes - // 3th bit: Scheme can add/remove global constraints - // 4rd bit: Scheme can upgrade the controller - // 5th bit: Scheme can call delegatecall - } - - struct GlobalConstraint { - address gcAddress; - bytes32 params; - } - - struct GlobalConstraintRegister { - bool isRegistered; //is registered - uint256 index; //index at globalConstraints - } - - struct Organization { - DAOToken nativeToken; - Reputation nativeReputation; - mapping(address=>Scheme) schemes; - // globalConstraintsPre that determine pre- conditions for all actions on the controller - GlobalConstraint[] globalConstraintsPre; - // globalConstraintsPost that determine post-conditions for all actions on the controller - GlobalConstraint[] globalConstraintsPost; - // globalConstraintsRegisterPre indicate if a globalConstraints is registered as a Pre global constraint. - mapping(address=>GlobalConstraintRegister) globalConstraintsRegisterPre; - // globalConstraintsRegisterPost indicate if a globalConstraints is registered as a Post global constraint. - mapping(address=>GlobalConstraintRegister) globalConstraintsRegisterPost; - } - - //mapping between organization's avatar address to Organization - mapping(address=>Organization) public organizations; - // newController will point to the new controller after the present controller is upgraded - // address external newController; - mapping(address=>address) public newControllers;//mapping between avatar address and newController address - //mapping for all reputation system and tokens addresses registered. - mapping(address=>bool) public actors; - - event MintReputation (address indexed _sender, address indexed _to, uint256 _amount, address indexed _avatar); - event BurnReputation (address indexed _sender, address indexed _from, uint256 _amount, address indexed _avatar); - event MintTokens (address indexed _sender, address indexed _beneficiary, uint256 _amount, address indexed _avatar); - event RegisterScheme (address indexed _sender, address indexed _scheme, address indexed _avatar); - event UnregisterScheme (address indexed _sender, address indexed _scheme, address indexed _avatar); - event UpgradeController(address indexed _oldController, address _newController, address _avatar); - - event AddGlobalConstraint( - address indexed _globalConstraint, - bytes32 _params, - GlobalConstraintInterface.CallPhase _when, - address indexed _avatar - ); - - event RemoveGlobalConstraint( - address indexed _globalConstraint, - uint256 _index, - bool _isPre, - address indexed _avatar - ); - - /** - * @dev newOrganization set up a new organization with default daoCreator. - * @param _avatar the organization avatar - */ - function newOrganization( - Avatar _avatar - ) external - { - require(!actors[address(_avatar)]); - actors[address(_avatar)] = true; - require(_avatar.owner() == address(this)); - DAOToken nativeToken = _avatar.nativeToken(); - Reputation nativeReputation = _avatar.nativeReputation(); - require(nativeToken.owner() == address(this)); - require(nativeReputation.owner() == address(this)); - //To guaranty uniqueness for the reputation systems. - require(!actors[address(nativeReputation)]); - actors[address(nativeReputation)] = true; - //To guaranty uniqueness for the nativeToken. - require(!actors[address(nativeToken)]); - actors[address(nativeToken)] = true; - organizations[address(_avatar)].nativeToken = nativeToken; - organizations[address(_avatar)].nativeReputation = nativeReputation; - organizations[address(_avatar)].schemes[msg.sender] = - Scheme({paramsHash: bytes32(0), permissions: bytes4(0x0000001f)}); - emit RegisterScheme(msg.sender, msg.sender, address(_avatar)); - } - - // Modifiers: - modifier onlyRegisteredScheme(address avatar) { - require(organizations[avatar].schemes[msg.sender].permissions&bytes4(0x00000001) == bytes4(0x00000001)); - _; - } - - modifier onlyRegisteringSchemes(address avatar) { - require(organizations[avatar].schemes[msg.sender].permissions&bytes4(0x00000002) == bytes4(0x00000002)); - _; - } - - modifier onlyGlobalConstraintsScheme(address avatar) { - require(organizations[avatar].schemes[msg.sender].permissions&bytes4(0x00000004) == bytes4(0x00000004)); - _; - } - - modifier onlyUpgradingScheme(address _avatar) { - require(organizations[_avatar].schemes[msg.sender].permissions&bytes4(0x00000008) == bytes4(0x00000008)); - _; - } - - modifier onlyGenericCallScheme(address _avatar) { - require(organizations[_avatar].schemes[msg.sender].permissions&bytes4(0x00000010) == bytes4(0x00000010)); - _; - } - - modifier onlyMetaDataScheme(address _avatar) { - require(organizations[_avatar].schemes[msg.sender].permissions&bytes4(0x00000010) == bytes4(0x00000010)); - _; - } - - modifier onlySubjectToConstraint(bytes32 func, address _avatar) { - uint256 idx; - GlobalConstraint[] memory globalConstraintsPre = organizations[_avatar].globalConstraintsPre; - GlobalConstraint[] memory globalConstraintsPost = organizations[_avatar].globalConstraintsPost; - for (idx = 0; idx < globalConstraintsPre.length; idx++) { - require( - (GlobalConstraintInterface(globalConstraintsPre[idx].gcAddress)) - .pre(msg.sender, globalConstraintsPre[idx].params, func)); - } - _; - for (idx = 0; idx < globalConstraintsPost.length; idx++) { - require( - (GlobalConstraintInterface(globalConstraintsPost[idx].gcAddress)) - .post(msg.sender, globalConstraintsPost[idx].params, func)); - } - } - - /** - * @dev Mint `_amount` of reputation that are assigned to `_to` . - * @param _amount amount of reputation to mint - * @param _to beneficiary address - * @param _avatar the address of the organization's avatar - * @return bool which represents a success - */ - function mintReputation(uint256 _amount, address _to, address _avatar) - external - onlyRegisteredScheme(_avatar) - onlySubjectToConstraint("mintReputation", _avatar) - returns(bool) - { - emit MintReputation(msg.sender, _to, _amount, _avatar); - return organizations[_avatar].nativeReputation.mint(_to, _amount); - } - - /** - * @dev Burns `_amount` of reputation from `_from` - * @param _amount amount of reputation to burn - * @param _from The address that will lose the reputation - * @return bool which represents a success - */ - function burnReputation(uint256 _amount, address _from, address _avatar) - external - onlyRegisteredScheme(_avatar) - onlySubjectToConstraint("burnReputation", _avatar) - returns(bool) - { - emit BurnReputation(msg.sender, _from, _amount, _avatar); - return organizations[_avatar].nativeReputation.burn(_from, _amount); - } - - /** - * @dev mint tokens . - * @param _amount amount of token to mint - * @param _beneficiary beneficiary address - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function mintTokens(uint256 _amount, address _beneficiary, address _avatar) - external - onlyRegisteredScheme(_avatar) - onlySubjectToConstraint("mintTokens", _avatar) - returns(bool) - { - emit MintTokens(msg.sender, _beneficiary, _amount, _avatar); - return organizations[_avatar].nativeToken.mint(_beneficiary, _amount); - } - - /** - * @dev register or update a scheme - * @param _scheme the address of the scheme - * @param _paramsHash a hashed configuration of the usage of the scheme - * @param _permissions the permissions the new scheme will have - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function registerScheme(address _scheme, bytes32 _paramsHash, bytes4 _permissions, address _avatar) - external - onlyRegisteringSchemes(_avatar) - onlySubjectToConstraint("registerScheme", _avatar) - returns(bool) - { - bytes4 schemePermission = organizations[_avatar].schemes[_scheme].permissions; - bytes4 senderPermission = organizations[_avatar].schemes[msg.sender].permissions; - // Check scheme has at least the permissions it is changing, and at least the current permissions: - // Implementation is a bit messy. One must recall logic-circuits ^^ - - // produces non-zero if sender does not have all of the perms that are changing between old and new - require(bytes4(0x0000001f)&(_permissions^schemePermission)&(~senderPermission) == bytes4(0)); - - // produces non-zero if sender does not have all of the perms in the old scheme - require(bytes4(0x0000001f)&(schemePermission&(~senderPermission)) == bytes4(0)); - - // Add or change the scheme: - organizations[_avatar].schemes[_scheme] = - Scheme({paramsHash:_paramsHash, permissions:_permissions|bytes4(0x00000001)}); - emit RegisterScheme(msg.sender, _scheme, _avatar); - return true; - } - - /** - * @dev unregister a scheme - * @param _scheme the address of the scheme - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function unregisterScheme(address _scheme, address _avatar) - external - onlyRegisteringSchemes(_avatar) - onlySubjectToConstraint("unregisterScheme", _avatar) - returns(bool) - { - bytes4 schemePermission = organizations[_avatar].schemes[_scheme].permissions; - //check if the scheme is registered - if (schemePermission&bytes4(0x00000001) == bytes4(0)) { - return false; - } - // Check the unregistering scheme has enough permissions: - require( - bytes4(0x0000001f)&(schemePermission&(~organizations[_avatar].schemes[msg.sender].permissions)) == bytes4(0)); - - // Unregister: - emit UnregisterScheme(msg.sender, _scheme, _avatar); - delete organizations[_avatar].schemes[_scheme]; - return true; - } - - /** - * @dev unregister the caller's scheme - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function unregisterSelf(address _avatar) external returns(bool) { - if (_isSchemeRegistered(msg.sender, _avatar) == false) { - return false; - } - delete organizations[_avatar].schemes[msg.sender]; - emit UnregisterScheme(msg.sender, msg.sender, _avatar); - return true; - } - - /** - * @dev add or update Global Constraint - * @param _globalConstraint the address of the global constraint to be added. - * @param _params the constraint parameters hash. - * @param _avatar the avatar of the organization - * @return bool which represents a success - */ - function addGlobalConstraint(address _globalConstraint, bytes32 _params, address _avatar) - external onlyGlobalConstraintsScheme(_avatar) returns(bool) - { - Organization storage organization = organizations[_avatar]; - GlobalConstraintInterface.CallPhase when = GlobalConstraintInterface(_globalConstraint).when(); - if ((when == GlobalConstraintInterface.CallPhase.Pre)|| - (when == GlobalConstraintInterface.CallPhase.PreAndPost)) { - if (!organization.globalConstraintsRegisterPre[_globalConstraint].isRegistered) { - organization.globalConstraintsPre.push(GlobalConstraint(_globalConstraint, _params)); - organization.globalConstraintsRegisterPre[_globalConstraint] = - GlobalConstraintRegister(true, organization.globalConstraintsPre.length-1); - }else { - organization - .globalConstraintsPre[organization.globalConstraintsRegisterPre[_globalConstraint].index] - .params = _params; - } - } - - if ((when == GlobalConstraintInterface.CallPhase.Post)|| - (when == GlobalConstraintInterface.CallPhase.PreAndPost)) { - if (!organization.globalConstraintsRegisterPost[_globalConstraint].isRegistered) { - organization.globalConstraintsPost.push(GlobalConstraint(_globalConstraint, _params)); - organization.globalConstraintsRegisterPost[_globalConstraint] = - GlobalConstraintRegister(true, organization.globalConstraintsPost.length-1); - } else { - organization - .globalConstraintsPost[organization.globalConstraintsRegisterPost[_globalConstraint].index] - .params = _params; - } - } - emit AddGlobalConstraint(_globalConstraint, _params, when, _avatar); - return true; - } - - /** - * @dev remove Global Constraint - * @param _globalConstraint the address of the global constraint to be remove. - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function removeGlobalConstraint (address _globalConstraint, address _avatar) - external onlyGlobalConstraintsScheme(_avatar) returns(bool) - { - GlobalConstraintInterface.CallPhase when = GlobalConstraintInterface(_globalConstraint).when(); - if ((when == GlobalConstraintInterface.CallPhase.Pre)|| - (when == GlobalConstraintInterface.CallPhase.PreAndPost)) { - removeGlobalConstraintPre(_globalConstraint, _avatar); - } - if ((when == GlobalConstraintInterface.CallPhase.Post)|| - (when == GlobalConstraintInterface.CallPhase.PreAndPost)) { - removeGlobalConstraintPost(_globalConstraint, _avatar); - } - return true; - } - - /** - * @dev upgrade the Controller - * The function will trigger an event 'UpgradeController'. - * @param _newController the address of the new controller. - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function upgradeController(address _newController, Avatar _avatar) - external onlyUpgradingScheme(address(_avatar)) returns(bool) - { - require(newControllers[address(_avatar)] == address(0)); // so the upgrade could be done once for a contract. - require(_newController != address(0)); - newControllers[address(_avatar)] = _newController; - _avatar.transferOwnership(_newController); - require(_avatar.owner() == _newController); - if (organizations[address(_avatar)].nativeToken.owner() == address(this)) { - organizations[address(_avatar)].nativeToken.transferOwnership(_newController); - require(organizations[address(_avatar)].nativeToken.owner() == _newController); - } - if (organizations[address(_avatar)].nativeReputation.owner() == address(this)) { - organizations[address(_avatar)].nativeReputation.transferOwnership(_newController); - require(organizations[address(_avatar)].nativeReputation.owner() == _newController); - } - emit UpgradeController(address(this), _newController, address(_avatar)); - return true; - } - - /** - * @dev perform a generic call to an arbitrary contract - * @param _contract the contract's address to call - * @param _data ABI-encoded contract call to call `_contract` address. - * @param _avatar the controller's avatar address - * @param _value value (ETH) to transfer with the transaction - * @return bool -success - * bytes - the return value of the called _contract's function. - */ - function genericCall(address _contract, bytes calldata _data, Avatar _avatar, uint256 _value) - external - onlyGenericCallScheme(address(_avatar)) - onlySubjectToConstraint("genericCall", address(_avatar)) - returns (bool, bytes memory) - { - return _avatar.genericCall(_contract, _data, _value); - } - - /** - * @dev send some ether - * @param _amountInWei the amount of ether (in Wei) to send - * @param _to address of the beneficiary - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function sendEther(uint256 _amountInWei, address payable _to, Avatar _avatar) - external - onlyRegisteredScheme(address(_avatar)) - onlySubjectToConstraint("sendEther", address(_avatar)) - returns(bool) - { - return _avatar.sendEther(_amountInWei, _to); - } - - /** - * @dev send some amount of arbitrary ERC20 Tokens - * @param _externalToken the address of the Token Contract - * @param _to address of the beneficiary - * @param _value the amount of ether (in Wei) to send - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function externalTokenTransfer(IERC20 _externalToken, address _to, uint256 _value, Avatar _avatar) - external - onlyRegisteredScheme(address(_avatar)) - onlySubjectToConstraint("externalTokenTransfer", address(_avatar)) - returns(bool) - { - return _avatar.externalTokenTransfer(_externalToken, _to, _value); - } - - /** - * @dev transfer token "from" address "to" address - * One must to approve the amount of tokens which can be spend from the - * "from" account.This can be done using externalTokenApprove. - * @param _externalToken the address of the Token Contract - * @param _from address of the account to send from - * @param _to address of the beneficiary - * @param _value the amount of ether (in Wei) to send - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function externalTokenTransferFrom( - IERC20 _externalToken, - address _from, - address _to, - uint256 _value, - Avatar _avatar) - external - onlyRegisteredScheme(address(_avatar)) - onlySubjectToConstraint("externalTokenTransferFrom", address(_avatar)) - returns(bool) - { - return _avatar.externalTokenTransferFrom(_externalToken, _from, _to, _value); - } - - /** - * @dev externalTokenApproval approve the spender address to spend a specified amount of tokens - * on behalf of msg.sender. - * @param _externalToken the address of the Token Contract - * @param _spender address - * @param _value the amount of ether (in Wei) which the approval is referring to. - * @return bool which represents a success - */ - function externalTokenApproval(IERC20 _externalToken, address _spender, uint256 _value, Avatar _avatar) - external - onlyRegisteredScheme(address(_avatar)) - onlySubjectToConstraint("externalTokenApproval", address(_avatar)) - returns(bool) - { - return _avatar.externalTokenApproval(_externalToken, _spender, _value); - } - - /** - * @dev metaData emits an event with a string, should contain the hash of some meta data. - * @param _metaData a string representing a hash of the meta data - * @param _avatar Avatar - * @return bool which represents a success - */ - function metaData(string calldata _metaData, Avatar _avatar) - external - onlyMetaDataScheme(address(_avatar)) - returns(bool) - { - return _avatar.metaData(_metaData); - } - - function isSchemeRegistered( address _scheme, address _avatar) external view returns(bool) { - return _isSchemeRegistered(_scheme, _avatar); - } - - function getSchemeParameters(address _scheme, address _avatar) external view returns(bytes32) { - return organizations[_avatar].schemes[_scheme].paramsHash; - } - - function getSchemePermissions(address _scheme, address _avatar) external view returns(bytes4) { - return organizations[_avatar].schemes[_scheme].permissions; - } - - function getGlobalConstraintParameters(address _globalConstraint, address _avatar) external view returns(bytes32) { - - Organization storage organization = organizations[_avatar]; - - GlobalConstraintRegister memory register = organization.globalConstraintsRegisterPre[_globalConstraint]; - - if (register.isRegistered) { - return organization.globalConstraintsPre[register.index].params; - } - - register = organization.globalConstraintsRegisterPost[_globalConstraint]; - - if (register.isRegistered) { - return organization.globalConstraintsPost[register.index].params; - } - } - - /** - * @dev globalConstraintsCount return the global constraint pre and post count - * @return uint256 globalConstraintsPre count. - * @return uint256 globalConstraintsPost count. - */ - function globalConstraintsCount(address _avatar) external view returns(uint, uint) { - return ( - organizations[_avatar].globalConstraintsPre.length, - organizations[_avatar].globalConstraintsPost.length - ); - } - - function isGlobalConstraintRegistered(address _globalConstraint, address _avatar) external view returns(bool) { - return (organizations[_avatar].globalConstraintsRegisterPre[_globalConstraint].isRegistered || - organizations[_avatar].globalConstraintsRegisterPost[_globalConstraint].isRegistered); - } - - /** - * @dev getNativeReputation - * @param _avatar the organization avatar. - * @return organization native reputation - */ - function getNativeReputation(address _avatar) external view returns(address) { - return address(organizations[_avatar].nativeReputation); - } - - /** - * @dev removeGlobalConstraintPre - * @param _globalConstraint the address of the global constraint to be remove. - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function removeGlobalConstraintPre(address _globalConstraint, address _avatar) - private returns(bool) - { - GlobalConstraintRegister memory globalConstraintRegister = - organizations[_avatar].globalConstraintsRegisterPre[_globalConstraint]; - GlobalConstraint[] storage globalConstraints = organizations[_avatar].globalConstraintsPre; - - if (globalConstraintRegister.isRegistered) { - if (globalConstraintRegister.index < globalConstraints.length-1) { - GlobalConstraint memory globalConstraint = globalConstraints[globalConstraints.length-1]; - globalConstraints[globalConstraintRegister.index] = globalConstraint; - organizations[_avatar].globalConstraintsRegisterPre[globalConstraint.gcAddress].index = - globalConstraintRegister.index; - } - globalConstraints.length--; - delete organizations[_avatar].globalConstraintsRegisterPre[_globalConstraint]; - emit RemoveGlobalConstraint(_globalConstraint, globalConstraintRegister.index, true, _avatar); - return true; - } - return false; - } - - /** - * @dev removeGlobalConstraintPost - * @param _globalConstraint the address of the global constraint to be remove. - * @param _avatar the organization avatar. - * @return bool which represents a success - */ - function removeGlobalConstraintPost(address _globalConstraint, address _avatar) - private returns(bool) - { - GlobalConstraintRegister memory globalConstraintRegister = - organizations[_avatar].globalConstraintsRegisterPost[_globalConstraint]; - GlobalConstraint[] storage globalConstraints = organizations[_avatar].globalConstraintsPost; - - if (globalConstraintRegister.isRegistered) { - if (globalConstraintRegister.index < globalConstraints.length-1) { - GlobalConstraint memory globalConstraint = globalConstraints[globalConstraints.length-1]; - globalConstraints[globalConstraintRegister.index] = globalConstraint; - organizations[_avatar].globalConstraintsRegisterPost[globalConstraint.gcAddress].index = - globalConstraintRegister.index; - } - globalConstraints.length--; - delete organizations[_avatar].globalConstraintsRegisterPost[_globalConstraint]; - emit RemoveGlobalConstraint(_globalConstraint, globalConstraintRegister.index, false, _avatar); - return true; - } - return false; - } - - function _isSchemeRegistered( address _scheme, address _avatar) private view returns(bool) { - return (organizations[_avatar].schemes[_scheme].permissions&bytes4(0x00000001) != bytes4(0)); - } -} diff --git a/contracts/schemes/Auction4Reputation.sol b/contracts/schemes/Auction4Reputation.sol index 71a3b835..7c07da14 100644 --- a/contracts/schemes/Auction4Reputation.sol +++ b/contracts/schemes/Auction4Reputation.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.11; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; import "../libs/SafeERC20.sol"; import "./Agreement.sol"; @@ -104,7 +104,7 @@ contract Auction4Reputation is Agreement { // check that the reputation is sum zero reputationRewardLeft = reputationRewardLeft.sub(reputation); require( - ControllerInterface(avatar.owner()) + Controller(avatar.owner()) .mintReputation(reputation, _beneficiary, address(avatar)), "mint reputation should succeed"); emit Redeem(_auctionId, _beneficiary, reputation); } diff --git a/contracts/schemes/ContinuousLockingToken4Reputation.sol b/contracts/schemes/ContinuousLockingToken4Reputation.sol index 855aed4d..0bb13437 100644 --- a/contracts/schemes/ContinuousLockingToken4Reputation.sol +++ b/contracts/schemes/ContinuousLockingToken4Reputation.sol @@ -2,7 +2,7 @@ pragma solidity ^0.5.11; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/math/Math.sol"; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; import "../libs/SafeERC20.sol"; import "./Agreement.sol"; import { RealMath } from "@daostack/infra/contracts/libs/RealMath.sol"; @@ -151,7 +151,7 @@ contract ContinuousLocking4Reputation is Agreement { // check that the reputation is sum zero reputationRewardLeft = reputationRewardLeft.sub(reputation); require( - ControllerInterface(avatar.owner()) + Controller(avatar.owner()) .mintReputation(reputation, _beneficiary, address(avatar)), "mint reputation should succeed"); } diff --git a/contracts/schemes/FixedReputationAllocation.sol b/contracts/schemes/FixedReputationAllocation.sol index 252572c2..af29d7e7 100644 --- a/contracts/schemes/FixedReputationAllocation.sol +++ b/contracts/schemes/FixedReputationAllocation.sol @@ -1,6 +1,6 @@ pragma solidity ^0.5.11; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; @@ -51,7 +51,7 @@ contract FixedReputationAllocation is Ownable { // solhint-disable-next-line not-rely-on-time require(now > redeemEnableTime, "require now > redeemEnableTime"); require( - ControllerInterface( + Controller( avatar.owner()) .mintReputation(beneficiaryReward, _beneficiary, address(avatar)), "mint reputation failed"); diff --git a/contracts/schemes/Forwarder.sol b/contracts/schemes/Forwarder.sol index 4dacc59a..12489e55 100644 --- a/contracts/schemes/Forwarder.sol +++ b/contracts/schemes/Forwarder.sol @@ -1,6 +1,6 @@ pragma solidity ^0.5.11; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; /** @@ -45,6 +45,6 @@ contract Forwarder is Ownable { function unregisterSelf() public returns(bool) { // solhint-disable-next-line not-rely-on-time require(expirationTime <= now, "expirationTime <= now"); - return ControllerInterface(avatar.owner()).unregisterSelf(address(avatar)); + return Controller(avatar.owner()).unregisterSelf(address(avatar)); } } diff --git a/contracts/schemes/GenericScheme.sol b/contracts/schemes/GenericScheme.sol index 625bea7a..f1070fee 100644 --- a/contracts/schemes/GenericScheme.sol +++ b/contracts/schemes/GenericScheme.sol @@ -108,7 +108,7 @@ contract GenericScheme is VotingMachineCallbacks, ProposalExecuteInterface { proposal.exist = false; bytes memory genericCallReturnValue; bool success; - ControllerInterface controller = ControllerInterface(avatar.owner()); + Controller controller = Controller(avatar.owner()); (success, genericCallReturnValue) = controller.genericCall(contractToCall, proposal.callData, avatar, proposal.value); if (success) { diff --git a/contracts/schemes/Locking4Reputation.sol b/contracts/schemes/Locking4Reputation.sol index 10153f9c..77775971 100644 --- a/contracts/schemes/Locking4Reputation.sol +++ b/contracts/schemes/Locking4Reputation.sol @@ -1,6 +1,6 @@ pragma solidity ^0.5.11; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; import "./Agreement.sol"; /** @@ -54,7 +54,7 @@ contract Locking4Reputation is Agreement { //check that the reputation is sum zero reputationRewardLeft = reputationRewardLeft.sub(reputation); require( - ControllerInterface( + Controller( avatar.owner()) .mintReputation(reputation, _beneficiary, address(avatar)), "mint reputation should succeed"); diff --git a/contracts/schemes/ReputationFromToken.sol b/contracts/schemes/ReputationFromToken.sol index ab5b1ae9..33bed86d 100644 --- a/contracts/schemes/ReputationFromToken.sol +++ b/contracts/schemes/ReputationFromToken.sol @@ -1,6 +1,6 @@ pragma solidity ^0.5.11; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./CurveInterface.sol"; import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; @@ -124,7 +124,7 @@ contract ReputationFromToken is Agreement { _beneficiary = _redeemer; } require( - ControllerInterface( + Controller( avatar.owner()) .mintReputation(tokenAmount, _beneficiary, address(avatar)), "mint reputation should succeed"); emit Redeem(_beneficiary, _redeemer, tokenAmount); diff --git a/contracts/schemes/SignalScheme.sol b/contracts/schemes/SignalScheme.sol index 62121b7e..3a19bcad 100644 --- a/contracts/schemes/SignalScheme.sol +++ b/contracts/schemes/SignalScheme.sol @@ -74,7 +74,7 @@ contract SignalScheme is VotingMachineCallbacks, ProposalExecuteInterface { external returns(bytes32) { - require(ControllerInterface(params.avatar.owner()).isSchemeRegistered(address(this), address(params.avatar)), + require(Controller(params.avatar.owner()).isSchemeRegistered(address(this), address(params.avatar)), "scheme is not registered"); bytes32 proposalId = params.intVote.propose( diff --git a/contracts/test/UniversalSchemeMock.sol b/contracts/test/UniversalSchemeMock.sol index a057a45f..5c35cc45 100644 --- a/contracts/test/UniversalSchemeMock.sol +++ b/contracts/test/UniversalSchemeMock.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.11; import "../universalSchemes/UniversalScheme.sol"; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; contract UniversalSchemeMock is UniversalScheme { @@ -11,7 +11,7 @@ contract UniversalSchemeMock is UniversalScheme { { address controller = _avatar.owner(); - return ControllerInterface(controller).genericCall( + return Controller(controller).genericCall( _contract, abi.encodeWithSignature("test(uint256,address,bytes32)", _a, _b, _c), _avatar, _value); } diff --git a/contracts/universalSchemes/ContributionReward.sol b/contracts/universalSchemes/ContributionReward.sol index a68fe62e..bde466ff 100644 --- a/contracts/universalSchemes/ContributionReward.sol +++ b/contracts/universalSchemes/ContributionReward.sol @@ -200,11 +200,11 @@ contract ContributionReward is UniversalScheme, VotingMachineCallbacks, Proposal reputation = int(periodsToPay) * _proposal.reputationChange; if (reputation > 0) { require( - ControllerInterface( + Controller( _avatar.owner()).mintReputation(uint(reputation), _proposal.beneficiary, address(_avatar))); } else if (reputation < 0) { require( - ControllerInterface( + Controller( _avatar.owner()).burnReputation(uint(reputation*(-1)), _proposal.beneficiary, address(_avatar))); } if (reputation != 0) { @@ -232,7 +232,7 @@ contract ContributionReward is UniversalScheme, VotingMachineCallbacks, Proposal amount = periodsToPay.mul(_proposal.nativeTokenReward); if (amount > 0) { - require(ControllerInterface(_avatar.owner()).mintTokens(amount, _proposal.beneficiary, address(_avatar))); + require(Controller(_avatar.owner()).mintTokens(amount, _proposal.beneficiary, address(_avatar))); proposal.redeemedPeriods[1] = proposal.redeemedPeriods[1].add(periodsToPay); emit RedeemNativeToken(address(_avatar), _proposalId, _proposal.beneficiary, amount); } @@ -258,7 +258,7 @@ contract ContributionReward is UniversalScheme, VotingMachineCallbacks, Proposal amount = periodsToPay.mul(_proposal.ethReward); if (amount > 0) { - require(ControllerInterface(_avatar.owner()).sendEther(amount, _proposal.beneficiary, _avatar)); + require(Controller(_avatar.owner()).sendEther(amount, _proposal.beneficiary, _avatar)); proposal.redeemedPeriods[2] = proposal.redeemedPeriods[2].add(periodsToPay); emit RedeemEther(address(_avatar), _proposalId, _proposal.beneficiary, amount); } @@ -286,7 +286,7 @@ contract ContributionReward is UniversalScheme, VotingMachineCallbacks, Proposal amount = periodsToPay.mul(_proposal.externalTokenReward); if (amount > 0) { require( - ControllerInterface( + Controller( _avatar.owner()) .externalTokenTransfer(_proposal.externalToken, _proposal.beneficiary, amount, _avatar)); proposal.redeemedPeriods[3] = proposal.redeemedPeriods[3].add(periodsToPay); diff --git a/contracts/universalSchemes/DaoCreator.sol b/contracts/universalSchemes/DaoCreator.sol index dd6791a3..226bf1c0 100644 --- a/contracts/universalSchemes/DaoCreator.sol +++ b/contracts/universalSchemes/DaoCreator.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.11; import "./UniversalScheme.sol"; -import "../controller/UController.sol"; import "../controller/Controller.sol"; import "../utils/DAOTracker.sol"; @@ -67,11 +66,11 @@ contract DaoCreator { for (uint256 i = 0; i < _founders.length; i++) { require(_founders[i] != address(0)); if (_foundersTokenAmount[i] > 0) { - ControllerInterface( + Controller( _avatar.owner()).mintTokens(_foundersTokenAmount[i], _founders[i], address(_avatar)); } if (_foundersReputationAmount[i] > 0) { - ControllerInterface( + Controller( _avatar.owner()).mintReputation(_foundersReputationAmount[i], _founders[i], address(_avatar)); } } @@ -88,8 +87,6 @@ contract DaoCreator { * receive in the new organization * @param _foundersReputationAmount An array of amount of reputation that the * founders receive in the new organization - * @param _uController universal controller instance - * if _uController address equal to zero the organization will use none universal controller. * @param _cap token cap - 0 for no cap. * @return The address of the avatar of the controller */ @@ -100,7 +97,6 @@ contract DaoCreator { address[] calldata _founders, uint[] calldata _foundersTokenAmount, uint[] calldata _foundersReputationAmount, - UController _uController, uint256 _cap ) external @@ -114,7 +110,6 @@ contract DaoCreator { _founders, _foundersTokenAmount, _foundersReputationAmount, - _uController, _cap); } @@ -139,7 +134,7 @@ contract DaoCreator { // for this controller require(locks[address(_avatar)] == msg.sender); // register initial schemes: - ControllerInterface controller = ControllerInterface(_avatar.owner()); + Controller controller = Controller(_avatar.owner()); for (uint256 i = 0; i < _schemes.length; i++) { controller.registerScheme(_schemes[i], _params[i], _permissions[i], address(_avatar)); } @@ -161,8 +156,6 @@ contract DaoCreator { * receive in the new organization * @param _foundersReputationAmount An array of amount of reputation that the * founders receive in the new organization - * @param _uController universal controller instance - * if _uController address equal to zero the organization will use none universal controller. * @param _cap token cap - 0 for no cap. * @return The address of the avatar of the controller */ @@ -173,7 +166,6 @@ contract DaoCreator { address[] memory _founders, uint[] memory _foundersTokenAmount, uint[] memory _foundersReputationAmount, - UController _uController, uint256 _cap ) private returns(address) { @@ -181,10 +173,10 @@ contract DaoCreator { require(_founders.length == _foundersTokenAmount.length); require(_founders.length == _foundersReputationAmount.length); require(_founders.length > 0); - DAOToken nativeToken = new DAOToken(_tokenName, _tokenSymbol, _cap); - Reputation nativeReputation = new Reputation(); - Avatar avatar = new Avatar(_orgName, nativeToken, nativeReputation); - ControllerInterface controller; + DAOToken nativeToken = new DAOToken(_tokenName, _tokenSymbol, _cap); + Reputation nativeReputation = new Reputation(); + Avatar avatar = new Avatar(_orgName, nativeToken, nativeReputation); + // Mint token and reputation for founders: for (uint256 i = 0; i < _founders.length; i++) { @@ -197,12 +189,7 @@ contract DaoCreator { } } - // Create Controller: - if (UController(0) == _uController) { - controller = ControllerInterface(controllerCreator.create(avatar)); - } else { - controller = _uController; - } + Controller controller = Controller(controllerCreator.create(avatar)); // Add the DAO to the tracking registry daoTracker.track(avatar, controller, ""); @@ -212,10 +199,6 @@ contract DaoCreator { nativeToken.transferOwnership(address(controller)); nativeReputation.transferOwnership(address(controller)); - if (controller == _uController) { - _uController.newOrganization(avatar); - } - locks[address(avatar)] = msg.sender; emit NewOrg (address(avatar)); diff --git a/contracts/universalSchemes/GlobalConstraintRegistrar.sol b/contracts/universalSchemes/GlobalConstraintRegistrar.sol index b3ca63f8..ac35e646 100644 --- a/contracts/universalSchemes/GlobalConstraintRegistrar.sol +++ b/contracts/universalSchemes/GlobalConstraintRegistrar.sol @@ -73,7 +73,7 @@ contract GlobalConstraintRegistrar is UniversalScheme, VotingMachineCallbacks, P if (_param == 1) { // Define controller and get the params: - ControllerInterface controller = ControllerInterface(avatar.owner()); + Controller controller = Controller(avatar.owner()); // Adding a GC if (proposal.addGC) { @@ -162,7 +162,7 @@ contract GlobalConstraintRegistrar is UniversalScheme, VotingMachineCallbacks, P * @return bytes32 -the proposal id */ function proposeToRemoveGC(Avatar _avatar, address _gc, string memory _descriptionHash) public returns(bytes32) { - ControllerInterface controller = ControllerInterface(_avatar.owner()); + Controller controller = Controller(_avatar.owner()); require(controller.isGlobalConstraintRegistered(_gc, address(_avatar))); Parameters memory params = parameters[getParametersFromController(_avatar)]; IntVoteInterface intVote = params.intVote; diff --git a/contracts/universalSchemes/SchemeRegistrar.sol b/contracts/universalSchemes/SchemeRegistrar.sol index dc5afac9..3b20bf9f 100644 --- a/contracts/universalSchemes/SchemeRegistrar.sol +++ b/contracts/universalSchemes/SchemeRegistrar.sol @@ -66,7 +66,7 @@ contract SchemeRegistrar is UniversalScheme, VotingMachineCallbacks, ProposalExe if (_param == 1) { // Define controller and get the params: - ControllerInterface controller = ControllerInterface(avatar.owner()); + Controller controller = Controller(avatar.owner()); // Add a scheme: if (proposal.addScheme) { diff --git a/contracts/universalSchemes/UniversalScheme.sol b/contracts/universalSchemes/UniversalScheme.sol index f8cf69ee..73ebc316 100644 --- a/contracts/universalSchemes/UniversalScheme.sol +++ b/contracts/universalSchemes/UniversalScheme.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.11; import "./UniversalSchemeInterface.sol"; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; import "../controller/Avatar.sol"; @@ -10,8 +10,8 @@ contract UniversalScheme is UniversalSchemeInterface { * @dev get the parameters for the current scheme from the controller */ function getParametersFromController(Avatar _avatar) internal view returns(bytes32) { - require(ControllerInterface(_avatar.owner()).isSchemeRegistered(address(this), address(_avatar)), + require(Controller(_avatar.owner()).isSchemeRegistered(address(this), address(_avatar)), "scheme is not registered"); - return ControllerInterface(_avatar.owner()).getSchemeParameters(address(this), address(_avatar)); + return Controller(_avatar.owner()).getSchemeParameters(address(this), address(_avatar)); } } diff --git a/contracts/universalSchemes/UpgradeScheme.sol b/contracts/universalSchemes/UpgradeScheme.sol index 1a269d0c..267e10a5 100644 --- a/contracts/universalSchemes/UpgradeScheme.sol +++ b/contracts/universalSchemes/UpgradeScheme.sol @@ -66,7 +66,7 @@ contract UpgradeScheme is UniversalScheme, VotingMachineCallbacks, ProposalExecu if (_param == 1) { // Define controller and get the params: - ControllerInterface controller = ControllerInterface(avatar.owner()); + Controller controller = Controller(avatar.owner()); // Upgrading controller: if (proposal.proposalType == 1) { require(controller.upgradeController(proposal.upgradeContract, avatar)); diff --git a/contracts/universalSchemes/VoteInOrganizationScheme.sol b/contracts/universalSchemes/VoteInOrganizationScheme.sol index 039a9279..e15c0744 100644 --- a/contracts/universalSchemes/VoteInOrganizationScheme.sol +++ b/contracts/universalSchemes/VoteInOrganizationScheme.sol @@ -61,7 +61,7 @@ contract VoteInOrganizationScheme is UniversalScheme, VotingMachineCallbacks, Pr // If no decision do nothing: if (_param == 1) { - ControllerInterface controller = ControllerInterface(avatar.owner()); + Controller controller = Controller(avatar.owner()); (success, callReturnValue) = controller.genericCall( address(proposal.originalIntVote), abi.encodeWithSignature("vote(bytes32,uint256,uint256,address)", diff --git a/contracts/utils/DAOTracker.sol b/contracts/utils/DAOTracker.sol index 94bdbcee..db4089bd 100644 --- a/contracts/utils/DAOTracker.sol +++ b/contracts/utils/DAOTracker.sol @@ -3,7 +3,7 @@ pragma solidity ^0.5.11; import "@daostack/infra/contracts/Reputation.sol"; import "../controller/DAOToken.sol"; import "../controller/Avatar.sol"; -import "../controller/ControllerInterface.sol"; +import "../controller/Controller.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; /** @@ -58,14 +58,14 @@ contract DAOTracker is Ownable { * @param _avatar the organization avatar * @param _controller the organization controller */ - function track(Avatar _avatar, ControllerInterface _controller, string memory _arcVersion) + function track(Avatar _avatar, Controller _controller, string memory _arcVersion) public onlyAvatarOwner(_avatar) notBlacklisted(_avatar) { // Only allow the information to be set once. In the case of a controller upgrades, // the subgraph will be updated via the UpgradeController event. require(_avatar != Avatar(0)); - require(_controller != ControllerInterface(0)); + require(_controller != Controller(0)); emit TrackDAO( address(_avatar), diff --git a/contracts/votingMachines/VotingMachineCallbacks.sol b/contracts/votingMachines/VotingMachineCallbacks.sol index 8eb104c0..b16128a4 100644 --- a/contracts/votingMachines/VotingMachineCallbacks.sol +++ b/contracts/votingMachines/VotingMachineCallbacks.sol @@ -28,7 +28,7 @@ contract VotingMachineCallbacks is VotingMachineCallbacksInterface { if (avatar == Avatar(0)) { return false; } - return ControllerInterface(avatar.owner()).mintReputation(_amount, _beneficiary, address(avatar)); + return Controller(avatar.owner()).mintReputation(_amount, _beneficiary, address(avatar)); } function burnReputation(uint256 _amount, address _beneficiary, bytes32 _proposalId) @@ -40,7 +40,7 @@ contract VotingMachineCallbacks is VotingMachineCallbacksInterface { if (avatar == Avatar(0)) { return false; } - return ControllerInterface(avatar.owner()).burnReputation(_amount, _beneficiary, address(avatar)); + return Controller(avatar.owner()).burnReputation(_amount, _beneficiary, address(avatar)); } function stakingTokenTransfer( @@ -56,7 +56,7 @@ contract VotingMachineCallbacks is VotingMachineCallbacksInterface { if (avatar == Avatar(0)) { return false; } - return ControllerInterface(avatar.owner()).externalTokenTransfer(_stakingToken, _beneficiary, _amount, avatar); + return Controller(avatar.owner()).externalTokenTransfer(_stakingToken, _beneficiary, _amount, avatar); } function balanceOfStakingToken(IERC20 _stakingToken, bytes32 _proposalId) external view returns(uint256) { diff --git a/migrations/2_deploy_organization.js b/migrations/2_deploy_organization.js index fb6353b3..ad3ef4bb 100644 --- a/migrations/2_deploy_organization.js +++ b/migrations/2_deploy_organization.js @@ -1,7 +1,6 @@ //this migration file is used only for testing purpose var constants = require('../test/constants'); var Avatar = artifacts.require('./Avatar.sol'); -var UController = artifacts.require('./UController.sol'); var DaoCreator = artifacts.require('./DaoCreator.sol'); var GlobalConstraintRegistrar = artifacts.require('./GlobalConstraintRegistrar.sol'); var SchemeRegistrar = artifacts.require('./SchemeRegistrar.sol'); @@ -46,7 +45,7 @@ module.exports = async function(deployer) { await web3.eth.getAccounts(function(err,res) { accounts = res; }); founders[0] = accounts[0]; var returnedParams = await daoCreatorInst.forgeOrg(orgName, tokenName, tokenSymbol, founders, - initTokenInWei, initRepInWei,NULL_ADDRESS,cap,{gas: constants.ARC_GAS_LIMIT}); + initTokenInWei, initRepInWei,cap,{gas: constants.ARC_GAS_LIMIT}); var AvatarInst = await Avatar.at(returnedParams.logs[0].args._avatar); await deployer.deploy(AbsoluteVote,{gas: constants.ARC_GAS_LIMIT}); // Deploy AbsoluteVote: @@ -91,17 +90,5 @@ module.exports = async function(deployer) { paramsArray, permissionArray, "metaData"); - //now deploy with universal controller - await deployer.deploy(UController, {gas: constants.ARC_GAS_LIMIT}); - var uController = await UController.deployed(); - returnedParams = await daoCreatorInst.forgeOrg(orgName, tokenName, tokenSymbol, founders, - initTokenInWei, initRepInWei,uController.address,cap,{gas: constants.ARC_GAS_LIMIT}); - AvatarInst = await Avatar.at(returnedParams.logs[0].args._avatar); - await daoCreatorInst.setSchemes( - AvatarInst.address, - schemesArray, - paramsArray, - permissionArray, - "metaData"); }); }; diff --git a/test/daocreator.js b/test/daocreator.js index f7defbe3..c71c3292 100644 --- a/test/daocreator.js +++ b/test/daocreator.js @@ -5,24 +5,18 @@ const Reputation = artifacts.require("./Reputation.sol"); const DaoCreator = artifacts.require("./DaoCreator.sol"); const Avatar = artifacts.require("./Avatar.sol"); const Controller = artifacts.require("./Controller.sol"); -const UController = artifacts.require("./UController.sol"); const ERC20Mock = artifacts.require('./test/ERC20Mock.sol'); const UniversalSchemeMock = artifacts.require('./test/UniversalSchemeMock.sol'); const ControllerCreator = artifacts.require("./ControllerCreator.sol"); const DAOTracker = artifacts.require("./DAOTracker.sol"); const zeroBytes32 = helpers.NULL_HASH; -var avatar,token,reputation,daoCreator,uController,controllerCreator; -const setup = async function (accounts,founderToken,founderReputation,useUController=false,cap=0) { +var avatar,token,reputation,daoCreator,controllerCreator; +const setup = async function (accounts,founderToken,founderReputation,cap=0) { controllerCreator = await ControllerCreator.new({gas: constants.ARC_GAS_LIMIT}); var daoTracker = await DAOTracker.new({gas: constants.ARC_GAS_LIMIT}); daoCreator = await DaoCreator.new(controllerCreator.address,daoTracker.address,{gas:constants.ARC_GAS_LIMIT}); - var uControllerAddress = helpers.NULL_ADDRESS; - if (useUController){ - uController = await UController.new({gas:constants.ARC_GAS_LIMIT}); - uControllerAddress = uController.address; - } - var tx = await daoCreator.forgeOrg("testOrg","TEST","TST",[accounts[0]],[founderToken],[founderReputation],uControllerAddress,cap,{gas:constants.ARC_GAS_LIMIT}); + var tx = await daoCreator.forgeOrg("testOrg","TEST","TST",[accounts[0]],[founderToken],[founderReputation],cap,{gas:constants.ARC_GAS_LIMIT}); assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "NewOrg"); var avatarAddress = tx.logs[0].args._avatar; @@ -168,134 +162,14 @@ contract('DaoCreator', function(accounts) { helpers.assertVMException(ex); } }); - // test with universal controller - it("forgeOrg with universal controller check avatar", async function() { - await setup(accounts,10,10,true); - assert.equal(await avatar.orgName(),"testOrg"); - }); - - it("forgeOrg with universal controller check reputations and tokens to founders", async function() { - await setup(accounts,10,10,true); - var founderBalance = await token.balanceOf(accounts[0]); - assert.equal(founderBalance,10); - var founderReputation = await reputation.balanceOf(accounts[0]); - assert.equal(founderReputation,10); - }); - - - it("forgeOrg with universal controller check transfer ownership", async function() { - //check the forgeOrg transfer ownership to avatar ,reputation and token - //to the controller contract - var amountToMint = 10; - await setup(accounts,amountToMint,amountToMint,true); - assert.equal(await avatar.owner(),uController.address); - assert.equal(await token.owner(),uController.address); - assert.equal(await reputation.owner(),uController.address); - }); - - it("setSchemes with universal controller to none UniversalScheme", async function() { - var amountToMint = 10; - await setup(accounts,amountToMint,amountToMint,true); - var tx = await daoCreator.setSchemes(avatar.address,[accounts[1]],[zeroBytes32],["0x0000000F"],"metaData"); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "InitialSchemesSet"); - assert.equal(tx.logs[0].args._avatar, avatar.address); - }); - - it("setSchemes with universal controller to UniversalScheme", async function() { - var amountToMint = 10; - await setup(accounts,amountToMint,amountToMint,true); - var universalSchemeMock = await UniversalSchemeMock.new(); - var tx = await daoCreator.setSchemes(avatar.address,[universalSchemeMock.address],[zeroBytes32],["0x8000000F"],"metaData"); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "InitialSchemesSet"); - assert.equal(tx.logs[0].args._avatar, avatar.address); - }); - - it("setSchemes with universal controller from account that does not hold the lock", async function() { - var amountToMint = 10; - await setup(accounts,amountToMint,amountToMint,true); - try { - await daoCreator.setSchemes(avatar.address,[accounts[1]],[zeroBytes32],["0x0000000F"],"metaData",{ from: accounts[1]}); - assert(false,"should fail because accounts[1] does not hold the lock"); - } - catch(ex){ - helpers.assertVMException(ex); - } - }); - - it("setSchemes with universal controller increase approval for scheme and register org in scheme", async function() { - var amountToMint = 10; - await setup(accounts,amountToMint,amountToMint,true); - var standardTokenMock = await ERC20Mock.new(avatar.address, 100); - var universalSchemeMock = await UniversalSchemeMock.new(); - var allowance = await standardTokenMock.allowance(avatar.address,universalSchemeMock.address); - assert.equal(allowance,0); - await daoCreator.setSchemes(avatar.address,[universalSchemeMock.address],[zeroBytes32],["0x8000000F"],"metaData"); - allowance = await standardTokenMock.allowance(avatar.address,universalSchemeMock.address); - assert.equal(allowance,0); - //check org registered in scheme - }); - - it("setSchemes with universal controller increase approval for scheme without fee", async function() { - var amountToMint = 10; - await setup(accounts,amountToMint,amountToMint,true); - var standardTokenMock = await ERC20Mock.new(accounts[0], 100); - var allowance = await standardTokenMock.allowance(avatar.address,accounts[1]); - assert.equal(allowance,0); - - await daoCreator.setSchemes(avatar.address,[accounts[1]],[zeroBytes32],["0x0000000F"],"metaData"); - allowance = await standardTokenMock.allowance(avatar.address,accounts[1]); - assert.equal(allowance,0); - }); - - it("setSchemes with universal controller check register", async function() { - var amountToMint = 10; - var controllerAddress,controller; - await setup(accounts,amountToMint,amountToMint,true); - await daoCreator.setSchemes(avatar.address,[accounts[1]],[zeroBytes32],["0x0000000F"],"metaData"); - controllerAddress = await avatar.owner(); - controller = await Controller.at(controllerAddress); - var isSchemeRegistered = await controller.isSchemeRegistered(accounts[1],avatar.address); - assert.equal(isSchemeRegistered,true); - }); - - it("setSchemes with universal controller check unregisterSelf", async function() { - var amountToMint = 10; - var controllerAddress,controller; - await setup(accounts,amountToMint,amountToMint,true); - controllerAddress = await avatar.owner(); - controller = await Controller.at(controllerAddress); - var isSchemeRegistered = await controller.isSchemeRegistered(daoCreator.address,avatar.address); - assert.equal(isSchemeRegistered,true); - await daoCreator.setSchemes(avatar.address,[accounts[1]],[zeroBytes32],["0x0000000F"],"metaData"); - controllerAddress = await avatar.owner(); - controller = await Controller.at(controllerAddress); - isSchemeRegistered = await controller.isSchemeRegistered(daoCreator.address,avatar.address); - assert.equal(isSchemeRegistered,false); - }); - - it("setSchemes with universal controller delete lock", async function() { - var amountToMint = 10; - await setup(accounts,amountToMint,amountToMint,true); - await daoCreator.setSchemes(avatar.address,[accounts[1]],[zeroBytes32],["0x0000000F"],"metaData"); - try { - await daoCreator.setSchemes(avatar.address,[accounts[1]],[zeroBytes32],["0x0000000F"],"metaData",{ from: accounts[1]}); - assert(false,"should fail because lock for account[0] suppose to be deleted by the first call"); - } - catch(ex){ - helpers.assertVMException(ex); - } - }); it("forgeOrg with different params length should revert", async function() { var amountToMint = 10; var controllerCreator = await ControllerCreator.new({gas: constants.ARC_GAS_LIMIT}); var daoTracker = await DAOTracker.new({gas: constants.ARC_GAS_LIMIT}); daoCreator = await DaoCreator.new(controllerCreator.address,daoTracker.address,{gas:constants.ARC_GAS_LIMIT}); - var uControllerAddress = helpers.NULL_ADDRESS; try { - await daoCreator.forgeOrg("testOrg","TEST","TST",[accounts[0]],[amountToMint],[],uControllerAddress,helpers.NULL_ADDRESS,{gas:constants.ARC_GAS_LIMIT}); + await daoCreator.forgeOrg("testOrg","TEST","TST",[accounts[0]],[amountToMint],[],helpers.NULL_ADDRESS,{gas:constants.ARC_GAS_LIMIT}); assert(false,"should revert because reputation array size is 0"); } catch(ex){ @@ -303,7 +177,7 @@ contract('DaoCreator', function(accounts) { } try { - await daoCreator.forgeOrg("testOrg","TEST","TST",[accounts[0],helpers.NULL_ADDRESS],[amountToMint,amountToMint],[amountToMint,amountToMint],uControllerAddress,0,{gas:constants.ARC_GAS_LIMIT}); + await daoCreator.forgeOrg("testOrg","TEST","TST",[accounts[0],helpers.NULL_ADDRESS],[amountToMint,amountToMint],[amountToMint,amountToMint],0,{gas:constants.ARC_GAS_LIMIT}); assert(false,"should revert because account is 0"); } catch(ex){ diff --git a/test/daotracker.js b/test/daotracker.js index 812dd760..a2c786c1 100644 --- a/test/daotracker.js +++ b/test/daotracker.js @@ -4,7 +4,7 @@ const DAOTracker = artifacts.require("./DAOTracker.sol"); const Reputation = artifacts.require("./Reputation.sol"); const DAOToken = artifacts.require("./DAOToken.sol"); const Avatar = artifacts.require("./Avatar.sol"); -const UController = artifacts.require("./UController.sol"); +const Controller = artifacts.require("./Controller.sol"); const opts = {gas: constants.ARC_GAS_LIMIT}; @@ -16,7 +16,7 @@ const setup = async function () { testSetup.avatar = await Avatar.new( "test", testSetup.daoToken.address, testSetup.reputation.address, opts, ); - testSetup.controller = await UController.new(opts); + testSetup.controller = await Controller.new(testSetup.avatar.address, opts); return testSetup; }; @@ -136,7 +136,7 @@ contract("DAOTracker", accounts => { } }); - it("reset", async () => { + it("reset", async () => { const testSetup = await setup(); const avatar = testSetup.avatar.address; const controller = testSetup.controller.address; diff --git a/test/forwarder.js b/test/forwarder.js index 8ae36e4f..65f23874 100644 --- a/test/forwarder.js +++ b/test/forwarder.js @@ -5,7 +5,7 @@ const DAOTracker = artifacts.require("./DAOTracker.sol"); const constants = require("./constants"); const ERC20Mock = artifacts.require("./test/ERC20Mock.sol"); var Forwarder = artifacts.require("./Forwarder.sol"); -var ControllerInterface = artifacts.require("./ControllerInterface.sol"); +var Controller = artifacts.require("./Controller.sol"); const setup = async function (accounts, _expirationTime = 300) @@ -56,8 +56,8 @@ contract('Forwarder', accounts => { // transferOwnership of testSetupA.forwarder to testSetupB avatar await testSetupA.forwarder.transferOwnership(testSetupB.org.avatar.address); //do generic call from testSetupB controller to testSetupA controller to "registerScheme" - let controllerB = await ControllerInterface.at(await testSetupB.org.avatar.owner()); - let controllerA = await ControllerInterface.at(await testSetupA.org.avatar.owner()); + let controllerB = await Controller.at(await testSetupB.org.avatar.owner()); + let controllerA = await Controller.at(await testSetupA.org.avatar.owner()); const encodeABI = await new web3.eth.Contract(controllerA.abi). methods. registerScheme(accounts[1],helpers.NULL_HASH,"0x0000001f",testSetupA.org.avatar.address). @@ -75,8 +75,8 @@ contract('Forwarder', accounts => { // transferOwnership of testSetupA.forwarder to testSetupB avatar await testSetupA.forwarder.transferOwnership(testSetupB.org.avatar.address); //do generic call from testSetupB controller to testSetupA controller to "registerScheme" - let controllerB = await ControllerInterface.at(await testSetupB.org.avatar.owner()); - let controllerA = await ControllerInterface.at(await testSetupA.org.avatar.owner()); + let controllerB = await Controller.at(await testSetupB.org.avatar.owner()); + let controllerA = await Controller.at(await testSetupA.org.avatar.owner()); const encodeABI = await new web3.eth.Contract(controllerA.abi). methods. registerScheme(accounts[1],helpers.NULL_HASH,"0x0000001f",testSetupA.org.avatar.address). @@ -101,8 +101,8 @@ contract('Forwarder', accounts => { let testSetupA = await setup(accounts); let testSetupB = await setup(accounts); //do generic call from testSetupB controller to testSetupA controller to "registerScheme" - let controllerB = await ControllerInterface.at(await testSetupB.org.avatar.owner()); - let controllerA = await ControllerInterface.at(await testSetupA.org.avatar.owner()); + let controllerB = await Controller.at(await testSetupB.org.avatar.owner()); + let controllerA = await Controller.at(await testSetupA.org.avatar.owner()); const encodeABI = await new web3.eth.Contract(controllerA.abi). methods. registerScheme(accounts[1],helpers.NULL_HASH,"0x0000001f",testSetupA.org.avatar.address). @@ -122,7 +122,7 @@ contract('Forwarder', accounts => { it("unregisterSelf", async () => { let testSetupA = await setup(accounts); let testSetupB = await setup(accounts); - let controllerA = await ControllerInterface.at(await testSetupA.org.avatar.owner()); + let controllerA = await Controller.at(await testSetupA.org.avatar.owner()); // transferOwnership of testSetupA.forwarder to testSetupB avatar await testSetupA.forwarder.transferOwnership(testSetupB.org.avatar.address); assert.equal(await controllerA.isSchemeRegistered(testSetupA.forwarder.address,testSetupA.org.avatar.address),true); diff --git a/test/helpers.js b/test/helpers.js index 2b968ca1..eb838393 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -179,9 +179,9 @@ export const setupGenesisProtocol = async function ( return votingMachine; }; -export const setupOrganizationWithArrays = async function (daoCreator,daoCreatorOwner,founderToken,founderReputation,controller=NULL_ADDRESS,cap=0) { +export const setupOrganizationWithArrays = async function (daoCreator,daoCreatorOwner,founderToken,founderReputation,cap=0) { var org = new Organization(); - var tx = await daoCreator.forgeOrg("testOrg","TEST","TST",daoCreatorOwner,founderToken,founderReputation,controller,cap,{gas: constants.ARC_GAS_LIMIT}); + var tx = await daoCreator.forgeOrg("testOrg","TEST","TST",daoCreatorOwner,founderToken,founderReputation,cap,{gas: constants.ARC_GAS_LIMIT}); assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "NewOrg"); var avatarAddress = tx.logs[0].args._avatar; @@ -193,9 +193,9 @@ export const setupOrganizationWithArrays = async function (daoCreator,daoCreator return org; }; -export const setupOrganization = async function (daoCreator,daoCreatorOwner,founderToken,founderReputation,controller=NULL_ADDRESS,cap=0) { +export const setupOrganization = async function (daoCreator,daoCreatorOwner,founderToken,founderReputation,cap=0) { var org = new Organization(); - var tx = await daoCreator.forgeOrg("testOrg","TEST","TST",[daoCreatorOwner],[founderToken],[founderReputation],controller,cap,{gas: constants.ARC_GAS_LIMIT}); + var tx = await daoCreator.forgeOrg("testOrg","TEST","TST",[daoCreatorOwner],[founderToken],[founderReputation],cap,{gas: constants.ARC_GAS_LIMIT}); assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "NewOrg"); var avatarAddress = tx.logs[0].args._avatar; diff --git a/test/ucontroller.js b/test/ucontroller.js deleted file mode 100644 index 6acc33e6..00000000 --- a/test/ucontroller.js +++ /dev/null @@ -1,700 +0,0 @@ -const helpers = require('./helpers'); -const UController = artifacts.require("./UController.sol"); -const Reputation = artifacts.require("./Reputation.sol"); -const Avatar = artifacts.require("./Avatar.sol"); -const DAOToken = artifacts.require("./DAOToken.sol"); -const ERC20Mock = artifacts.require('./ERC20Mock.sol'); -const GlobalConstraintMock = artifacts.require('./test/GlobalConstraintMock.sol'); -const ActionMock = artifacts.require('./test/ActionMock.sol'); -const UniversalSchemeMock = artifacts.require('./test/UniversalSchemeMock.sol'); -var constants = require('./constants'); -var uint32 = require('uint32'); - - -let reputation, avatar,token,controller; -var amountToMint = 10; - -const setup = async function (accounts,permission='0x00000000',registerScheme = accounts[0]) { - var uController = await UController.new({gas: constants.ARC_GAS_LIMIT}); - token = await DAOToken.new("TEST","TST",0); - // set up a reputation system - reputation = await Reputation.new(); - await token.transferOwnership(uController.address); - await reputation.transferOwnership(uController.address); - avatar = await Avatar.new('name', token.address, reputation.address); - await avatar.transferOwnership(uController.address); - if (permission !== '0x00000000'){ - await uController.newOrganization(avatar.address,{from:accounts[1]}); - await uController.registerScheme(registerScheme,helpers.NULL_HASH,permission,avatar.address,{from:accounts[1]}); - await uController.unregisterSelf(avatar.address,{from:accounts[1]}); - } - else { - await uController.newOrganization(avatar.address); - } - return uController; -}; - -const constraint = async function (method, pre=false, post=false) { - var globalConstraints = await GlobalConstraintMock.new(); - let globalConstraintsCountOrig = await controller.globalConstraintsCount(avatar.address); - await globalConstraints.setConstraint(web3.utils.asciiToHex(method),pre,post); - await controller.addGlobalConstraint(globalConstraints.address,helpers.NULL_HASH,avatar.address); - let globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0].toNumber(),globalConstraintsCountOrig[0].toNumber() + (pre ? 0 : 1)); - assert.equal(globalConstraintsCount[1].toNumber(),globalConstraintsCountOrig[1].toNumber() + (post ? 0 : 1)); - return globalConstraints; -}; - -contract('UController',accounts => { - - it("getGlobalConstraintParameters", async() => { - controller = await setup(accounts); - // separate cases for pre and post - var globalConstraints = await constraint("gcParams1", true); - await controller.addGlobalConstraint(globalConstraints.address,"0x1235",avatar.address); - - var paramsHash = await controller.getGlobalConstraintParameters(globalConstraints.address, avatar.address); - - assert.equal(paramsHash,"0x1235000000000000000000000000000000000000000000000000000000000000"); - - globalConstraints = await constraint("gcParams2", false, true); - await controller.addGlobalConstraint(globalConstraints.address,"0x1236",avatar.address); - - paramsHash = await controller.getGlobalConstraintParameters(globalConstraints.address, avatar.address); - - assert.equal(paramsHash,"0x1236000000000000000000000000000000000000000000000000000000000000"); - }); - - it("newOrganization without controller owner of the avatar", async () => { - var uController = await UController.new({gas: constants.ARC_GAS_LIMIT}); - token = await DAOToken.new("TEST","TST",0); - // set up a reputation system - reputation = await Reputation.new(); - avatar = await Avatar.new('name', token.address, reputation.address); - try { - await uController.newOrganization(avatar.address); - assert(false, 'newOrganization should fail because controller is not the avatar owner'); - } catch (ex) { - helpers.assertVMException(ex); - } - }); - - it("newOrganization with same avatar", async () => { - controller = await setup(accounts); - try { - await controller.newOrganization(avatar.address); - assert(false, 'trying to call new organization with an avatar which already registered should fail.'); - } catch (ex) { - helpers.assertVMException(ex); - } - }); - - it("newOrganization with same reputation and token", async () => { - controller = await setup(accounts); - let fakeAvatar = await Avatar.new("0x1234", reputation.address, token.address); - await fakeAvatar.transferOwnership(controller.address); - try { - await controller.newOrganization(fakeAvatar.address); - assert(false, 'trying to call new organization with same reputation and token'); - } catch (ex) { - helpers.assertVMException(ex); - } - - fakeAvatar = await Avatar.new("0x1234", token.address, reputation.address); - await fakeAvatar.transferOwnership(controller.address); - - try { - await controller.newOrganization(fakeAvatar.address); - assert(false, 'trying to call new organization with same reputation and token'); - } catch (ex) { - helpers.assertVMException(ex); - } - - fakeAvatar = await Avatar.new("0x1234", token.address, token.address); - await fakeAvatar.transferOwnership(controller.address); - - try { - await controller.newOrganization(fakeAvatar.address); - assert(false, 'trying to call new organization with same reputation and token'); - } catch (ex) { - helpers.assertVMException(ex); - } - - fakeAvatar = await Avatar.new("0x1234", reputation.address, reputation.address); - await fakeAvatar.transferOwnership(controller.address); - - try { - await controller.newOrganization(fakeAvatar.address); - assert(false, 'trying to call new organization with same reputation and token'); - } catch (ex) { - helpers.assertVMException(ex); - } - }); - - it("mint reputation via controller", async () => { - controller = await setup(accounts); - let tx = await controller.mintReputation(amountToMint,accounts[0],avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "MintReputation"); - assert.equal(tx.logs[0].args._amount, amountToMint); - assert.equal(tx.logs[0].args._to, accounts[0]); - let rep = await reputation.balanceOf(accounts[0]); - assert.equal(rep,amountToMint); - }); - - it("burn reputation via controller", async () => { - controller = await setup(accounts); - await controller.mintReputation(amountToMint,accounts[0],avatar.address); - let tx = await controller.burnReputation(amountToMint-1,accounts[0],avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "BurnReputation"); - assert.equal(tx.logs[0].args._amount, amountToMint-1); - assert.equal(tx.logs[0].args._from, accounts[0]); - let rep = await reputation.balanceOf(accounts[0]); - assert.equal(rep,1); - }); - - it("mint tokens via controller", async () => { - controller = await setup(accounts); - let tx = await controller.mintTokens(amountToMint,accounts[0],avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "MintTokens"); - assert.equal(tx.logs[0].args._amount, amountToMint); - let balance = await token.balanceOf(accounts[0]); - assert.equal(balance,amountToMint); - }); - - it("register schemes", async () => { - controller = await setup(accounts); - let tx = await controller.registerScheme(accounts[1], helpers.NULL_HASH,"0x00000000",avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "RegisterScheme"); - }); - - it("register schemes - check permissions for register new scheme", async () => { - // Check scheme has at least the permissions it is changing, and at least the current permissions. - var i,j; - var controller; - for(j = 0; j <= 15; j++ ){ - //registered scheme has already permission to register(2) - controller = await setup(accounts,'0x'+uint32.toHex(j|2)); - var register; - for(i = 0; i <= 15; i++ ){ - register = true; - try { - await controller.registerScheme(accounts[1],helpers.NULL_HASH,'0x'+uint32.toHex(i),avatar.address); - } catch (ex) { - //registered scheme has already permission to register(2) and is register(1). - assert.notEqual(i&(~(j|3),0)); - register = false; - } - if (register){ - await controller.unregisterScheme(accounts[1],avatar.address); - register= false; - } - } - } - }); - - it("register schemes - check permissions for updating existing scheme", async () => { - // Check scheme has at least the permissions it is changing, and at least the current permissions. - controller = await setup(accounts,'0x0000000F'); - // scheme with permission 0x0000000F should be able to register scheme with permission 0x00000001 - let tx = await controller.registerScheme(accounts[0],helpers.NULL_HASH,"0x00000001",avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "RegisterScheme"); - - controller = await setup(accounts,'0x00000001'); - try { - await controller.registerScheme(accounts[0],helpers.NULL_HASH,"0x00000002",avatar.address); - assert(false, 'scheme with permission 0x00000001 should not be able to register scheme with permission 0x00000002'); - } catch (ex) { - helpers.assertVMException(ex); - } - }); - - it("unregister schemes", async () => { - controller = await setup(accounts); - let tx = await controller.unregisterScheme(accounts[0],avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "UnregisterScheme"); - }); - it("unregister none registered scheme", async () => { - controller = await setup(accounts); - let tx = await controller.unregisterScheme(accounts[1],avatar.address); - assert.equal(tx.logs.length, 0); - }); - - it("unregister schemes - check permissions unregister scheme", async () => { - // Check scheme has at least the permissions it is changing, and at least the current permissions. - //1. setup - controller = await setup(accounts); - //2. account[0] register schemes ,on account[1] with variables permissions which could unregister other schemes. - var i,j; - var tx; - var registeredScheme = accounts[1]; - var unregisteredScheme = accounts[2]; - for(i = 0; i <= 15; i++ ){ - //registered scheme has already permission to register(2) - tx = await controller.registerScheme(registeredScheme,helpers.NULL_HASH,'0x'+uint32.toHex(i|3),avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "RegisterScheme"); - for(j = 0; j <= 15; j++ ){ - tx = await controller.registerScheme(unregisteredScheme,helpers.NULL_HASH,'0x'+uint32.toHex(j),avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "RegisterScheme"); - //try to unregisterScheme - if (j&(~(i|3))) { - //unregister should fail - try { - await controller.unregisterScheme(unregisteredScheme,avatar.address,{ from: registeredScheme }); - assert(false, "scheme with permission " +uint32.toHex(i|3)+ " should not be able to unregister scheme with permission"+uint32.toHex(j)); - } catch (ex) { - helpers.assertVMException(ex); - } - }else{ - //unregister should succeed - tx = await controller.unregisterScheme(unregisteredScheme,avatar.address,{ from: registeredScheme }); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "UnregisterScheme"); - } - } - } - }); - - it("unregister self", async () => { - var tx; - controller = await setup(accounts,"0x00000000"); - tx = await controller.unregisterSelf(avatar.address,{ from: accounts[1]}); - assert.equal(tx.logs.length, 0); // scheme was not registered - - tx = await controller.unregisterSelf(avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "UnregisterScheme"); - }); - - it("isSchemeRegistered ", async () => { - var isSchemeRegistered; - controller = await setup(accounts,"0x00000000"); - isSchemeRegistered = await controller.isSchemeRegistered(accounts[1],avatar.address); - assert.equal(isSchemeRegistered, false); - isSchemeRegistered = await controller.isSchemeRegistered(accounts[0],avatar.address); - assert.equal(isSchemeRegistered, true); - }); - - it("addGlobalConstraint ", async () => { - controller = await setup(accounts); - var globalConstraints = await constraint("0"); - var tx = await controller.addGlobalConstraint(globalConstraints.address,helpers.NULL_HASH,avatar.address); - assert.equal(await controller.isGlobalConstraintRegistered(globalConstraints.address,avatar.address),true); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "AddGlobalConstraint"); - var count = await controller.globalConstraintsCount(avatar.address); - assert.equal(count[0], 1); - }); - - it("removeGlobalConstraint ", async () => { - controller = await setup(accounts); - var globalConstraints = await GlobalConstraintMock.new(); - await globalConstraints.setConstraint(web3.utils.asciiToHex("0"),false,false); - var globalConstraints1 = await GlobalConstraintMock.new(); - await globalConstraints1.setConstraint(web3.utils.asciiToHex("method"),false,false); - var globalConstraints2 = await GlobalConstraintMock.new(); - await globalConstraints2.setConstraint(web3.utils.asciiToHex("method"),false,false); - var globalConstraints3 = await GlobalConstraintMock.new(); - await globalConstraints3.setConstraint(web3.utils.asciiToHex("method"),false,false); - var globalConstraints4 = await GlobalConstraintMock.new(); - await globalConstraints4.setConstraint(web3.utils.asciiToHex("method"),false,false); - - assert.equal(await controller.isGlobalConstraintRegistered(globalConstraints.address,avatar.address),false); - await controller.addGlobalConstraint(globalConstraints.address,helpers.NULL_HASH,avatar.address); - await controller.addGlobalConstraint(globalConstraints1.address,helpers.NULL_HASH,avatar.address); - await controller.addGlobalConstraint(globalConstraints2.address,helpers.NULL_HASH,avatar.address); - await controller.addGlobalConstraint(globalConstraints3.address,helpers.NULL_HASH,avatar.address); - await controller.addGlobalConstraint(globalConstraints4.address,helpers.NULL_HASH,avatar.address); - var tx = await controller.removeGlobalConstraint(globalConstraints2.address,avatar.address); - assert.equal(tx.logs.length, 2); - assert.equal(tx.logs[0].event, "RemoveGlobalConstraint"); - assert.equal(await controller.isGlobalConstraintRegistered(globalConstraints.address,avatar.address),true); - assert.equal(await controller.isGlobalConstraintRegistered(globalConstraints1.address,avatar.address),true); - assert.equal(await controller.isGlobalConstraintRegistered(globalConstraints2.address,avatar.address),false); - assert.equal(await controller.isGlobalConstraintRegistered(globalConstraints3.address,avatar.address),true); - assert.equal(await controller.isGlobalConstraintRegistered(globalConstraints4.address,avatar.address),true); - - let gcCount = await controller.globalConstraintsCount(avatar.address); - - assert.equal(gcCount[0],4); - assert.equal(gcCount[1],4); - - await controller.removeGlobalConstraint(globalConstraints4.address,avatar.address); - assert.equal(await controller.isGlobalConstraintRegistered(globalConstraints4.address,avatar.address),false); - gcCount = await controller.globalConstraintsCount(avatar.address); - assert.equal(gcCount[0],3); - assert.equal(gcCount[1],3); - }); - - it("upgrade controller ", async () => { - controller = await setup(accounts); - var tx = await controller.upgradeController(accounts[1],avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "UpgradeController"); - }); - - it("upgrade controller check permission", async () => { - controller = await setup(accounts,'0x00000007'); - try{ - await controller.upgradeController(accounts[1],avatar.address); - assert(false,"scheme with permission 0x00000007 is not allowed to upgrade "); - } catch (ex) { - helpers.assertVMException(ex); - } - }); - - it("generic call log", async () => { - controller = await setup(accounts,'0x00000010'); - let actionMock = await ActionMock.new(); - let a = 7; - let b = actionMock.address; - let c = "0x1234"; - const encodeABI = await new web3.eth.Contract(actionMock.abi).methods.test(a,b,c).encodeABI(); - var tx = await controller.genericCall(actionMock.address,encodeABI,avatar.address,0); - await avatar.getPastEvents('GenericCall', { - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"GenericCall"); - assert.equal(events[0].args._contract,actionMock.address); - }); - - }); - - it("generic call", async () => { - controller = await setup(accounts,'0x00000010'); - let actionMock = await ActionMock.new(); - let a = 7; - let b = actionMock.address; - let c = "0x1234"; - const encodeABI = await new web3.eth.Contract(actionMock.abi).methods.test(a,b,c).encodeABI(); - var result = await controller.genericCall.call(actionMock.address,encodeABI,avatar.address,0); - assert.equal(result[1], 14); - - }); - it("generic call withoutReturnValue", async () => { - controller = await setup(accounts,'0x00000010'); - let actionMock = await ActionMock.new(); - const actionMockContract = await new web3.eth.Contract(actionMock.abi); - const encodeABI = actionMockContract.methods.withoutReturnValue(avatar.address).encodeABI(); - var tx = await controller.genericCall(actionMock.address,encodeABI,avatar.address,0); - await actionMock.getPastEvents('WithoutReturnValue', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"WithoutReturnValue"); - }); - }); - - it("generic call via contract scheme", async () => { - var scheme = await UniversalSchemeMock.new(); - controller = await setup(accounts,'0x00000010',scheme.address); - let actionMock = await ActionMock.new(); - let a = 7; - let b = actionMock.address; - let c = "0x1234"; - let result = await scheme.genericCall.call(avatar.address,actionMock.address, a,b,c,0); - assert.equal(result[1], 14); - - }); - - it("sendEther", async () => { - controller = await setup(accounts); - let otherAvatar = await Avatar.new('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS); - //send some ether to the avatar - await web3.eth.sendTransaction({from:accounts[0],to:avatar.address, value: web3.utils.toWei('1', "ether")}); - //send some ether from an organization's avatar to the otherAvatar - var tx = await controller.sendEther(web3.utils.toWei('1', "ether"),otherAvatar.address,avatar.address); - await avatar.getPastEvents('SendEther', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"SendEther"); - }); - var avatarBalance = await web3.eth.getBalance(avatar.address)/web3.utils.toWei('1', "ether"); - assert.equal(avatarBalance, 0); - var otherAvatarBalance = await web3.eth.getBalance(otherAvatar.address)/web3.utils.toWei('1', "ether"); - assert.equal(otherAvatarBalance, 1); - }); - - it("externalTokenTransfer", async () => { - //External transfer token from avatar contract to other address - controller = await setup(accounts); - var standardToken = await ERC20Mock.new(avatar.address, 100); - let balanceAvatar = await standardToken.balanceOf(avatar.address); - assert.equal(balanceAvatar, 100); - var tx = await controller.externalTokenTransfer(standardToken.address,accounts[1],50,avatar.address); - await avatar.getPastEvents('ExternalTokenTransfer', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"ExternalTokenTransfer"); - }); - balanceAvatar = await standardToken.balanceOf(avatar.address); - assert.equal(balanceAvatar, 50); - let balance1 = await standardToken.balanceOf(accounts[1]); - assert.equal(balance1, 50); - }); - - it("externalTokenTransferFrom & ExternalTokenApproval", async () => { - var tx; - var to = accounts[1]; - controller = await setup(accounts); - var standardToken = await ERC20Mock.new(avatar.address, 100); - tx = await controller.externalTokenApproval(standardToken.address,avatar.address,50,avatar.address); - await avatar.getPastEvents('ExternalTokenApproval', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"ExternalTokenApproval"); - }); - tx = await controller.externalTokenTransferFrom(standardToken.address,avatar.address,to,50,avatar.address); - - await avatar.getPastEvents('ExternalTokenTransferFrom', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"ExternalTokenTransferFrom"); - }); - let balanceAvatar = await standardToken.balanceOf(avatar.address); - assert.equal(balanceAvatar, 50); - let balanceTo = await standardToken.balanceOf(to); - assert.equal(balanceTo, 50); - }); - - it("globalConstraints mintReputation add & remove", async () => { - controller = await setup(accounts); - var globalConstraints = await constraint("mintReputation"); - try { - await controller.mintReputation(amountToMint,accounts[0],avatar.address); - assert(false,"mint reputation should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - var globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - assert.equal(globalConstraintsCount[1],0); - let tx = await controller.mintReputation(amountToMint,accounts[0],avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "MintReputation"); - assert.equal(tx.logs[0].args._amount, amountToMint); - let rep = await reputation.balanceOf(accounts[0]); - assert.equal(rep,amountToMint); - }); - - it("globalConstraints mintTokens add & remove", async () => { - - controller = await setup(accounts); - var globalConstraints = await constraint("mintTokens"); - try { - await controller.mintTokens(amountToMint,accounts[0],avatar.address); - assert(false,"mint tokens should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - var globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - assert.equal(globalConstraintsCount[1],0); - let tx = await controller.mintTokens(amountToMint,accounts[0],avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "MintTokens"); - assert.equal(tx.logs[0].args._amount, amountToMint); - let balance = await token.balanceOf(accounts[0]); - assert.equal(balance,amountToMint); - }); - - it("globalConstraints register schemes add & remove", async () => { - controller = await setup(accounts); - var globalConstraints = await constraint("registerScheme"); - try { - await controller.registerScheme(accounts[1], helpers.NULL_HASH,"0x00000000",avatar.address); - assert(false,"registerScheme should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - var globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - assert.equal(globalConstraintsCount[1],0); - let tx = await controller.registerScheme(accounts[1], helpers.NULL_HASH,"0x00000000",avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "RegisterScheme"); - }); - - it("globalConstraints unregister schemes add & remove", async () => { - controller = await setup(accounts); - var globalConstraints = await constraint("registerScheme"); - try { - await controller.unregisterScheme(accounts[0],avatar.address); - assert(false,"unregisterScheme should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - var globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - assert.equal(globalConstraintsCount[1],0); - let tx = await controller.unregisterScheme(accounts[0],avatar.address); - assert.equal(tx.logs.length, 1); - assert.equal(tx.logs[0].event, "UnregisterScheme"); - }); - - it("globalConstraints generic call add & remove", async () => { - controller = await setup(accounts,'0x00000014'); - var globalConstraints = await constraint("genericCall"); - let actionMock = await ActionMock.new(); - let a = 7; - let b = actionMock.address; - let c = "0x1234"; - const encodeABI = await new web3.eth.Contract(actionMock.abi).methods.test(a,b,c).encodeABI(); - try { - await controller.genericCall.call(actionMock.address,encodeABI,avatar.address,0); - assert(false,"genericAction should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - var globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - assert.equal(globalConstraintsCount[1],0); - var tx = await controller.genericCall(actionMock.address,encodeABI,avatar.address,0); - await avatar.getPastEvents('GenericCall', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"GenericCall"); - }); - }); - - it("globalConstraints sendEther add & remove", async () => { - controller = await setup(accounts); - var globalConstraints = await constraint("sendEther"); - let otherAvatar = await Avatar.new('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS); - web3.eth.sendTransaction({from:accounts[0],to:avatar.address, value: web3.utils.toWei('1', "ether")}); - - try { - await controller.sendEther(web3.utils.toWei('1', "ether"),otherAvatar.address,avatar.address); - assert(false,"sendEther should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - var globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - assert.equal(globalConstraintsCount[1],0); - var tx = await controller.sendEther(web3.utils.toWei('1', "ether"),otherAvatar.address,avatar.address); - await avatar.getPastEvents('SendEther', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"SendEther"); - }); - var avatarBalance = await web3.eth.getBalance(avatar.address)/web3.utils.toWei('1', "ether"); - assert.equal(avatarBalance, 0); - var otherAvatarBalance = await web3.eth.getBalance(otherAvatar.address)/web3.utils.toWei('1', "ether"); - assert.equal(otherAvatarBalance, 1); - }); - - it("globalConstraints externalTokenTransfer add & remove", async () => { - controller = await setup(accounts); - var globalConstraints = await constraint("externalTokenTransfer"); - var standardToken = await ERC20Mock.new(avatar.address, 100); - let balanceAvatar = await standardToken.balanceOf(avatar.address); - assert.equal(balanceAvatar, 100); - - try { - await controller.externalTokenTransfer(standardToken.address,accounts[1],50,avatar.address); - assert(false,"externalTokenTransfer should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - var globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - assert.equal(globalConstraintsCount[1],0); - var tx = await controller.externalTokenTransfer(standardToken.address,accounts[1],50,avatar.address); - await avatar.getPastEvents('ExternalTokenTransfer', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"ExternalTokenTransfer"); - }); - balanceAvatar = await standardToken.balanceOf(avatar.address); - assert.equal(balanceAvatar, 50); - let balance1 = await standardToken.balanceOf(accounts[1]); - assert.equal(balance1, 50); - }); - - it("globalConstraints externalTokenTransferFrom , externalTokenApproval", async () => { - var tx; - var to = accounts[1]; - controller = await setup(accounts); - var globalConstraints = await constraint("externalTokenApproval"); - var standardToken = await ERC20Mock.new(avatar.address, 100); - try { - await controller.externalTokenApproval(standardToken.address,avatar.address,50,avatar.address); - assert(false,"externalTokenIncreaseApproval should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - var globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - assert.equal(globalConstraintsCount[1],0); - - tx = await controller.externalTokenApproval(standardToken.address,avatar.address,50,avatar.address); - await avatar.getPastEvents('ExternalTokenApproval', { - filter: {_addr: avatar.address}, // Using an array means OR: e.g. 20 or 23 - fromBlock: tx.blockNumber, - toBlock: 'latest' - }) - .then(function(events){ - assert.equal(events[0].event,"ExternalTokenApproval"); - }); - globalConstraints = await constraint("externalTokenTransferFrom"); - try { - await controller.externalTokenTransferFrom(standardToken.address,avatar.address,to,50,avatar.address); - assert(false,"externalTokenTransferFrom should fail due to the global constraint "); - } - catch(ex){ - helpers.assertVMException(ex); - } - await controller.removeGlobalConstraint(globalConstraints.address,avatar.address); - globalConstraintsCount =await controller.globalConstraintsCount(avatar.address); - assert.equal(globalConstraintsCount[0],0); - }); -});