├── wallets.template ├── conf └── configs_template ├── libs ├── singleton.py ├── common.py └── global_config.py ├── core ├── wallet_manager.py ├── batch_mint_manager.py ├── tool_helper.py ├── batch_manager.py └── xen_manager.py ├── LICENSE ├── main.py ├── .gitignore ├── mint_tool_demo_runner.py ├── README.md ├── contracts └── UpgradebleStormSender_flat.sol ├── georli_runner.py ├── space_id_airdrop_requester.py ├── scroll_testnet_runner.py └── zksync_testnet_runner.py /wallets.template: -------------------------------------------------------------------------------- 1 | No.,Address,PrivateKey 2 | 1,0x......,xxxx -------------------------------------------------------------------------------- /conf/configs_template: -------------------------------------------------------------------------------- 1 | [ApiKey] 2 | moralis_key = xxx 3 | 4 | [RPCKey] 5 | xxx = yyy -------------------------------------------------------------------------------- /libs/singleton.py: -------------------------------------------------------------------------------- 1 | class SingletonType(type): 2 | def __call__(cls, *args, **kwargs): 3 | if not hasattr(cls, "_instance"): 4 | cls._instance = super(SingletonType, cls).__call__(*args, **kwargs) 5 | return cls._instance 6 | -------------------------------------------------------------------------------- /libs/common.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | PROJECT_ABSOLUTE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 | REPLACE_WALLET_ADDR = '$ReplaceWallet$' 5 | 6 | 7 | def get_file_path(f_path): 8 | return os.path.join(PROJECT_ABSOLUTE_PATH, f_path) 9 | -------------------------------------------------------------------------------- /core/wallet_manager.py: -------------------------------------------------------------------------------- 1 | from web3.eth import Account 2 | 3 | 4 | def bytes_to_hex(bs): 5 | return ''.join(['%02X' % b for b in bs]) 6 | 7 | 8 | def create_new_wallet(): 9 | Account.enable_unaudited_hdwallet_features() 10 | account = Account.create() 11 | privateKey = str.lower(bytes_to_hex(account.key)) 12 | address = account.address 13 | return address, privateKey 14 | 15 | 16 | def create_new_wallet_with_mnemonic(): 17 | Account.enable_unaudited_hdwallet_features() 18 | create_result = Account.create_with_mnemonic() 19 | account = create_result[0] 20 | mnemonic = create_result[1] 21 | privateKey = str.lower(bytes_to_hex(account.key)) 22 | address = account.address 23 | return address, privateKey, mnemonic 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 blusehuang1121 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from core import xen_manager as xen 2 | 3 | current_network = xen.Network.eth 4 | 5 | def batch_claim_rank(): 6 | x = xen.XenManager(current_network) 7 | print('begin to batch claim rank') 8 | x.batch_claim_rank('wallets.csv', 300) 9 | 10 | 11 | def batch_claim_mint_reward_and_share(): 12 | x = xen.XenManager(current_network) 13 | print('begin to batch claim mint reward and share') 14 | x.batch_claim_mint_reward_and_share('wallets.csv', '归集地址') 15 | 16 | 17 | def update_all_mints(): 18 | x = xen.XenManager(current_network) 19 | x.update_all_mints('wallets.csv', f'xen_mint_data_{x._current_network}.csv') 20 | 21 | 22 | def batch_get_balance(): 23 | x = xen.XenManager(current_network) 24 | x.batch_get_balance('wallets.csv') 25 | 26 | 27 | def batch_transfer(): 28 | from_wallet = [0, '转账地址', '私钥'] 29 | x = xen.XenManager(xen.Network.eth) 30 | x.transfer_money(0.001, from_wallet, 'wallets.csv') 31 | 32 | 33 | if __name__ == '__main__': 34 | print('Demo batch functions for XEN') 35 | current_network = xen.Network.bsc 36 | # 更新全部钱包的mint信息 37 | # update_all_mints() 38 | 39 | # 批量获得钱包余额 40 | # batch_get_balance() 41 | 42 | # 批量转账给小钱包 43 | #batch_transfer() 44 | 45 | # 批量mint 46 | # batch_claim_rank() 47 | 48 | # 批量获得代币并转移 49 | # batch_claim_mint_reward_and_share() 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /libs/global_config.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | import os 3 | import random 4 | 5 | from libs.common import get_file_path 6 | from libs.singleton import SingletonType 7 | 8 | APIKEY_SECTION = 'ApiKey' 9 | RPC_SECTION = 'RPCKey' 10 | 11 | 12 | class GlobalConfig(metaclass=SingletonType): 13 | _proxy_list = [] 14 | _proxy_index = -1 15 | _use_proxy = False 16 | 17 | def __init__(self): 18 | self._config_parser = configparser.ConfigParser() 19 | self._config_parser.read(get_file_path('conf/configs')) 20 | self.read_proxy_list() 21 | 22 | def read_proxy_list(self): 23 | self._proxy_list.clear() 24 | file_path = 'conf/proxies' 25 | if not os.path.exists(file_path): 26 | return 27 | pf = open(file_path) 28 | lines = pf.readlines(1000) 29 | for line in lines: 30 | if len(line) < 12: 31 | continue 32 | splits = line.strip().split(':') 33 | if len(splits) > 2: 34 | proxy = f"http://{splits[2]}:{splits[3]}@{splits[0]}:{splits[1]}" 35 | else: 36 | proxy = f"http://{splits[0]}:{splits[1]}" 37 | self._proxy_list.append(proxy) 38 | self.random_proxy() 39 | 40 | def moralis_key(self): 41 | return self._config_parser.get(APIKEY_SECTION, 'moralis_key') 42 | 43 | def has_rpc_key(self, rpc_key): 44 | return self._config_parser.has_option(RPC_SECTION, rpc_key) 45 | 46 | def get_rpc(self, rpc_key): 47 | if not self._config_parser.has_option(RPC_SECTION, rpc_key): 48 | return '' 49 | return self._config_parser.get(RPC_SECTION, rpc_key) 50 | 51 | def get(self, section, key): 52 | return self._config_parser.get(section, key) 53 | 54 | def random_proxy(self): 55 | self._proxy_index = random.randrange(-1, len(self._proxy_list)) 56 | 57 | def get_a_proxy(self): 58 | if self._use_proxy is False or self._proxy_index < 0 or len(self._proxy_list) <= 0: 59 | return None 60 | return self._proxy_list[self._proxy_index] 61 | 62 | def use_proxy(self): 63 | self._use_proxy = True 64 | 65 | def is_use_proxy(self): 66 | return self._use_proxy 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | wheels/ 22 | pip-wheel-metadata/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | db.sqlite3-journal 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | target/ 75 | 76 | # Jupyter Notebook 77 | .ipynb_checkpoints 78 | 79 | # IPython 80 | profile_default/ 81 | ipython_config.py 82 | 83 | # pyenv 84 | .python-version 85 | 86 | # pipenv 87 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 88 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 89 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 90 | # install all needed dependencies. 91 | #Pipfile.lock 92 | 93 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 94 | __pypackages__/ 95 | 96 | # Celery stuff 97 | celerybeat-schedule 98 | celerybeat.pid 99 | 100 | # SageMath parsed files 101 | *.sage.py 102 | 103 | # Environments 104 | .env 105 | .venv 106 | env/ 107 | venv/ 108 | ENV/ 109 | env.bak/ 110 | venv.bak/ 111 | 112 | # Spyder project settings 113 | .spyderproject 114 | .spyproject 115 | 116 | # Rope project settings 117 | .ropeproject 118 | 119 | # mkdocs documentation 120 | /site 121 | 122 | # mypy 123 | .mypy_cache/ 124 | .dmypy.json 125 | dmypy.json 126 | 127 | # Pyre type checker 128 | .pyre/ 129 | /*.csv 130 | /.idea 131 | /.idea/* 132 | /xen_mints 133 | /conf/configs 134 | /conf/proxies 135 | /scroll_result.txt 136 | -------------------------------------------------------------------------------- /core/batch_mint_manager.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import requests 4 | from web3 import Web3 5 | from core.batch_manager import BatchManager, Network, Addr_Index, No_Index 6 | from libs.common import REPLACE_WALLET_ADDR 7 | from libs.global_config import GlobalConfig 8 | 9 | 10 | class BatchMintManager(BatchManager): 11 | _is_gas_limited = False 12 | _gas_max_fee = 10 13 | _gas_limit = 200000 14 | _priority_fee = 1.5 15 | 16 | def __init__(self, network: Network = Network.eth, network_data: dict = {}) -> None: 17 | super().__init__(network, network_data) 18 | self.moralis_key = GlobalConfig().moralis_key() 19 | 20 | def limit_gas(self, gas_limit, max_fee, priority_fee=1.5): 21 | self._is_gas_limited = True 22 | self._gas_max_fee = max_fee 23 | self._gas_limit = gas_limit 24 | self._priority_fee = priority_fee 25 | 26 | def call_read_func_with_args(self, func_name, func_args: tuple): 27 | result = self._contract.get_function_by_name(func_name)(*func_args).call() 28 | # print(result) 29 | return result 30 | 31 | def call_read_func(self, func_name): 32 | result = self._contract.get_function_by_name(func_name)().call() 33 | # print(result) 34 | return result 35 | 36 | def single_call_write_func_with_value(self, wallet, value, func_name, func_args): 37 | self.each_call_func(wallet, value, func_name, func_args) 38 | 39 | def single_call_write_func(self, wallet, func_name, func_args): 40 | self.each_call_func(wallet, 0, func_name, func_args) 41 | 42 | def batch_call_write_func_with_value(self, csv_path, value, func_name, func_args): 43 | callback = lambda wallet: { 44 | self.each_call_func(wallet, value, func_name, func_args) 45 | } 46 | self.read_wallets_and_callback(csv_path, callback) 47 | 48 | def batch_call_write_func(self, csv_path, func_name, func_args): 49 | callback = lambda wallet: { 50 | self.each_call_func(wallet, 0, func_name, func_args) 51 | } 52 | self.read_wallets_and_callback(csv_path, callback) 53 | 54 | def each_call_func(self, wallet, value, func_name, func_args: tuple): 55 | func_name = func_name 56 | args = [] 57 | 58 | if type(func_args) == tuple: 59 | arg_list = list(func_args) 60 | for index, arg in enumerate(arg_list): 61 | if arg_list[index] == REPLACE_WALLET_ADDR: 62 | arg_list[index] = wallet[Addr_Index] 63 | func_args = tuple(arg_list) 64 | 65 | contract_func = self._contract.get_function_by_name(func_name)(*func_args) 66 | for arg in func_args: 67 | args.append(arg) 68 | else: 69 | contract_func = self._contract.get_function_by_name(func_name)(func_args) 70 | args.append(func_args) 71 | try: 72 | self.call_contract_func(wallet, func_name, args, contract_func, value) 73 | except Exception as e: 74 | print(f'[Failed] Call contract func has an error {wallet[Addr_Index]}, {repr(e)}') 75 | 76 | def update_mint_gas(self, contract_func, trans_params): 77 | if not self._is_gas_limited: 78 | super().update_mint_gas(contract_func, trans_params) 79 | else: 80 | trans_params['gas'] = self._gas_limit 81 | if self._current_network in [Network.bsc, Network.bsc_test]: 82 | trans_params['gasPrice'] = self._web3.eth.gas_price 83 | else: 84 | trans_params['maxFeePerGas'] = self._web3.to_wei(self._gas_max_fee, 'gwei') 85 | trans_params['maxPriorityFeePerGas'] = self._web3.to_wei(self._priority_fee, 'gwei') 86 | 87 | def batch_collect_nft(self, csv_path, to_addr, is_transfer): 88 | callback = lambda wallet: { 89 | self.each_collect_nft(wallet, to_addr, is_transfer) 90 | } 91 | self.read_wallets_and_callback(csv_path, callback) 92 | 93 | def each_collect_nft(self, wallet, to_addr, is_transfer): 94 | headers = { 95 | "accept": "application/json", 96 | "X-API-Key": self.moralis_key 97 | } 98 | 99 | url = f"https://deep-index.moralis.io/api/v2/{wallet[Addr_Index]}/nft?chain={self._current_network.name}&format=decimal&token_addresses={self._contract.address}&normalizeMetadata=false" 100 | response = requests.get(url, headers=headers) 101 | nft_result = json.loads(response.text) 102 | 103 | if nft_result['total'] <= 0: 104 | print(f'No Nft found in Wallet {wallet[No_Index]} {wallet[Addr_Index]}, Ignored.') 105 | return 106 | 107 | print(f'Has Nft in Wallet {wallet[No_Index]} {wallet[Addr_Index]}.') 108 | if not is_transfer: 109 | return 110 | 111 | for each_result in nft_result['result']: 112 | token_id = int(each_result['token_id']) 113 | print(f'Start to Collect nft from Wallet {wallet[No_Index]} {wallet[Addr_Index]} {token_id}...') 114 | self.each_call_func(wallet, 'transferFrom', 115 | (Web3.to_checksum_address(wallet[Addr_Index]), Web3.to_checksum_address(to_addr), token_id)) 116 | 117 | def multi_transfer(self, from_wallet, csv_path, amount=0): 118 | wallets = [] 119 | amounts = [] 120 | total_value = 0 121 | 122 | callback = lambda wallet: { 123 | wallets.append(wallet[Addr_Index]) 124 | } 125 | self.read_wallets_and_callback(csv_path, callback) 126 | 127 | for w in wallets: 128 | amount_wei = self._web3.to_wei(amount, 'ether') 129 | amounts.append(amount_wei) 130 | total_value += amount_wei 131 | 132 | total_value += self._web3.to_wei(0.001, 'ether') 133 | 134 | func_name = 'multisendEther' 135 | contract_func = self._contract.get_function_by_name(func_name)(wallets, amounts) 136 | self.call_contract_func(from_wallet, func_name, [wallets, amounts], contract_func, total_value) 137 | -------------------------------------------------------------------------------- /core/tool_helper.py: -------------------------------------------------------------------------------- 1 | from web3 import Web3 2 | 3 | from core.batch_manager import Network, Addr_Index 4 | from core.batch_mint_manager import BatchMintManager 5 | from libs.common import get_file_path 6 | 7 | 8 | class ToolHelper: 9 | _erc721_abi: str = '[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]' 10 | _network: Network = Network.eth 11 | _addr = '' 12 | _abi = '[]' 13 | _gas_limit = 21000 14 | _gas_max_fee = 1 15 | _gas_priority_fee = 1.5 16 | _is_gas_limit = False 17 | _value = 0 18 | _is_wait_for_complete = False 19 | 20 | def contract(self, addr): 21 | return ContractRunner(Web3.to_checksum_address(addr)) 22 | 23 | def network(self, network): 24 | self._network = network 25 | return self 26 | 27 | def abi(self, c_abi): 28 | self._abi = c_abi 29 | return self 30 | 31 | def gas_limit(self, limit): 32 | self._is_gas_limit = True 33 | self._gas_limit = limit 34 | return self 35 | 36 | def gas_max_fee(self, price): 37 | self._gas_max_fee = price 38 | return self 39 | 40 | def gas_priority_fee(self, p_fee): 41 | self._gas_priority_fee = p_fee 42 | return self 43 | 44 | def get_balance(self, wallet): 45 | network_data = { 46 | self._network: { 47 | 'addr': self._addr, 48 | 'contract_abi': self._abi 49 | } 50 | } 51 | b = BatchMintManager(self._network, network_data) 52 | return b.get_balance(wallet) 53 | 54 | def value(self, amount=0): 55 | self._value = Web3.to_wei(amount, 'ether') 56 | return self 57 | 58 | def transfer_eth(self, amount, from_wallet, to_wallets_csv): 59 | network_data = { 60 | self._network: { 61 | 'addr': self._addr, 62 | 'contract_abi': self._abi 63 | } 64 | } 65 | b = BatchMintManager(self._network, network_data) 66 | b.transfer_money(amount, from_wallet, to_wallets_csv) 67 | 68 | def transfer_eth_single(self, amount, from_wallet, to_wallet): 69 | network_data = { 70 | self._network: { 71 | 'addr': self._addr, 72 | 'contract_abi': self._abi 73 | } 74 | } 75 | b = BatchMintManager(self._network, network_data) 76 | b.set_wait_for_complete(self._is_wait_for_complete) 77 | b.transfer_money_single(amount, from_wallet, to_wallet) 78 | 79 | 80 | class ContractRunner(ToolHelper): 81 | def __init__(self, addr): 82 | self._addr = addr 83 | self._abi = self._erc721_abi 84 | self._is_transfer = False 85 | self._transfer_to_addr = '' 86 | self._wallet_file_path = '' 87 | self._wallet = [] 88 | self._is_single_wallet = False 89 | 90 | def only_scan(self): 91 | self._is_transfer = False 92 | self._transfer_to_addr = '' 93 | return self 94 | 95 | def transfer_to(self, to_addr): 96 | self._is_transfer = True 97 | self._transfer_to_addr = to_addr 98 | return self 99 | 100 | def wallets(self, wallet_file_path): 101 | self._wallet_file_path = get_file_path(wallet_file_path) 102 | self._is_single_wallet = False 103 | return self 104 | 105 | def wallet(self, wallet): 106 | self._wallet = wallet 107 | self._is_single_wallet = True 108 | return self 109 | 110 | def collect_nft(self): 111 | network_data = { 112 | self._network: { 113 | 'addr': self._addr, 114 | 'contract_abi': self._abi 115 | } 116 | } 117 | b = BatchMintManager(self._network, network_data) 118 | b.batch_collect_nft(self._wallet_file_path, self._transfer_to_addr, self._is_transfer) 119 | 120 | def call_read(self, method_name, args): 121 | network_data = { 122 | self._network: { 123 | 'addr': self._addr, 124 | 'contract_abi': self._abi 125 | } 126 | } 127 | b = BatchMintManager(self._network, network_data) 128 | return b.call_read_func_with_args(method_name, args) 129 | 130 | def wait_for_complete(self, is_wait): 131 | self._is_wait_for_complete = is_wait 132 | return self 133 | 134 | 135 | def call_write(self, method_name, args): 136 | network_data = { 137 | self._network: { 138 | 'addr': self._addr, 139 | 'contract_abi': self._abi 140 | } 141 | } 142 | b = BatchMintManager(self._network, network_data) 143 | b.set_wait_for_complete(self._is_wait_for_complete) 144 | if self._is_gas_limit: 145 | b.limit_gas(self._gas_limit, self._gas_max_fee, self._gas_priority_fee) 146 | 147 | if self._is_single_wallet: 148 | if self._value > 0: 149 | b.single_call_write_func_with_value(self._wallet, self._value, method_name, args) 150 | else: 151 | b.single_call_write_func(self._wallet, method_name, args) 152 | else: 153 | if self._value > 0: 154 | b.batch_call_write_func_with_value(self._wallet_file_path, self._value, method_name, args) 155 | else: 156 | b.batch_call_write_func(self._wallet_file_path, method_name, args) 157 | -------------------------------------------------------------------------------- /mint_tool_demo_runner.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | from core.batch_manager import Network 4 | from core.batch_mint_manager import BatchMintManager 5 | from core.tool_helper import ToolHelper 6 | 7 | 8 | def multi_transfer_using_contract(): 9 | with open('./xen_mints/base_transfer_wallet.csv') as f: 10 | reader = csv.reader(f) 11 | from_wallet = list(reader)[1] 12 | 13 | network_data = { 14 | Network.bsc_test: { 15 | 'addr': '0xEc1996E2996217f38d02A06d19Ff6BaD6E2C7E5b', 16 | 'contract_abi': '[{"constant":false,"inputs":[],"name":"claimOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"upgradeabilityOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pendingOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"total","type":"uint256"},{"indexed":false,"name":"tokenAddress","type":"address"}],"name":"Multisended","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"ClaimedTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"customer","type":"address"}],"name":"txCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"arrayLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newLimit","type":"uint256"}],"name":"setArrayLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"discountStep","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newStep","type":"uint256"}],"name":"setDiscountStep","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_customer","type":"address"}],"name":"currentFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newStep","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_customer","type":"address"}],"name":"discountRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"_contributors","type":"address[]"},{"name":"_balances","type":"uint256[]"}],"name":"multisendToken","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_contributors","type":"address[]"},{"name":"_balances","type":"uint256[]"}],"name":"multisendEther","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"claimTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]' 17 | } 18 | } 19 | b = BatchMintManager(Network.bsc_test, network_data) 20 | b.multi_transfer(from_wallet, 'xen_mints/wallets_tomint.csv', 0.0005) 21 | 22 | 23 | if __name__ == '__main__': 24 | print('Demo batch functions for batch mint') 25 | 26 | # enegy core contract: 0xBC867E76D1360b2D21eB1C2753f94b1C103415e1 27 | # leggi contract: 0xfE542c1FEcc88f1d8B0E53171B8E4d486391fb98 28 | 29 | # 扫描csv文件里的所有钱包,是否有指定地址的nft 30 | ToolHelper().contract('0xBC867E76D1360b2D21eB1C2753f94b1C103415e1') \ 31 | .network(Network.bsc) \ 32 | .only_scan() \ 33 | .wallets('xen_mints/wallets_tomint.csv') \ 34 | .collect_nft() 35 | 36 | # 扫描csv文件里的所有钱包,将指定地址的nft全部归集到某个钱包内 37 | # ToolHelper().contract('0xfE542c1FEcc88f1d8B0E53171B8E4d486391fb98')\ 38 | # .network(Network.bsc) \ 39 | # .wallets('xen_mints/wallets_tomint.csv') \ 40 | # .transfer_to('xxxx')\ 41 | # .collect_nft() 42 | 43 | # 批量mint nft,指定合约地址或者设置gas 44 | # c_abi = '[{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"internalType":"struct MockTokenFaucet.Token[]","name":"erc20Tokens","type":"tuple[]"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"internalType":"struct MockTokenFaucet.Token[]","name":"erc721Tokens","type":"tuple[]"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"internalType":"struct MockTokenFaucet.Token","name":"punks","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"internalType":"struct MockTokenFaucet.Token[]","name":"_tokens","type":"tuple[]"}],"name":"addERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"internalType":"struct MockTokenFaucet.Token[]","name":"_tokens","type":"tuple[]"}],"name":"addERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allMockERC20Tokens","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"internalType":"struct MockTokenFaucet.Token[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allMockERC721Tokens","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"internalType":"struct MockTokenFaucet.Token[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cryptoPunks","outputs":[{"internalType":"contract ICryptoPunksMarket","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"name":"mintERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"name":"mintERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"removeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"removeERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenInfo","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"mintValue","type":"uint256"}],"internalType":"struct MockTokenFaucet.Token","name":"punk","type":"tuple"}],"name":"updatePunk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"}]' 45 | # ToolHelper().contract('0x6BABAdFfBD254b386387290cce48e3011bb1F882')\ 46 | # .abi(c_abi)\ 47 | # .network(Network.goerli)\ 48 | # .wallets('xen_mints/wallets_tomint.csv') \ 49 | # .call_write('mint', (Web3.toChecksumAddress('0x1C3Ab4068337A13533246b3e6ac226BdE74579cb'))) 50 | -------------------------------------------------------------------------------- /core/batch_manager.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import time 3 | 4 | from web3 import Web3 5 | from enum import Enum 6 | 7 | from web3.contract import Contract 8 | from web3.gas_strategies.time_based import medium_gas_price_strategy 9 | from web3.middleware import geth_poa_middleware 10 | 11 | from libs.global_config import GlobalConfig 12 | 13 | 14 | class Network(Enum): 15 | eth = 1, 16 | bsc = 2, 17 | goerli = 3, 18 | sepolia = 4, 19 | bsc_test = 5, 20 | scroll_test_l1 = 6, 21 | scroll_test_l2 = 7, 22 | zksync_testnet = 8, 23 | scroll_alpha = 9 24 | 25 | 26 | No_Index = 0 27 | Addr_Index = 1 28 | PriKey_Index = 2 29 | 30 | LastNonceMap = {} 31 | 32 | # using https://chainlist.org to find the best RPC url 33 | class BatchManager: 34 | _web3: Web3 35 | _contract: Contract 36 | _current_network: Network 37 | _nonce_index = 0 38 | _max_fee_multiply = 1.1 39 | _last_nonce = -1 40 | _is_wait_for_complete = False 41 | 42 | _network_info = { 43 | Network.eth: { 44 | 'rpc': 'https://eth-mainnet.blastapi.io/7612f97c-4943-4f55-872f-e571b941016e', 45 | 'chain_id': 1, 46 | }, 47 | Network.bsc: { 48 | 'rpc': 'https://rpc.ankr.com/bsc', 49 | 'chain_id': 56, 50 | }, 51 | Network.goerli: { 52 | 'rpc': 'https://eth-goerli.blastapi.io/7612f97c-4943-4f55-872f-e571b941016e', 53 | 'chain_id': 5, 54 | }, 55 | Network.sepolia: { 56 | 'rpc': 'https://rpc.sepolia.org', 57 | 'chain_id': 11155111 58 | }, 59 | Network.bsc_test: { 60 | 'rpc': 'https://bsc-testnet.blastapi.io/7612f97c-4943-4f55-872f-e571b941016e', 61 | 'chain_id': 97 62 | }, 63 | Network.scroll_test_l1: { 64 | 'rpc': 'https://prealpha.scroll.io/l1', 65 | 'chain_id': 534351 66 | }, 67 | Network.scroll_test_l2: { 68 | 'rpc': 'https://prealpha.scroll.io/l2', 69 | 'chain_id': 534354 70 | }, 71 | Network.zksync_testnet: { 72 | 'rpc': 'https://zksync2-testnet.zksync.dev', 73 | 'chain_id': 280 74 | }, 75 | Network.scroll_alpha: { 76 | 'rpc': 'https://alpha-rpc.scroll.io/l2', 77 | 'chain_id': 534353 78 | } 79 | } 80 | 81 | def __init__(self, network, network_data): 82 | self._last_nonce = -1 83 | if network in LastNonceMap.keys(): 84 | self._last_nonce = LastNonceMap.get(network) 85 | 86 | for net, info in self._network_info.items(): 87 | merged_info = info.copy() 88 | if not net in network_data.keys(): 89 | continue 90 | merged_info.update(network_data[net]) 91 | self._network_info[net] = merged_info 92 | 93 | if GlobalConfig().has_rpc_key(network.name): 94 | self._network_info[Network.eth]['rpc'] = GlobalConfig().get_rpc(network.name) 95 | network_info = self._network_info[network] 96 | 97 | self._addr = network_info['addr'] 98 | self._chain_id = network_info['chain_id'] 99 | self._rpc = network_info['rpc'] 100 | self._abi = network_info['contract_abi'] 101 | self._current_network = network 102 | 103 | if GlobalConfig().is_use_proxy(): 104 | proxy = GlobalConfig().get_a_proxy() 105 | self._web3 = Web3(Web3.HTTPProvider(self._rpc, request_kwargs={"proxies": {'https': proxy, 'http': proxy}})) 106 | print(f"Use proxy {proxy} to make Web3 RPC") 107 | else: 108 | self._web3 = Web3(Web3.HTTPProvider(self._rpc)) 109 | 110 | self._contract = self._web3.eth.contract(address=self._addr, abi=self._abi) 111 | self._web3.eth.set_gas_price_strategy(medium_gas_price_strategy) 112 | # self._max_priority_fee_per_gas = self._web3.eth.max_priority_fee 113 | # self._max_fee_per_gas = self._web3.eth.max_priority_fee * 2 114 | 115 | if network in [Network.bsc, Network.bsc_test]: 116 | self._web3.middleware_onion.inject(geth_poa_middleware, layer=0) 117 | elif network in [Network.eth, Network.goerli]: 118 | self._max_fee_per_gas = self._web3.eth.max_priority_fee + int( 119 | self._max_fee_multiply * self._web3.eth.get_block('latest')['baseFeePerGas']) 120 | 121 | print(f"Current network: {self._current_network}, Connection status: {self._web3.is_connected()}") 122 | 123 | @staticmethod 124 | def write_info_to_file(info_data, info_csv_path): 125 | with open(info_csv_path, "w", newline='') as csvfile: 126 | writer = csv.writer(csvfile) 127 | writer.writerow(['No.', 'Address', 'Term', 'Maturity', 'Xen Count']) 128 | writer.writerows(info_data) 129 | 130 | @staticmethod 131 | def local_time(timestamp): 132 | time_local = time.localtime(timestamp) 133 | dt = time.strftime("%Y-%m-%d %H:%M:%S", time_local) 134 | return dt 135 | 136 | def set_wait_for_complete(self, is_wait): 137 | self._is_wait_for_complete = is_wait 138 | 139 | def update_mint_gas(self, contract_func, trans_params): 140 | estimate_param = { 141 | 'chainId': trans_params['chainId'], 142 | 'from': trans_params['from'] 143 | } 144 | trans_params['gas'] = contract_func.estimate_gas(estimate_param) # self._web3.toHex(210000)# 145 | 146 | if self._current_network in [Network.bsc, Network.bsc_test]: 147 | trans_params['gasPrice'] = self._web3.eth.gas_price 148 | else: 149 | trans_params['maxFeePerGas'] = self._max_fee_per_gas 150 | trans_params['maxPriorityFeePerGas'] = self._max_priority_fee_per_gas 151 | 152 | def call_contract_func(self, wallet, func_name, func_args, contract_func, value=0): 153 | if len(wallet) <= 1: 154 | return 155 | addr = wallet[Addr_Index] 156 | private_key = wallet[PriKey_Index] 157 | 158 | if len(private_key.strip()) <= 0: 159 | print(f'{addr} private key is empty, ignored.') 160 | return 161 | 162 | encodedData = self._contract.encodeABI(fn_name=func_name, args=func_args) 163 | trans_params = { 164 | 'chainId': self._chain_id, 165 | "from": addr, 166 | 'to': self._addr, 167 | "nonce": self._web3.eth.get_transaction_count(addr), 168 | 'data': encodedData 169 | } 170 | if value > 0: 171 | trans_params["value"] = value 172 | 173 | self.update_mint_gas(contract_func, trans_params) 174 | print(f'[Wallet {wallet[No_Index]}] Start to {func_name} from {addr} {trans_params}') 175 | signed_tx = self._web3.eth.account.sign_transaction(trans_params, private_key=private_key) 176 | tx_hash = self._web3.eth.send_raw_transaction(signed_tx.rawTransaction) 177 | print(f'Transaction sent to chain...{self._web3.to_hex(tx_hash)}') 178 | if self._is_wait_for_complete: 179 | self._web3.eth.wait_for_transaction_receipt(tx_hash) 180 | # receipt = self._web3.eth.waitForTransactionReceipt(tx_hash) 181 | # print("Transaction receipt mined: \n") 182 | # print(dict(receipt)) 183 | # print("Was transaction successful? \n") 184 | # print(receipt['status']) 185 | 186 | @staticmethod 187 | def read_wallets_and_callback(csv_path, callback): 188 | with open(csv_path) as f: 189 | f_csv = csv.reader(f) 190 | next(f_csv) 191 | for each_wallet in f_csv: 192 | callback(each_wallet) 193 | 194 | def is_connect(self): 195 | return self._web3.is_connected() 196 | 197 | def transfer_money_single(self, amount, from_wallet, to_wallet): 198 | if len(to_wallet) < 1: 199 | return 200 | from_addr = Web3.to_checksum_address(from_wallet[Addr_Index]) 201 | to_addr = Web3.to_checksum_address(to_wallet[Addr_Index]) 202 | if from_addr == to_addr: 203 | return 204 | nonce = self._web3.eth.get_transaction_count(from_addr) 205 | 206 | try_count = 0 207 | while nonce <= self._last_nonce: 208 | print('.', end=' ') 209 | time.sleep(1) 210 | nonce = self._web3.eth.get_transaction_count(from_addr) 211 | try_count += 1 212 | if try_count > 120: 213 | nonce += 1 214 | break 215 | 216 | self._last_nonce = nonce 217 | LastNonceMap[self._current_network] = nonce 218 | params = { 219 | 'chainId': self._chain_id, 220 | 'nonce': nonce, 221 | 'from': from_addr, 222 | 'to': to_addr, 223 | 'value': self._web3.to_wei(amount, 'ether'), 224 | 'gas': 21000, 225 | } 226 | self.update_transfer_gas(from_addr, to_addr, params) 227 | print( 228 | f'[wallet {to_wallet[No_Index]}] Transferring {amount} from {from_wallet[Addr_Index]} to {to_wallet[Addr_Index]}, Chain:{self._chain_id}, Nonce:{params["nonce"]}, GasLimit:{params["gas"]}, GasPrice:{params["maxFeePerGas"]}') 229 | signed_tx = self._web3.eth.account.sign_transaction(params, private_key=from_wallet[PriKey_Index]) 230 | tx_hash = self._web3.eth.send_raw_transaction(signed_tx.rawTransaction) 231 | print(f'Eth Transfer sent to chain...{self._web3.to_hex(tx_hash)}') 232 | if self._is_wait_for_complete: 233 | self._web3.eth.wait_for_transaction_receipt(tx_hash) 234 | # print("Transaction receipt mined: \n") 235 | 236 | def transfer_money(self, amount, from_wallet, csv_path): 237 | to_wallets = [] 238 | callback = lambda wallet: { 239 | to_wallets.append(wallet) 240 | } 241 | self.read_wallets_and_callback(csv_path, callback) 242 | 243 | for to_wallet in to_wallets: 244 | self.transfer_money_single(amount, from_wallet, to_wallet) 245 | 246 | def update_transfer_gas(self, from_addr, to_addr, trans_params): 247 | estimate_gas = self._web3.eth.estimate_gas({'to': from_addr, 'from': to_addr, 'value': 0}) 248 | trans_params['gas'] = estimate_gas 249 | 250 | if self._current_network in [Network.eth, Network.goerli]: 251 | trans_params['maxFeePerGas'] = max(self._max_fee_per_gas * 2, self._web3.to_wei(3, 'gwei')) 252 | trans_params['maxPriorityFeePerGas'] = max(self._web3.eth.max_priority_fee, self._web3.to_wei(1.5 * 2, 'gwei')) 253 | else: 254 | trans_params['gasPrice'] = self._web3.eth.gas_price 255 | 256 | def get_balance(self, wallet): 257 | return self._web3.from_wei(self._web3.eth.get_balance(Web3.to_checksum_address(wallet[Addr_Index])), "ether") 258 | 259 | def batch_get_balance(self, csv_path): 260 | wallets = [] 261 | callback = lambda wallet: { 262 | wallets.append(wallet) 263 | } 264 | self.read_wallets_and_callback(csv_path, callback) 265 | for wallet in wallets: 266 | if len(wallet) < 1: 267 | continue 268 | balance = self._web3.from_wei(self._web3.eth.get_balance(Web3.to_checksum_address(wallet[Addr_Index])), "ether") 269 | print(f'Wallet {wallet[No_Index]} {wallet[Addr_Index]} balance {balance}') 270 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # web3_tools 简要说明 2 | 3 | ### 准备工作 4 |   安装web3组件 5 | `pip install web3` 6 | 7 | *** 8 | 9 | ### 2002.11.29更新 10 | #### 新增ToolHelper工具类,辅助批量NFT Mint和归集,使用方法(代码参考见mint_tool_demo_runner.py): 11 | 1. 批量ERC721 Mint 12 | ``` 13 | c_abi = 'xxx' #指定合约的abi 14 | ToolHelper().contract('xxx')\ #设置ERC721的合约地址 15 | .abi(c_abi)\ #设置abi 16 | .network(Network.goerli)\ #设置合约所在网络 17 | .wallets('xen_mints/wallets_tomint.csv') \ #设置钱包列表文件(模板见wallets.template) 18 | .call_write('MethodName', (arg1, arg2, arg3)) #指定合约的Mint方法名称,以及传递Mint参数 19 | ``` 20 | 2. 如何手动设置gas 21 | ``` 22 | .gas_limit(xx) #设置gas limit 23 | .gas_max_fee(xx) #设置最大gas fee(需支持EIP1559) 24 | .gas_priority_fee(xx) #设置小费(需支持EIP1559) 25 | ``` 26 | 3. 如何批量归集(ERC721通用abi已经内置) 27 | ``` 28 | ToolHelper().contract('xxx')\ #设置ERC721的合约地址 29 | .network(Network.bsc) \ #设置合约所在网络 30 | .wallets('xen_mints/wallets_tomint.csv') \ #设置钱包列表文件(模板见wallets.template) 31 | .transfer_to('xxxx')\ #指定归集地址 32 | .run() #执行归集 33 | ``` 34 | 35 | *** 36 | 37 | ### 如何创建钱包 38 | ``` 39 | import wallet_manager as wal 40 | wal_info = wal.create_new_wallet() 41 | ``` 42 | wal_info包含三个字段,序号、地址、私钥 43 | 44 | ### 如何批量转账 45 | ``` 46 | #转账的母钱包,使用该钱包的余额给其他子钱包转账 47 | from_wallet = [0, '转账地址', '私钥'] 48 | 49 | #给csv文件中的所有钱包转账,金额0.001 50 | manager.transfer_money(0.001, from_wallet, 'xxx.csv') 51 | ``` 52 | 53 | ### 如何批量获得余额 54 | ``` 55 | manager.batch_get_balance('xxx.csv') 56 | ``` 57 | 58 | ### 如何批量操作XEN 59 | + 选择网络并实例化(暂时只支持bsc、eth) 60 | `manager = xen.XenManager(Network.eth)` 61 | + 调用批量方法 62 | `manager.batch_claim_rank('xxx.csv', 天数)` 63 | + 获得最大的ClaimRank天数 64 | `manager.get_max_term_days()` 65 | + 到期后可批量Claim然后归集到统一的地址 66 | `manager.batch_claim_mint_reward_and_share('xxx.csv', 归集地址)` 67 | + 更新钱包的XEN信息(到期时间、数量等) 68 | `manager.update_all_mints('xxx.csv', 'data.csv')` 69 | 70 | ### 如何多钱包调用合约,例如Mint 71 | + 需要制定合约的地址和abi(拿猫头鹰举例) 72 | ``` 73 | network_data = { 74 | Network.eth: { 75 | 'addr': '0xdd44443d8A3563E947EAd8A2254b36f8D8b28581', 76 | 'contract_abi': '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint64","name":"stageNum","type":"uint64"},{"internalType":"uint64","name":"maxPerStage","type":"uint64"},{"internalType":"uint64","name":"maxPerAddress","type":"uint64"},{"internalType":"bool","name":"isWhiteListMintActive","type":"bool"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"bool","name":"isPublicMintActive","type":"bool"}],"indexed":false,"internalType":"struct Owl.StageMintConfig","name":"config","type":"tuple"}],"name":"StageMintConfigChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"addressMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"address_","type":"address"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"isKYCAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"quantity","type":"uint64"}],"name":"publicMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_kycMerkleRoot","type":"bytes32"}],"name":"setKycMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newMaxPerAddress","type":"uint64"}],"name":"setMaxPerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newMaxPerStage","type":"uint64"}],"name":"setMaxPerStage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"mintStarted","type":"bool"}],"name":"setPublicMintActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"stageNum","type":"uint64"},{"internalType":"uint64","name":"maxPerStage","type":"uint64"},{"internalType":"uint64","name":"maxPerAddress","type":"uint64"},{"internalType":"bool","name":"isWhiteListMintActive","type":"bool"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"bool","name":"isPublicMintActive","type":"bool"}],"internalType":"struct Owl.StageMintConfig","name":"config_","type":"tuple"}],"name":"setStageMintConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"tokenURI_","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"mintStarted","type":"bool"}],"name":"setWhiteListMintActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stageMintConfig","outputs":[{"internalType":"uint64","name":"stageNum","type":"uint64"},{"internalType":"uint64","name":"maxPerStage","type":"uint64"},{"internalType":"uint64","name":"maxPerAddress","type":"uint64"},{"internalType":"bool","name":"isWhiteListMintActive","type":"bool"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"bool","name":"isPublicMintActive","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"quantity","type":"uint64"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"whitelistMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]' 77 | } 78 | } 79 | ``` 80 | + 制定合约的方法名和参数,调用批量方法 81 | ``` 82 | manager = BatchMintManager(Network.eth, network_data) 83 | manager.batch_call_write_func('xxx.csv', 'publicMint', (1)) 84 | ``` 85 | + 如果需要,可以不使用动态gas,而通过调用limit_gas方法指定gas限制 86 | 87 | ### 如何进行ERC721 NFT归集 88 | + 去moralis.io申请一个API KEY,用免费的即可 89 | + 新建配置文件configs,参考模板configs_template,填写API KEY 90 | ``` 91 | manager = BatchMintManager(network, network_data) 92 | manager.batch_collect_nft('xxx.csv', NFT合约地址, 归集地址, 是否归集(否为只扫描不归集)) 93 | ``` 94 | 95 | 96 | *** 97 | 98 | ##### *XEN的示例代码参考main.py* 99 | ##### *批量Mint猫头鹰的实例代码参考batch_func_runner.py* 100 | -------------------------------------------------------------------------------- /contracts/UpgradebleStormSender_flat.sol: -------------------------------------------------------------------------------- 1 | 2 | // File: contracts/EternalStorage.sol 3 | 4 | // Roman Storm Multi Sender 5 | // To Use this Dapp: https://rstormsf.github.io/multisender 6 | pragma solidity 0.4.24; 7 | 8 | 9 | /** 10 | * @title EternalStorage 11 | * @dev This contract holds all the necessary state variables to carry out the storage of any contract. 12 | */ 13 | contract EternalStorage { 14 | 15 | mapping(bytes32 => uint256) internal uintStorage; 16 | mapping(bytes32 => string) internal stringStorage; 17 | mapping(bytes32 => address) internal addressStorage; 18 | mapping(bytes32 => bytes) internal bytesStorage; 19 | mapping(bytes32 => bool) internal boolStorage; 20 | mapping(bytes32 => int256) internal intStorage; 21 | 22 | } 23 | 24 | // File: contracts/UpgradeabilityOwnerStorage.sol 25 | 26 | // Roman Storm Multi Sender 27 | // To Use this Dapp: https://rstormsf.github.io/multisender 28 | 29 | 30 | /** 31 | * @title UpgradeabilityOwnerStorage 32 | * @dev This contract keeps track of the upgradeability owner 33 | */ 34 | contract UpgradeabilityOwnerStorage { 35 | // Owner of the contract 36 | address private _upgradeabilityOwner; 37 | 38 | /** 39 | * @dev Tells the address of the owner 40 | * @return the address of the owner 41 | */ 42 | function upgradeabilityOwner() public view returns (address) { 43 | return _upgradeabilityOwner; 44 | } 45 | 46 | /** 47 | * @dev Sets the address of the owner 48 | */ 49 | function setUpgradeabilityOwner(address newUpgradeabilityOwner) internal { 50 | _upgradeabilityOwner = newUpgradeabilityOwner; 51 | } 52 | 53 | } 54 | 55 | // File: contracts/UpgradeabilityStorage.sol 56 | 57 | // Roman Storm Multi Sender 58 | // To Use this Dapp: https://rstormsf.github.io/multisender 59 | 60 | 61 | /** 62 | * @title UpgradeabilityStorage 63 | * @dev This contract holds all the necessary state variables to support the upgrade functionality 64 | */ 65 | contract UpgradeabilityStorage { 66 | // Version name of the current implementation 67 | string internal _version; 68 | 69 | // Address of the current implementation 70 | address internal _implementation; 71 | 72 | /** 73 | * @dev Tells the version name of the current implementation 74 | * @return string representing the name of the current version 75 | */ 76 | function version() public view returns (string) { 77 | return _version; 78 | } 79 | 80 | /** 81 | * @dev Tells the address of the current implementation 82 | * @return address of the current implementation 83 | */ 84 | function implementation() public view returns (address) { 85 | return _implementation; 86 | } 87 | } 88 | 89 | // File: contracts/OwnedUpgradeabilityStorage.sol 90 | 91 | // Roman Storm Multi Sender 92 | // To Use this Dapp: https://rstormsf.github.io/multisender 93 | 94 | 95 | 96 | 97 | 98 | /** 99 | * @title OwnedUpgradeabilityStorage 100 | * @dev This is the storage necessary to perform upgradeable contracts. 101 | * This means, required state variables for upgradeability purpose and eternal storage per se. 102 | */ 103 | contract OwnedUpgradeabilityStorage is UpgradeabilityOwnerStorage, UpgradeabilityStorage, EternalStorage {} 104 | 105 | // File: contracts/SafeMath.sol 106 | 107 | // Roman Storm Multi Sender 108 | // To Use this Dapp: https://rstormsf.github.io/multisender 109 | 110 | 111 | /** 112 | * @title SafeMath 113 | * @dev Math operations with safety checks that throw on error 114 | */ 115 | library SafeMath { 116 | 117 | /** 118 | * @dev Multiplies two numbers, throws on overflow. 119 | */ 120 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 121 | if (a == 0) { 122 | return 0; 123 | } 124 | uint256 c = a * b; 125 | assert(c / a == b); 126 | return c; 127 | } 128 | 129 | /** 130 | * @dev Integer division of two numbers, truncating the quotient. 131 | */ 132 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 133 | // assert(b > 0); // Solidity automatically throws when dividing by 0 134 | uint256 c = a / b; 135 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 136 | return c; 137 | } 138 | 139 | /** 140 | * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). 141 | */ 142 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 143 | assert(b <= a); 144 | return a - b; 145 | } 146 | 147 | /** 148 | * @dev Adds two numbers, throws on overflow. 149 | */ 150 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 151 | uint256 c = a + b; 152 | assert(c >= a); 153 | return c; 154 | } 155 | } 156 | 157 | // File: contracts/multisender/Ownable.sol 158 | 159 | // Roman Storm Multi Sender 160 | // To Use this Dapp: https://rstormsf.github.io/multisender 161 | 162 | 163 | 164 | /** 165 | * @title Ownable 166 | * @dev This contract has an owner address providing basic authorization control 167 | */ 168 | contract Ownable is EternalStorage { 169 | /** 170 | * @dev Event to show ownership has been transferred 171 | * @param previousOwner representing the address of the previous owner 172 | * @param newOwner representing the address of the new owner 173 | */ 174 | event OwnershipTransferred(address previousOwner, address newOwner); 175 | 176 | /** 177 | * @dev Throws if called by any account other than the owner. 178 | */ 179 | modifier onlyOwner() { 180 | require(msg.sender == owner()); 181 | _; 182 | } 183 | 184 | /** 185 | * @dev Tells the address of the owner 186 | * @return the address of the owner 187 | */ 188 | function owner() public view returns (address) { 189 | return addressStorage[keccak256("owner")]; 190 | } 191 | 192 | /** 193 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 194 | * @param newOwner the address to transfer ownership to. 195 | */ 196 | function transferOwnership(address newOwner) public onlyOwner { 197 | require(newOwner != address(0)); 198 | setOwner(newOwner); 199 | } 200 | 201 | /** 202 | * @dev Sets a new owner address 203 | */ 204 | function setOwner(address newOwner) internal { 205 | emit OwnershipTransferred(owner(), newOwner); 206 | addressStorage[keccak256("owner")] = newOwner; 207 | } 208 | } 209 | 210 | // File: contracts/multisender/Claimable.sol 211 | 212 | // Roman Storm Multi Sender 213 | // To Use this Dapp: https://rstormsf.github.io/multisender 214 | 215 | 216 | 217 | 218 | /** 219 | * @title Claimable 220 | * @dev Extension for the Ownable contract, where the ownership needs to be claimed. 221 | * This allows the new owner to accept the transfer. 222 | */ 223 | contract Claimable is EternalStorage, Ownable { 224 | function pendingOwner() public view returns (address) { 225 | return addressStorage[keccak256("pendingOwner")]; 226 | } 227 | 228 | /** 229 | * @dev Modifier throws if called by any account other than the pendingOwner. 230 | */ 231 | modifier onlyPendingOwner() { 232 | require(msg.sender == pendingOwner()); 233 | _; 234 | } 235 | 236 | /** 237 | * @dev Allows the current owner to set the pendingOwner address. 238 | * @param newOwner The address to transfer ownership to. 239 | */ 240 | function transferOwnership(address newOwner) public onlyOwner { 241 | require(newOwner != address(0)); 242 | addressStorage[keccak256("pendingOwner")] = newOwner; 243 | } 244 | 245 | /** 246 | * @dev Allows the pendingOwner address to finalize the transfer. 247 | */ 248 | function claimOwnership() public onlyPendingOwner { 249 | emit OwnershipTransferred(owner(), pendingOwner()); 250 | addressStorage[keccak256("owner")] = addressStorage[keccak256("pendingOwner")]; 251 | addressStorage[keccak256("pendingOwner")] = address(0); 252 | } 253 | } 254 | 255 | // File: contracts/multisender/UpgradebleStormSender.sol 256 | 257 | // Roman Storm Multi Sender 258 | // To Use this Dapp: https://rstormsf.github.io/multisender 259 | 260 | 261 | 262 | 263 | /** 264 | * @title ERC20Basic 265 | * @dev Simpler version of ERC20 interface 266 | * @dev see https://github.com/ethereum/EIPs/issues/179 267 | */ 268 | contract ERC20Basic { 269 | function totalSupply() public view returns (uint256); 270 | function balanceOf(address who) public view returns (uint256); 271 | function transfer(address to, uint256 value) public returns (bool); 272 | event Transfer(address indexed from, address indexed to, uint256 value); 273 | } 274 | 275 | 276 | contract ERC20 is ERC20Basic { 277 | function allowance(address owner, address spender) public view returns (uint256); 278 | function transferFrom(address from, address to, uint256 value) public returns (bool); 279 | function approve(address spender, uint256 value) public returns (bool); 280 | event Approval(address indexed owner, address indexed spender, uint256 value); 281 | } 282 | 283 | 284 | contract UpgradebleStormSender is OwnedUpgradeabilityStorage, Claimable { 285 | using SafeMath for uint256; 286 | 287 | event Multisended(uint256 total, address tokenAddress); 288 | event ClaimedTokens(address token, address owner, uint256 balance); 289 | 290 | modifier hasFee() { 291 | if (currentFee(msg.sender) > 0) { 292 | require(msg.value >= currentFee(msg.sender)); 293 | } 294 | _; 295 | } 296 | 297 | function() public payable {} 298 | 299 | function initialize(address _owner) public { 300 | require(!initialized()); 301 | setOwner(_owner); 302 | setArrayLimit(200); 303 | //setDiscountStep(0.00005 ether); 304 | //setFee(0.005 ether); 305 | boolStorage[keccak256("rs_multisender_initialized")] = true; 306 | } 307 | 308 | function initialized() public view returns (bool) { 309 | return boolStorage[keccak256("rs_multisender_initialized")]; 310 | } 311 | 312 | function txCount(address customer) public view returns(uint256) { 313 | return uintStorage[keccak256(abi.encodePacked("txCount", customer))]; 314 | } 315 | 316 | function arrayLimit() public view returns(uint256) { 317 | return uintStorage[keccak256(abi.encodePacked("arrayLimit"))]; 318 | } 319 | 320 | function setArrayLimit(uint256 _newLimit) public onlyOwner { 321 | require(_newLimit != 0); 322 | uintStorage[keccak256("arrayLimit")] = _newLimit; 323 | } 324 | 325 | function discountStep() public view returns(uint256) { 326 | return uintStorage[keccak256("discountStep")]; 327 | } 328 | 329 | function setDiscountStep(uint256 _newStep) public onlyOwner { 330 | require(_newStep != 0); 331 | uintStorage[keccak256("discountStep")] = _newStep; 332 | } 333 | 334 | function fee() public view returns(uint256) { 335 | return uintStorage[keccak256("fee")]; 336 | } 337 | 338 | function currentFee(address _customer) public view returns(uint256) { 339 | if (fee() > discountRate(msg.sender)) { 340 | return fee().sub(discountRate(_customer)); 341 | } else { 342 | return 0; 343 | } 344 | } 345 | 346 | function setFee(uint256 _newStep) public onlyOwner { 347 | require(_newStep != 0); 348 | uintStorage[keccak256("fee")] = _newStep; 349 | } 350 | 351 | function discountRate(address _customer) public view returns(uint256) { 352 | uint256 count = txCount(_customer); 353 | return count.mul(discountStep()); 354 | } 355 | 356 | function multisendToken(address token, address[] _contributors, uint256[] _balances) public payable { 357 | if (token == 0x000000000000000000000000000000000000bEEF){ 358 | multisendEther(_contributors, _balances); 359 | } else { 360 | uint256 total = 0; 361 | require(_contributors.length <= arrayLimit()); 362 | ERC20 erc20token = ERC20(token); 363 | uint8 i = 0; 364 | for (i; i < _contributors.length; i++) { 365 | erc20token.transferFrom(msg.sender, _contributors[i], _balances[i]); 366 | total += _balances[i]; 367 | } 368 | setTxCount(msg.sender, txCount(msg.sender).add(1)); 369 | emit Multisended(total, token); 370 | } 371 | } 372 | 373 | function multisendEther(address[] _contributors, uint256[] _balances) public payable { 374 | uint256 total = msg.value; 375 | //uint256 userfee = currentFee(msg.sender); 376 | //require(total >= userfee); 377 | require(_contributors.length <= arrayLimit()); 378 | //total = total.sub(userfee); 379 | uint256 i = 0; 380 | for (i; i < _contributors.length; i++) { 381 | require(total >= _balances[i]); 382 | total = total.sub(_balances[i]); 383 | _contributors[i].transfer(_balances[i]); 384 | } 385 | setTxCount(msg.sender, txCount(msg.sender).add(1)); 386 | emit Multisended(msg.value, 0x000000000000000000000000000000000000bEEF); 387 | } 388 | 389 | function claimTokens(address _token) public onlyOwner { 390 | if (_token == 0x0) { 391 | owner().transfer(address(this).balance); 392 | return; 393 | } 394 | ERC20 erc20token = ERC20(_token); 395 | uint256 balance = erc20token.balanceOf(this); 396 | erc20token.transfer(owner(), balance); 397 | emit ClaimedTokens(_token, owner(), balance); 398 | } 399 | 400 | function setTxCount(address customer, uint256 _txCount) private { 401 | uintStorage[keccak256(abi.encodePacked("txCount", customer))] = _txCount; 402 | } 403 | 404 | } -------------------------------------------------------------------------------- /georli_runner.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import random 3 | import time 4 | 5 | from web3 import Web3 6 | 7 | from core.batch_manager import Network 8 | from core.tool_helper import ToolHelper 9 | from libs.common import REPLACE_WALLET_ADDR 10 | from libs.global_config import GlobalConfig 11 | 12 | 13 | def get_random_amount(amount): 14 | return amount + (random.randrange(-10, 10) / 100) * amount 15 | 16 | 17 | usdc_contract_addr = '0x80732890c93c6D9c6C23E06F888eD0CB88A06018' 18 | weth_abi = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]' 19 | weth_contract_addr = '0x05fDbDfaE180345C6Cff5316c286727CF1a43327' 20 | uniswap_router_abi = '[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]' 21 | swap_contract_addr = '0xEe0e03C1a621084cA3c542F36E4A5D0230304471' 22 | l1_bridge_amount = get_random_amount(0.005) 23 | l2_bridge_amount = get_random_amount(0.004) 24 | 25 | 26 | def interact_single_wallet(base_wallet, to_wallet): 27 | # Transfer Eth to wallets in csv file 28 | print('*************开始转账到小钱包****************') 29 | ToolHelper().contract('0x60371a3af7eA5A1cE594de2E419FF942134B1F70') \ 30 | .abi('[]') \ 31 | .network(Network.goerli) \ 32 | .wait_for_complete(True) \ 33 | .transfer_eth_single(get_random_amount(0.01), base_wallet, to_wallet) 34 | 35 | 36 | def batch_transfer_to_wallets_from(from_wallet, wallets_file, start_from = 0): 37 | result_f = open('georli_failed_result.txt', 'w') 38 | with open(wallets_file) as f: 39 | f_csv = csv.reader(f) 40 | next(f_csv) 41 | for each_wallet in f_csv: 42 | try: 43 | if start_from > int(each_wallet[0]): 44 | continue 45 | interact_single_wallet(from_wallet, each_wallet) 46 | except Exception as e: 47 | print(f'interact zksync error {repr(e)}') 48 | result_f.write(','.join(each_wallet)) 49 | result_f.write('\n') 50 | result_f.flush() 51 | result_f.close() 52 | 53 | 54 | if __name__ == '__main__': 55 | print('Begin georli interact...') 56 | 57 | with open('xen_mints/base_transfer_wallet.csv') as f: 58 | reader = csv.reader(f) 59 | from_wallet = list(reader)[1] 60 | 61 | batch_transfer_to_wallets_from(from_wallet, 'xen_mints/wallets_tomint.csv', 107) 62 | 63 | 64 | -------------------------------------------------------------------------------- /space_id_airdrop_requester.py: -------------------------------------------------------------------------------- 1 | # send post request to 'https://graphigo.prd.space.id/query' with the following body '{"operationName":"AirdropDetail","variables":{"addr":"0x3D720D4246913BAf517680a8f4626cEDA20072dA"},"query":"query AirdropDetail($addr: String!) {\n AirDropDetail(addr: $addr) {\n exists\n bnbThreeDigit\n bnbFourDigit\n arbThreeDigit\n arbFourDigit\n holdingTime\n daysToExpiry\n setPrimaryName\n voyageCount\n voyage1\n voyage2\n voyage3\n bothBnbArb\n recordsRole\n tokenAmount\n galxeOat\n __typename\n }\n}"}' 2 | # receive response json string like '{"data":{"AirDropDetail":{"exists":true,"bnbThreeDigit":0,"bnbFourDigit":1,"arbThreeDigit":0,"arbFourDigit":0,"holdingTime":190,"daysToExpiry":272,"setPrimaryName":1,"voyageCount":1,"voyage1":1,"voyage2":0,"voyage3":0,"bothBnbArb":0,"recordsRole":0,"tokenAmount":"546052356032160000000","galxeOat":1,"__typename":"AirdropDetail"}}}' 3 | # parse the json string to get the value of 'tokenAmount' 4 | # convert the value to decimal 5 | import csv 6 | 7 | import requests 8 | import json 9 | 10 | from web3 import Web3 11 | 12 | from core.batch_manager import Network, Addr_Index 13 | from core.tool_helper import ToolHelper 14 | 15 | 16 | def get_space_id_airdrop_requester(addr): 17 | url = 'https://graphigo.prd.space.id/query' 18 | data = { 19 | "operationName": "AirdropDetail", 20 | "variables": { 21 | "addr": addr 22 | }, 23 | "query": "query AirdropDetail($addr: String!) {\n AirDropDetail(addr: $addr) {\n exists\n bnbThreeDigit\n bnbFourDigit\n arbThreeDigit\n arbFourDigit\n holdingTime\n daysToExpiry\n setPrimaryName\n voyageCount\n voyage1\n voyage2\n voyage3\n bothBnbArb\n recordsRole\n tokenAmount\n galxeOat\n __typename\n }\n}" 24 | } 25 | headers = {'Content-Type': 'application/json', 'authority': 'graphigo.prd.space.id', 'method': 'POST', 'path': '/query', 'scheme': 'https', 'accept': '*/*', 26 | 'sec-ch-ua':'" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"' , 'sec-ch-ua-mobile':'?0', 'sec-fetch-dest':'empty', 'sec-fetch-mode':'cors', 'sec-fetch-site':'same-site', 27 | 'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'origin':'https://space.id', 'referer':'https://space.id/'} 28 | response = requests.post(url, json=data, headers=headers) 29 | 30 | #enable request logging 31 | # print(response.request.headers) 32 | # print(response.request.body) 33 | # print(response.request.url) 34 | # print(response.request.method) 35 | # print(response.request) 36 | 37 | response_json = response.json() 38 | print(response_json) 39 | token_amount = response_json['data']['AirDropDetail']['tokenAmount'] 40 | #if token amount is empty string 41 | if token_amount == '': 42 | return 0 43 | return int(int(token_amount)/10e17) 44 | 45 | 46 | def check_airdrops(): 47 | results = [] 48 | with open('xen_mints/wallets_tocheck.csv') as f: 49 | f_csv = csv.reader(f) 50 | headers = next(f_csv) 51 | row_no = 1 52 | for each_wallet in f_csv: 53 | if len(each_wallet) == 0: 54 | continue 55 | 56 | try: 57 | wallet_addr = each_wallet[1] 58 | token_count = get_space_id_airdrop_requester(wallet_addr) 59 | results.append([wallet_addr, token_count]) 60 | except: 61 | continue 62 | # write results to csv 63 | with open('space_id_airdrop_requester.csv', 'w', newline='') as f: 64 | f_csv = csv.writer(f) 65 | f_csv.writerow(['wallet_addr', 'token_count']) 66 | f_csv.writerows(results) 67 | 68 | 69 | def batch_transfer(from_wallet, to_addr, amount): 70 | abi = '[{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]' 71 | ToolHelper().contract('0x2dfF88A56767223A5529eA5960Da7A3F5f766406') \ 72 | .abi(abi) \ 73 | .network(Network.bsc) \ 74 | .gas_max_fee(1.5) \ 75 | .gas_priority_fee(1.5) \ 76 | .wallet(from_wallet) \ 77 | .wait_for_complete(True) \ 78 | .call_write('transfer', (Web3.to_checksum_address(to_addr), amount)) 79 | 80 | 81 | def get_token_amount(from_wallet): 82 | abi = '[{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]' 83 | balance = ToolHelper().contract('0x2dfF88A56767223A5529eA5960Da7A3F5f766406') \ 84 | .abi(abi) \ 85 | .network(Network.bsc) \ 86 | .wallet(from_wallet) \ 87 | .call_read('balanceOf', tuple([Web3.to_checksum_address(from_wallet[Addr_Index])])) 88 | return balance 89 | 90 | 91 | if __name__ == '__main__': 92 | # print(get_space_id_airdrop_requester()) 93 | # check_airdrops() 94 | with open('xen_mints/wallets_tocheck.csv') as f: 95 | f_csv = csv.reader(f) 96 | headers = next(f_csv) 97 | row_no = 1 98 | for each_wallet in f_csv: 99 | if len(each_wallet) == 0: 100 | continue 101 | amount = get_token_amount(each_wallet) 102 | if amount <= 0: 103 | continue 104 | print(f'begin to transfer from {each_wallet}, amount {amount}') 105 | batch_transfer(each_wallet, '0x3D720D4246913BAf517680a8f4626cEDA20072dA', amount) 106 | 107 | 108 | -------------------------------------------------------------------------------- /scroll_testnet_runner.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import random 3 | import time 4 | 5 | from web3 import Web3 6 | 7 | from core.batch_manager import Network 8 | from core.tool_helper import ToolHelper 9 | from libs.common import REPLACE_WALLET_ADDR 10 | from libs.global_config import GlobalConfig 11 | 12 | 13 | def get_random_amount(amount): 14 | return amount + (random.randrange(-10, 10) / 100) * amount 15 | 16 | 17 | usdc_contract_addr = '0x80732890c93c6D9c6C23E06F888eD0CB88A06018' 18 | weth_abi = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]' 19 | weth_contract_addr = '0x05fDbDfaE180345C6Cff5316c286727CF1a43327' 20 | uniswap_router_abi = '[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]' 21 | swap_contract_addr = '0xEe0e03C1a621084cA3c542F36E4A5D0230304471' 22 | l1_bridge_amount = get_random_amount(0.005) 23 | l2_bridge_amount = get_random_amount(0.004) 24 | 25 | 26 | def interact_single_wallet_with_scroll_l1(base_wallet, to_wallet): 27 | # Transfer Eth to wallets in csv file 28 | # Scroll L2 转账 29 | print('*************开始转账到L1的小钱包****************') 30 | ToolHelper().contract('0x8318ed43dD6760dA6A01B7605C408841e7062419') \ 31 | .abi('[]') \ 32 | .network(Network.scroll_test_l1) \ 33 | .wait_for_complete(True) \ 34 | .transfer_eth_single(get_random_amount(0.0065), base_wallet, to_wallet) 35 | 36 | # Bridge from L1 to L2 37 | # L1 bridge contract[0x94Cf11667B017e9Fef7Ab557E2eF9EFf6fdfeDc3 ] 38 | print('*************开始跨链,从L1到L2****************') 39 | bridge_abi = '[{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"depositETH","outputs":[],"stateMutability":"payable","type":"function"}]' 40 | ToolHelper().contract('0x94Cf11667B017e9Fef7Ab557E2eF9EFf6fdfeDc3') \ 41 | .abi(bridge_abi) \ 42 | .network(Network.scroll_test_l1) \ 43 | .value(l1_bridge_amount) \ 44 | .gas_limit(130000) \ 45 | .gas_max_fee(1.5) \ 46 | .gas_priority_fee(1.5) \ 47 | .wallet(to_wallet) \ 48 | .wait_for_complete(True) \ 49 | .call_write('depositETH', (0)) 50 | 51 | 52 | def interact_single_wallet_with_scroll_l2(to_wallet): 53 | approve_usdc_in_l2(to_wallet) 54 | 55 | bridge_l2_to_l1(to_wallet) 56 | 57 | swap_from_eth_to_weth(to_wallet) 58 | 59 | swap_from_eth_to_usdc(to_wallet) 60 | 61 | add_liquidity_eth_usdc(to_wallet) 62 | 63 | 64 | def add_liquidity_eth_usdc(to_wallet): 65 | # Step 2, make swap TSETH to TSUSDC 66 | print('*************增加流动性 ETH/USDC****************') 67 | liquidity_amount = 0.0005 68 | amount_in = Web3.toWei(liquidity_amount, 'ether') 69 | swap_path = [weth_contract_addr, usdc_contract_addr] 70 | amount_path_out = ToolHelper().contract(swap_contract_addr) \ 71 | .abi(uniswap_router_abi) \ 72 | .network(Network.scroll_test_l2) \ 73 | .wallet(to_wallet) \ 74 | .call_read('getAmountsOut', (amount_in, swap_path)) 75 | amount_out = amount_path_out[1] 76 | deadline = int(time.time() + 60) 77 | ToolHelper().contract(swap_contract_addr) \ 78 | .abi(uniswap_router_abi) \ 79 | .value(liquidity_amount) \ 80 | .network(Network.scroll_test_l2) \ 81 | .gas_limit(200000) \ 82 | .gas_max_fee(1.5) \ 83 | .gas_priority_fee(1.5) \ 84 | .wallet(to_wallet) \ 85 | .call_write('addLiquidityETH', ( 86 | Web3.toChecksumAddress('0x80732890c93c6D9c6C23E06F888eD0CB88A06018'), amount_out, 0, 0, REPLACE_WALLET_ADDR, 87 | deadline)) 88 | 89 | 90 | def swap_from_eth_to_usdc(to_wallet): 91 | # Make swap in L2 92 | # Step1, get TSUSDC amount out 93 | # uniswap contract [0xEe0e03C1a621084cA3c542F36E4A5D0230304471] 94 | # TSUSDC contract [0x80732890c93c6D9c6C23E06F888eD0CB88A06018] 95 | print('*************开始Swap,把ETH换成USDC****************') 96 | swap_eu = l2_bridge_amount / 5 97 | amount_in = Web3.toWei(swap_eu, 'ether') 98 | swap_path = [weth_contract_addr, usdc_contract_addr] 99 | amount_path_out = ToolHelper().contract(swap_contract_addr) \ 100 | .abi(uniswap_router_abi) \ 101 | .network(Network.scroll_test_l2) \ 102 | .wallet(to_wallet) \ 103 | .call_read('getAmountsOut', (amount_in, swap_path)) 104 | # Step 2, make swap TSETH to TSUSDC 105 | amount_out = amount_path_out[1] 106 | deadline = int(time.time() + 60) 107 | ToolHelper().contract(swap_contract_addr) \ 108 | .abi(uniswap_router_abi) \ 109 | .value(swap_eu) \ 110 | .network(Network.scroll_test_l2) \ 111 | .gas_limit(200000) \ 112 | .gas_max_fee(1.5) \ 113 | .gas_priority_fee(1.5) \ 114 | .wallet(to_wallet) \ 115 | .wait_for_complete(True) \ 116 | .call_write('swapExactETHForTokens', (amount_out, swap_path, REPLACE_WALLET_ADDR, deadline)) 117 | 118 | 119 | def swap_from_eth_to_weth(to_wallet): 120 | # Wrap ether in L2 121 | # WETH contract [0x05fDbDfaE180345C6Cff5316c286727CF1a43327] 122 | print('*************开始Swap,把ETH换成WETH****************') 123 | ToolHelper().contract(weth_contract_addr) \ 124 | .abi(weth_abi) \ 125 | .network(Network.scroll_test_l2) \ 126 | .value(l2_bridge_amount / 6) \ 127 | .gas_limit(50000) \ 128 | .gas_max_fee(1.5) \ 129 | .gas_priority_fee(1.5) \ 130 | .wallet(to_wallet) \ 131 | .wait_for_complete(True) \ 132 | .call_write('deposit', ()) 133 | 134 | 135 | def bridge_l2_to_l1(to_wallet): 136 | # Bridge from L2 to L1 137 | # L2 bridge contract[0x8318ed43dD6760dA6A01B7605C408841e7062419] 138 | print('*************开始跨链,从L2到L1****************') 139 | bridge_abi = '[{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"withdrawETH","outputs":[],"stateMutability":"payable","type":"function"}]' 140 | ToolHelper().contract('0x8318ed43dD6760dA6A01B7605C408841e7062419') \ 141 | .abi(bridge_abi) \ 142 | .network(Network.scroll_test_l2) \ 143 | .value(l2_bridge_amount / 10) \ 144 | .gas_limit(200000) \ 145 | .gas_max_fee(1.5) \ 146 | .gas_priority_fee(1.5) \ 147 | .wallet(to_wallet) \ 148 | .wait_for_complete(True) \ 149 | .call_write('withdrawETH', (0)) 150 | 151 | 152 | def approve_usdc_in_l2(to_wallet): 153 | print('*************APPROVE USDC to SWAP****************') 154 | ToolHelper().contract(usdc_contract_addr) \ 155 | .abi( 156 | '[{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]') \ 157 | .network(Network.scroll_test_l2) \ 158 | .gas_limit(200000) \ 159 | .gas_max_fee(1.5) \ 160 | .gas_priority_fee(1.5) \ 161 | .wallet(to_wallet) \ 162 | .wait_for_complete(True) \ 163 | .call_write('approve', ( 164 | Web3.toChecksumAddress('0xEe0e03C1a621084cA3c542F36E4A5D0230304471'), Web3.toWei(2 ** 64 - 1, 'ether'))) 165 | 166 | 167 | def interact_wallets_with_scroll(from_wallet, wallets_file): 168 | # 先操作L1,由于L1到L2跨链需要时间,等待一段时间后再操作L2 169 | 170 | result_f = open('scroll_failed_result.txt', 'w') 171 | with open(wallets_file) as f: 172 | f_csv = csv.reader(f) 173 | next(f_csv) 174 | for each_wallet in f_csv: 175 | try: 176 | GlobalConfig().use_proxy() 177 | GlobalConfig().random_proxy() 178 | interact_single_wallet_with_scroll_l1(from_wallet, each_wallet) 179 | except Exception as e: 180 | print(f'interact scroll l2 error {repr(e)}') 181 | result_f.write(','.join(each_wallet)) 182 | result_f.write('\n') 183 | result_f.flush() 184 | # result_f.write(f"Failed! Wallet {each_wallet[0]} interact scroll l1\n") 185 | 186 | with open(wallets_file) as f: 187 | f_csv = csv.reader(f) 188 | next(f_csv) 189 | for each_wallet in f_csv: 190 | try: 191 | GlobalConfig().use_proxy() 192 | GlobalConfig().random_proxy() 193 | interact_single_wallet_with_scroll_l2(each_wallet) 194 | # add_liquidity_eth_usdc(each_wallet) 195 | except Exception as e: 196 | print(f'interact scroll l2 error {repr(e)}') 197 | # result_f.write(f"Failed! Wallet {each_wallet[0]} interact scroll l2\n") 198 | result_f.write(','.join(each_wallet)) 199 | result_f.write('\n') 200 | result_f.flush() 201 | result_f.close() 202 | 203 | 204 | if __name__ == '__main__': 205 | print('Begin scroll testnet interact...') 206 | # 批量操作scroll 207 | # 测试网领水地址 https://prealpha.scroll.io/faucet/ 208 | 209 | with open('xen_mints/base_transfer_wallet.csv') as f: 210 | reader = csv.reader(f) 211 | from_wallet = list(reader)[1] 212 | 213 | interact_wallets_with_scroll(from_wallet, 'xen_mints/wallets_tomint.csv') 214 | -------------------------------------------------------------------------------- /zksync_testnet_runner.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import random 3 | import time 4 | 5 | from web3 import Web3 6 | 7 | from core.batch_manager import Network 8 | from core.tool_helper import ToolHelper 9 | from libs.common import REPLACE_WALLET_ADDR 10 | from libs.global_config import GlobalConfig 11 | 12 | 13 | def get_random_amount(amount): 14 | return amount + (random.randrange(-10, 10) / 100) * amount 15 | 16 | 17 | usdc_contract_addr = '0x80732890c93c6D9c6C23E06F888eD0CB88A06018' 18 | weth_abi = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]' 19 | weth_contract_addr = '0x05fDbDfaE180345C6Cff5316c286727CF1a43327' 20 | uniswap_router_abi = '[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]' 21 | swap_contract_addr = '0xEe0e03C1a621084cA3c542F36E4A5D0230304471' 22 | l1_bridge_amount = get_random_amount(0.005) 23 | l2_bridge_amount = get_random_amount(0.004) 24 | 25 | 26 | def interact_single_wallet_with_zksync(base_wallet, to_wallet): 27 | # Transfer Eth to wallets in csv file 28 | print('*************开始转账到小钱包****************') 29 | ToolHelper().contract('0x60371a3af7eA5A1cE594de2E419FF942134B1F70') \ 30 | .abi('[]') \ 31 | .network(Network.zksync_testnet) \ 32 | .wait_for_complete(True) \ 33 | .transfer_eth_single(get_random_amount(0.01), base_wallet, to_wallet) 34 | 35 | # # Bridge from L1 to L2 36 | # # L1 bridge contract[0x94Cf11667B017e9Fef7Ab557E2eF9EFf6fdfeDc3 ] 37 | # print('*************开始跨链,从L1到L2****************') 38 | # bridge_abi = '[{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"depositETH","outputs":[],"stateMutability":"payable","type":"function"}]' 39 | # ToolHelper().contract('0x94Cf11667B017e9Fef7Ab557E2eF9EFf6fdfeDc3') \ 40 | # .abi(bridge_abi) \ 41 | # .network(Network.scroll_test_l1) \ 42 | # .value(l1_bridge_amount) \ 43 | # .gas_limit(130000) \ 44 | # .gas_max_fee(1.5) \ 45 | # .gas_priority_fee(1.5) \ 46 | # .wallet(to_wallet) \ 47 | # .wait_for_complete(True) \ 48 | # .call_write('depositETH', (0)) 49 | 50 | 51 | def interact_single_wallet_with_scroll_l2(to_wallet): 52 | approve_usdc_in_l2(to_wallet) 53 | 54 | bridge_l2_to_l1(to_wallet) 55 | 56 | swap_from_eth_to_weth(to_wallet) 57 | 58 | swap_from_eth_to_usdc(to_wallet) 59 | 60 | add_liquidity_eth_usdc(to_wallet) 61 | 62 | 63 | def add_liquidity_eth_usdc(to_wallet): 64 | # Step 2, make swap TSETH to TSUSDC 65 | print('*************增加流动性 ETH/USDC****************') 66 | liquidity_amount = 0.0005 67 | amount_in = Web3.toWei(liquidity_amount, 'ether') 68 | swap_path = [weth_contract_addr, usdc_contract_addr] 69 | amount_path_out = ToolHelper().contract(swap_contract_addr) \ 70 | .abi(uniswap_router_abi) \ 71 | .network(Network.scroll_test_l2) \ 72 | .wallet(to_wallet) \ 73 | .call_read('getAmountsOut', (amount_in, swap_path)) 74 | amount_out = amount_path_out[1] 75 | deadline = int(time.time() + 60) 76 | ToolHelper().contract(swap_contract_addr) \ 77 | .abi(uniswap_router_abi) \ 78 | .value(liquidity_amount) \ 79 | .network(Network.scroll_test_l2) \ 80 | .gas_limit(200000) \ 81 | .gas_max_fee(1.5) \ 82 | .gas_priority_fee(1.5) \ 83 | .wallet(to_wallet) \ 84 | .call_write('addLiquidityETH', ( 85 | Web3.to_checksum_address('0x80732890c93c6D9c6C23E06F888eD0CB88A06018'), amount_out, 0, 0, REPLACE_WALLET_ADDR, 86 | deadline)) 87 | 88 | 89 | def swap_from_eth_to_usdc(to_wallet): 90 | # Make swap in L2 91 | # Step1, get TSUSDC amount out 92 | # uniswap contract [0xEe0e03C1a621084cA3c542F36E4A5D0230304471] 93 | # TSUSDC contract [0x80732890c93c6D9c6C23E06F888eD0CB88A06018] 94 | print('*************开始Swap,把ETH换成USDC****************') 95 | swap_eu = l2_bridge_amount / 5 96 | amount_in = Web3.to_wei(swap_eu, 'ether') 97 | swap_path = [weth_contract_addr, usdc_contract_addr] 98 | amount_path_out = ToolHelper().contract(swap_contract_addr) \ 99 | .abi(uniswap_router_abi) \ 100 | .network(Network.scroll_test_l2) \ 101 | .wallet(to_wallet) \ 102 | .call_read('getAmountsOut', (amount_in, swap_path)) 103 | # Step 2, make swap TSETH to TSUSDC 104 | amount_out = amount_path_out[1] 105 | deadline = int(time.time() + 60) 106 | ToolHelper().contract(swap_contract_addr) \ 107 | .abi(uniswap_router_abi) \ 108 | .value(swap_eu) \ 109 | .network(Network.scroll_test_l2) \ 110 | .gas_limit(200000) \ 111 | .gas_max_fee(1.5) \ 112 | .gas_priority_fee(1.5) \ 113 | .wallet(to_wallet) \ 114 | .wait_for_complete(True) \ 115 | .call_write('swapExactETHForTokens', (amount_out, swap_path, REPLACE_WALLET_ADDR, deadline)) 116 | 117 | 118 | def swap_from_eth_to_weth(to_wallet): 119 | # Wrap ether in L2 120 | # WETH contract [0x05fDbDfaE180345C6Cff5316c286727CF1a43327] 121 | print('*************开始Swap,把ETH换成WETH****************') 122 | ToolHelper().contract(weth_contract_addr) \ 123 | .abi(weth_abi) \ 124 | .network(Network.scroll_test_l2) \ 125 | .value(l2_bridge_amount / 6) \ 126 | .gas_limit(50000) \ 127 | .gas_max_fee(1.5) \ 128 | .gas_priority_fee(1.5) \ 129 | .wallet(to_wallet) \ 130 | .wait_for_complete(True) \ 131 | .call_write('deposit', ()) 132 | 133 | 134 | def bridge_l2_to_l1(to_wallet): 135 | # Bridge from L2 to L1 136 | # L2 bridge contract[0x8318ed43dD6760dA6A01B7605C408841e7062419] 137 | print('*************开始跨链,从L2到L1****************') 138 | bridge_abi = '[{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"withdrawETH","outputs":[],"stateMutability":"payable","type":"function"}]' 139 | ToolHelper().contract('0x8318ed43dD6760dA6A01B7605C408841e7062419') \ 140 | .abi(bridge_abi) \ 141 | .network(Network.scroll_test_l2) \ 142 | .value(l2_bridge_amount / 10) \ 143 | .gas_limit(200000) \ 144 | .gas_max_fee(1.5) \ 145 | .gas_priority_fee(1.5) \ 146 | .wallet(to_wallet) \ 147 | .wait_for_complete(True) \ 148 | .call_write('withdrawETH', (0)) 149 | 150 | 151 | def approve_usdc_in_l2(to_wallet): 152 | print('*************APPROVE USDC to SWAP****************') 153 | ToolHelper().contract(usdc_contract_addr) \ 154 | .abi( 155 | '[{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]') \ 156 | .network(Network.scroll_test_l2) \ 157 | .gas_limit(200000) \ 158 | .gas_max_fee(1.5) \ 159 | .gas_priority_fee(1.5) \ 160 | .wallet(to_wallet) \ 161 | .wait_for_complete(True) \ 162 | .call_write('approve', ( 163 | Web3.to_checksum_address('0xEe0e03C1a621084cA3c542F36E4A5D0230304471'), Web3.to_wei(2 ** 64 - 1, 'ether'))) 164 | 165 | 166 | def batch_transfer_to_wallets_from(from_wallet, wallets_file): 167 | result_f = open('zksync_failed_result.txt', 'w') 168 | with open(wallets_file) as f: 169 | f_csv = csv.reader(f) 170 | next(f_csv) 171 | for each_wallet in f_csv: 172 | try: 173 | interact_single_wallet_with_zksync(from_wallet, each_wallet) 174 | except Exception as e: 175 | print(f'interact zksync error {repr(e)}') 176 | result_f.write(','.join(each_wallet)) 177 | result_f.write('\n') 178 | result_f.flush() 179 | 180 | 181 | def interact_wallets_with_zksync(from_wallet, wallets_file): 182 | result_f = open('zksync_failed_result.txt', 'w') 183 | with open(wallets_file) as f: 184 | f_csv = csv.reader(f) 185 | next(f_csv) 186 | for each_wallet in f_csv: 187 | interact_single_wallet_with_zksync(from_wallet, each_wallet) 188 | try: 189 | pass 190 | # GlobalConfig().use_proxy() 191 | # GlobalConfig().random_proxy() 192 | except Exception as e: 193 | print(f'interact zksync error {repr(e)}') 194 | result_f.write(','.join(each_wallet)) 195 | result_f.write('\n') 196 | result_f.flush() 197 | # result_f.write(f"Failed! Wallet {each_wallet[0]} interact scroll l1\n") 198 | 199 | # with open(wallets_file) as f: 200 | # f_csv = csv.reader(f) 201 | # next(f_csv) 202 | # for each_wallet in f_csv: 203 | # try: 204 | # GlobalConfig().use_proxy() 205 | # GlobalConfig().random_proxy() 206 | # interact_single_wallet_with_scroll_l2(each_wallet) 207 | # # add_liquidity_eth_usdc(each_wallet) 208 | # except Exception as e: 209 | # print(f'interact scroll l2 error {repr(e)}') 210 | # # result_f.write(f"Failed! Wallet {each_wallet[0]} interact scroll l2\n") 211 | # result_f.write(','.join(each_wallet)) 212 | # result_f.write('\n') 213 | # result_f.flush() 214 | result_f.close() 215 | 216 | 217 | if __name__ == '__main__': 218 | print('Begin zksync testnet interact...') 219 | # 批量操作zksync testnet, https://portal.zksync.io/ 220 | 221 | with open('xen_mints/base_transfer_wallet.csv') as f: 222 | reader = csv.reader(f) 223 | from_wallet = list(reader)[1] 224 | 225 | batch_transfer_to_wallets_from(from_wallet, 'xen_mints/wallets_tomint.csv') 226 | 227 | 228 | -------------------------------------------------------------------------------- /core/xen_manager.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import math 3 | import time 4 | from web3 import Web3 5 | from core.batch_manager import BatchManager, Network, Addr_Index, No_Index 6 | 7 | 8 | class XenManager(BatchManager): 9 | 10 | def __init__(self, network: Network = Network.eth) -> None: 11 | network_data = { 12 | Network.eth: { 13 | 'addr': '0x06450dEe7FD2Fb8E39061434BAbCFC05599a6Fb8', 14 | 'contract_abi': '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"MintClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rank","type":"uint256"}],"name":"RankClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"AUTHORS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAYS_IN_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_RANK_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_RANK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PENALTY_PCT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TERM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER_THRESHOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWAL_WINDOW_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_DAYS_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_MIN_BURN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_MIN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeMinters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimMintReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"other","type":"address"},{"internalType":"uint256","name":"pct","type":"uint256"}],"name":"claimMintRewardAndShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pct","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimMintRewardAndStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimRank","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAPY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEAAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentMaxTerm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rankDelta","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"eaa","type":"uint256"}],"name":"getGrossReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getUserMint","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"internalType":"struct XENCrypto.MintInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserStake","outputs":[{"components":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"internalType":"struct XENCrypto.StakeInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalRank","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalXenStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBurns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMints","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userStakes","outputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]' 15 | }, 16 | Network.bsc: { 17 | 'addr': '0x2AB0e9e4eE70FFf1fB9D67031E44F6410170d00e', 18 | 'contract_abi': '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"MintClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rank","type":"uint256"}],"name":"RankClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"AUTHORS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAYS_IN_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_RANK_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_RANK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PENALTY_PCT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TERM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER_THRESHOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWAL_WINDOW_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_DAYS_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_MIN_BURN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_MIN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeMinters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimMintReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"other","type":"address"},{"internalType":"uint256","name":"pct","type":"uint256"}],"name":"claimMintRewardAndShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pct","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimMintRewardAndStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimRank","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAPY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEAAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentMaxTerm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rankDelta","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"eaa","type":"uint256"}],"name":"getGrossReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getUserMint","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"internalType":"struct XENCrypto.MintInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserStake","outputs":[{"components":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"internalType":"struct XENCrypto.StakeInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalRank","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalXenStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBurns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMints","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userStakes","outputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]' 19 | }, 20 | Network.goerli: { 21 | 'addr': '0xc78b129025A0877c75FDDa406E8908047092C582', 22 | 'contract_abi': '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"MintClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rank","type":"uint256"}],"name":"RankClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"AUTHORS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAYS_IN_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_RANK_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_RANK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PENALTY_PCT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TERM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER_THRESHOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWAL_WINDOW_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_DAYS_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_MIN_BURN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_MIN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeMinters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimMintReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"other","type":"address"},{"internalType":"uint256","name":"pct","type":"uint256"}],"name":"claimMintRewardAndShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pct","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimMintRewardAndStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimRank","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAPY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEAAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentMaxTerm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rankDelta","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"eaa","type":"uint256"}],"name":"getGrossReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getUserMint","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"internalType":"struct XENCrypto.MintInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserStake","outputs":[{"components":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"internalType":"struct XENCrypto.StakeInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalRank","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalXenStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBurns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMints","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userStakes","outputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]' 23 | } 24 | } 25 | super(XenManager, self).__init__(network, network_data) 26 | 27 | def get_global_rank(self) -> int: 28 | return self._contract.functions.globalRank().call() 29 | 30 | def get_max_term_days(self): 31 | return int(self._contract.functions.getCurrentMaxTerm().call() / 3600 / 24) 32 | 33 | def get_mint_info(self, addr): 34 | return self._contract.functions.userMints(addr).call() 35 | 36 | @staticmethod 37 | def cal_estimated_xen(term, global_rank, rank, amp, eaa): 38 | return term * math.log2(max(global_rank - rank, 2)) * amp * (1 + eaa / 1000) 39 | 40 | def update_all_mints(self, csv_path, info_csv_path): 41 | info_datas = [] 42 | global_rank = self.get_global_rank() 43 | with open(csv_path) as f: 44 | f_csv = csv.reader(f) 45 | headers = next(f_csv) 46 | row_no = 1 47 | for each_wallet in f_csv: 48 | self.handle_each_wallet(each_wallet, info_datas, global_rank, row_no) 49 | row_no += 1 50 | 51 | self.write_info_to_file(info_datas, info_csv_path) 52 | 53 | def handle_each_wallet(self, each_wallet, info_datas, global_rank, row_no): 54 | if len(each_wallet) <= 1: 55 | return 56 | addr = each_wallet[Addr_Index] 57 | mint_info = self.get_mint_info(addr) 58 | term = mint_info[1] 59 | maturityTs = mint_info[2] 60 | rank = mint_info[3] 61 | amp = mint_info[4] 62 | eaa = mint_info[5] 63 | 64 | if rank == 0: 65 | print(f'Wallet {each_wallet[No_Index]} {addr} has no Xen mint info, ignored.') 66 | return 67 | xen_count = self.cal_estimated_xen(term, global_rank, rank, amp, eaa) 68 | mint_info_data = [each_wallet[No_Index], addr, term, self.local_time(maturityTs), int(xen_count)] 69 | print(mint_info_data) 70 | info_datas.append(mint_info_data) 71 | 72 | def each_claim_rank(self, wallet, term): 73 | func_name = 'claimRank' 74 | func_args = [term] 75 | contract_func = self._contract.functions.claimRank(term) 76 | try: 77 | self.call_contract_func(wallet, func_name, func_args, contract_func) 78 | except Exception as e: 79 | print(f'claimRank has an error {wallet[Addr_Index]}, {repr(e)}') 80 | 81 | def each_claim_mint_reward_and_share(self, wallet, to_addr): 82 | if len(wallet) < 1: 83 | return 84 | mint_info = self.get_mint_info(wallet[Addr_Index]) 85 | maturityTs = mint_info[2] 86 | if maturityTs <= 0: 87 | print(f'Wallet {wallet[Addr_Index]} not minted XEN, ignored.') 88 | return 89 | 90 | current_time = int(time.time()) 91 | if current_time < maturityTs: 92 | print(f'Wallet {wallet[Addr_Index]} claim XEN Not available, ignored.') 93 | return 94 | 95 | func_name = 'claimMintRewardAndShare' 96 | percent = 100 97 | to_addr = Web3.toChecksumAddress(to_addr) 98 | func_args = [to_addr, percent] 99 | contract_func = self._contract.functions.claimMintRewardAndShare(to_addr, percent) 100 | 101 | try: 102 | self.call_contract_func(wallet, func_name, func_args, contract_func) 103 | except Exception as e: 104 | print(f'claimMintRewardAndShare has an error {wallet[Addr_Index]}, {repr(e)}') 105 | 106 | # eth使用EIP1559的gas策略 其他使用传统gas方法 107 | # 如果要限制eth的gas使用,可以调整maxFeePerGas 108 | 109 | def batch_claim_rank(self, csv_path, term): 110 | callback = lambda wallet: { 111 | self.each_claim_rank(wallet, term) 112 | } 113 | self.read_wallets_and_callback(csv_path, callback) 114 | 115 | def batch_claim_mint_reward_and_share(self, csv_path, share_addr): 116 | callback = lambda wallet: { 117 | self.each_claim_mint_reward_and_share(wallet, share_addr) 118 | } 119 | self.read_wallets_and_callback(csv_path, callback) 120 | --------------------------------------------------------------------------------