3
fokus pada
1444
Pengikut

Cara menerapkan penempatan pesanan di bursa terdesentralisasi — Mengambil Curve sebagai contoh

Dibuat di: 2025-03-13 14:28:33, diperbarui pada: 2025-03-14 17:27:53
comments   1
hits   933

Mengapa harus memesan?

Di pasar mata uang kripto, peluang perdagangan sering kali cepat berlalu, terutama peluang arbitrase, yang mungkin hanya berlangsung selama beberapa menit. Jika Anda mengandalkan operasi manual, pengguna mungkin tidak dapat memanfaatkan peluang terbaik pada waktunya atau kehilangan harga terbaik. Misalnya, beberapa waktu lalu, karena serangan peretas terhadap Bybit, USDe dipisahkan, yang menyebabkan harganya berfluktuasi drastis. Pada saat itu, tingkat pengembalian tahunan melalui pembelian sUSDe dan penebusannya melebihi 300%. Jendela hasil tinggi ini biasanya berlangsung dalam jangka waktu yang sangat singkat, dan sulit bagi perdagangan manual untuk mengikuti ritme pasar tanpa menetapkan pesanan terlebih dahulu. Oleh karena itu, fungsi penempatan pesanan telah menjadi alat penting bagi pengguna bursa terdesentralisasi (DEX), yang secara signifikan meningkatkan efisiensi transaksi.

Prinsip dan kekurangan perintah DEX

Beberapa DEX menawarkan fungsionalitas limit order, masing-masing dengan implementasi dan struktur biaya yang berbeda. Ambil Cow Swap dan Odos sebagai contoh. Prinsip intinya adalah menggunakan fungsi agregatornya untuk memantau likuiditas dan harga berbagai DEX secara real-time. Ketika harga pasar memenuhi kondisi batas, pesanan akan dipicu oleh pengambil, dan kontrak pintar akan secara otomatis mengeksekusi transaksi dan membayar biaya gas. Cow juga menyimpan pesanan pengguna di luar rantai, yang kemudian dicocokkan secara kompetitif oleh sekelompok node terdesentralisasi yang disebut “Solvers,” tetapi pada akhirnya dieksekusi di dalam rantai. Singkatnya, meskipun GAS dikecualikan, laba ekstra yang dihasilkan oleh transaksi yang diselesaikan oleh DEX ini untuk Anda dapat menutupi biaya GAS.

Namun, hal ini menimbulkan masalah: jika salah satu pesanan Anda tertunda pada harga 90U dan agregator memantau bahwa harga DEX tertentu telah turun menjadi 80U, maka agregator akan mengeksekusi transaksi untuk Anda. Pesanan Anda akhirnya dieksekusi pada harga 90U, menghasilkan laba sebesar 10U. Bagaimana laba ini didistribusikan? Dalam pengoperasian sesungguhnya, berbagai platform menanganinya secara berbeda. Mengambil Cow Swap sebagai contoh, mekanismenya dengan jelas menetapkan bahwa ketika harga eksekusi lebih baik daripada harga batas, surplus yang dihasilkan (yaitu, 10U) akan dibagi antara platform dan pengguna, dengan Cow Swap mengambil 50% dan pengguna mendapatkan sisanya 50%. Odos akan menyetorkan kelebihannya ke kas negara. Intinya, pesanan Anda diarbitrasekan bebas risiko oleh bursa DEX.

Selain itu, untuk menghemat biaya transaksi, pesanan DEX merupakan transaksi agregat, yaitu banyak transaksi dikemas bersama-sama setiap saat, dan ETH memiliki blok 12 detik, yang akan mengakibatkan hilangnya beberapa peluang yang mungkin terjadi. Tentu saja, DEX masih memiliki banyak kelebihan, seperti pencarian lebih banyak jalur, pencocokan offline, penghematan GAS, dan lain sebagainya, yang sudah cukup bagi sebagian besar pengguna.

Keuntungan memesan dengan program Anda sendiri

Dibandingkan dengan mengandalkan pesanan agregat DEX, perdagangan langsung melalui kontrak pintar memiliki keunggulan yang unik. Pertama, pengguna memiliki kontrol penuh atas logika eksekusi order dan semua perolehan. Kedua, menempatkan pesanan Anda sendiri menghindari penundaan pengemasan transaksi agregat dan dapat merespons perubahan pasar lebih cepat, terutama memanfaatkan peluang dalam waktu 12 detik selama volatilitas tinggi. Selain itu, pending order khusus dapat secara fleksibel mengatur kondisi yang kompleks (seperti perdagangan portofolio multi-aset atau stop profit dan stop loss) tanpa dibatasi oleh fungsi yang telah ditetapkan pada platform. Namun, hal ini memerlukan keterampilan pemrograman tertentu, dan seseorang perlu membayar biaya gas sendiri, dan mungkin ada risiko keamanan pada rantai tersebut. Oleh karena itu, menempatkan pesanan sendiri cocok untuk pengguna tingkat lanjut yang memiliki kemampuan teknis kuat dan mengejar keuntungan maksimal.

