Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions contracts/ProxyOwnedByDao.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pragma solidity ^0.4.23;

import "@thetta/core/contracts/DaoBase.sol";
import "@thetta/core/contracts/DaoClient.sol";

import "./Proxy.sol";

contract ProxyOwnedByDAO is DaoClient {
Proxy public proxy;

bytes32 public constant TRANSFER_DELEGATION = keccak256("Proxy_TransferDelegation");
bytes32 public constant TRANSFER_OWNERSHIP = keccak256("Proxy_TransferOwnership");

constructor(DaoBase _daoBase, Proxy _proxy) DaoClient(_daoBase) {
// Please don't forget to call _proxy.transferOwnership() to this contract immediately
// after ProxyOwnedByDAO_1 is instantiated
proxy = _proxy;
}

// These methods now require special custom permissions:
function DAO_transferDelegation(address _newDelegation) public isCanDo(TRANSFER_DELEGATION) {
proxy.transferDelegation(_newDelegation);
}

function DAO_transferOwnership(address _newOwner) public isCanDo(TRANSFER_OWNERSHIP) {
proxy.transferOwnership(_newOwner);
}
}

7 changes: 7 additions & 0 deletions migrations/3_deploy_contracts_dao.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var migrateLibs = require('@thetta/core/scripts/migrateLibs');

module.exports = function (deployer, network, accounts) {
let additionalContracts = [ "./ProxyOwnedByDAO"];

return migrateLibs(artifacts, additionalContracts, deployer, network, accounts);
};
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@
"babel-preset-stage-2": "^6.18.0",
"babel-preset-stage-3": "^6.17.0",
"babel-register": "^6.23.0",
"truffle-privatekey-provider": "0.0.6",
"dotenv": "^5.0.1",
"ganache-cli": "^6.0.3",
"solium": "^1.1.2",
"truffle": "4.0.6"
"truffle": "^4.1.14",
"truffle-privatekey-provider": "0.0.6"
},
"dependencies": {
"@thetta/core": "^1.4.1",
"bignumber.js": "^4.0.1",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"zeppelin-solidity": "^1.6.0"
}
}
104 changes: 104 additions & 0 deletions test/icomalta_dao.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
const Proxy = artifacts.require('./Proxy.sol');
const ProxyOwnedByDAO = artifacts.require('./ProxyOwnedByDAO.sol');
const Controller = artifacts.require('./Controller.sol');

const { assertRevert } = require('./helpers/assertThrow')

// Thetta
var DaoBase = artifacts.require('./DaoBase');
var StdDaoToken = artifacts.require('./StdDaoToken');
var DaoStorage = artifacts.require('./DaoStorage');

contract('ProxyOwnedByDAO', (accounts) => {
let proxy;
let proxyDao;
let token;
let controller;

beforeEach(async () => {
proxy = await Proxy.new();

controller = await Controller.new();
token = Controller.at(proxy.address);
});

describe('proxy + proxyDAO with no permissions', async() => {
beforeEach(async () => {
// Create new proxyDao
let t = await StdDaoToken.new("StdToken","STDT",18, true, true, 1000000000);
let store = await DaoStorage.new([t.address]);
let daoBase = await DaoBase.new(store.address);
proxyDao = await ProxyOwnedByDAO.new(daoBase.address, proxy.address);
await t.transferOwnership(daoBase.address);
await store.transferOwnership(daoBase.address);

// finish initialization of DAOBase
await daoBase.renounceOwnership();

// initialize token contract
await token.initialize(controller.address, 400000000);

// transfer ownership to proxyDao
await proxy.transferOwnership(proxyDao.address);
assert.equal(await proxy.owner(), proxyDao.address);
});

it('should not allow to transfer ownership directly', async() => {
return assertRevert(async () => {
await proxy.transferOwnership(accounts[1]);
});
assert.notEqual(await proxy.owner(), accounts[1]);
});

it('should not allow to transfer ownership through the proxyDAO', async() => {
return assertRevert(async () => {
await proxyDao.DAO_transferOwnership(accounts[1]);
});
assert.notEqual(await proxy.owner(), accounts[1]);
});
});

describe('proxy + proxyDAO with permissions', async() => {
beforeEach(async () => {
// Create new proxyDao
let t = await StdDaoToken.new("StdToken","STDT",18, true, true, 1000000000);
let store = await DaoStorage.new([t.address]);
let daoBase = await DaoBase.new(store.address);
proxyDao = await ProxyOwnedByDAO.new(daoBase.address, proxy.address);
await t.transferOwnership(daoBase.address);
await store.transferOwnership(daoBase.address);

// set permissions
await daoBase.addGroupMember("Employees", accounts[0]);

const transferDelegationPerm = await proxyDao.TRANSFER_DELEGATION();
const transferOwnershipPerm = await proxyDao.TRANSFER_OWNERSHIP();
// NOTE: we can use votings here instead!
await daoBase.allowActionByAnyMemberOfGroup(transferDelegationPerm, "Employees");
await daoBase.allowActionByAnyMemberOfGroup(transferOwnershipPerm, "Employees");

// finish initialization of DAOBase
await daoBase.renounceOwnership();

// initialize token contract
await token.initialize(controller.address, 400000000);

// transfer ownership to proxyDao
await proxy.transferOwnership(proxyDao.address);
assert.equal(await proxy.owner(), proxyDao.address);
});

it('should not allow to transfer ownership directly', async() => {
return assertRevert(async () => {
await proxy.transferOwnership(accounts[1]);
});
assert.notEqual(await proxy.owner(), accounts[1]);
});

it('should allow to transfer ownership through the proxyDAO!', async() => {
await proxyDao.DAO_transferOwnership(accounts[1]);
assert.equal(await proxy.owner(), accounts[1]);
});
});

});
2 changes: 1 addition & 1 deletion truffle.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
host: "localhost",
port: 8545,
gasPrice: 10000000000,
gas: 5000000,
gas: 9000000,
network_id: "*" // Match any network id
},
kovan: {
Expand Down