-
Notifications
You must be signed in to change notification settings - Fork 33
/
generate_interface.py
106 lines (87 loc) · 2.65 KB
/
generate_interface.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env python
"""
## INSTALLATION
- copypasta `generate_interface.py` to your brownie dir
- install the excellent [`abi-to-sol`](https://github.com/gnidan/abi-to-sol):
```
npm install abi-to-sol
```
- make sure to have installed `prettier` and its solidity plugin alongside `abi-to-sol`:
```
npm install --save-dev prettier prettier-plugin-solidity
```
## USAGE
```
python generate_interface.py 0xb2Bf1d48F2C2132913278672e6924efda3385de2
```
it will generate a clean `.sol` interface file in `interfaces/autogenerated/`.
## TODO
- support vyper contracts (eg `0x1Ba86c33509013c937344f6e231DA2E63ea45197`)
"""
import os
import re
import requests
import sys
from dotenv import load_dotenv
# https://etherscan.io/contract-license-types
# https://spdx.org/licenses/
ETHERSCAN_TO_SPDX = {
"Unlicense": "Unlicense",
"MIT": "MIT",
"GNU GPLv2": "GPL-2.0",
"GNU GPLv3": "GPL-3.0",
"GNU LGPLv2.1": "LGPL-2.1",
"GNU LGPLv3": "LGPL-3.0",
"BSD-2-Clause": "BSD-2-Clause",
"BSD-3-Clause": "BSD-3-Clause",
"MPL-2.0": "MPL-2.0",
"OSL-3.0": "OSL-3.0",
"Apache-2.0": "Apache-2.0",
"GNU AGPLv3": "AGPL-3.0",
"BSL 1.1": "BUSL-1.1",
}
def get_from_etherscan(address):
r = requests.get(
"https://api.etherscan.io/api",
params={
"module": "contract",
"action": "getsourcecode",
"address": address,
"apikey": os.getenv("ETHERSCAN_TOKEN"),
},
).json()
if r["status"] != "1":
raise Exception(r["result"])
result = r["result"][0]
if result["Proxy"] != "0":
return get_from_etherscan(result["Implementation"])
contract = {}
contract["name"] = result["ContractName"]
try:
contract["license"] = ETHERSCAN_TO_SPDX[result["LicenseType"]]
except KeyError:
contract["license"] = None
contract["version"] = re.findall(r"v(\d+\.\d+\.\d+)\+", result["CompilerVersion"])[
0
]
contract["abi"] = result["ABI"]
return contract
def main(address):
load_dotenv()
dump_dir = "interfaces/autogenerated/"
os.makedirs(dump_dir, exist_ok=True)
contract = get_from_etherscan(address)
dump_tmp = f"{dump_dir}I{contract['name']}.tmp"
with open(dump_tmp, "w") as f:
f.write(contract["abi"])
command = f"cat {dump_tmp} | abi-to-sol --validate -S -A"
if contract["license"]:
command += f" -L={contract['license']}"
if contract["version"]:
command += f" -V=^{contract['version']}"
command += f" I{contract['name']} > {dump_dir}I{contract['name']}.sol"
print(command)
os.system(command)
os.remove(dump_tmp)
if __name__ == "__main__":
main(sys.argv[1])