Skip to content

Commit 3392422

Browse files
committed
Add core abi diff logic & tests
1 parent ecde305 commit 3392422

File tree

13 files changed

+632
-7
lines changed

13 files changed

+632
-7
lines changed

lib/api.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const istanbul = require('sc-istanbul');
66
const assert = require('assert');
77
const detect = require('detect-port');
88
const _ = require('lodash/lang');
9+
const ethersABI = require("@ethersproject/abi");
10+
const difflib = require('difflib');
911

1012
const ConfigValidator = require('./validator');
1113
const Instrumenter = require('./instrumenter');
@@ -342,6 +344,104 @@ class API {
342344
}
343345
}
344346

347+
// =========
348+
// Abi Diff
349+
// =========
350+
diffAbis(orig={}, cur={}){
351+
let origHR;
352+
let curHR;
353+
let plus = 0;
354+
let minus = 0;
355+
356+
const origFunctions = new ethersABI.Interface(orig.abi).functions;
357+
const curFunctions = new ethersABI.Interface(cur.abi).functions;
358+
359+
origHR = this.toHumanReadable(origFunctions)
360+
curHR = this.toHumanReadable(curFunctions)
361+
362+
const fns = difflib.unifiedDiff(
363+
origHR,
364+
curHR,
365+
{
366+
fromfile: orig.contractName,
367+
tofile: cur.contractName,
368+
fromfiledate: `sha: ${orig.sha}`,
369+
tofiledate: `sha: ${cur.sha}`,
370+
lineterm: ''
371+
}
372+
);
373+
374+
const origEvents = new ethersABI.Interface(orig.abi).events;
375+
const curEvents = new ethersABI.Interface(cur.abi).events;
376+
377+
origHR = this.toHumanReadable(origEvents)
378+
curHR = this.toHumanReadable(curEvents)
379+
380+
let events = difflib.unifiedDiff(
381+
origHR,
382+
curHR,
383+
{
384+
fromfile: orig.contractName,
385+
tofile: cur.contractName,
386+
fromfiledate: `sha: ${orig.sha}`,
387+
tofiledate: `sha: ${cur.sha}`,
388+
lineterm: ''
389+
}
390+
);
391+
392+
if (events.length && fns.length){
393+
events = events.slice(3);
394+
}
395+
396+
const diff = fns.concat(events);
397+
398+
// Count changes (unified diff always has a plus & minus in header);
399+
if (diff.length){
400+
plus = -1;
401+
minus = -1;
402+
}
403+
404+
diff.forEach(line => {
405+
if (line[0] === `+`) plus++;
406+
if (line[0] === `-`) minus++;
407+
})
408+
409+
return {
410+
plus,
411+
minus,
412+
diff
413+
}
414+
}
415+
416+
toHumanReadable(ethersOutput){
417+
const human = [];
418+
const signatures = Object.keys(ethersOutput);
419+
420+
for (const sig of signatures){
421+
const method = ethersOutput[sig];
422+
423+
let returns = '';
424+
if (method.outputs){
425+
method.outputs.forEach(output => {
426+
(returns.length)
427+
? returns += `, ${output.type}`
428+
: returns += output.type;
429+
});
430+
};
431+
432+
const mutability = method.stateMutability || '';
433+
let readable = `${method.type} ${sig} ${mutability}`;
434+
435+
if (returns.length){
436+
readable += ` returns (${returns})`
437+
}
438+
439+
human.push(readable);
440+
}
441+
442+
return human;
443+
}
444+
345445
// ========
346446
// File I/O
347447
// ========

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
"author": "",
2525
"license": "ISC",
2626
"dependencies": {
27+
"@ethersproject/abi": "^5.0.9",
2728
"@solidity-parser/parser": "^0.10.1",
2829
"@truffle/provider": "^0.2.24",
2930
"chalk": "^2.4.2",
3031
"death": "^1.1.0",
3132
"detect-port": "^1.3.0",
33+
"difflib": "^0.2.4",
3234
"fs-extra": "^8.1.0",
3335
"ganache-cli": "^6.11.0",
3436
"ghost-testrpc": "^0.0.2",
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
pragma solidity ^0.7.0;
2+
3+
contract Old {
4+
uint public y;
5+
6+
function a() public {
7+
bool x = true;
8+
}
9+
10+
function b() external {
11+
bool x = true;
12+
}
13+
14+
function c() external {
15+
bool x = true;
16+
}
17+
}
18+
19+
contract New {
20+
uint public y;
21+
22+
function a() public {
23+
bool x = true;
24+
}
25+
26+
function b() external {
27+
bool x = true;
28+
}
29+
30+
function c() external {
31+
bool x = true;
32+
}
33+
34+
function d() external {
35+
bool x = true;
36+
}
37+
}
38+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
pragma solidity ^0.7.0;
2+
3+
contract Old {
4+
uint y;
5+
6+
event Evt(uint x, bytes8 y);
7+
8+
function a() public {
9+
bool x = true;
10+
}
11+
}
12+
13+
contract New {
14+
uint y;
15+
16+
function a() public {
17+
bool x = true;
18+
}
19+
20+
event aEvt(bytes8);
21+
event _Evt(bytes8 x, bytes8 y);
22+
}
23+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
pragma solidity ^0.7.0;
2+
3+
contract Old {
4+
uint y;
5+
6+
function a() public {
7+
bool x = true;
8+
}
9+
10+
function b() external {
11+
bool x = true;
12+
}
13+
14+
function c() external {
15+
bool x = true;
16+
}
17+
}
18+
19+
contract New {
20+
uint y;
21+
22+
function a() public {
23+
bool x = true;
24+
}
25+
26+
function b() external {
27+
bool x = true;
28+
}
29+
30+
function c() external {
31+
bool x = true;
32+
}
33+
}
34+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
pragma solidity ^0.7.0;
2+
3+
contract Old {
4+
uint y;
5+
6+
function a() public {
7+
bool x = true;
8+
}
9+
10+
function b() external {
11+
bool x = true;
12+
}
13+
14+
function c() external {
15+
bool x = true;
16+
}
17+
}
18+
19+
contract New {
20+
uint y;
21+
22+
function a() public {
23+
bool x = true;
24+
}
25+
26+
function b(bytes8 z) external {
27+
bool x = true;
28+
}
29+
30+
function c(uint q, uint r) external {
31+
bool x = true;
32+
}
33+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
pragma solidity ^0.7.0;
2+
3+
contract Old {
4+
uint y;
5+
6+
function a() public {
7+
bool x = true;
8+
}
9+
10+
function b() external {
11+
bool x = true;
12+
}
13+
14+
function c() external {
15+
bool x = true;
16+
}
17+
}
18+
19+
contract New {
20+
uint y;
21+
22+
function a() public {
23+
bool x = true;
24+
}
25+
26+
function b() external {
27+
bool x = true;
28+
}
29+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
pragma solidity ^0.7.0;
2+
3+
contract Old {
4+
uint y;
5+
6+
function a() public {
7+
bool x = true;
8+
}
9+
10+
function b() external {
11+
bool x = true;
12+
}
13+
14+
function c() external {
15+
bool x = true;
16+
}
17+
}
18+
19+
contract New {
20+
uint y;
21+
22+
function c() external {
23+
bool x = true;
24+
}
25+
26+
function a() public {
27+
bool x = true;
28+
}
29+
30+
function b() external {
31+
bool x = true;
32+
}
33+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
pragma solidity ^0.7.0;
2+
3+
contract Old {
4+
function a() public view returns (uint) {
5+
return 1;
6+
}
7+
}
8+
9+
contract New {
10+
function a() public view returns (bool) {
11+
return true;
12+
}
13+
14+
function e() public view returns (uint8[2] memory) {
15+
return [5,7];
16+
}
17+
18+
function f() public view returns (uint8[2] memory, uint) {
19+
return ([5,7], 7);
20+
}
21+
22+
function g() public view returns (uint8[3] memory) {
23+
return [5,7,8];
24+
}
25+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
pragma solidity ^0.7.0;
2+
3+
contract Old {
4+
function a() public {
5+
bool x = true;
6+
}
7+
}
8+
9+
contract New {
10+
function a() public view returns (bool) {
11+
return true;
12+
}
13+
}

0 commit comments

Comments
 (0)