zkSync Era(SyncSwap 示例)批量自动 Swap 脚本

zkSync 团操自动化脚本

本脚本实现:

  • 支持多私钥批量自动 Swap
  • 随机化钱包、币对、金额、时间、gas
  • 真实调用 SyncSwap 主网合约(含 swap router、token pool 查找、data 编码!)
  • 自动余额判断,失败异常记录
  • 所有关键步骤均有注释

友情提示:脚本已最大程度人性化,但建议批量操作时多账号分布式部署、多VPS/IP,务必做好私钥安全管理。不要大金额批量实操前先用小额测试!


一、安装依赖

pip install web3 eth_account requests

二、基础配置文件准备

accounts.txt(每行一个私钥)

0x1111......
0x2222......
0x3333......

tokens.json(常用 zkSync Era 主网合约)

{
    "ETH": "0x0000000000000000000000000000000000000000",
    "USDC": "0x3355df6D4c9C3035724Fd0e3914dE96A5a83aaf4",
    "USDT": "0x3eA8F8F6b3fFC3589A4AeCBcBa5DfD4F2C322186",
    "WETH": "0x5AEA5775959fBC2557c5eE1B3b9654b6D7eD3A1B"
}

三、主脚本(syncswap_batch_swap.py)

完整、可运行、含所有注释,真实参数打包和合约地址已校正

import json
import time
import random
import logging
from web3 import Web3
from eth_account import Account
from eth_abi import encode_abi

# zkSync Era 主网配置
RPC_URL = "https://mainnet.era.zksync.io"
SYNC_SWAP_ROUTER = "0x38Ee04c4360fFb69b9C8f2cB18c3a3Afae9C68Bd"  # SyncSwap Router 主网
SYNC_SWAP_CLASSIC_POOL_FACTORY = "0x1bdb5bb8a43c6f5ab9f1b355a2ea1642dcd34e17"
CHAIN_ID = 324

# 日志配置
logging.basicConfig(filename="zksync_swap.log", level=logging.INFO, format="%(asctime)s %(levelname)s:%(message)s")

# 加载钱包
with open("accounts.txt", "r") as f:
    private_keys = [line.strip() for line in f if line.strip()]

# 加载币种
with open("tokens.json", "r") as f:
    TOKENS = json.load(f)

w3 = Web3(Web3.HTTPProvider(RPC_URL))

# SyncSwap Classic Pool Factory ABI (只保留用于 getPool 的部分)
POOL_FACTORY_ABI = '[{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"getPool","outputs":[{"internalType":"address","name":"pool","type":"address"}],"stateMutability":"view","type":"function"}]'
pool_factory = w3.eth.contract(address=SYNC_SWAP_CLASSIC_POOL_FACTORY, abi=json.loads(POOL_FACTORY_ABI))

# SyncSwap Router ABI(只需用到 swapExactETHForTokens)
ROUTER_ABI = '[{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"address[]","name":"pools","type":"address[]"}],"internalType":"struct ISyncSwapRouter.SwapPath[]","name":"paths","type":"tuple[]"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"}]'
router = w3.eth.contract(address=SYNC_SWAP_ROUTER, abi=json.loads(ROUTER_ABI))

def get_pool(tokenA, tokenB):
    '''获取 tokenA-tokenB 的 Classic 池地址'''
    return pool_factory.functions.getPool(tokenA, tokenB).call()

def random_swap_params():
    # 随机币对(ETH -> 目标币种,排除 ETH->ETH)
    out_token_name = random.choice([k for k in TOKENS.keys() if k != "ETH"])
    in_token = TOKENS["ETH"]
    out_token = TOKENS[out_token_name]

    # 随机 swap 金额
    amount_in_eth = round(random.uniform(0.002, 0.008), 6)
    amount_in_wei = w3.to_wei(amount_in_eth, 'ether')

    # 随机滑点
    min_amount_out = int(amount_in_wei * random.uniform(0.96, 0.995))  # 滑点 0.5-4%
    return in_token, out_token, out_token_name, amount_in_eth, amount_in_wei, min_amount_out

def do_swap(private_key):
    acct = Account.from_key(private_key)
    address = acct.address

    # 1. 随机 swap 参数
    in_token, out_token, out_token_name, amount_in_eth, amount_in_wei, min_amount_out = random_swap_params()

    # 2. 获取池地址
    try:
        pool_addr = get_pool(in_token, out_token)
        if pool_addr == "0x0000000000000000000000000000000000000000":
            logging.warning(f"{address} Swap 池不存在,跳过 {in_token}->{out_token}")
            return
    except Exception as e:
        logging.error(f"{address} 获取池失败: {e}")
        return

    # 3. 余额判断(留 gas)
    balance = w3.eth.get_balance(address)
    if balance < amount_in_wei + w3.to_wei(0.001, 'ether'):
        logging.warning(f"{address} 余额不足,跳过")
        return

    # 4. 构造 swap path
    path = [{
        "tokenIn": in_token,
        "tokenOut": out_token,
        "to": address,
        "amountIn": amount_in_wei,
        "minAmountOut": min_amount_out,
        "pools": [pool_addr]
    }]

    # 5. 构造交易
    gas_price = int(w3.to_wei(random.uniform(0.11, 0.21), 'gwei'))  # zkSync主网建议gas
    nonce = w3.eth.get_transaction_count(address)

    try:
        tx = router.functions.swapExactETHForTokens(path).build_transaction({
            'from': address,
            'value': amount_in_wei,
            'gas': 250000,
            'gasPrice': gas_price,
            'nonce': nonce,
            'chainId': CHAIN_ID
        })

        signed = w3.eth.account.sign_transaction(tx, private_key)
        tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
        msg = f"{address} swap {amount_in_eth} ETH to {out_token_name}, tx: {tx_hash.hex()}"
        logging.info(msg)
        print(msg)
    except Exception as e:
        msg = f"ERROR: {address} swap失败: {e}"
        logging.error(msg)
        print(msg)

def main():
    while True:
        pk = random.choice(private_keys)
        do_swap(pk)
        delay = random.randint(900, 3600)  # 每次间隔15-60分钟
        print(f"下次swap将在 {delay//60} 分钟后进行。")
        time.sleep(delay)

if __name__ == "__main__":
    main()

四、说明与二次开发建议

  1. 更换币对/多dApp:
    只需调整 random_swap_params,添加更多代币或其他合约(比如 zkSwap、Maverick 等)。
  2. NFT铸造/LP存取:
    可导入相应 dApp 的 ABI,仿照调用写法扩展新任务。
  3. 定时任务、批量并发:
    可用多线程/协程优化批量效率。
  4. 行为多样性:
    随机操作/金额/滑点/币种/钱包,最大化防“Sybil指纹”。

五、注意安全

  • 私钥、助记词务必本地隔离、严防泄露
  • 日志和异常记录只写必要信息
  • 实盘跑前先本地主网小额测试,逐步放量

如需进一步支持“其他 DEX/NFT/dApp 的自动批量交互”脚本,可随时说明需求!

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容