From a9784bb02cf5b9b81c9c62de6f2ba3bebc0a68f7 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Tue, 4 May 2021 20:56:53 -0400 Subject: [PATCH] Update to @openzeppelin/contracts-upgradeable from @openzeppelin/contracts --- contracts/karma-1-ERC20.sol | 28 +++++++ contracts/karma-ERC20.sol | 134 ++---------------------------- migrations/2_deploy_karma.js | 9 +- migrations/3_deploy_proxy.js | 11 +++ migrations/4_upgrade_karma.js | 9 ++ package-lock.json | 151 ++++++++++++++++++++++++++++++++-- package.json | 2 + truffle-config.js | 13 +-- 8 files changed, 210 insertions(+), 147 deletions(-) create mode 100644 contracts/karma-1-ERC20.sol create mode 100644 migrations/3_deploy_proxy.js create mode 100644 migrations/4_upgrade_karma.js diff --git a/contracts/karma-1-ERC20.sol b/contracts/karma-1-ERC20.sol new file mode 100644 index 0000000..37efbba --- /dev/null +++ b/contracts/karma-1-ERC20.sol @@ -0,0 +1,28 @@ +// Copyright [2021] - [2021], [Shaun Reed] and [Karma] contributors +// SPDX-License-Identifier: MIT + +pragma solidity >= 0.8.0; + +// ---------------------------------------------------------------------------- +// Import ERC Token Standard #20 Interface +// ETH EIP repo: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md +// ---------------------------------------------------------------------------- +import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +// ---------------------------------------------------------------------------- +// Karma Contract +// ---------------------------------------------------------------------------- + +contract KarmaV2 is Initializable, ERC20Upgradeable +{ + function initialize(string memory name, string memory symbol, uint256 initialSupply) public virtual initializer { + __ERC20_init(name, symbol); + _mint(_msgSender(), initialSupply); + } + + function isToken() public returns (bool) + { + return true; + } +} diff --git a/contracts/karma-ERC20.sol b/contracts/karma-ERC20.sol index 01c0e4c..b976fe9 100644 --- a/contracts/karma-ERC20.sol +++ b/contracts/karma-ERC20.sol @@ -7,136 +7,18 @@ pragma solidity >= 0.8.0; // Import ERC Token Standard #20 Interface // ETH EIP repo: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md // ---------------------------------------------------------------------------- -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; // ---------------------------------------------------------------------------- // Karma Contract // ---------------------------------------------------------------------------- -contract Karma is IERC20, Initializable + + +contract Karma is Initializable, ERC20Upgradeable { - // Avoid initializing fields in declarations - // https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#avoid-initial-values-in-field-declarations - string public name; - string public symbol; - uint8 public decimals; // 18 decimals is the strongly suggested default, avoid changing it - uint256 public _totalSupply; - - // Balances for each account; A hashmap using wallet address as key and uint as value - mapping(address => uint) balances; - - // Owner of account approves the transfer of an amount to another account - mapping(address => mapping(address => uint)) allowed; -// -// /** -// * Constrctor function -// * -// * Initializes contract with initial supply tokens to the creator of the contract -// */ -// constructor() -// { -// name = "Karma"; // Name of the token -// symbol = "KRMA"; // Abbreviation of the token -// decimals = 18; // Number of decimals that can be used to split token -// -// -// // FORMAT: -// // Where SUPPLY is the number of coins in base 10 decimal notation -// // And DECIMALS is a trailing number of 0's; Count must match `decimals` value set above -// // 1000 000 000 000000000000000000 == 1 billion total supply; -// // + trailing 0's represent the 18 decimal locations that can be used to send fractions -// _totalSupply = 1000000000000000000000000000; -// -// -// // Set the remaining balance of the contract owner to the total supply -// balances[msg.sender] = _totalSupply; // msg.sender is the calling address for this constructor -// // Transfer the total supply to the contract owner on initialization -// emit Transfer(address(0), msg.sender, _totalSupply); // address(0) is used to represent a new TX -// } - - function initialize() public initializer - { - // ERC20 Standard dictates names of these variables - // https://ethereum.org/en/developers/docs/standards/tokens/erc-20/#body - name = "Karma"; // Name of the token - symbol = "KRMA"; // Abbreviation of the token - decimals = 18; // Number of decimals that can be used to split token - - - // FORMAT: - // Where SUPPLY is the number of coins in base 10 decimal notation - // And DECIMALS is a trailing number of 0's; Count must match `decimals` value set above - // 1000 000 000 000000000000000000 == 1 billion total supply; - // + trailing 0's represent the 18 decimal locations that can be used to send fractions - _totalSupply = 1000000000000000000000000000; - - - // Set the remaining balance of the contract owner to the total supply - balances[msg.sender] = _totalSupply; // msg.sender is the calling address for this constructor - // Transfer the total supply to the contract owner on initialization - emit Transfer(address(0), msg.sender, _totalSupply); // address(0) is used to represent a new TX + function initialize(string memory name, string memory symbol, uint256 initialSupply) public virtual initializer { + __ERC20_init(name, symbol); + _mint(_msgSender(), initialSupply); } - - - // Get the total circulating supply of the token - function totalSupply() public override view returns (uint) - { - // By subtracting from tokens held at address(0), we provide an address to 'burn' the supply - return _totalSupply - balances[address(0)]; // Subtract from tokens held at address(0) - } - - // Get the token balance for account `tokenOwner` - function balanceOf(address tokenOwner) public override view returns (uint balance) - { - return balances[tokenOwner]; // Return the balance of the owner's address - } - - // To initiate a transaction, we first approve an address to withdraw from our wallet - // + msg.sender is approving spender to withdraw from its balance _value tokens - // Allow `spender` to withdraw from your account, multiple times, up to the `tokens` - // If this function is called again it overwrites the current allowance with _value - function approve(address spender, uint _value) public override returns (bool success) - { - // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - //if ((value != 0) && (allowed[msg.sender][spender] != 0)) throw; - - allowed[msg.sender][spender] = _value; - emit Approval(msg.sender, spender, _value); - return true; - } - - // Helper to check the amount of tokens allowed for this spender at this address - // @param tokenOwner The address of the account owning tokens - // @param spender The address of the account able to transfer the tokens - // returns Amount of remaining tokens allowed to spent - function allowance(address tokenOwner, address spender) public override view returns (uint remaining) - { - return allowed[tokenOwner][spender]; - } - - // Send `_value` amount of tokens from address `from` to address `to` - function transferFrom(address from, address to, uint _value) public override returns (bool success) - { - // Set this wallet balance -= _value - balances[from] = balances[from] - _value; - - // Update this wallet's approved balance for the withdrawing address -// uint allowance = allowed[from][msg.sender]; - allowed[from][msg.sender] -= _value; - - // Add the amount of tokens to the balance at the receiving address - balances[to] = balances[to] + _value; - emit Transfer(from, to, _value); - return true; - } - - // Transfer the balance from owner's account to another account - function transfer(address to, uint tokens) public override returns (bool success) - { - balances[msg.sender] = balances[msg.sender] - tokens; - balances[to] = balances[to] + tokens; - emit Transfer(msg.sender, to, tokens); - return true; - } - } diff --git a/migrations/2_deploy_karma.js b/migrations/2_deploy_karma.js index 43ca7d1..1188dc0 100644 --- a/migrations/2_deploy_karma.js +++ b/migrations/2_deploy_karma.js @@ -1,10 +1,5 @@ -const { deployProxy } = require('@openzeppelin/truffle-upgrades'); - const Karma = artifacts.require('Karma'); module.exports = async function (deployer) { - // initializer chooses function to call on initialization - // + initialize() defined in karma-ERC20.sol, marked as initializer - // https://docs.openzeppelin.com/upgrades-plugins/1.x/api-truffle-upgrades#deploy-proxy - await deployProxy(Karma, {deployer, initializer: 'initialize'}); -}; \ No newline at end of file + await deployer.deploy(Karma); +}; diff --git a/migrations/3_deploy_proxy.js b/migrations/3_deploy_proxy.js new file mode 100644 index 0000000..3148f27 --- /dev/null +++ b/migrations/3_deploy_proxy.js @@ -0,0 +1,11 @@ +const Karma = artifacts.require('Karma'); + +const { deployProxy } = require('@openzeppelin/truffle-upgrades'); + +module.exports = async function (deployer) { + await deployProxy( + Karma, + ['Karma', 'KRMA', '1000000000000000000000000000'], + { deployer, initializer: 'initialize' } + ); +}; \ No newline at end of file diff --git a/migrations/4_upgrade_karma.js b/migrations/4_upgrade_karma.js new file mode 100644 index 0000000..24070b1 --- /dev/null +++ b/migrations/4_upgrade_karma.js @@ -0,0 +1,9 @@ +const { upgradeProxy } = require('@openzeppelin/truffle-upgrades'); + +const Karma = artifacts.require('Karma'); +const KarmaV2 = artifacts.require('KarmaV2'); + +module.exports = async function (deployer) { + const existing = await Karma.deployed(); + await upgradeProxy(existing.address, KarmaV2, { deployer }); +}; diff --git a/package-lock.json b/package-lock.json index 3ae9db2..1132955 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3541,6 +3541,12 @@ "integrity": "sha512-UcIJl/vUVjTr3H1yYXZi7Sr2PlXzBEHVUJKOUlVyzyy0FI8oQCCy0Wx+BuK/fojdnmLeMvUk4KUvhKUybP+C7Q==", "dev": true }, + "@openzeppelin/contracts-upgradeable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.1.0.tgz", + "integrity": "sha512-QZSvbYqNpU/x60vARhq/jghh97VWjml3NAlKfu4u1XehvpEBbHVXJyKTBSZtZY7jviG305jOczEisnN8VeOMcw==", + "dev": true + }, "@openzeppelin/truffle-upgrades": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@openzeppelin/truffle-upgrades/-/truffle-upgrades-1.6.0.tgz", @@ -3808,12 +3814,128 @@ "dev": true, "optional": true }, + "@resolver-engine/core": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.2.1.tgz", + "integrity": "sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "request": "^2.85.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "@resolver-engine/fs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.2.1.tgz", + "integrity": "sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg==", + "dev": true, + "requires": { + "@resolver-engine/core": "^0.2.1", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "@resolver-engine/imports": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.2.2.tgz", + "integrity": "sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg==", + "dev": true, + "requires": { + "@resolver-engine/core": "^0.2.1", + "debug": "^3.1.0", + "hosted-git-info": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "@resolver-engine/imports-fs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz", + "integrity": "sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ==", + "dev": true, + "requires": { + "@resolver-engine/fs": "^0.2.1", + "@resolver-engine/imports": "^0.2.2", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", "dev": true }, + "@solidity-parser/parser": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.8.2.tgz", + "integrity": "sha512-8LySx3qrNXPgB5JiULfG10O3V7QTxI/TLzSw5hFQhXWSkVxZBAv4rZQ0sYgLEbc8g3L2lmnujj1hKul38Eu5NQ==", + "dev": true + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -10157,7 +10279,6 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, - "optional": true, "requires": { "locate-path": "^2.0.0" } @@ -11010,8 +11131,7 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "optional": true + "dev": true }, "htmlparser2": { "version": "3.10.1", @@ -13422,7 +13542,6 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, - "optional": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -15692,7 +15811,6 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, - "optional": true, "requires": { "p-try": "^1.0.0" } @@ -15702,7 +15820,6 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, - "optional": true, "requires": { "p-limit": "^1.1.0" } @@ -15727,8 +15844,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "optional": true + "dev": true }, "pako": { "version": "1.0.11", @@ -19522,6 +19638,19 @@ "original-require": "^1.0.1" } }, + "truffle-flattener": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/truffle-flattener/-/truffle-flattener-1.5.0.tgz", + "integrity": "sha512-vmzWG/L5OXoNruMV6u2l2IaheI091e+t+fFCOR9sl46EE3epkSRIwGCmIP/EYDtPsFBIG7e6exttC9/GlfmxEQ==", + "dev": true, + "requires": { + "@resolver-engine/imports-fs": "^0.2.2", + "@solidity-parser/parser": "^0.8.0", + "find-up": "^2.1.0", + "mkdirp": "^1.0.4", + "tsort": "0.0.1" + } + }, "truffle-plugin-verify": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/truffle-plugin-verify/-/truffle-plugin-verify-0.5.7.tgz", @@ -19562,6 +19691,12 @@ "dev": true, "optional": true }, + "tsort": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", + "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=", + "dev": true + }, "tty-table": { "version": "2.8.13", "resolved": "https://registry.npmjs.org/tty-table/-/tty-table-2.8.13.tgz", diff --git a/package.json b/package.json index 39bba6f..4e618f0 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,11 @@ "license": "MIT", "devDependencies": { "@openzeppelin/contracts": "^4.0.0", + "@openzeppelin/contracts-upgradeable": "^4.1.0", "@openzeppelin/truffle-upgrades": "^1.6.0", "@truffle/hdwallet-provider": "^1.3.0", "truffle": "^5.3.3", + "truffle-flattener": "^1.5.0", "truffle-plugin-verify": "^0.5.7" } } diff --git a/truffle-config.js b/truffle-config.js index ba4e433..2496492 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -26,6 +26,12 @@ const { alchemyApiUrl, mnemonic, etherscanApiKey } = require('./secrets.json'); // const mnemonic = fs.readFileSync(".secret").toString().trim(); module.exports = { + plugins: [ + 'truffle-plugin-verify' + ], + api_keys: { + etherscan: etherscanApiKey + }, /** * Networks define how you connect to your ethereum client and let you set the * defaults web3 uses to send transactions. If you don't specify one truffle @@ -111,10 +117,5 @@ module.exports = { db: { enabled: false }, - api_keys: { - etherscan: etherscanApiKey - }, - plugins: [ - 'truffle-plugin-verify' - ] + };