paymaster 允许用非eth作为 gas, 在mute 里面做swap 交易
逐步解释下代码的功能和行为:
1. 导入所需的模块和库:代码开始处导入了一些所需的模块和库,包括`zksync2`、`web3`、`eth_account`等。
2. 定义`mute_paymaster`函数:这个函数包含了一系列的操作步骤。
3. 通过`ZkSyncBuilder.build`构建`zk_web3`对象:使用`ZkSyncBuilder.build`方法创建了一个`zk_web3`对象,用于与 ZkSync 网络进行交互。
4. 通过私钥创建`account`对象:使用给定的私钥创建了一个`account`对象,用于进行以太坊账户相关的操作。
5. 定义了`weth`和`usdc`变量:这两个变量分别存储了 WETH 和 USDC 的地址值。
6. 定义了`paymaster_address`和`routerAddress`变量:这两个变量分别存储了 Paymaster 和 Router 的地址值。
7. 进入一个无限循环,直到成功获取 USDC 余额:使用`get_balance`函数获取 USDC 的余额,如果出现异常则继续尝试获取,直到成功为止。
8. 根据 USDC 余额判断是否进行后续操作:如果 USDC 余额大于2,则继续进行后续操作,否则打印余额不足的提示信息并返回。
9. 调用`token_approve_query`函数查询代币授权额度:该函数用于查询指定代币的授权额度。
10. 判断授权额度是否满足交易金额:如果授权额度小于交易金额,则进入授权过程;否则打印授权额度充足的提示信息。
11. 进入授权过程:使用`token_aprove`函数进行代币授权,并通过`eth_wait_for_transaction_receipt`方法等待交易完成。
12. 构建交易的`calldata`:根据一系列规则和变量值构建了交易的`calldata`。
13. 定义`paymaster_params`对象:根据给定的参数构建了一个`paymaster_params`对象。
14. 定义`chain_id`、`gas_price`和`signer`对象:分别定义了链ID、燃料价格和签名者对象。
15. 定义`tx_func_call`对象:使用各种参数构建了一个`TxFunctionCall`对象,用于表示交易的各种属性和参数。
16. 预估交易的燃料费用:使用`zk_web3.zksync.eth_estimate_gas`方法预估了交易的燃料费用。
17. 将交易转换为 EIP-712 格式:使用`tx_func_call.tx712`将交易转换为 EIP-712 格式的消息。
18. 签名消息并进行编码:使用私钥对消息进行签名,并进行编码。
19. 发送原始交易:使用`zk_web3.zksync.send_raw_transaction`方法发送原始交易。
20. 等待交易被打包进块:使用`zk_web3.zksync.wait_for_transaction_receipt`方法等待交易被打包进块,并获取交易的收据。
21. 打印交易状态:打印交易的状态(成功或失败)。
涵盖了一系列的操作,包括获取代币余额、授权代币、构建交易参数、估算燃料费用、签名交易、发送交易等。
from zksync2.core.types import EthBlockParams, PaymasterParams
from zksync2.manage_contracts.paymaster_utils import PaymasterFlowEncoder
from zksync2.module.module_builder import ZkSyncBuilder
from zksync2.signer.eth_signer import PrivateKeyEthSigner
from zksync2.transaction.transaction_builders import TxFunctionCall
from web3 import Web3,constants
from eth_account import Account
def mute_paymaster():
print('mute_paymaster')
try:
zk_web3 = ZkSyncBuilder.build('https://1rpc.io/zksync2-era')
account = Account.from_key(private_key)
weth=Web3.to_checksum_address('0x5aea5775959fbc2557cc8789bc1bf90a239d9a91')
usdc=Web3.to_checksum_address('0x3355df6D4c9C3035724Fd0e3914dE96A5a83aaf4')
paymaster_address = zk_web3.to_checksum_address("0x4ae2Ba9A5C653038C6d2F5D9F80B28011A454597")
routerAddress=Web3.to_checksum_address('0x8B791913eB07C32779a16750e3868aA8495F5964')
#先查询USDC余额
while True:
try:
amount1,balance_token=get_balance(usdc,ABI,from_address)
break
except:
pass
if balance_token>2:
amountin=int(amount1-2000000)
else:
print(f'USDC余额{balance_token},不太足')
return
appove_value=token_approve_query(usdc,ABI,from_address,routerAddress)
if appove_value<amountin:
print('授权额度不够,准备授权')
while True:
try:
result=token_aprove(usdc,ABI,routerAddress,from_address,private_key,chainId=chainId)
time.sleep(5)
#response=w3.eth.wait_for_transaction_receipt(result['txn_hash'])
response=w3.eth.get_transaction_receipt(result['txn_hash'])
#print(f'----------{response.status}')
if response.status==1:
print('----确认代币授权成功----')
time.sleep(5)
break
else:
print('失败,重来')
except:
pass
else:
print("授权额度充足,无需授权")
#USDC换ETH,构建calldata
method='0xacc8723d'
data1=Web3.to_hex(amountin)[2:].rjust(64,'0')+'0000000000000000000000000000000000000000000000000000000000000000'#获得这个输出数量太难了。
data2='00000000000000000000000000000000000000000000000000000000000000c0'
data3=from_address[2:].rjust(64,'0')
data4=Web3.to_hex(int(time.time())+1800)[2:].rjust(64,'0')
data5='0000000000000000000000000000000000000000000000000000000000000120'+'0000000000000000000000000000000000000000000000000000000000000002'
data6=usdc[2:].rjust(64,'0')
data7=weth[2:].rjust(64,'0')
data8='0000000000000000000000000000000000000000000000000000000000000002'+'0000000000000000000000000000000000000000000000000000000000000001'+'0000000000000000000000000000000000000000000000000000000000000000'
calladata=method+data1+data2+data3+data4+data5+data6+data7+data8
print('构建calldata成功')
paymaster_params = PaymasterParams(**{
"paymaster": paymaster_address,
"paymaster_input": zk_web3.to_bytes(hexstr='0x949431dc0000000000000000000000003355df6d4c9c3035724fd0e3914de96a5a83aaf4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000')
})
chain_id = zk_web3.zksync.chain_id
gas_price = zk_web3.zksync.gas_price
signer = PrivateKeyEthSigner(account, chain_id)
tx_func_call = TxFunctionCall(
chain_id=zk_web3.zksync.chain_id,
nonce=zk_web3.zksync.get_transaction_count(account.address, EthBlockParams.LATEST.value),
from_=account.address,
to=routerAddress,
data=calladata.lower(),
gas_limit=0, # Unknown at this state, estimation is done in next step
gas_price=gas_price,
max_priority_fee_per_gas=100_000_000,
paymaster_params=paymaster_params
)
# ZkSync transaction gas estimation
try:
estimate_gas = zk_web3.zksync.eth_estimate_gas(tx_func_call.tx)
print('预估gas:',estimate_gas)
except Exception as e:
print('预估gas出错,设置成3000000')
estimate_gas=3000000
#print(f"Fee for transaction is: {estimate_gas * gas_price}")
# Convert transaction to EIP-712 format
tx_712 = tx_func_call.tx712(estimate_gas)
# Sign message & encode it
signed_message = signer.sign_typed_data(tx_712.to_eip712_struct())
# Encode signed message
msg = tx_712.encode(signed_message)
# Transfer ETH
tx_hash = zk_web3.zksync.send_raw_transaction(msg)
print(f"Transaction hash is : {tx_hash.hex()}")
# Wait for transaction to be included in a block
tx_receipt = zk_web3.zksync.wait_for_transaction_receipt(
tx_hash, timeout=240, poll_latency=0.5
)
print(f"Tx status: {tx_receipt['status']}")
except Exception as e:
print('swap失败')
return