Perlindungan kunci pribadi

Jika Anda ingin mengoperasikan kontrak pintar dengan program Anda sendiri, keamanan kunci pribadi Anda tidak diragukan lagi merupakan perhatian terbesar Anda. Solusi yang saya temukan adalah menggunakan Python untuk mengenkripsi kunci pribadi saya secara offline, dan menyimpan ciphertext terenkripsi pada server yang menjalankan host. Kata sandi yang didekripsi diteruskan menggunakan parameter robot platform FMZ, dan program berjalan pada host dan membaca serta mendekripsinya (dapat dihapus setelah program berjalan). Dengan cara ini, meskipun server Anda diretas, tidak akan ada masalah, tetapi Anda tetap harus berhati-hati agar tidak membocorkan akun FMZ Anda. Karena hanya melibatkan satu plaintext di luar jaringan, keamanannya dapat diterima. Kode spesifiknya adalah sebagai berikut, yang dapat dijalankan secara lokal di luar jaringan

from web3 import Web3  # Web3.py 是与以太坊区块链交互的Python库
import json  # 用于处理JSON数据
import time  # 用于设置时间间隔
import requests  # 用于发送HTTP请求
from cryptography.fernet import Fernet
import base64
import hashlib
from datetime import datetime
from hexbytes import HexBytes

def generate_key(password: str) -> bytes:
    """通过用户密码生成 AES 密钥"""
    return base64.urlsafe_b64encode(hashlib.sha256(password.encode()).digest())

def encrypt_private_key(private_key: str, password: str) -> str:
    """使用密码加密私钥"""
    key = generate_key(password)
    cipher = Fernet(key)
    return cipher.encrypt(private_key.encode()).decode()

def decrypt_private_key(encrypted_key: str, password: str) -> str:
    """使用密码解密私钥"""
    key = generate_key(password)
    cipher = Fernet(key)
    return cipher.decrypt(encrypted_key.encode()).decode()

def save_key_to_file(key, file_path):
    # 将加密密钥保存到txt文件
    with open(file_path, 'w') as file:
        file.write(key) 

def load_key_from_file(file_path):
    # 从txt文件读取加密密钥
    with open(file_path, 'r') as file:
        return str(file.read())

def main():
    encrypt_key = encrypt_private_key('my_private_key', 'password') # my_private_key是自己的私钥,password是自己设置的密码
    save_key_to_file(encrypt_key,'encrypt_key.txt')
    print("加密后的私钥", encrypt_key)
    decrypt_key = decrypt_private_key(load_key_from_file('encrypt_key.txt'), 'password')
        print("解密的私钥", decrypt_key)

Persiapan sebelum menghubungkan ETH

Web3.py adalah pustaka Python yang canggih untuk berinteraksi dengan jaringan Ethereum. Instal dengan perintah berikut: pip install web3. Fungsinya adalah untuk menyederhanakan komunikasi antara pengembang dan node Ethereum, dan mendukung operasi seperti menanyakan saldo, memanggil kontrak pintar, dan mengirim transaksi. Misalnya, memeriksa saldo akun hanya membutuhkan beberapa baris kode, menjadikan Web3.py alat yang ideal untuk membangun DApps atau mengotomatiskan transaksi.

python
from web3 import Web3
w3 = Web3(Web3.HTTPProvider('你的RPC地址'))
balance = w3.eth.get_balance('0x某个地址')
print(w3.from_wei(balance, 'ether'))

RPC (Remote Procedure Call) adalah antarmuka komunikasi yang disediakan oleh node Ethereum, yang berinteraksi dengan blockchain dengan mengirimkan permintaan JSON melalui protokol HTTP atau WebSocket. Misalnya, eth_blockNumber dapat menanyakan tinggi blok terkini. Karena tingginya biaya menjalankan node lokal, pengembang biasanya mengandalkan penyedia RPC pihak ketiga. Pilihan umum meliputi:

  • Infura: Layanan bawaan MetaMask, mudah digunakan tetapi dengan kuota gratis rendah (100.000 permintaan per hari).
  • Alchemy: Performa unggul, kuota gratis tinggi, dan dukungan fitur lebih banyak.
  • QuickNode: Cocok untuk persyaratan kinerja tinggi, tetapi bias terhadap pengguna berbayar.
