@1inch/solidity-utils 1.2.1 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/contracts/libraries/AddressArray.sol +1 -1
- package/contracts/libraries/AddressSet.sol +1 -1
- package/js/profileEVM.js +63 -17
- package/package.json +14 -13
- package/.eslintignore +0 -2
- package/.eslintrc +0 -52
- package/.github/workflows/ci.yml +0 -86
- package/.solcover.js +0 -9
- package/.solhint.json +0 -11
- package/contracts/mocks/AddressArrayMock.sol +0 -36
- package/contracts/mocks/AddressSetMock.sol +0 -32
- package/contracts/mocks/TokenMock.sol +0 -21
- package/contracts/mocks/libraries/StringUtilNaive.sol +0 -25
- package/contracts/tests/RevertReasonParserTest.sol +0 -85
- package/contracts/tests/StringUtilTest.sol +0 -26
- package/hardhat.config.js +0 -33
- package/hardhat.networks.js +0 -48
- package/test/asserts.js +0 -88
- package/test/libraries/AddressArray.js +0 -149
- package/test/libraries/AddressSet.js +0 -122
- package/test/libraries/RevertReasonParser.js +0 -45
- package/test/libraries/StringUtil.js +0 -90
- package/test/profileEVM.js +0 -45
- package/test/utils.js +0 -166
package/README.md
CHANGED
|
@@ -18,12 +18,14 @@ This repository contains frequently used smart contracts, libraries and interfac
|
|
|
18
18
|
|--|--|--|
|
|
19
19
|
|contracts|`EthReceiver`||
|
|
20
20
|
|contracts|`Permitable`||
|
|
21
|
-
|contracts
|
|
21
|
+
|contracts|`GasChecker`||
|
|
22
|
+
|contracts/interfaces|`IDaiLikePermit`|Interface of token which has `permit` method like DAI token|
|
|
22
23
|
|contracts/interfaces|`IWETH`|WETH token interface|
|
|
23
|
-
|contracts/libraries|`
|
|
24
|
-
|contracts/libraries|`
|
|
24
|
+
|contracts/libraries|`AddressArray`|library for work with array of addresses|
|
|
25
|
+
|contracts/libraries|`AddressSet`|library for work with set of addresses|
|
|
26
|
+
|contracts/libraries|`RevertReasonParser`|library parse the message from reverted method to readble format|
|
|
27
|
+
|contracts/libraries|`StringUtil`|optimized methods to convert data to hex|
|
|
25
28
|
|contracts/libraries|`UniERC20`||
|
|
26
|
-
|contracts/mocks|`TokenMock`|Mocked ERC20 token|
|
|
27
29
|
|
|
28
30
|
### JS
|
|
29
31
|
|
|
@@ -40,3 +42,6 @@ This repository contains frequently used smart contracts, libraries and interfac
|
|
|
40
42
|
|profileEVM|`profileEVM(txHash, instruction, optionalTraceFile)`|the same as the `countInstructions()` with option of writing all trace to `optionalTraceFile`|
|
|
41
43
|
|profileEVM|`gasspectEVM(txHash, optionalTraceFile)`|returns all used operations in `txHash` transaction and their costs with option of writing all trace to `optionalTraceFile`|
|
|
42
44
|
|
|
45
|
+
### UTILS
|
|
46
|
+
|
|
47
|
+
...
|
package/js/profileEVM.js
CHANGED
|
@@ -1,23 +1,65 @@
|
|
|
1
1
|
const { promisify } = require('util');
|
|
2
2
|
const fs = require('fs').promises;
|
|
3
3
|
|
|
4
|
-
function _normalizeOp (
|
|
5
|
-
if (
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
function _normalizeOp (ops, i) {
|
|
5
|
+
if (ops[i].op === 'STATICCALL') {
|
|
6
|
+
ops[i].gasCost = ops[i].gasCost - ops[i + 1].gas;
|
|
7
|
+
|
|
8
|
+
if (ops[i].stack.length > 8 && ops[i].stack[ops[i].stack.length - 8] === '0000000000000000000000000000000000000000000000000000000000000001') {
|
|
9
|
+
ops[i].op = 'STATICCALL-ECRECOVER';
|
|
10
|
+
} else if (ops[i].stack.length > 8 && ops[i].stack[ops[i].stack.length - 8] <= '00000000000000000000000000000000000000000000000000000000000000FF') {
|
|
11
|
+
ops[i].op = 'STATICCALL-' + ops[i].stack[ops[i].stack.length - 8].substr(62, 2);
|
|
12
12
|
} else {
|
|
13
|
-
|
|
13
|
+
ops[i].args = [
|
|
14
|
+
'0x' + ops[i].stack[ops[i].stack.length - 2].substr(24),
|
|
15
|
+
'0x' + (ops[i].memory || []).join('').substr(
|
|
16
|
+
2 * web3.utils.toBN(ops[i].stack[ops[i].stack.length - 3]).toNumber(),
|
|
17
|
+
2 * web3.utils.toBN(ops[i].stack[ops[i].stack.length - 4]).toNumber(),
|
|
18
|
+
),
|
|
19
|
+
];
|
|
20
|
+
if (ops[i].gasCost === 100) {
|
|
21
|
+
ops[i].op += '_R';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (['CALL', 'DELEGATECALL', 'CALLCODE'].indexOf(ops[i].op) !== -1) {
|
|
26
|
+
ops[i].args = [
|
|
27
|
+
'0x' + ops[i].stack[ops[i].stack.length - 2].substr(24),
|
|
28
|
+
'0x' + (ops[i].memory || []).join('').substr(
|
|
29
|
+
2 * web3.utils.toBN(ops[i].stack[ops[i].stack.length - 4]).toNumber(),
|
|
30
|
+
2 * web3.utils.toBN(ops[i].stack[ops[i].stack.length - 5]).toNumber(),
|
|
31
|
+
),
|
|
32
|
+
];
|
|
33
|
+
ops[i].gasCost = ops[i].gasCost - ops[i + 1].gas;
|
|
34
|
+
ops[i].res = ops[i + 1].stack[ops[i + 1].stack.length - 1];
|
|
35
|
+
|
|
36
|
+
if (ops[i].gasCost === 100) {
|
|
37
|
+
ops[i].op += '_R';
|
|
14
38
|
}
|
|
15
39
|
}
|
|
16
|
-
if (['
|
|
17
|
-
|
|
40
|
+
if (['RETURN', 'REVERT', 'INVALID'].indexOf(ops[i].op) !== -1) {
|
|
41
|
+
ops[i].gasCost = 3;
|
|
42
|
+
}
|
|
43
|
+
if (['SSTORE', 'SLOAD'].indexOf(ops[i].op) !== -1) {
|
|
44
|
+
ops[i].args = [
|
|
45
|
+
'0x' + ops[i].stack[ops[i].stack.length - 1],
|
|
46
|
+
];
|
|
47
|
+
if (ops[i].op === 'SSTORE') {
|
|
48
|
+
ops[i].args.push('0x' + ops[i].stack[ops[i].stack.length - 2]);
|
|
49
|
+
}
|
|
50
|
+
if (ops[i].gasCost === 100) {
|
|
51
|
+
ops[i].op += '_R';
|
|
52
|
+
}
|
|
53
|
+
if (ops[i].gasCost === 20000) {
|
|
54
|
+
ops[i].op += '_I';
|
|
55
|
+
}
|
|
56
|
+
ops[i].res = ops[i + 1].stack[ops[i + 1].stack.length - 1];
|
|
18
57
|
}
|
|
19
|
-
if ([
|
|
20
|
-
|
|
58
|
+
if (ops[i].op === 'EXTCODESIZE') {
|
|
59
|
+
ops[i].args = [
|
|
60
|
+
'0x' + ops[i].stack[ops[i].stack.length - 1].substr(24),
|
|
61
|
+
];
|
|
62
|
+
ops[i].res = ops[i + 1].stack[ops[i + 1].stack.length - 1];
|
|
21
63
|
}
|
|
22
64
|
}
|
|
23
65
|
|
|
@@ -44,7 +86,7 @@ async function profileEVM (txHash, instruction, optionalTraceFile) {
|
|
|
44
86
|
return str.split('"' + instruction.toUpperCase() + '"').length - 1;
|
|
45
87
|
}
|
|
46
88
|
|
|
47
|
-
async function gasspectEVM (txHash, optionalTraceFile) {
|
|
89
|
+
async function gasspectEVM (txHash, options = {}, optionalTraceFile) {
|
|
48
90
|
const trace = await promisify(web3.currentProvider.send.bind(web3.currentProvider))({
|
|
49
91
|
jsonrpc: '2.0',
|
|
50
92
|
method: 'debug_traceTransaction',
|
|
@@ -55,9 +97,9 @@ async function gasspectEVM (txHash, optionalTraceFile) {
|
|
|
55
97
|
const ops = trace.result.structLogs;
|
|
56
98
|
|
|
57
99
|
const traceAddress = [0, -1];
|
|
58
|
-
for (const op of ops) {
|
|
100
|
+
for (const [i, op] of ops.entries()) {
|
|
59
101
|
op.traceAddress = traceAddress.slice(0, traceAddress.length - 1);
|
|
60
|
-
_normalizeOp(
|
|
102
|
+
_normalizeOp(ops, i);
|
|
61
103
|
|
|
62
104
|
if (op.depth + 2 > traceAddress.length) {
|
|
63
105
|
traceAddress[traceAddress.length - 1] += 1;
|
|
@@ -69,7 +111,11 @@ async function gasspectEVM (txHash, optionalTraceFile) {
|
|
|
69
111
|
}
|
|
70
112
|
}
|
|
71
113
|
|
|
72
|
-
const
|
|
114
|
+
const minOpGasCost = options.minOpGasCost ? options.minOpGasCost : 300;
|
|
115
|
+
const result = ops.filter(op => op.gasCost > minOpGasCost).map(op => op.traceAddress.join('-') + '-' + op.op +
|
|
116
|
+
(options.args ? '(' + (op.args || []).join(',') + ')' : '') +
|
|
117
|
+
(options.res ? (op.res ? ':0x' + op.res : '') : '') +
|
|
118
|
+
' = ' + op.gasCost);
|
|
73
119
|
|
|
74
120
|
if (optionalTraceFile) {
|
|
75
121
|
await fs.writeFile(optionalTraceFile, JSON.stringify(result));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1inch/solidity-utils",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,28 +8,29 @@
|
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@openzeppelin/contracts": "^4.
|
|
11
|
+
"@openzeppelin/contracts": "^4.4.0",
|
|
12
|
+
"ethereumjs-wallet": "^1.0.2"
|
|
12
13
|
},
|
|
13
14
|
"devDependencies": {
|
|
14
|
-
"@nomiclabs/hardhat-etherscan": "^2.1.
|
|
15
|
+
"@nomiclabs/hardhat-etherscan": "^2.1.8",
|
|
15
16
|
"@nomiclabs/hardhat-truffle5": "^2.0.0",
|
|
16
17
|
"@nomiclabs/hardhat-web3": "^2.0.0",
|
|
17
|
-
"@openzeppelin/test-helpers": "^0.5.
|
|
18
|
+
"@openzeppelin/test-helpers": "^0.5.15",
|
|
18
19
|
"chai": "^4.3.4",
|
|
19
20
|
"cross-spawn": "^7.0.3",
|
|
20
21
|
"dotenv": "^10.0.0",
|
|
21
|
-
"eslint": "^
|
|
22
|
+
"eslint": "^8.3.0",
|
|
22
23
|
"eslint-config-standard": "^16.0.3",
|
|
23
|
-
"eslint-plugin-import": "^2.
|
|
24
|
+
"eslint-plugin-import": "^2.25.3",
|
|
24
25
|
"eslint-plugin-node": "^11.1.0",
|
|
25
|
-
"eslint-plugin-promise": "^5.1.
|
|
26
|
+
"eslint-plugin-promise": "^5.1.1",
|
|
26
27
|
"eslint-plugin-standard": "^5.0.0",
|
|
27
|
-
"hardhat": "^2.
|
|
28
|
-
"hardhat-deploy": "^0.9.
|
|
29
|
-
"hardhat-gas-reporter": "^1.0.
|
|
28
|
+
"hardhat": "^2.7.0",
|
|
29
|
+
"hardhat-deploy": "^0.9.14",
|
|
30
|
+
"hardhat-gas-reporter": "^1.0.6",
|
|
30
31
|
"rimraf": "^3.0.2",
|
|
31
32
|
"shx": "^0.3.3",
|
|
32
|
-
"solc": "^0.8.
|
|
33
|
+
"solc": "^0.8.10",
|
|
33
34
|
"solhint": "^3.3.6",
|
|
34
35
|
"solidity-coverage": "^0.7.17"
|
|
35
36
|
},
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
"solidity-utils-docify": "utils/docify.utils.js"
|
|
38
39
|
},
|
|
39
40
|
"scripts": {
|
|
40
|
-
"build": "rimraf ./dist && mkdir dist && shx cp -R js ./dist/js && shx cp -R utils ./dist/utils && shx cp package.json ./dist && cp -R ./contracts ./dist/contracts",
|
|
41
|
+
"build": "rimraf ./dist && mkdir dist && shx cp -R js ./dist/js && shx cp -R utils ./dist/utils && shx cp package.json ./dist && shx cp README.md ./dist && shx cp -R ./contracts ./dist/contracts && shx rm -rf dist/contracts/mocks dist/contracts/tests",
|
|
41
42
|
"coverage": "hardhat coverage",
|
|
42
43
|
"lint": "yarn run lint:js && yarn run lint:sol",
|
|
43
44
|
"lint:fix": "yarn run lint:js:fix && yarn run lint:sol:fix",
|
|
@@ -55,5 +56,5 @@
|
|
|
55
56
|
"test": "test"
|
|
56
57
|
},
|
|
57
58
|
"author": "1inch",
|
|
58
|
-
"description": ""
|
|
59
|
+
"description": "Solidity and JS utils"
|
|
59
60
|
}
|
package/.eslintignore
DELETED
package/.eslintrc
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends" : [
|
|
3
|
-
"standard",
|
|
4
|
-
"plugin:promise/recommended"
|
|
5
|
-
],
|
|
6
|
-
"plugins": [
|
|
7
|
-
"promise"
|
|
8
|
-
],
|
|
9
|
-
"env": {
|
|
10
|
-
"browser" : true,
|
|
11
|
-
"node" : true,
|
|
12
|
-
"mocha" : true,
|
|
13
|
-
"jest" : true
|
|
14
|
-
},
|
|
15
|
-
"globals" : {
|
|
16
|
-
"artifacts": false,
|
|
17
|
-
"contract": false,
|
|
18
|
-
"assert": false,
|
|
19
|
-
"web3": false
|
|
20
|
-
},
|
|
21
|
-
"rules": {
|
|
22
|
-
|
|
23
|
-
// Strict mode
|
|
24
|
-
"strict": [2, "global"],
|
|
25
|
-
|
|
26
|
-
// Code style
|
|
27
|
-
"indent": [2, 4],
|
|
28
|
-
"quotes": [2, "single"],
|
|
29
|
-
"semi": ["error", "always"],
|
|
30
|
-
"space-before-function-paren": ["error", "always"],
|
|
31
|
-
"no-use-before-define": 0,
|
|
32
|
-
"no-unused-expressions": "off",
|
|
33
|
-
"eqeqeq": [2, "smart"],
|
|
34
|
-
"dot-notation": [2, {"allowKeywords": true, "allowPattern": ""}],
|
|
35
|
-
"no-redeclare": [2, {"builtinGlobals": true}],
|
|
36
|
-
"no-trailing-spaces": [2, { "skipBlankLines": true }],
|
|
37
|
-
"eol-last": 1,
|
|
38
|
-
"comma-spacing": [2, {"before": false, "after": true}],
|
|
39
|
-
"camelcase": [2, {"properties": "always"}],
|
|
40
|
-
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
|
|
41
|
-
"comma-dangle": [1, "always-multiline"],
|
|
42
|
-
"no-dupe-args": 2,
|
|
43
|
-
"no-dupe-keys": 2,
|
|
44
|
-
"no-debugger": 0,
|
|
45
|
-
"no-undef": 2,
|
|
46
|
-
"object-curly-spacing": [2, "always"],
|
|
47
|
-
"max-len": [2, 200, 2],
|
|
48
|
-
"generator-star-spacing": ["error", "before"],
|
|
49
|
-
"promise/avoid-new": 0,
|
|
50
|
-
"promise/always-return": 0
|
|
51
|
-
}
|
|
52
|
-
}
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ master ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ master ]
|
|
8
|
-
jobs:
|
|
9
|
-
lint:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- uses: actions/checkout@v2
|
|
14
|
-
|
|
15
|
-
- uses: actions/setup-node@v2
|
|
16
|
-
with:
|
|
17
|
-
node-version: '16.x'
|
|
18
|
-
|
|
19
|
-
- run: npm install -g yarn
|
|
20
|
-
|
|
21
|
-
- id: yarn-cache
|
|
22
|
-
run: echo "::set-output name=dir::$(yarn cache dir)"
|
|
23
|
-
|
|
24
|
-
- uses: actions/cache@v2
|
|
25
|
-
with:
|
|
26
|
-
path: ${{ steps.yarn-cache.outputs.dir }}
|
|
27
|
-
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
28
|
-
restore-keys: |
|
|
29
|
-
${{ runner.os }}-yarn-
|
|
30
|
-
|
|
31
|
-
- run: yarn
|
|
32
|
-
- run: yarn lint
|
|
33
|
-
|
|
34
|
-
test:
|
|
35
|
-
runs-on: ubuntu-latest
|
|
36
|
-
|
|
37
|
-
steps:
|
|
38
|
-
- uses: actions/checkout@v2
|
|
39
|
-
|
|
40
|
-
- uses: actions/setup-node@v2
|
|
41
|
-
with:
|
|
42
|
-
node-version: '16.x'
|
|
43
|
-
|
|
44
|
-
- run: npm install -g yarn
|
|
45
|
-
|
|
46
|
-
- id: yarn-cache
|
|
47
|
-
run: echo "::set-output name=dir::$(yarn cache dir)"
|
|
48
|
-
|
|
49
|
-
- uses: actions/cache@v2
|
|
50
|
-
with:
|
|
51
|
-
path: ${{ steps.yarn-cache.outputs.dir }}
|
|
52
|
-
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
53
|
-
restore-keys: |
|
|
54
|
-
${{ runner.os }}-yarn-
|
|
55
|
-
|
|
56
|
-
- run: yarn
|
|
57
|
-
- run: yarn test
|
|
58
|
-
|
|
59
|
-
coverage:
|
|
60
|
-
runs-on: ubuntu-latest
|
|
61
|
-
steps:
|
|
62
|
-
- uses: actions/checkout@v2
|
|
63
|
-
|
|
64
|
-
- uses: actions/setup-node@v2
|
|
65
|
-
with:
|
|
66
|
-
node-version: 16.x
|
|
67
|
-
|
|
68
|
-
- run: npm install -g yarn
|
|
69
|
-
|
|
70
|
-
- id: yarn-cache
|
|
71
|
-
run: echo "::set-output name=dir::$(yarn cache dir)"
|
|
72
|
-
|
|
73
|
-
- uses: actions/cache@v2
|
|
74
|
-
with:
|
|
75
|
-
path: ${{ steps.yarn-cache.outputs.dir }}
|
|
76
|
-
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
77
|
-
restore-keys: |
|
|
78
|
-
${{ runner.os }}-yarn-
|
|
79
|
-
|
|
80
|
-
- run: yarn
|
|
81
|
-
- run: yarn coverage
|
|
82
|
-
|
|
83
|
-
- name: Coveralls
|
|
84
|
-
uses: coverallsapp/github-action@v1.1.2
|
|
85
|
-
with:
|
|
86
|
-
github-token: ${{ secrets.GITHUB_TOKEN }}
|
package/.solcover.js
DELETED
package/.solhint.json
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
|
|
3
|
-
pragma solidity 0.8.9;
|
|
4
|
-
|
|
5
|
-
import "../libraries/AddressArray.sol";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
contract AddressArrayMock {
|
|
9
|
-
using AddressArray for AddressArray.Data;
|
|
10
|
-
|
|
11
|
-
AddressArray.Data private _self;
|
|
12
|
-
|
|
13
|
-
function length() external view returns(uint256) {
|
|
14
|
-
return AddressArray.length(_self);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function at(uint i) external view returns(address) {
|
|
18
|
-
return AddressArray.at(_self, i);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function get() external view returns(address[] memory arr) {
|
|
22
|
-
return AddressArray.get(_self);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function push(address account) external returns(uint256) {
|
|
26
|
-
return AddressArray.push(_self, account);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function pop() external {
|
|
30
|
-
AddressArray.pop(_self);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function set(uint256 index, address account) external {
|
|
34
|
-
AddressArray.set(_self, index, account);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
|
|
3
|
-
pragma solidity 0.8.9;
|
|
4
|
-
|
|
5
|
-
import "../libraries/AddressSet.sol";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
contract AddressSetMock {
|
|
9
|
-
using AddressSet for AddressSet.Data;
|
|
10
|
-
|
|
11
|
-
AddressSet.Data private _self;
|
|
12
|
-
|
|
13
|
-
function length() external view returns(uint) {
|
|
14
|
-
return AddressSet.length(_self);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function at(uint index) external view returns(address) {
|
|
18
|
-
return AddressSet.at(_self, index);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function contains(address item) external view returns(bool) {
|
|
22
|
-
return AddressSet.contains(_self, item);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function add(address item) external returns(bool) {
|
|
26
|
-
return AddressSet.add(_self, item);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function remove(address item) external returns(bool) {
|
|
30
|
-
return AddressSet.remove(_self, item);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
|
|
3
|
-
pragma solidity ^0.8.0;
|
|
4
|
-
pragma abicoder v1;
|
|
5
|
-
|
|
6
|
-
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
7
|
-
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
contract TokenMock is ERC20, Ownable {
|
|
11
|
-
// solhint-disable-next-line no-empty-blocks
|
|
12
|
-
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
|
|
13
|
-
|
|
14
|
-
function mint(address account, uint256 amount) external onlyOwner {
|
|
15
|
-
_mint(account, amount);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function burn(address account, uint256 amount) external onlyOwner {
|
|
19
|
-
_burn(account, amount);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
|
|
3
|
-
pragma solidity ^0.8.0;
|
|
4
|
-
pragma abicoder v1;
|
|
5
|
-
|
|
6
|
-
library StringUtilNaive {
|
|
7
|
-
bytes16 private constant _ALPHABET = 0x30313233343536373839616263646566;
|
|
8
|
-
|
|
9
|
-
function toHex(uint256 value) internal pure returns(string memory) {
|
|
10
|
-
return toHex(abi.encodePacked(value));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function toHex(bytes memory data) internal pure returns(string memory) {
|
|
14
|
-
unchecked {
|
|
15
|
-
bytes memory str = new bytes(2 + data.length * 2);
|
|
16
|
-
str[0] = "0";
|
|
17
|
-
str[1] = "x";
|
|
18
|
-
for (uint256 i = 0; i < data.length; i++) {
|
|
19
|
-
str[2 * i + 2] = _ALPHABET[uint8(data[i] >> 4)];
|
|
20
|
-
str[2 * i + 3] = _ALPHABET[uint8(data[i] & 0x0f)];
|
|
21
|
-
}
|
|
22
|
-
return string(str);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
|
|
3
|
-
pragma solidity ^0.8.0;
|
|
4
|
-
pragma abicoder v1;
|
|
5
|
-
|
|
6
|
-
import "../libraries/RevertReasonParser.sol";
|
|
7
|
-
|
|
8
|
-
contract RevertReasonParserTest {
|
|
9
|
-
function emptyRevert() external pure {
|
|
10
|
-
revert(); // solhint-disable-line reason-string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function emptyStringRevert() external pure {
|
|
14
|
-
revert("");
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function nonEmptyRevert() external pure {
|
|
18
|
-
revert("reason");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function assertion() external pure {
|
|
22
|
-
assert(false);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function longStringRevert() external pure {
|
|
26
|
-
// solhint-disable-next-line reason-string
|
|
27
|
-
revert("Very long text to test for reverts that return string of more than 32 bytes length");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function withoutAssertion() external pure {
|
|
31
|
-
assert(true);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function testEmptyRevert() external view {
|
|
35
|
-
_test(this.emptyRevert, "Unknown(0x)");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function testEmptyStringRevert() external view {
|
|
39
|
-
_test(this.emptyStringRevert, "Error()");
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function testNonEmptyRevert() external view {
|
|
43
|
-
_test(this.nonEmptyRevert, "Error(reason)");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function testAssertion() external view {
|
|
47
|
-
_test(this.assertion, "Panic(0x0000000000000000000000000000000000000000000000000000000000000001)");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function testLongStringRevert() external view {
|
|
51
|
-
_test(this.longStringRevert, "Error(Very long text to test for reverts that return string of more than 32 bytes length)");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function testParseWithThrow() external view {
|
|
55
|
-
try this.nonEmptyRevert() { // solhint-disable-line no-empty-blocks
|
|
56
|
-
} catch (bytes memory reason) {
|
|
57
|
-
bytes32 invalidReasonPart1;
|
|
58
|
-
bytes32 invalidReasonPart2;
|
|
59
|
-
bytes32 invalidReasonPart3;
|
|
60
|
-
assembly { // solhint-disable-line no-inline-assembly
|
|
61
|
-
invalidReasonPart1 := mload(add(reason, 0x20))
|
|
62
|
-
invalidReasonPart2 := mload(add(reason, 0x40))
|
|
63
|
-
invalidReasonPart3 := mload(add(reason, 0x40))
|
|
64
|
-
}
|
|
65
|
-
bytes memory invalidReason = abi.encodePacked(invalidReasonPart1, invalidReasonPart2, invalidReasonPart3);
|
|
66
|
-
RevertReasonParser.parse(invalidReason, "");
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function testWithThrow() external view {
|
|
71
|
-
_test(this.withoutAssertion, "Error(reason)");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function _test(function() external pure testFunction, string memory expectedReason) private pure {
|
|
75
|
-
try testFunction() {
|
|
76
|
-
revert("testFunctions without throw");
|
|
77
|
-
} catch (bytes memory reason) {
|
|
78
|
-
string memory parsedReason = RevertReasonParser.parse(reason, "");
|
|
79
|
-
require(
|
|
80
|
-
keccak256(abi.encodePacked(expectedReason)) == keccak256(abi.encodePacked(parsedReason)),
|
|
81
|
-
string(abi.encodePacked("Expected { ", expectedReason, " }, but got { ", parsedReason, " }"))
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
|
|
3
|
-
pragma solidity ^0.8.0;
|
|
4
|
-
pragma abicoder v1;
|
|
5
|
-
|
|
6
|
-
import "../libraries/StringUtil.sol";
|
|
7
|
-
import "../mocks/libraries/StringUtilNaive.sol";
|
|
8
|
-
import "../GasChecker.sol";
|
|
9
|
-
|
|
10
|
-
contract StringUtilTest is GasChecker {
|
|
11
|
-
function toHex(uint256 value, uint256 expectedGasCost) external view checkGasCost(expectedGasCost) returns (string memory) {
|
|
12
|
-
return StringUtil.toHex(value);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function toHexBytes(bytes memory data, uint256 expectedGasCost) external view checkGasCost(expectedGasCost) returns (string memory) {
|
|
16
|
-
return StringUtil.toHex(data);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function toHexNaive(uint256 value, uint256 expectedGasCost) external view checkGasCost(expectedGasCost) returns (string memory) {
|
|
20
|
-
return StringUtilNaive.toHex(value);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function toHexNaiveBytes(bytes memory data, uint256 expectedGasCost) external view checkGasCost(expectedGasCost) returns (string memory) {
|
|
24
|
-
return StringUtilNaive.toHex(data);
|
|
25
|
-
}
|
|
26
|
-
}
|
package/hardhat.config.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
require('@nomiclabs/hardhat-etherscan');
|
|
2
|
-
require('@nomiclabs/hardhat-truffle5');
|
|
3
|
-
require('dotenv').config();
|
|
4
|
-
require('hardhat-deploy');
|
|
5
|
-
require('hardhat-gas-reporter');
|
|
6
|
-
require('solidity-coverage');
|
|
7
|
-
|
|
8
|
-
const networks = require('./hardhat.networks');
|
|
9
|
-
|
|
10
|
-
module.exports = {
|
|
11
|
-
etherscan: {
|
|
12
|
-
apiKey: process.env.ETHERSCAN_KEY,
|
|
13
|
-
},
|
|
14
|
-
solidity: {
|
|
15
|
-
version: '0.8.9',
|
|
16
|
-
settings: {
|
|
17
|
-
optimizer: {
|
|
18
|
-
enabled: true,
|
|
19
|
-
runs: 1000000,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
networks,
|
|
24
|
-
namedAccounts: {
|
|
25
|
-
deployer: {
|
|
26
|
-
default: 0,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
gasReporter: {
|
|
30
|
-
enable: true,
|
|
31
|
-
currency: 'USD',
|
|
32
|
-
},
|
|
33
|
-
};
|