From 115edb6544a93f82dbd9cbe3f4deeb9fcfd43539 Mon Sep 17 00:00:00 2001 From: Satyam Agrawal Date: Wed, 12 Jun 2019 13:16:21 +0530 Subject: [PATCH] [3.38]: Add ST storage layout check script in CI pipeline (#704) * add st storage layout check script in CI pipeline * add info comment --- .circleci/config.yml | 16 ++++++++++++ contracts/tokens/OZStorage.sol | 15 +++++++++--- contracts/tokens/STGetter.sol | 2 +- package.json | 4 +-- scripts/compareStorageLayout.js | 43 +++++++++++++++++---------------- 5 files changed, 53 insertions(+), 27 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 42c27b22c..2f8945d91 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,6 +69,21 @@ jobs: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules + st-storage-layout-check: + docker: + - image: maxsam4/solidity-kit + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package.json" }} + - run: yarn install + - run: node --version + - run: truffle version + - run: npm run st-storage-layout-check + - save_cache: + key: dependency-cache-{{ checksum "package.json" }} + paths: + - node_modules docs: docker: - image: maxsam4/solidity-kit @@ -90,6 +105,7 @@ workflows: jobs: - coverage - clash-check + - st-storage-layout-check daily-builds: triggers: - schedule: diff --git a/contracts/tokens/OZStorage.sol b/contracts/tokens/OZStorage.sol index 01e415c0a..b61cf0ec0 100644 --- a/contracts/tokens/OZStorage.sol +++ b/contracts/tokens/OZStorage.sol @@ -1,12 +1,17 @@ pragma solidity ^0.5.0; +/* + * @dev It is the contract that contains the storage items related to the ERC20 contract implementaiton + * of the openzeppelin-solidity. Used to allow the storage declaration of ERC20 to the STGetter contract +*/ + contract OZStorage { - mapping (address => uint256) public _balances; + mapping (address => uint256) private _balances; - mapping (address => mapping (address => uint256)) public _allowed; + mapping (address => mapping (address => uint256)) private _allowed; - uint256 public _totalSupply; + uint256 private _totalSupply; /// @dev counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; @@ -19,4 +24,8 @@ contract OZStorage { return _balances[_investor]; } + function _allowance(address owner, address spender) internal view returns(uint256) { + return _allowed[owner][spender]; + } + } diff --git a/contracts/tokens/STGetter.sol b/contracts/tokens/STGetter.sol index 19960f4be..9b34272e1 100644 --- a/contracts/tokens/STGetter.sol +++ b/contracts/tokens/STGetter.sol @@ -212,7 +212,7 @@ contract STGetter is OZStorage, SecurityTokenStorage { * @return Whether the `_operator` is an operator for all partitions of `_tokenHolder` */ function isOperator(address _operator, address _tokenHolder) external view returns (bool) { - return (_allowed[_tokenHolder][_operator] == uint(-1)); + return (_allowance(_tokenHolder, _operator) == uint(-1)); } /** diff --git a/package.json b/package.json index 9eaf3e5a4..a88497524 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "flatten-all": "npm run flatten-modules && npm run flatten-token && npm run flatten-mocks && npm run flatten-oracles && npm run flatten-proxies && npm run flatten && npm run flatten-proxyFactories", "ethereum-bridge": "node_modules/.bin/ethereum-bridge -H localhost:8545 -a 9 --dev", "st20generator": "node demo/ST20Generator", - "pretty": "prettier --write --print-width 140 --tab-width 4 \"**/*.js\"" + "pretty": "prettier --write --print-width 140 --tab-width 4 \"**/*.js\"", + "st-storage-layout-check": "node scripts/compareStorageLayout.js SecurityToken STGetter" }, "repository": { "type": "git", @@ -84,7 +85,6 @@ "mocha-junit-reporter": "^1.18.0", "openzeppelin-solidity": "2.2.0", "prettier": "^1.15.3", - "prompt": "^1.0.0", "request": "^2.88.0", "request-promise": "^4.2.2", "sol-merger": "^0.1.2", diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js index 9faf22692..6b08defa3 100644 --- a/scripts/compareStorageLayout.js +++ b/scripts/compareStorageLayout.js @@ -1,47 +1,48 @@ const fs = require("fs"); const _ = require("underscore"); const solc = require("solc"); -const prompt = require("prompt"); const path = require("path"); const util = require("util"); const exec = util.promisify(require("child_process").exec); -console.log(`Mandatory: Solc cli tool should be installed globally. Please put the contract name only`); -prompt.start(); +console.log(`Mandatory: Solc cli tool should be installed globally. Please put the contract name only in any order`); -prompt.get(["LogicContract", "ProxyContract"], async (err, result) => { - let temp; - let logicFilePath; - let proxyFilePath; +let contractA = process.argv.slice(2)[0]; +let contractB = process.argv.slice(2)[1]; - const fileList = walkSync("./contracts", []); +compareStorage(contractA, contractB); + +async function compareStorage() { - let paths = findPath(result.LogicContract, result.ProxyContract, fileList); + const fileList = walkSync("./contracts", []); + let paths = findPath(contractA, contractB, fileList); if (paths.length == 2) { console.log("Contracts exists \n"); await flatContracts(paths); let temp; - let logicFilePath = `./flat/${path.basename(paths[0])}`; - let proxyFilePath = `./flat/${path.basename(paths[1])}`; + let contractAPath = `./flat/${path.basename(paths[0])}`; + let contractBPath = `./flat/${path.basename(paths[1])}`; - if (path.basename(paths[0]) === result.LogicContract) { - temp = logicFilePath; - logicFilePath = proxyFilePath; - proxyFilePath = temp; + if (path.basename(paths[0]) === contractA) { + temp = contractAPath; + contractAPath = contractBPath; + contractBPath = temp; } - let logicAST = await getAST(logicFilePath); - let proxyAST = await getAST(proxyFilePath); + let contractAAST = await getAST(contractAPath); + let contractBAST = await getAST(contractBPath); // Deleting the temp folder (no longer required) await flushTemp(); - console.log(compareStorageLayouts(parseContract(logicAST), parseContract(proxyAST))); + var result = compareStorageLayouts(parseContract(contractAAST), parseContract(contractBAST)); + if (!result) + process.exit(1); } else { console.log("Contracts doesn't exists"); } -}); +} function traverseAST(_input, _elements) { if (_input.children) { @@ -101,7 +102,7 @@ function parseContract(input) { return orderedStateVariables; } -var walkSync = function(dir, filelist) { +function walkSync(dir, filelist) { files = fs.readdirSync(dir); filelist = filelist || []; files.forEach(function(file) { @@ -114,7 +115,7 @@ var walkSync = function(dir, filelist) { return filelist; }; -var findPath = function(logicContractName, proxyContractName, fileList) { +function findPath(logicContractName, proxyContractName, fileList) { let paths = new Array(); for (let i = 0; i < fileList.length; i++) { if (