| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 |
- from web3 import Web3, HTTPProvider, WebsocketProvider, IPCProvider
- import time, datetime, traceback, random, json, requests
- from web3.middleware import geth_poa_middleware
- import re
- import os
- from web3._utils.module import attach_modules
- from osTools import *
- from config import *
- from sqlTools import *
- class debug():
- def __init__(self):
- self.decodeCCAddress = '0x0000004885B7FF4bfc4dDB48e921cc25c4c877e1'
- self.decodeAbi = json.loads(open('abi/decode.json').read())
- self.decodeContract = w3.eth.contract(address=self.decodeCCAddress, abi=self.decodeAbi)
- def traceCall(self, fromAdd, toAdd , data, value = 0 , blockNumber = 'latest'):
- if type(blockNumber) == int:
- blockNumber = hex(blockNumber)
- value = hex(int(value))
- try:
- r = w3.provider.make_request('debug_traceCall', [
- {
- 'from': fromAdd,
- 'to': toAdd,
- 'data': data,
- 'value':value,
- },
- blockNumber,
- {
- "tracer": "callTracer", "timeout" : '0.1s'
- }
- ])
- return r['result']
- except BaseException as err:
- print('trace err', r)
- return False
- def traceTransaction(self, hash):
- try:
- return w3.provider.make_request('debug_traceTransaction', [hash, {
- "tracer": "callTracer", "timeout" : '1s'
- }])['result']
- except:
- return False
- def functionDecodeFromCallData(self, data):
- tradeInfo = []
- for call in (data):
- try:
- #print(call['input'])
- if 'calls' in call:
- tradeInfo = tradeInfo + self.functionDecodeFromCallData(call['calls'])
- inputData = call['input']
- function = inputData[0:10]
- if function == '0x60806040':
- continue
- #空input无效
- if inputData == '0x':
- continue
- callType = call['type']
- toAdd = call['to']
- #空地址调用无效
- if toAdd[:38] == '0x000000000000000000000000000000000000':
- continue
- fromAdd = call['from']
- functionInput, decodeInput = self.decodeContract.decode_function_input(inputData)
- outPut = self.decodeOutput(call['output'])
- print(fromAdd, toAdd, functionInput, decodeInput, outPut)
- if str(functionInput) == '<Function transfer(address,uint256)>':
- #printTime(toAdd, fromAdd, decodeInput['dst'], decodeInput['wad'])
- tradeInfo.append({
- 'token': toAdd.lower(),
- 'from': fromAdd.lower(),
- 'to': decodeInput['dst'].lower(),
- 'amount': decodeInput['wad']})
- if str(functionInput) == '<Function transferFrom(address,address,uint256)>':
- #printTime(toAdd, decodeInput['src'], decodeInput['dst'], decodeInput['wad'])
- tradeInfo.append({
- 'token': toAdd.lower(),
- 'from': decodeInput['src'].lower(),
- 'to': decodeInput['dst'].lower(),
- 'amount': decodeInput['wad']})
- #print(functionInput, decodeInput, toAdd, outPut)
- except:
- #print('err', inputData, toAdd)
- continue
- return tradeInfo
- def decodeOutput(self, outputData):
- info = []
- outputData = outputData[2:]
- i = 0
- iMax = len(outputData) / 64
- while i < iMax:
- r = outputData[(0 + 64 * i):(64 + 64 * i)]
- if int(r[:24], 16) == 0 and int(r[24:28], 16) != 0:
- r = '0x' + r[24:]
- else :
- r = int(r, 16)
- info.append(r)
- i = i + 1
- return info
- def transferDecodeFromCalldata(self, calldata):
- tradeInfo = []
- for call in (calldata):
- if 'calls' in call:
- tradeInfo = tradeInfo + self.transferDecodeFromCalldata(call['calls'])
- inputData = call['input']
- function = inputData[0:10]
- toAdd = call['to']
- fromAdd = call['from']
- if 'value' in call:
- value = int(call['value'],16)
- if value != 0 :
- tradeInfo.append({
- 'token': '0xethw',
- 'from': fromAdd.lower(),
- 'to': toAdd.lower(),
- 'amount': value})
- try:
- #'<Function transferFrom(address,address,uint256)>'
- if function == '0x23b872dd':
- tradeInfo.append({
- 'token':toAdd,
- 'from':'0x' + inputData[34:74],
- 'to': '0x' + inputData[34 + 64:74+ 64],
- 'amount':int(inputData[34 + 64 *2 :74+ 64 *2 ],16)})
- #'<Function transfer(address,uint256)>'
- if function == '0xa9059cbb':
- tradeInfo.append({
- 'token':toAdd,
- 'from':fromAdd,
- 'to': '0x' + inputData[34 :74],
- 'amount':int(inputData[34 + 64 :74+ 64],16)})
- except:
- print('trace err', inputData)
- return tradeInfo
- def transferDecodeHashFromLogs(self, hs):
- r = w3.eth.getTransactionReceipt(hs)
- tradeInfo = []
- for logI in r['logs']:
- toAdd = logI['address'].lower()
- data = logI['data']
- if len(logI['topics']) == 3 and logI['topics'][0].hex() == '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef':
- tradeInfo.append({
- 'token':toAdd,
- 'from':'0x' + logI['topics'][1].hex()[26:],
- 'to': '0x' + logI['topics'][2].hex()[26:],
- 'amount':int(data,16)})
- if len(logI['topics']) == 2 and logI['topics'][
- 0].hex() == '0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c':
- tradeInfo.append({
- 'token': '0xeth',
- 'from': '0x',
- 'to': '0x' + logI['topics'][1].hex()[26:],
- 'amount': int(data, 16)})
- if len(logI['topics']) == 2 and logI['topics'][
- 0].hex() == '0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65':
- tradeInfo.append({
- 'token': '0xeth',
- 'from': '0x',
- 'to': '0x' + logI['topics'][1].hex()[26:],
- 'amount': int(data, 16)})
- return tradeInfo
- def transferDecodeHashFromTrace2(self, data):
- tradeInfo = []
- for call in data:
- try:
- if 'calls' in call:
- tradeInfoi = self.transferDecodeHashFromTrace2(call['calls'])
- if tradeInfoi:
- tradeInfo = tradeInfo + tradeInfoi
- inputData = call['input']
- function = inputData[0:10]
- callType = call['type']
- toAdd = call['to']
- value = int(call['value'],16)
- fromAdd = call['from']
- if value > 1e9:
- tradeInfo.append({
- 'token': '0xethw',
- 'from': fromAdd.lower(),
- 'to': toAdd.lower(),
- 'amount': value})
- continue
- functionInput, decodeInput = self.decodeContract.decode_function_input(inputData)
- outPut = self.decodeOutput(call['output'])
- if str(functionInput) == '<Function transfer(address,uint256)>':
- tradeInfo.append({
- 'token': toAdd.lower(),
- 'from': fromAdd.lower(),
- 'to': decodeInput['dst'].lower(),
- 'amount': decodeInput['wad']})
- if str(functionInput) == '<Function transferFrom(address,address,uint256)>':
- #print(toAdd, decodeInput['src'], decodeInput['dst'], decodeInput['wad'])
- tradeInfo.append({
- 'token': toAdd.lower(),
- 'from': decodeInput['src'].lower(),
- 'to': decodeInput['dst'].lower(),
- 'amount': decodeInput['wad']})
- if str(functionInput) == '<Function withdraw(uint256)>':
- #print(toAdd, decodeInput['src'], decodeInput['dst'], decodeInput['wad'])
- tradeInfo.append({
- 'token': toAdd.lower(),
- 'from': fromAdd.lower(),
- 'to': toAdd.lower(),
- 'amount': decodeInput['wad']})
- except:
- continue
- return tradeInfo
- def transferDecodeHashFromTrace(self, hs):
- try:
- r = self.traceTransaction(hs)
- tradeInfo = []
- value = int(r['value'], 16)
- fromAdd = r['from']
- toAdd = r['to']
- if value > 1e9:
- tradeInfo.append({
- 'token': '0xethw',
- 'from': fromAdd.lower(),
- 'to': toAdd.lower(),
- 'amount': value})
- if 'calls' in r:
- tradeInfo = tradeInfo + self.transferDecodeFromCalldata(r['calls'])
- return tradeInfo
- except:
- return []
- class dex():
- def __init__(self):
- toolsddress = '0xDE93d2cd45b7E0056671A542FfB4343DFd67dA51'
- toolsAbi = json.loads(open('abi/tools.json').read())
- self.abi = toolsAbi
- self.contractAddress = w3.toChecksumAddress(toolsddress)
- self.contract = w3.eth.contract(address=self.contractAddress, abi=self.abi)
- def getTokenBalance(self, address, token, block = 'latest'):
- address = address.replace('0x', '')
- data = "0x70a08231000000000000000000000000" + address
- r = web3Call(myAddress, token, data, block)
- r = int(r, 16)
- return r
- def getERC20Info(self, address):
- address = w3.toChecksumAddress(address)
- abi = json.loads(open('abi/ERC20.json').read())
- contractAddress = w3.toChecksumAddress(address)
- contract = w3.eth.contract(address=contractAddress, abi=abi)
- decimals = contract.functions.decimals().call()
- name = contract.functions.name().call()
- symbol = contract.functions.symbol().call()
- try:
- name = re.sub(r'[^A-Za-z0-9 ]+', '', name)
- except:
- name = 'T' + address[2:6]
- try:
- symbol = re.sub(r'[^A-Za-z0-9 ]+', '', symbol)
- except:
- symbol = 'T' + address[2:6]
- return {'name': name, 'symbol': symbol, 'decimals': decimals}
- def getFactory(self, address, block = 'latest'):
- address = w3.toChecksumAddress(address)
- info = self.contract.functions.getFactory(address).call(block_identifier = block)
- return info
- def getTotalPairV2(self, address, block = 'latest'):
- address = w3.toChecksumAddress(address)
- info = self.contract.functions.getTotalPair(address,).call(block_identifier = block)
- return info
- def getPairAddSV2(self, factoryAddr, token0, token1, block = 'latest'):
- addressNew = factoryAddr
- data = {}
- inputData = '0x8979b282' + encodeInput(0x60, token0, token1, addressNew)
- info = web3Call(toolsAddress, toolsAddress, inputData, block)
- info = w3.debug.decodeOutput(info)
- for i in range(0, len(addressNew)):
- fee = topFactoryFee[addressNew[i].lower()]
- address = info[i + 2]
- if address == 0:
- continue
- data[address] = fee
- return data
- def getPairFromIdSInfoV2(self, facrotyAddress, ids, block = 'latest'):
- facrotyAddress = w3.toChecksumAddress(facrotyAddress)
- info = self.contract.functions.getPairIdSInfo(facrotyAddress, ids).call(block_identifier = block)
- return info
- def getPairSBalance(self, addressNew, block = 'latest'):
- inputData = '0xd94ccee1' + encodeInput(0x20, addressNew)
- r = web3Call(myAddress, toolsAddress, inputData, block)
- r = w3.debug.decodeOutput(r)
- info = {}
- length = len(addressNew)
- for index in range(0, length):
- lpAddress = addressNew[index]
- r0 = r[index + 3]
- r1 = r[index + 4 + length]
- info[lpAddress] = [r0, r1]
- return info
- def getPairAddV3AllFee(self, token0Address , token1Address, block = 'latest'):
- fee = [100,500,3000,10000]
- data = {}
- token0Address = w3.toChecksumAddress(token0Address)
- token1Address = w3.toChecksumAddress(token1Address)
- for feeI in fee:
- try:
- info = self.contract.functions.getPoolV3(token0Address, token1Address, feeI).call(block_identifier = block)
- if info != '0x0000000000000000000000000000000000000000':
- data[info] = feeI
- except:
- info = '0x'
- return data
- def getPairAddV3(self, token0Address, token1Address, fee, block = 'latest'):
- token0Address = w3.toChecksumAddress(token0Address)
- token1Address = w3.toChecksumAddress(token1Address)
- info = self.contract.functions.getPoolV3(token0Address, token1Address, fee).call(block_identifier = block)
- return info
- def getPairInfoFromIdV3(self, ids, block = 'latest'):
- info = self.contract.functions.getPairInfoV3(ids).call(block_identifier = block)
- return info
- def getAmountOutV3(self, tokenIn, tokenOut, fee, amountIn, block = 'latest'):
- tokenIn = w3.toChecksumAddress(tokenIn)
- tokenOut = w3.toChecksumAddress(tokenOut)
- fee = int(fee)
- amountIn = int(amountIn)
- try:
- info = self.contract.functions.getAmountOutV3(tokenIn, tokenOut, fee, amountIn, 0).call(block_identifier = block)
- except:
- info = 0
- return info
- def getAmountInV3(self, tokenIn, tokenOut, fee, amountOut, block = 'latest'):
- tokenIn = w3.toChecksumAddress(tokenIn)
- tokenOut = w3.toChecksumAddress(tokenOut)
- fee = int(fee)
- amountOut = int(amountOut)
- try:
- info = self.contract.functions.getAmountOutV3(tokenIn, tokenOut, fee, amountOut, 0).call(block_identifier = block)
- except:
- info = 0
- return info
- class new():
- def resultManager(self, result):
- if 'error' in result:
- raise NameError(result['error'])
- if 'result' in result:
- return result['result']
- return False
- def getBlock(self, blockNumber = 'pending', state = False):
- if blockNumber == 'pending' or blockNumber == 'latest':
- blockNumber = blockNumber
- elif type(blockNumber) == str and blockNumber[:2] != '0x':
- blockNumber = int(blockNumber)
- elif type(blockNumber) == int:
- blockNumber = hex(blockNumber)
- r = w3.provider.make_request('eth_getBlockByNumber', params=[blockNumber, state])
- return self.resultManager(r)
- def getTransaction(self, hash):
- r = w3.provider.make_request('eth_getTransactionByHash', params=[hash])
- return self.resultManager(r)
- def getTransactionReceipt(self, hash):
- r = w3.provider.make_request('eth_getTransactionReceipt', params=[hash])
- return self.resultManager(r)
- def blcokNumber(self):
- r = w3.provider.make_request('eth_blockNumber', params=[])
- return int(self.resultManager(r),16)
- def sendTransaction(self, fromAdd, toAdd, inputData, nonce, gasPrice, gasLimit):
- params = {}
- params['from'] = fromAdd
- params['to'] = toAdd
- params['data'] = inputData
- params['nonce'] = hex(int(nonce))
- params['gasPrice'] = hex(int(gasPrice))
- params['gas'] = hex(int(gasLimit))
- params['value'] = hex(0)
- params['chainId'] = hex(10001)
- r = w3.provider.make_request('eth_sendTransaction', params=[params])
- try:
- hs = self.resultManager(r)
- printTime('https://www.oklink.com/en/ethw/tx/' + str(hs))
- return str(hs)
- except BaseException as err:
- printTime('sendTransaction err', params['from'], params['nonce'], err)
- return False
- def getTransactionCount(self, address, blockNumber = "latest"):
- r = w3.provider.make_request('eth_getTransactionCount', [address, blockNumber])
- return self.resultManager(r)
- def getPendingTxpool():
- try:
- data = json.dumps({
- 'jsonrpc': '2.0',
- 'method': 'txpool_content',
- 'params': [],
- 'id': int(time.time() * 1000)
- })
- headers = {'Content-type': 'application/json'}
- rspnow = requests.post(url, data=data, headers=headers).json()
- transactionArray = []
- for x in rspnow['result']['pending']:
- addressTransaction = (rspnow['result']['pending'][x])
- for addressTransactioni in addressTransaction.values():
- transactionArray.append(addressTransactioni)
- return transactionArray
- except BaseException as err:
- print(traceback.format_exc())
- print(err)
- def getBaseGasPrice(blockNumber = 'pending'):
- try:
- return int(w3.new.getBlock(blockNumber)['baseFeePerGas'],16)
- except:
- return w3.eth.gasPrice
- def getTokenTradeFromBlock(blockNumber):
- tokenArray = []
- info = w3.eth.getBlock(blockNumber, True)
- info = (info['transactions'])
- for hsI in info:
- try:
- hsInfo = {}
- hsInfo['block'] = hsI['blockNumber']
- hsInfo['gasUsed'] = hsI['gas']
- hsInfo['fromAdd'] = hsI['from'].lower()
- hsInfo['toAdd'] = str(hsI['to']).lower()
- hsInfo['input'] = hsI['input']
- hsInfo['value'] = hsI['value']
- hsInfo['nonce'] = hsI['nonce'] # 对比nonce
- hsInfo['function'] = hsInfo['input'][:10]
- hsInfo['hs'] = hsI['hash'].hex()
- # 创建合约
- if hsInfo['gasUsed'] < 90000:
- continue
- if hsInfo['function'] == '0x77c46431' or hsInfo['function'] == '0x60806040':
- continue
- if hsInfo['input'] == '0x':
- continue
- if len(hsInfo['input']) < 76:
- continue
- if len(hsInfo['input']) > 64 * 64:
- continue
- # opensea
- if hsInfo['toAdd'] == '0x00000000006c3852cbef3e08e8df289169ede581':
- continue
- # X2Y2
- if hsInfo['toAdd'] == '0x74312363e45dcaba76c59ec49a7aa8a65a67eed3':
- continue
- tradeInfo = w3.debug.transferDecodeHashFromLogs(hsInfo['hs'])
- #tradeInfo = w3.debug.transferDecodeHashFromTrace(hsInfo['hs'])
- if tradeInfo:
- # 进行了token交易或者转载两次
- if len(tradeInfo) < 2:
- continue
- # 是否来来回交易
- tokenAyyay = []
- tradeType = False
- for tradeI in tradeInfo:
- token = tradeI['token']
- fromAdd = tradeI['from']
- to = tradeI['to']
- if token not in tokenAyyay:
- tokenAyyay.append(token)
- for tradeII in tradeInfo:
- fromAddI = tradeII['from']
- toI = tradeII['to']
- if fromAdd == toI or to == fromAddI:
- tradeType = True
- break
- if not tradeType:
- continue
- # 是否有两个币交易过
- if len(tokenAyyay) < 2:
- continue
- for tradeI in tradeInfo:
- token = tradeI['token']
- if token == '0xeth':
- continue
- if token in tokenArray:
- continue
- tokenArray.append(token)
- except BaseException as err:
- continue
- return tokenArray
- def web3Call(fromAddress, toAddress = None, inputData = None, blockNumber = 'latest'):
- if type(fromAddress) == dict:
- input = fromAddress
- else:
- input = {'from': fromAddress, 'to':toAddress, 'data':inputData}
- if type(blockNumber) == int:
- blockNumber = hex(blockNumber)
- r = w3.provider.make_request('eth_call', params=[input, blockNumber])
- if 'result' in r:
- return r['result']
- else:
- raise NameError(r)
- def encodeInput(*array):
- data = ''
- for i in array:
- if type(i) == str:
- if len(i) > 64:
- i = i.replace('0x', '')
- times = int(len(i) / 64 ) + 1
- i = i.ljust(64*times, '0')
- else:
- i = i.replace('0x', '').rjust(64, '0')
- data = data + i
- elif type(i) == int:
- i = hex((i)).replace('0x', '').rjust(64, '0')
- data = data + i
- elif type(i) == float:
- i = hex(int(i)).replace('0x', '').rjust(64, '0')
- data = data + i
- elif type(i) == list:
- data = data + hex(len(i)).replace('0x', '').rjust(64, '0')
- for j in i:
- data = data + encodeInput(j)
- return data
- def encodeFunction( string):
- string = w3.toBytes(text=string)
- string = w3.sha3(string)
- string = w3.toHex(string)
- string = string[:10]
- return string
- def batchCall(paramsDataArray ,blockNumber = 'latest'):
- if blockNumber == 'pending' or blockNumber == 'latest':
- blockNumber = blockNumber
- elif type(blockNumber) == str and blockNumber[:2] != '0x':
- blockNumber = int(blockNumber)
- elif type(blockNumber) == int:
- blockNumber = hex(blockNumber)
- if type(paramsDataArray) != list:
- paramsDataArray = [paramsDataArray]
- r = w3.provider.make_request('eth_batchCall', [{"Block": blockNumber, "Calls": paramsDataArray}])
- return r
- def decodeBatchCall(result):
- info = []
- for i in result:
- if 'Return' in i:
- info.append(w3.debug.decodeOutput(i['Return']))
- return info
- #url = 'http://3.227.34.41:18545'
- #w3 = Web3(WebsocketProvider('ws://127.0.0.1:8546'))
- w3= Web3(IPCProvider('/ethereum_pow_800/data/geth.ipc'))
- attach_modules(w3, {"debug": (debug,)})
- attach_modules(w3, {"dex": (dex,)})
- attach_modules(w3, {"new": (new,)})
- printTime('Web3:OK', )
- printTime('Now Block Number:', w3.eth.blockNumber, 'Now Gas:', getBaseGasPrice())
|