from web3 import Web3
w3 = Web3(Web3.HTTPProvider('https://eth-mainnet.g.alchemy.com/v2/你的API密钥'))
print(w3.is_connected())

Disarankan untuk menggunakan Alchemy. Dibandingkan dengan Infura milik MetaMask, Alchemy menyediakan kuota gratis yang lebih tinggi. Setelah registrasi, Anda bisa mendapatkan alamat RPC, seperti https://eth-mainnet.g.alchemy.com/v2/kunci API Anda, dan mengonfigurasinya ke Web3.py untuk digunakan.

Alamat kontrak kurva dan ABI

Mengambil kumpulan Crve dari sDAI/sUSDe sebagai contoh https://curve.fi/dex/ethereum/pools/factory-stable-ng-102/swap/, Anda dapat dengan mudah menemukan alamat kedua token dan alamat kumpulan tersebut. Cara menerapkan penempatan pesanan di bursa terdesentralisasi — Mengambil Curve sebagai contoh

ABI mendefinisikan cara berinteraksi dengan kontrak, jadi penting juga untuk mendapatkannya. Lihat kontrak di ethscan https://etherscan.io/address/0x167478921b907422f8e88b43c4af2b8bea278d3a#code. Anda dapat melihat abi di halaman kontrak dan menyalinnya secara langsung.

Tautkan kontrak untuk mendapatkan harga

Pertama, hubungkan dompet ETH. Jika alamat dompet Anda tercetak, berarti prosesnya berhasil.

def main():
    # 文件路径
    file_path = 'encrypted_key.txt'

    # 从文件中读取加密的私钥
    encrypted_private_key = load_key_from_file(file_path)
    private_key = decrypt_private_key(encrypted_private_key, Password) #Password为密码,定义为策略的参数
    web3 = Web3(Web3.HTTPProvider(HTTPProvider)) # HTTPProvider为RPC的链接,定义为参数
    account = web3.eth.account.from_key(private_key)
    address = account.address  # 获取账户的公开地址
    Log('链接账户', address)

Berikut ini adalah proses untuk mendapatkan harga. Terakhir, tanpa memperhitungkan biaya GAS, investasi saat ini sebesar 100.000 SDAI akan menghasilkan keuntungan sebesar 335U setelah satu minggu. Mungkin terlihat agak rumit, tetapi sebenarnya tidak sulit untuk dipahami.

    # --------------- 合约设置 ---------------
    # Curve.fi sDAI/sUSDe 池合约地址和ABI
    pool_address = '0x167478921b907422F8E88B43C4Af2B8BEa278d3A'  # Curve池子的合约地址
    # 以下是简化的ABI,仅包含我们需要的函数
    pool_abi = json.loads('''[{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]}]''')
    # 创建池子合约对象
    pool_contract = web3.eth.contract(address=pool_address, abi=pool_abi)

    # ERC20 代币标准合约ABI
    erc20_abi = json.loads('''[
        {"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"type":"function"},
        {"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"type":"function"},
        {"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"}
    ]''')

    sdai_address = '0x83F20F44975D03b1b09e64809B757c47f942BEeA'  # sDAI代币的合约地址
    susde_address = '0x9D39A5DE30e57443BfF2A8307A4256c8797A3497'  # sUSDE代币的合约地址
    # 池子中代币的索引
    SDAI_INDEX = 0  # sDAI代币在池子中的索引
    SUSDE_INDEX = 1  # sUSDE代币在池子中的索引
    # 创建代币合约对象
    sdai_contract = web3.eth.contract(address=sdai_address, abi=erc20_abi)
    susde_contract = web3.eth.contract(address=susde_address, abi=erc20_abi)
    SUSDE_PRICE = 1.1623 #这个价格是ethena官网价格,1周后可赎回
    SDAI_PRICE = 1.15 #sDAI是收益代币,价值会累计,目前价格1.15

    try:
        SDAI_DECIMALS = sdai_contract.functions.decimals().call()
        SUSDE_DECIMALS = susde_contract.functions.decimals().call()
    except:
        # 如果无法获取,假设为标准的18位精度
        SDAI_DECIMALS = 18
        SUSDE_DECIMALS = 18
    amount_in = 100000
    amount_out = pool_contract.functions.get_dy(
                    SDAI_INDEX,  # 输入代币索引
                    SUSDE_INDEX,  # 输出代币索引
                    int(amount_in *  10**SDAI_DECIMALS)   # 输入数量(wei)
                ).call()
    profit =  SUSDE_PRICE * amount_out / 10**SUSDE_DECIMALS -  amount_in * SDAI_PRICE
    Log(round(profit, 2), round(amount_out / 10**SUSDE_DECIMALS, 2))

