Skip to content

Commit

Permalink
Merge pull request #625 from PolymathNetwork/clash-script
Browse files Browse the repository at this point in the history
Added script to detect function selector clashes
  • Loading branch information
maxsam4 authored Apr 12, 2019
2 parents 67f46f9 + 949dc2e commit abc5837
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ jobs:
- node_modules
- store_artifacts:
path: ./coverage/lcov.info
clash-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 clash-check
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- node_modules
docs:
docker:
- image: maxsam4/solidity-kit
Expand All @@ -74,6 +89,7 @@ workflows:
commit:
jobs:
- coverage
- clash-check
daily-builds:
triggers:
- schedule:
Expand Down
4 changes: 4 additions & 0 deletions contracts/mocks/FunctionSigClash1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
contract functionSigClash1 {
// function clash550254402() public {
// }
}
4 changes: 4 additions & 0 deletions contracts/mocks/FunctionSigClash2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
contract functionSigClash2 {
// function proxyOwner() public {
// }
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"scripts": {
"test": "scripts/test.sh 2> /dev/null",
"clash-check": "node scripts/clashCheck.js",
"gas": "scripts/gasUsage.sh",
"wintest": "scripts\\wintest.cmd",
"wincov": "scripts\\wincov.cmd",
Expand Down
55 changes: 55 additions & 0 deletions scripts/clashCheck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const fs = require('fs');
const exec = require('child_process').execSync;
const chalk = require('chalk');
const Web3 = require('web3');

async function readFiles() {
if (fs.existsSync("./build/contracts/")) {
return fs.readdirSync("./build/contracts/");
} else {
console.log(chalk.yellow('Compiling contracts. This may take a while, please wait.'));
exec('truffle compile');
return fs.readdirSync("./build/contracts/");
}
}

async function checkClashes() {
console.log(chalk.green("Starting function selector clash check"));
let files = await readFiles();
let contractFunctions = new Set();
let functionSelectors = new Map();
files.forEach(item => {
let ABI = JSON.parse(fs.readFileSync(`./build/contracts/${item}`).toString()).abi;
ABI.forEach(element => {
if (element['type'] == 'function') {
let functionSig = element['name'] + '(';
element['inputs'].forEach(input => {
functionSig = functionSig + input['type'] + ',';
});
if(functionSig[functionSig.length - 1] == ',')
functionSig = functionSig.slice(0, -1) + ')';
else
functionSig = functionSig + ')';
contractFunctions.add(functionSig);
}
});
});
let clashesFound = false;
contractFunctions.forEach(functionSig => {
let fnSelector = Web3.utils.sha3(functionSig).slice(0, 10);
if(functionSelectors.has(fnSelector)) {
clashesFound = true;
console.log(chalk.red('Function selector clash found!', functionSelectors.get(fnSelector), 'and', functionSig, 'have the same function selector:', fnSelector));
functionSelectors.set(fnSelector, functionSelectors.get(fnSelector) + ', ' + functionSig);
} else {
functionSelectors.set(fnSelector, functionSig);
}
});
if (clashesFound) {
console.log(chalk.yellow("The clash(es) might be in two different contracts and hence not be am Issue.\nThis script can not detect this (yet) because of proxy contracts"));
throw("Clash(es) found! Please fix.");
}
console.log(chalk.green("Clash check finished. No Clashes found."));
}

checkClashes();

0 comments on commit abc5837

Please sign in to comment.