├── .gitignore
├── contracts
└── @cryptosvinarnik.zip
├── requirements.txt
├── README.md
├── config.py
├── utils
├── scan_api.py
├── deployment.py
└── saving.py
├── app.py
├── app_cmd.py
└── templates
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 |
--------------------------------------------------------------------------------
/contracts/@cryptosvinarnik.zip:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | beautifulsoup4==4.11.1
2 | eth_account==0.5.6
3 | Flask==2.2.2
4 | httpx==0.23.0
5 | loguru==0.5.3
6 | requests==2.27.1
7 | web3==5.25.0
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # contract-parser
2 | Install requirements: pip install -r requirements.txt
3 |
4 | Run app.py for saver with local server or run app_cmd.py for cmd version.
5 |
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | API_KEY = "" # <--- input your API_KEY from etherscan.io
2 |
3 |
4 | # DON'T TOUCH THIS
5 | ENDPOINTS = {"1": "https://api.etherscan.io", "2": "https://api.bscscan.com", "3": "https://api.polygonscan.com", "4": "https://api-rinkeby.etherscan.io/"}
6 | SCANS = {"1": "https://etherscan.io", "2": "https://bscscan.com", "3": "https://polygonscan.com", "4": "https://rinkeby.etherscan.io/"}
7 |
--------------------------------------------------------------------------------
/utils/scan_api.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | import requests
4 |
5 |
6 | @dataclass
7 | class EVMScan():
8 | api_key: str
9 | endpoint: str
10 |
11 | def get_source_code(self, address: str) -> dict:
12 | return requests.get(
13 | f"{self.endpoint}/api",
14 | params={
15 | "module": "contract",
16 | "action": "getsourcecode",
17 | "address": address,
18 | "apikey": self.api_key
19 | }
20 | ).json()
21 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, request, send_file
2 |
3 | from utils.saving import save_contract
4 | from utils.scan_api import EVMScan
5 |
6 | app = Flask(__name__, static_folder="contracts")
7 |
8 |
9 | with open("templates/index.html") as f:
10 | html = f.read()
11 |
12 | @app.route('/', methods=['GET', 'POST'])
13 | def index():
14 | if request.method == "POST":
15 | api_key = request.form.get("api-key")
16 | contract = request.form.get("address")
17 | endpoint = request.form.get("endpoint")
18 |
19 | file = save_contract(EVMScan(api_key, endpoint), contract.lower())
20 |
21 | return send_file(file, as_attachment=True)
22 |
23 | return html
24 |
25 | if __name__ == "__main__":
26 | app.run()
27 |
--------------------------------------------------------------------------------
/utils/deployment.py:
--------------------------------------------------------------------------------
1 | from eth_account import Account
2 | from web3 import Web3
3 | from web3.middleware import geth_poa_middleware
4 |
5 |
6 | class Deployer():
7 |
8 | def __init__(self, rpc_provider: str, private_key: str) -> None:
9 | self.w3 = Web3(Web3.HTTPProvider(rpc_provider))
10 | self.w3.middleware_onion.inject(geth_poa_middleware, layer=0)
11 | self.private_key = private_key
12 |
13 | def deploy_contract(self, bytecode: str, gas: int, chain_id: int, gwei: float) -> str:
14 | tx = {
15 | "data": bytecode,
16 | "chainId": chain_id,
17 | "nonce": self.w3.eth.get_transaction_count(Account().from_key(self.private_key).address),
18 | "gas": gas,
19 | "gasPrice": self.w3.toWei(gwei, "gwei")
20 | }
21 | signed_tx = self.w3.eth.account.sign_transaction(tx, private_key=self.private_key)
22 |
23 | return self.w3.eth.sendRawTransaction(signed_tx.rawTransaction).hex()
24 |
25 |
26 | def deploy_contract(rpc: str, private_key: str, bytecode: str, chain_id: int, gas_limit: int, gwei: float) -> str:
27 | deployer = Deployer(rpc, private_key)
28 |
29 | return deployer.deploy_contract(bytecode, gas_limit, chain_id, gwei)
30 |
--------------------------------------------------------------------------------
/app_cmd.py:
--------------------------------------------------------------------------------
1 | from loguru import logger
2 |
3 | from config import API_KEY, ENDPOINTS, SCANS
4 | from utils.deployment import deploy_contract
5 | from utils.saving import get_contract_bytecode, save_contract
6 | from utils.scan_api import EVMScan
7 |
8 |
9 | if __name__ == "__main__":
10 | action = input("Select an action (1 - save the contract, 2 - deploy to testnet): ")
11 |
12 | endpoint = input("Choise mainnet endpoint (1 - ether, 2 - bsc, 3 - polygon, 4 - rinkeby): ")
13 | address = input("Input address of a verified smart contract: ")
14 |
15 | if action.strip() == "1":
16 | save_contract(EVMScan(API_KEY, ENDPOINTS[endpoint]), address)
17 |
18 | elif action.strip() == "2":
19 | bytecode = get_contract_bytecode(SCANS[endpoint], address)
20 |
21 | chain_id = int(input(f"Choose chain_id (rinkeby - 4 , goerli - 5, kovan - 42, ropsten - 3, bsc_testnet - 97): "))
22 | rpc = input("Enter the RPC http: ")
23 | private_key = input("Enter the private key: ")
24 | gas_limit = int(input("Enter the gas limit: "))
25 | gwei = float(input("Enter the value of gwei: "))
26 |
27 | txn_hash = deploy_contract(rpc, private_key, bytecode, chain_id, gas_limit, gwei)
28 |
29 | logger.success(f"Hash: {txn_hash}")
30 |
--------------------------------------------------------------------------------
/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |