Skip to content

Commit 4d0f8c1

Browse files
Amxxfrangio
andauthored
Check inheritance tree consistency (#2727)
Co-authored-by: Francisco Giordano <[email protected]>
1 parent 27e0900 commit 4d0f8c1

File tree

5 files changed

+173
-3
lines changed

5 files changed

+173
-3
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ jobs:
2929
env:
3030
FORCE_COLOR: 1
3131
ENABLE_GAS_REPORT: true
32+
- run: npm run test:inheritance
3233
- name: Print gas report
3334
run: cat gas-report.txt
3435

contracts/mocks/ERC1155ReceiverMock.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
55
import "../token/ERC1155/IERC1155Receiver.sol";
66
import "../utils/introspection/ERC165.sol";
77

8-
contract ERC1155ReceiverMock is IERC1155Receiver, ERC165 {
8+
contract ERC1155ReceiverMock is ERC165, IERC1155Receiver {
99
bytes4 private _recRetval;
1010
bool private _recReverts;
1111
bytes4 private _batRetval;

package-lock.json

Lines changed: 130 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"release": "scripts/release/release.sh",
2929
"version": "scripts/release/version.sh",
3030
"test": "hardhat test",
31+
"test:inheritance": "node scripts/inheritanceOrdering artifacts/build-info/*",
3132
"gas-report": "env ENABLE_GAS_REPORT=true npm run test"
3233
},
3334
"repository": {
@@ -64,6 +65,7 @@
6465
"eth-sig-util": "^3.0.0",
6566
"ethereumjs-util": "^7.0.7",
6667
"ethereumjs-wallet": "^1.0.1",
68+
"graphlib": "^2.1.8",
6769
"hardhat": "^2.0.6",
6870
"hardhat-gas-reporter": "^1.0.4",
6971
"keccak256": "^1.0.2",
@@ -75,6 +77,7 @@
7577
"prettier-plugin-solidity": "^1.0.0-beta.13",
7678
"rimraf": "^3.0.2",
7779
"solhint": "^3.3.6",
80+
"solidity-ast": "^0.4.25",
7881
"solidity-coverage": "^0.7.11",
7982
"solidity-docgen": "^0.5.3",
8083
"web3": "^1.3.0",

scripts/inheritanceOrdering.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const path = require('path');
2+
const graphlib = require('graphlib');
3+
const { findAll } = require('solidity-ast/utils');
4+
const { _: artifacts } = require('yargs').argv;
5+
6+
for (const artifact of artifacts) {
7+
const { output: solcOutput } = require(path.resolve(__dirname, '..', artifact));
8+
9+
const graph = new graphlib.Graph({ directed: true });
10+
const names = {};
11+
const linearized = [];
12+
13+
for (const source in solcOutput.contracts) {
14+
for (const contractDef of findAll('ContractDefinition', solcOutput.sources[source].ast)) {
15+
names[contractDef.id] = contractDef.name;
16+
linearized.push(contractDef.linearizedBaseContracts);
17+
18+
contractDef.linearizedBaseContracts.forEach((c1, i, contracts) => contracts.slice(i + 1).forEach(c2 => {
19+
graph.setEdge(c1, c2);
20+
}));
21+
}
22+
}
23+
24+
graphlib.alg.findCycles(graph).forEach(([ c1, c2 ]) => {
25+
console.log(`Conflict between ${names[c1]} and ${names[c2]} detected in the following dependency chains:`);
26+
linearized
27+
.filter(chain => chain.includes(parseInt(c1)) && chain.includes(parseInt(c2)))
28+
.forEach(chain => {
29+
const comp = chain.indexOf(c1) < chain.indexOf(c2) ? '>' : '<';
30+
console.log(`- ${names[c1]} ${comp} ${names[c2]}: ${chain.reverse().map(id => names[id]).join(', ')}`);
31+
});
32+
process.exitCode = 1;
33+
});
34+
}
35+
36+
if (!process.exitCode) {
37+
console.log('Contract ordering is consistent.');
38+
}

0 commit comments

Comments
 (0)