From f9fc8d2e961be8f93b12f0a02c57665d8abfe773 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 18 Apr 2018 18:10:26 -0300 Subject: [PATCH] adapt contracts for upgradeability --- contracts/lifecycle/Migrations.sol | 4 ++++ contracts/mocks/DetailedERC20Mock.sol | 4 +++- contracts/mocks/ERC721TokenMock.sol | 6 ++--- contracts/mocks/PausableMock.sol | 2 ++ contracts/mocks/PausableTokenMock.sol | 2 ++ contracts/ownership/Ownable.sol | 8 +++---- contracts/token/ERC20/DetailedERC20.sol | 6 ++--- contracts/token/ERC20/MintableToken.sol | 4 ++-- contracts/token/ERC20/TokenTimelock.sol | 6 ++--- contracts/token/ERC20/TokenVesting.sol | 9 ++++++-- contracts/token/ERC721/ERC721Token.sol | 5 +++-- package-lock.json | 30 ++++++++++++++++--------- package.json | 3 ++- test/ownership/Ownable.test.js | 1 + test/token/ERC20/MintableToken.test.js | 3 ++- test/token/ERC20/TokenTimelock.test.js | 6 +++-- test/token/ERC20/TokenVesting.test.js | 6 +++-- 17 files changed, 68 insertions(+), 37 deletions(-) diff --git a/contracts/lifecycle/Migrations.sol b/contracts/lifecycle/Migrations.sol index b12a39b2d..caf1fd56b 100644 --- a/contracts/lifecycle/Migrations.sol +++ b/contracts/lifecycle/Migrations.sol @@ -10,6 +10,10 @@ import "../ownership/Ownable.sol"; contract Migrations is Ownable { uint256 public lastCompletedMigration; + function Migrations() public { + Ownable.initialize(msg.sender); + } + function setCompleted(uint256 completed) onlyOwner public { lastCompletedMigration = completed; } diff --git a/contracts/mocks/DetailedERC20Mock.sol b/contracts/mocks/DetailedERC20Mock.sol index eb0f8cee0..9ead14d70 100644 --- a/contracts/mocks/DetailedERC20Mock.sol +++ b/contracts/mocks/DetailedERC20Mock.sol @@ -5,5 +5,7 @@ import "../token/ERC20/DetailedERC20.sol"; contract DetailedERC20Mock is StandardToken, DetailedERC20 { - function DetailedERC20Mock(string _name, string _symbol, uint8 _decimals) DetailedERC20(_name, _symbol, _decimals) public {} + function DetailedERC20Mock(string _name, string _symbol, uint8 _decimals) public { + DetailedERC20.initialize(_name, _symbol, _decimals); + } } diff --git a/contracts/mocks/ERC721TokenMock.sol b/contracts/mocks/ERC721TokenMock.sol index 5fe3668ef..29bfe7439 100644 --- a/contracts/mocks/ERC721TokenMock.sol +++ b/contracts/mocks/ERC721TokenMock.sol @@ -9,9 +9,9 @@ import "../token/ERC721/ERC721Token.sol"; * and a public setter for metadata URI */ contract ERC721TokenMock is ERC721Token { - function ERC721TokenMock(string name, string symbol) public - ERC721Token(name, symbol) - { } + function ERC721TokenMock(string name, string symbol) public { + ERC721Token.initialize(name, symbol); + } function mint(address _to, uint256 _tokenId) public { super._mint(_to, _tokenId); diff --git a/contracts/mocks/PausableMock.sol b/contracts/mocks/PausableMock.sol index e28576b89..2e9022e60 100644 --- a/contracts/mocks/PausableMock.sol +++ b/contracts/mocks/PausableMock.sol @@ -10,6 +10,8 @@ contract PausableMock is Pausable { uint256 public count; function PausableMock() public { + Ownable.initialize(msg.sender); + drasticMeasureTaken = false; count = 0; } diff --git a/contracts/mocks/PausableTokenMock.sol b/contracts/mocks/PausableTokenMock.sol index 24aa6c891..66d79ae3a 100644 --- a/contracts/mocks/PausableTokenMock.sol +++ b/contracts/mocks/PausableTokenMock.sol @@ -7,6 +7,8 @@ import "../token/ERC20/PausableToken.sol"; contract PausableTokenMock is PausableToken { function PausableTokenMock(address initialAccount, uint initialBalance) public { + Ownable.initialize(msg.sender); + balances[initialAccount] = initialBalance; } diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index 0d08f73dd..1c8c47321 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -1,24 +1,24 @@ pragma solidity ^0.4.21; +import 'zos-lib/contracts/migrations/Migratable.sol'; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ -contract Ownable { +contract Ownable is Migratable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ - function Ownable() public { - owner = msg.sender; + function initialize(address _sender) public isInitializer("Ownable", "0") { + owner = _sender; } /** diff --git a/contracts/token/ERC20/DetailedERC20.sol b/contracts/token/ERC20/DetailedERC20.sol index a4807fea7..00ddac633 100644 --- a/contracts/token/ERC20/DetailedERC20.sol +++ b/contracts/token/ERC20/DetailedERC20.sol @@ -1,14 +1,14 @@ pragma solidity ^0.4.21; import "./ERC20.sol"; +import 'zos-lib/contracts/migrations/Migratable.sol'; - -contract DetailedERC20 is ERC20 { +contract DetailedERC20 is Migratable, ERC20 { string public name; string public symbol; uint8 public decimals; - function DetailedERC20(string _name, string _symbol, uint8 _decimals) public { + function initialize(address _sender, string _name, string _symbol, uint8 _decimals) public isInitializer("DetailedERC20", "0") { name = _name; symbol = _symbol; decimals = _decimals; diff --git a/contracts/token/ERC20/MintableToken.sol b/contracts/token/ERC20/MintableToken.sol index b9719529f..36d24587a 100644 --- a/contracts/token/ERC20/MintableToken.sol +++ b/contracts/token/ERC20/MintableToken.sol @@ -2,7 +2,7 @@ pragma solidity ^0.4.21; import "./StandardToken.sol"; import "../../ownership/Ownable.sol"; - +import "zos-lib/contracts/migrations/Migratable.sol"; /** * @title Mintable token @@ -10,7 +10,7 @@ import "../../ownership/Ownable.sol"; * @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120 * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol */ -contract MintableToken is StandardToken, Ownable { +contract MintableToken is Migratable, Ownable, StandardToken { event Mint(address indexed to, uint256 amount); event MintFinished(); diff --git a/contracts/token/ERC20/TokenTimelock.sol b/contracts/token/ERC20/TokenTimelock.sol index a14d904b5..05d840ffb 100644 --- a/contracts/token/ERC20/TokenTimelock.sol +++ b/contracts/token/ERC20/TokenTimelock.sol @@ -1,14 +1,14 @@ pragma solidity ^0.4.21; import "./SafeERC20.sol"; - +import "zos-lib/contracts/migrations/Migratable.sol"; /** * @title TokenTimelock * @dev TokenTimelock is a token holder contract that will allow a * beneficiary to extract the tokens after a given release time */ -contract TokenTimelock { +contract TokenTimelock is Migratable { using SafeERC20 for ERC20Basic; // ERC20 basic token contract being held @@ -20,7 +20,7 @@ contract TokenTimelock { // timestamp when token release is enabled uint256 public releaseTime; - function TokenTimelock(ERC20Basic _token, address _beneficiary, uint256 _releaseTime) public { + function initialize(address _sender, ERC20Basic _token, address _beneficiary, uint256 _releaseTime) public isInitializer("TokenTimelock", "0") { // solium-disable-next-line security/no-block-members require(_releaseTime > block.timestamp); token = _token; diff --git a/contracts/token/ERC20/TokenVesting.sol b/contracts/token/ERC20/TokenVesting.sol index 8e902eac7..ceeb19d6b 100644 --- a/contracts/token/ERC20/TokenVesting.sol +++ b/contracts/token/ERC20/TokenVesting.sol @@ -6,6 +6,7 @@ import "./ERC20Basic.sol"; import "./SafeERC20.sol"; import "../../ownership/Ownable.sol"; import "../../math/SafeMath.sol"; +import 'zos-lib/contracts/migrations/Migratable.sol'; /** @@ -14,7 +15,7 @@ import "../../math/SafeMath.sol"; * typical vesting scheme, with a cliff and vesting period. Optionally revocable by the * owner. */ -contract TokenVesting is Ownable { +contract TokenVesting is Migratable, Ownable { using SafeMath for uint256; using SafeERC20 for ERC20Basic; @@ -42,7 +43,8 @@ contract TokenVesting is Ownable { * @param _duration duration in seconds of the period in which the tokens will vest * @param _revocable whether the vesting is revocable or not */ - function TokenVesting( + function initialize( + address _sender, address _beneficiary, uint256 _start, uint256 _cliff, @@ -50,7 +52,10 @@ contract TokenVesting is Ownable { bool _revocable ) public + isInitializer("TokenVesting", "0") { + Ownable.initialize(_sender); + require(_beneficiary != address(0)); require(_cliff <= _duration); diff --git a/contracts/token/ERC721/ERC721Token.sol b/contracts/token/ERC721/ERC721Token.sol index 7e43ec7e9..24c48f953 100644 --- a/contracts/token/ERC721/ERC721Token.sol +++ b/contracts/token/ERC721/ERC721Token.sol @@ -2,6 +2,7 @@ pragma solidity ^0.4.21; import "./ERC721.sol"; import "./ERC721BasicToken.sol"; +import "zos-lib/contracts/migrations/Migratable.sol"; /** @@ -10,7 +11,7 @@ import "./ERC721BasicToken.sol"; * Moreover, it includes approve all functionality using operator terminology * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ -contract ERC721Token is ERC721, ERC721BasicToken { +contract ERC721Token is Migratable, ERC721, ERC721BasicToken { // Token name string internal name_; @@ -35,7 +36,7 @@ contract ERC721Token is ERC721, ERC721BasicToken { /** * @dev Constructor function */ - function ERC721Token(string _name, string _symbol) public { + function initialize(address _sender, string _name, string _symbol) public isInitializer("ERC721Token", "0") { name_ = _name; symbol_ = _symbol; } diff --git a/package-lock.json b/package-lock.json index 9e56a7db8..d35924e33 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2755,7 +2755,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/ethjs-abi/-/ethjs-abi-0.2.1.tgz", "integrity": "sha1-4KepOn6BFjqUR3utVu3lJKtt5TM=", - "dev": true, "requires": { "bn.js": "4.11.6", "js-sha3": "0.5.5", @@ -2765,14 +2764,12 @@ "bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" }, "js-sha3": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", - "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=", - "dev": true + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=" } } }, @@ -4824,8 +4821,7 @@ "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", - "dev": true + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, "is-my-json-valid": { "version": "2.16.0", @@ -6394,7 +6390,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", - "dev": true, "requires": { "bn.js": "4.11.6", "strip-hex-prefix": "1.0.0" @@ -6403,8 +6398,7 @@ "bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" } } }, @@ -8025,7 +8019,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "dev": true, "requires": { "is-hex-prefixed": "1.0.0" } @@ -9452,6 +9445,21 @@ } } } + }, + "zeppelin-solidity": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/zeppelin-solidity/-/zeppelin-solidity-1.8.0.tgz", + "integrity": "sha512-7Mxq6Y7EES0PSLrRF6v0EVYqBVRRo8hFrr7m3jEs69VbbQ5kpANzizeEdbP1/PWKSOmBOg208qP2vSA0FlzFLA==", + "requires": { + "dotenv": "4.0.0", + "ethjs-abi": "0.2.1" + } + }, + "zos-lib": { + "version": "git://github.com/zeppelinos/zos-lib.git#a4fc8fedbf0c4414717c9aafa24494775423db86", + "requires": { + "zeppelin-solidity": "1.8.0" + } } } } diff --git a/package.json b/package.json index 613b38c8a..afc120c15 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "truffle-hdwallet-provider": "0.0.3" }, "dependencies": { - "dotenv": "^4.0.0" + "dotenv": "^4.0.0", + "zos-lib": "git://github.com/zeppelinos/zos-lib.git" } } diff --git a/test/ownership/Ownable.test.js b/test/ownership/Ownable.test.js index 209a209b1..23f454289 100644 --- a/test/ownership/Ownable.test.js +++ b/test/ownership/Ownable.test.js @@ -8,6 +8,7 @@ contract('Ownable', function (accounts) { beforeEach(async function () { ownable = await Ownable.new(); + await ownable.initialize(accounts[0]); }); it('should have an owner', async function () { diff --git a/test/token/ERC20/MintableToken.test.js b/test/token/ERC20/MintableToken.test.js index a6b2d268e..8e169e58f 100644 --- a/test/token/ERC20/MintableToken.test.js +++ b/test/token/ERC20/MintableToken.test.js @@ -3,7 +3,8 @@ const MintableToken = artifacts.require('MintableToken'); contract('Mintable', function ([owner, anotherAccount]) { beforeEach(async function () { - this.token = await MintableToken.new({ from: owner }); + this.token = await MintableToken.new(); + await this.token.initialize(owner); }); describe('minting finished', function () { diff --git a/test/token/ERC20/TokenTimelock.test.js b/test/token/ERC20/TokenTimelock.test.js index d99c4b247..a8f2e20d8 100644 --- a/test/token/ERC20/TokenTimelock.test.js +++ b/test/token/ERC20/TokenTimelock.test.js @@ -15,9 +15,11 @@ contract('TokenTimelock', function ([_, owner, beneficiary]) { const amount = new BigNumber(100); beforeEach(async function () { - this.token = await MintableToken.new({ from: owner }); + this.token = await MintableToken.new(); + await this.token.initialize(owner); this.releaseTime = latestTime() + duration.years(1); - this.timelock = await TokenTimelock.new(this.token.address, beneficiary, this.releaseTime); + this.timelock = await TokenTimelock.new(); + await this.timelock.initialize(this.token.address, beneficiary, this.releaseTime); await this.token.mint(this.timelock.address, amount, { from: owner }); }); diff --git a/test/token/ERC20/TokenVesting.test.js b/test/token/ERC20/TokenVesting.test.js index e6ce5c177..82101e4c8 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/token/ERC20/TokenVesting.test.js @@ -16,13 +16,15 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { const amount = new BigNumber(1000); beforeEach(async function () { - this.token = await MintableToken.new({ from: owner }); + this.token = await MintableToken.new(); + await this.token.initialize(owner); this.start = latestTime() + duration.minutes(1); // +1 minute so it starts after contract instantiation this.cliff = duration.years(1); this.duration = duration.years(2); - this.vesting = await TokenVesting.new(beneficiary, this.start, this.cliff, this.duration, true, { from: owner }); + this.vesting = await TokenVesting.new(); + await this.vesting.initialize(owner, beneficiary, this.start, this.cliff, this.duration, true); await this.token.mint(this.vesting.address, amount, { from: owner }); });