Program Lengkap

Terakhir, kami menggunakan polling untuk terus memperoleh harga, dan menempatkan pesanan ketika keuntungan yang diharapkan tercapai. Perhatikan kode iniIni hanya contoh kode, jangan menggunakannya secara langsungPembaca mungkin menghadapi berbagai masalah dalam praktiknya, tetapi AI saat ini sangat canggih dan pada dasarnya dapat menjawab berbagai pertanyaan. AI juga dapat membantu penulisan kode secara langsung. Editor kode FMZ juga mengintegrasikan ChatGPT, yang dapat digunakan lebih sering.

def execute_trade(amount_in, min_amount_out, direction):
    gas_price = web3.eth.gas_price
    index_in = SUSDE_INDEX
    index_out = SDAI_INDEX
    if direction == 'buy':
        index_in = SDAI_INDEX
        index_out = SUSDE_INDEX
    # 第二步:执行代币交换交易
    swap_tx = pool_contract.functions.exchange(
        index_in,  # 输入代币索引
        index_out,  # 输出代币索引
        int(amount_in*10**SDAI_DECIMALS),  # 输入数量
        int(min_amount_out*10**SUSDE_DECIMALS)  # 最小输出数量(考虑滑点)
    ).build_transaction({
        'from': address,  # 交易发送方
        'gas': 600000,  # gas限制
        'gasPrice': int(2*gas_price) ,
        'nonce': web3.eth.get_transaction_count(address),  # 获取新的nonce值
    })
    
    # 签名并发送交换交易
    signed_swap_tx = web3.eth.account.sign_transaction(swap_tx, private_key)
    swap_tx_hash = web3.eth.send_raw_transaction(signed_swap_tx.rawTransaction)
    
    Log(f"交换交易已提交,交易哈希: {swap_tx_hash.hex()}")

def get_buy_profit(amount_in):
    amount_out = pool_contract.functions.get_dy(
                    SDAI_INDEX,  # 输入代币索引
                    SUSDE_INDEX,  # 输出代币索引
                    int(amount_in *  10**SDAI_DECIMALS)   # 输入数量(wei)
                ).call()
    return  SUSDE_PRICE * amount_out / 10**SUSDE_DECIMALS -  amount_in * SDAI_PRICE, amount_out / 10**SUSDE_DECIMALS

def main():
    while True:
        try:
            sdai_balance = sdai_contract.functions.balanceOf(address).call() / 10**SDAI_DECIMALS
            susde_balance = susde_contract.functions.balanceOf(address).call() / 10**SUSDE_DECIMALS
            amount_in = 100000 #交易的DAI数量
            profit, amount_out = get_buy_profit(amount_in)
            LogStatus(f"SDAI数量:{sdai_balance}, SUSDE数量:{susde_balance}, 收益:{profit}")
            if profit > 1000 and sdai_balance > amount_in: #利润空间
                Log("\n开始执行SDAI->SUSDE交易...")
                execute_trade(amount_in, 0.999*amount_out, 'buy') #一定要设置滑点
            wait_time = 3  # 等待时间(秒)
            time.sleep(wait_time)
            
        except Exception as e:
            # 全局错误处理
            print(f"程序发生错误: {e}")
            print("60秒后重试...")
            time.sleep(60)  # 出错后等待更长时间

Pengingat Risiko

Operasi on-chain relatif berisiko bagi pemula. Selain risiko kebocoran kunci pribadi yang disebutkan di atas, ada berbagai risiko lainnya:

  • Robot MEV harus menetapkan output minimum min_amount_out saat mengeksekusi transaksi untuk memastikan keuntungan bahkan dalam skenario terburuk, jika tidak, mereka akan dieksploitasi oleh MEV. Hari ini, seseorang menggunakan 220.000 USDC untuk ditukar hanya dengan 5272 USDT di Uniswap. Alasannya adalah amountOutMinimum ditetapkan ke 0.
  • Kesalahan strategi, seperti halnya API pertukaran, jika terjadi bug dalam transaksi program on-chain, GAS akan sering dikonsumsi.

Bagi pemula dalam perdagangan on-chain, mereka perlu mempelajari dasar-dasarnya: memahami konsep seperti Gas, slippage, MEV, dll. Selalu mulai dengan jumlah yang rendah dan tingkatkan secara bertahap. Pantau transaksi menggunakan sesuatu seperti Etherscan. Lebih baik kehilangan kesempatan daripada mengambil risiko kehilangan modal Anda.