From 3dc552d2feca0445937f77bdbf163e89994925da Mon Sep 17 00:00:00 2001 From: Chandan Kumar Date: Tue, 27 Jun 2017 18:29:37 +0530 Subject: [PATCH] Make organisation upgradeable by coding to an interface The Parent contract is now coded to an Organisation interface rather than its implementation. This enables upgrading of the Organisation contract as long as the ABI doesn't change. This also implies that Parent can no longer create Organisations. In this implementation, Organisation needs to be instantiated by the user and passed on to the Parent contract for registering or upgrading. --- contracts/Organisation.sol | 10 +-- contracts/OrganisationInterface.sol | 33 ++++++++ contracts/OrganisationUpdated.sol | 79 ------------------- contracts/Parent.sol | 26 +++--- migrations/2_deploy_parent.js | 13 +++ ..._contracts.js => 3_deploy_organisation.js} | 14 +--- 6 files changed, 64 insertions(+), 111 deletions(-) create mode 100644 contracts/OrganisationInterface.sol delete mode 100644 contracts/OrganisationUpdated.sol create mode 100644 migrations/2_deploy_parent.js rename migrations/{2_deploy_contracts.js => 3_deploy_organisation.js} (55%) diff --git a/contracts/Organisation.sol b/contracts/Organisation.sol index be60706..9f071d8 100755 --- a/contracts/Organisation.sol +++ b/contracts/Organisation.sol @@ -12,16 +12,16 @@ contract Organisation is DataVerifiable using SecurityLibrary for address; address public eternalStorage; - function Organisation(address _tokenLedger, address _eternalStorage) { - tokenLedger = ITokenLedger(_tokenLedger); - eternalStorage = _eternalStorage; - } - modifier onlyAdmins { if (!eternalStorage.isUserAdmin(msg.sender)) throw; _; } + function setDataStore(address _tokenLedger, address _eternalStorage) { + tokenLedger = ITokenLedger(_tokenLedger); + eternalStorage = _eternalStorage; + } + function addProposal(bytes32 _name) onlyAdmins refundEtherSentByAccident diff --git a/contracts/OrganisationInterface.sol b/contracts/OrganisationInterface.sol new file mode 100644 index 0000000..d497313 --- /dev/null +++ b/contracts/OrganisationInterface.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.4.8; + +import "./DataVerifiable.sol"; +import "./ITokenLedger.sol"; + +contract OrganisationInterface is DataVerifiable +{ + function tokenLedger() constant returns (ITokenLedger); + + function eternalStorage() constant returns (address); + + function setDataStore(address _tokenLedger, address _eternalStorage); + + function addProposal(bytes32 _name); + + function proposalsCount() constant returns (uint256); + + function getProposal(uint256 _id) constant returns (bytes32 _name, uint256 _eth); + + function updateProposal(uint256 _id, bytes32 _name); + + function fundProposal(uint256 _id); + + function setProposalFund(uint256 _id, uint256 _eth); + + function generateTokens(uint256 _amount); + + function getBalance(address _account) constant returns (uint256); + + function setTokenLedgerAddress(address _tokenLedger); + + function kill(address upgradedOrganisation_); +} diff --git a/contracts/OrganisationUpdated.sol b/contracts/OrganisationUpdated.sol deleted file mode 100644 index c458b76..0000000 --- a/contracts/OrganisationUpdated.sol +++ /dev/null @@ -1,79 +0,0 @@ -pragma solidity ^0.4.8; - -import "./TokenLedger.sol"; -import "./EternalStorage.sol"; - -contract OrganisationUpdated -{ - event ProposalAdded(uint256 id, uint256 when); - event ProposalUpdated(uint256 id, uint256 when); - - TokenLedger public tokenLedger; - EternalStorage public eternalStorage; - - function OrganisationUpdated(address _tokenLedger, address _eternalStorage) { - tokenLedger = TokenLedger(_tokenLedger); - eternalStorage = EternalStorage(_eternalStorage); - } - - function addProposal(bytes32 _name) - { - var newId = proposalsCount(); - eternalStorage.setBytes32Value(sha3("proposal_name", newId), _name); - eternalStorage.setUIntValue(sha3("proposal_eth", newId), 0); - eternalStorage.setUIntValue(sha3("ProposalCount"), newId+1); - - ProposalAdded(newId, now); - } - - function proposalsCount() constant returns (uint256) - { - return eternalStorage.getUIntValue(sha3("ProposalCount")); - } - - function getProposal(uint256 _id) constant returns (bytes32 _name, uint256 _eth) - { - var proposalName = eternalStorage.getBytes32Value(sha3("proposal_name", _id)); - var proposalEth = eternalStorage.getUIntValue(sha3("proposal_eth", _id)); - - return (proposalName, proposalEth); - } - - function updateProposal(uint256 _id, bytes32 _name) - { - eternalStorage.setBytes32Value(sha3("proposal_name", _id), _name); - ProposalUpdated(_id, now); - } - - function fundProposal(uint256 _id) payable - { - eternalStorage.setUIntValue(sha3("proposal_eth", _id), msg.value); - } - - function setProposalFund(uint256 _id, uint256 _eth) - { - eternalStorage.setUIntValue(sha3("proposal_eth", _id), _eth); - } - - function generateTokens(uint256 _amount) - { - tokenLedger.generateTokens(_amount); - } - - function getBalance(address _account) constant returns (uint256) - { - return tokenLedger.balanceOf(_account); - } - - function kill(address upgradedOrganisation_) - { - var tokenBalance = tokenLedger.balanceOf(this); - tokenLedger.transfer(upgradedOrganisation_, tokenBalance); - selfdestruct(upgradedOrganisation_); - } - - function coolLogic() constant returns (bool) - { - return true; - } -} diff --git a/contracts/Parent.sol b/contracts/Parent.sol index bc51515..eacc4d2 100755 --- a/contracts/Parent.sol +++ b/contracts/Parent.sol @@ -1,33 +1,31 @@ pragma solidity ^0.4.8; -import "./Organisation.sol"; -import "./OrganisationUpdated.sol"; +import "./OrganisationInterface.sol"; import "./TokenLedger.sol"; import "./EternalStorage.sol"; import "./SecurityLibrary.sol"; contract Parent { - event OrganisationCreated(address organisation, uint now); event OrganisationUpgraded(address organisation, uint now); using SecurityLibrary for EternalStorage; mapping(bytes32 => address) public organisations; - function createOrganisation(bytes32 key_) + function registerOrganisation(bytes32 key_, address orgAddress) { + var tokenLedger = new TokenLedger(); var eternalStorage = new EternalStorage(); // Set the calling user as the first colony admin eternalStorage.addAdmin(msg.sender); - var organisation = new Organisation(tokenLedger, eternalStorage); + OrganisationInterface(orgAddress).setDataStore(tokenLedger, eternalStorage); // Set the organisation as the storage owner - eternalStorage.changeOwner(organisation); + eternalStorage.changeOwner(orgAddress); - organisations[key_] = organisation; - OrganisationCreated(organisation, now); + organisations[key_] = orgAddress; } function getOrganisation(bytes32 key_) constant returns (address) @@ -35,18 +33,18 @@ contract Parent { return organisations[key_]; } - function upgradeOrganisation(bytes32 key_) + function upgradeOrganisation(bytes32 key_, address newOrgAddress) { address organisationAddress = organisations[key_]; - var organisation = Organisation(organisationAddress); + var organisation = OrganisationInterface(organisationAddress); var tokenLedger = organisation.tokenLedger(); var eternalStorage = organisation.eternalStorage(); - OrganisationUpdated organisationNew = new OrganisationUpdated(tokenLedger, eternalStorage); + OrganisationInterface(newOrgAddress).setDataStore(tokenLedger, eternalStorage); - organisation.kill(organisationNew); + organisation.kill(newOrgAddress); - organisations[key_] = organisationNew; - OrganisationUpgraded(organisationNew, now); + organisations[key_] = newOrgAddress; + OrganisationUpgraded(newOrgAddress, now); } } diff --git a/migrations/2_deploy_parent.js b/migrations/2_deploy_parent.js new file mode 100644 index 0000000..d2c8026 --- /dev/null +++ b/migrations/2_deploy_parent.js @@ -0,0 +1,13 @@ +var EternalStorage = artifacts.require("./EternalStorage.sol"); +var SecurityLibrary = artifacts.require("./SecurityLibrary.sol"); +var TokenLedger = artifacts.require("./TokenLedger.sol"); +var Parent = artifacts.require("./Parent.sol"); + +module.exports = function(deployer) { + deployer.deploy(EternalStorage); + deployer.deploy(SecurityLibrary); + deployer.deploy(TokenLedger); + + deployer.link(SecurityLibrary, Parent); + deployer.deploy(Parent); +}; diff --git a/migrations/2_deploy_contracts.js b/migrations/3_deploy_organisation.js similarity index 55% rename from migrations/2_deploy_contracts.js rename to migrations/3_deploy_organisation.js index ee3aeec..d125b11 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/3_deploy_organisation.js @@ -1,27 +1,15 @@ var DataVerifiable = artifacts.require("./DataVerifiable.sol"); var EternalStorage = artifacts.require("./EternalStorage.sol"); var Organisation = artifacts.require("./Organisation.sol"); -var OrganisationUpdated = artifacts.require("./OrganisationUpdated.sol"); -var Ownable = artifacts.require("./Ownable.sol"); -var Parent = artifacts.require("./Parent.sol"); var ProposalsLibrary = artifacts.require("./ProposalsLibrary.sol"); var SecurityLibrary = artifacts.require("./SecurityLibrary.sol"); -var TokenLedger = artifacts.require("./TokenLedger.sol"); module.exports = function(deployer) { deployer.deploy(DataVerifiable); - deployer.deploy(EternalStorage); - deployer.deploy(OrganisationUpdated); - deployer.deploy(Ownable); - deployer.deploy(TokenLedger); - deployer.deploy(ProposalsLibrary); deployer.deploy(SecurityLibrary); + deployer.link(ProposalsLibrary, Organisation); deployer.link(SecurityLibrary, Organisation); deployer.deploy(Organisation); - - deployer.link(ProposalsLibrary, Parent); - deployer.link(SecurityLibrary, Parent); - deployer.deploy(Parent); };