Type/to search
8
Follow
1364
Followers
Práctica de la plataforma FMZ Web3 Ethereum: intercambio de órdenes basado en contratos inteligentes
Discussions
Created 2025-03-17 11:00:33  Updated 2025-03-18 15:54:46
 0
 883

img

Prefacio

En el mercado de criptomonedas, las oportunidades comerciales son fugaces, especialmente las ventanas de arbitraje de alto rendimiento, que a menudo duran muy poco tiempo. Si confía únicamente en el trading manual, a menudo resultará difícil mantenerse al día con el mercado. Por lo tanto, el trading con órdenes pendientes se convierte en un medio importante para mejorar la eficiencia del trading.

Este artículo se basa en las ideas del artículo de Xiaocao. Reconstruye la estrategia de órdenes de pool de trading de Curve.fi en la plataforma FMZ y explica cómo lograr el mismo efecto a través de ella. Al mismo tiempo, también se discutirá en detalle el esquema de protección de clave privada para garantizar tanto la seguridad como la conveniencia en el proceso de comercio programático.

La estrategia está escrita en JavaScript y utiliza el objeto de intercambio eth web3 de la plataforma FMZ.

Seguridad por diseño

Basado en el artículoCómo implementar la colocación de órdenes en intercambios descentralizados: tomando Curve como ejemploEn el diseño de seguridad, utilizamos un método de cifrado AES similar. Utilizamos una contraseña y un conteo para encriptar los datos.

  • Contraseña: contraseña, cifrada con sha256.
  • Contar: contar, utiliza la marca de tiempo como un conteo aleatorio para participar en el cifrado.
  1. Cifre la clave privada sin conexión. Use la "contraseña" y el "conteo" para cifrar la clave privada y obtener una clave secreta cifrada.
  2. Configure la clave cifrada, la contraseña, el recuento, etc., en la plataforma FMZ y utilice el parámetro de interfaz de política "Cadena cifrada". El contenido introducido en el control se cifrará, y la información de configuración registrada en la plataforma no es el texto sin formato del control.
  3. Cuando la estrategia se está ejecutando, el custodio puede descifrar la información y cargar la clave secreta (después de cargar la clave secreta, se restablecerán todas las variables relacionadas).

img

javascript
// 加密/解密方式 function cryptoKey(type, data, passWord, count) { // 加载加密库 eval(HttpQuery("https://cdnjs.cloudflare.com/ajax/libs/aes-js/3.1.2/index.min.js")) // sha256 密码 var hash = Encode("sha256", "string", "hex", passWord).substring(0, 32) if (type == "encrypt") { var key = aesjs.utils.utf8.toBytes(hash.substring(0, 32)) var counter = new aesjs.Counter(count) var textBytes = aesjs.utils.utf8.toBytes(data) var aesCtr = new aesjs.ModeOfOperation.ctr(key, counter) var encryptedBytes = aesCtr.encrypt(textBytes) var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes) return encryptedHex } else if (type == "decrypt") { var key = aesjs.utils.utf8.toBytes(hash.substring(0, 32)) var counter = new aesjs.Counter(count) var aesCtrDecrypt = new aesjs.ModeOfOperation.ctr(key, counter) const decryptedBytes = aesCtrDecrypt.decrypt(aesjs.utils.hex.toBytes(data)) const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes) return decryptedText } else { throw "function cryptoKey(), param 'type' not support" } }

Configurar el objeto de intercambio web3

https://www.fmz.com/m/platforms/add

img

Hay muchos nodos de Ethereum disponibles en línea, los más utilizados son:

Puedes solicitar la creación de tu propia dirección y luego configurarla para su uso. No entraré en detalles aquí. Puede completar la información clave a voluntad. Planeamos cargarla dinámicamente, así que no tiene sentido configurarla aquí.

javascript
exchange.IO("key", cryptoKey(descCryptoType[cryptoType], keyData, password, count)) walletAddress = exchange.IO("address") Log("载入秘钥,钱包地址:", walletAddress)

Utilice la función exchange.IO("key", ...) encapsulada por la plataforma para cargar y actualizar la clave privada después del descifrado.

Registro de ABI

Después de resolver el problema de seguridad, el siguiente paso es realizar algunas operaciones en el contrato inteligente de Ethereum. Según el DEX Curve.fi mencionado por Xiaocao, podemos encontrar fácilmente esta dApp en línea:

https://curve.fi/dex/ethereum/pools/factory-stable-ng-102/deposit/

En la página del pool de intercambio sDAI/sUSDe, puede encontrar la dirección del contrato del pool de intercambio y observar el contrato. Los métodos que podemos utilizar son:

  • Monedas: Obtenga la dirección del contrato del token que participa en la transacción en el pool
  • get_dy: Calcula la cantidad de intercambio actual en el pool.
  • intercambio: ejecutar intercambio.

Para llamar a estos métodos, primero debe registrar la ABI del contrato del pool. No filtré los métodos utilizados, sino que copié y pegué directamente la ABI completa y la registré:

javascript
// sDAI/sUSDe 池合约地址和ABI var poolAddress = "0x167478921b907422F8E88B43C4Af2B8BEa278d3A" // 合约ABI var poolABI = `[{"name":"Transfer","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchangeUnderlying","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_id","type":"int128","indexed":false},{"name":"token_amount","type":"uint256","indexed":false},{"name":"coin_amount","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityImbalance","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampA","inputs":[{"name":"old_A","type":"uint256","indexed":false},{"name":"new_A","type":"uint256","indexed":false},{"name":"initial_time","type":"uint256","indexed":false},{"name":"future_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"name":"A","type":"uint256","indexed":false},{"name":"t","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ApplyNewFee","inputs":[{"name":"fee","type":"uint256","indexed":false},{"name":"offpeg_fee_multiplier","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetNewMATime","inputs":[{"name":"ma_exp_time","type":"uint256","indexed":false},{"name":"D_ma_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_A","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_offpeg_fee_multiplier","type":"uint256"},{"name":"_ma_exp_time","type":"uint256"},{"name":"_coins","type":"address[]"},{"name":"_rate_multipliers","type":"uint256[]"},{"name":"_asset_types","type":"uint8[]"},{"name":"_method_ids","type":"bytes4[]"},{"name":"_oracles","type":"address[]"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_received","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_received","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_min_mint_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_received","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_received","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_max_burn_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_max_burn_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"},{"name":"_receiver","type":"address"},{"name":"_claim_admin_fees","type":"bool"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"withdraw_admin_fees","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"last_price","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ema_price","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_p","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_oracle","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D_oracle","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"transfer","inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"transferFrom","inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"approve","inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"permit","inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"DOMAIN_SEPARATOR","inputs":[],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"view","type":"function","name":"get_dx","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_is_deposit","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"A_precise","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_balances","inputs":[],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"view","type":"function","name":"stored_rates","inputs":[],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"view","type":"function","name":"dynamic_fee","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"ramp_A","inputs":[{"name":"_future_A","type":"uint256"},{"name":"_future_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_new_fee","inputs":[{"name":"_new_fee","type":"uint256"},{"name":"_new_offpeg_fee_multiplier","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_ma_exp_time","inputs":[{"name":"_ma_exp_time","type":"uint256"},{"name":"_D_ma_time","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"N_COINS","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"offpeg_fee_multiplier","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_exp_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D_ma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_last_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8"}]},{"stateMutability":"view","type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"balanceOf","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"allowance","inputs":[{"name":"arg0","type":"address"},{"name":"arg1","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"nonces","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"salt","inputs":[],"outputs":[{"name":"","type":"bytes32"}]}]` // 注册ABI exchange.IO("abi", poolAddress, poolABI)

Leer el saldo de la billetera y el saldo del token

La lectura del saldo del token de la billetera, la precisión del token, el nombre del token, etc. son todos métodos de los contratos ERC20, que se registran de forma predeterminada.

javascript
var token0Name = exchange.IO("api", token0Address, "symbol") var token1Name = exchange.IO("api", token1Address, "symbol") var token0Decimals = exchange.IO("api", token0Address, "decimals") var token1Decimals = exchange.IO("api", token1Address, "decimals")
javascript
var sDAI_Balance = exchange.IO("api", sDAI["address"], "balanceOf", walletAddress) var sUSDe_Balance = exchange.IO("api", sUSDe["address"], "balanceOf", walletAddress)

Monitoreo de pools de intercambio

javascript
function getBuyProfit(poolAddress, sDAI, sUSDe, amountIn, entryPriceForDAI) { var data = exchange.IO("api", poolAddress, "get_dy", sDAI["idx"], sUSDe["idx"], toInnerAmount(amountIn, sDAI["decimals"])) Log("get_dy:", data) var amountOut = toAmount(data, sUSDe["decimals"]) if (!amountOut) { return null } var profit = amountOut - entryPriceForDAI * amountIn return {"profit": profit, "amountOut": amountOut, "sDAI_sUSDe_price": amountOut / amountIn} }

Las condiciones de activación están diseñadas de la siguiente manera:

javascript
if (profit > 1000 && sDAI_Balance > amountIn) { Log("达到兑换条件,开始执行 sDAI -> sUSDe 兑换交易...") /* 兑换操作代码仅为教学演示,该功能请慎用,请先测试 executeTrade(poolAddress, sDAI, sUSDe, amountIn, 0.999*amountOut) */ }

La operación de intercambio solo se puede realizar cuando el monto de intercambio actual satisface la ganancia mayor a 1000 y hay suficientes tokens sDAI en la billetera.

Operación de Intercambio

javascript
function executeTrade(poolAddress, tokenIn, tokenOut, amountIn, minOutAmount) { // exchange : i , j , _dx , _min_dy var swapTx = exchange.IO("api", poolAddress, "exchange", tokenIn["idx"], tokenOut["idx"], toInnerAmount(amountIn, tokenIn["decimals"]), toInnerAmount(minOutAmount, tokenOut["decimals"])) if (swapTx) { while (true) { Sleep(1000 * 3) let info = e.IO("api", "eth", "eth_getTransactionReceipt", swapTx) if (info && info.gasUsed) { return true } Log('Transaction not yet mined', swapTx) } } return false }

img

Código de estrategia completo

javascript
function toAmount(s, decimals) { return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString()) } function toInnerAmount(n, decimals) { return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0) } function getBuyProfit(poolAddress, sDAI, sUSDe, amountIn, entryPriceForDAI) { var data = exchange.IO("api", poolAddress, "get_dy", sDAI["idx"], sUSDe["idx"], toInnerAmount(amountIn, sDAI["decimals"])) var amountOut = toAmount(data, sUSDe["decimals"]) if (!amountOut) { return null } var profit = amountOut - entryPriceForDAI * amountIn return {"profit": profit, "amountOut": amountOut, "sDAI_sUSDe_price": amountOut / amountIn} } function executeTrade(poolAddress, tokenIn, tokenOut, amountIn, minOutAmount) { // exchange : i , j , _dx , _min_dy var swapTx = exchange.IO("api", poolAddress, "exchange", tokenIn["idx"], tokenOut["idx"], toInnerAmount(amountIn, tokenIn["decimals"]), toInnerAmount(minOutAmount, tokenOut["decimals"])) if (swapTx) { while (true) { Sleep(1000 * 3) let info = e.IO("api", "eth", "eth_getTransactionReceipt", swapTx) if (info && info.gasUsed) { return true } Log('Transaction not yet mined', swapTx) } } return false } // 加密/解密方式 function cryptoKey(type, data, passWord, count) { // 加载加密库 eval(HttpQuery("https://cdnjs.cloudflare.com/ajax/libs/aes-js/3.1.2/index.min.js")) // sha256 密码 var hash = Encode("sha256", "string", "hex", passWord).substring(0, 32) if (type == "encrypt") { var key = aesjs.utils.utf8.toBytes(hash.substring(0, 32)) var counter = new aesjs.Counter(count) var textBytes = aesjs.utils.utf8.toBytes(data) var aesCtr = new aesjs.ModeOfOperation.ctr(key, counter) var encryptedBytes = aesCtr.encrypt(textBytes) var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes) return encryptedHex } else if (type == "decrypt") { var key = aesjs.utils.utf8.toBytes(hash.substring(0, 32)) var counter = new aesjs.Counter(count) var aesCtrDecrypt = new aesjs.ModeOfOperation.ctr(key, counter) const decryptedBytes = aesCtrDecrypt.decrypt(aesjs.utils.hex.toBytes(data)) const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes) return decryptedText } else { throw "function cryptoKey(), param 'type' not support" } } // 加密/解密选项 const descCryptoType = ["encrypt", "decrypt"] function main() { LogReset(1) var count = _G("count") if (!count) { count = new Date().getTime() _G("count", count) } var walletAddress = null if (cryptoType == 1) { exchange.IO("key", cryptoKey(descCryptoType[cryptoType], keyData, password, count)) walletAddress = exchange.IO("address") Log("载入秘钥,钱包地址:", walletAddress) } else { Log("加密后的秘钥:", cryptoKey(descCryptoType[cryptoType], keyData, password, count)) return } Log("钱包ETH余额:", toAmount(exchange.IO("api", "eth", "eth_getBalance", walletAddress, "latest"), 18)) // sDAI/sUSDe 池合约地址和ABI var poolAddress = "0x167478921b907422F8E88B43C4Af2B8BEa278d3A" // 合约ABI var poolABI = `[{"name":"Transfer","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchangeUnderlying","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_id","type":"int128","indexed":false},{"name":"token_amount","type":"uint256","indexed":false},{"name":"coin_amount","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityImbalance","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampA","inputs":[{"name":"old_A","type":"uint256","indexed":false},{"name":"new_A","type":"uint256","indexed":false},{"name":"initial_time","type":"uint256","indexed":false},{"name":"future_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"name":"A","type":"uint256","indexed":false},{"name":"t","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ApplyNewFee","inputs":[{"name":"fee","type":"uint256","indexed":false},{"name":"offpeg_fee_multiplier","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetNewMATime","inputs":[{"name":"ma_exp_time","type":"uint256","indexed":false},{"name":"D_ma_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_A","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_offpeg_fee_multiplier","type":"uint256"},{"name":"_ma_exp_time","type":"uint256"},{"name":"_coins","type":"address[]"},{"name":"_rate_multipliers","type":"uint256[]"},{"name":"_asset_types","type":"uint8[]"},{"name":"_method_ids","type":"bytes4[]"},{"name":"_oracles","type":"address[]"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_received","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_received","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_min_mint_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_received","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_received","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_max_burn_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_max_burn_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"},{"name":"_receiver","type":"address"},{"name":"_claim_admin_fees","type":"bool"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"withdraw_admin_fees","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"last_price","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ema_price","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_p","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_oracle","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D_oracle","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"transfer","inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"transferFrom","inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"approve","inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"permit","inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"DOMAIN_SEPARATOR","inputs":[],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"view","type":"function","name":"get_dx","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_is_deposit","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"A_precise","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_balances","inputs":[],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"view","type":"function","name":"stored_rates","inputs":[],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"view","type":"function","name":"dynamic_fee","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"ramp_A","inputs":[{"name":"_future_A","type":"uint256"},{"name":"_future_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_new_fee","inputs":[{"name":"_new_fee","type":"uint256"},{"name":"_new_offpeg_fee_multiplier","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_ma_exp_time","inputs":[{"name":"_ma_exp_time","type":"uint256"},{"name":"_D_ma_time","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"N_COINS","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"offpeg_fee_multiplier","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_exp_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D_ma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_last_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8"}]},{"stateMutability":"view","type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"balanceOf","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"allowance","inputs":[{"name":"arg0","type":"address"},{"name":"arg1","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"nonces","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"salt","inputs":[],"outputs":[{"name":"","type":"bytes32"}]}]` // 注册ABI exchange.IO("abi", poolAddress, poolABI) // 获取池子中的代币地址、名称 var token0Address = exchange.IO("api", poolAddress, "coins", 0) var token1Address = exchange.IO("api", poolAddress, "coins", 1) var token0Name = exchange.IO("api", token0Address, "symbol") var token1Name = exchange.IO("api", token1Address, "symbol") var token0Decimals = exchange.IO("api", token0Address, "decimals") var token1Decimals = exchange.IO("api", token1Address, "decimals") var sDAI = {} var sUSDe = {} if (token0Name == "sDAI") { sDAI["name"] = token0Name sDAI["address"] = token0Address sDAI["idx"] = 0 sDAI["decimals"] = token0Decimals ? token0Decimals : 18 } else { throw "pool error" } if (token1Name == "sUSDe") { sUSDe["name"] = token1Name sUSDe["address"] = token1Address sUSDe["idx"] = 1 sUSDe["decimals"] = token1Decimals ? token1Decimals : 18 } else { throw "pool error" } // 假设 DAI 入手成本价: 0.9929 var entryPriceForDAI = 0.9929 while (true) { var sDAI_Balance = exchange.IO("api", sDAI["address"], "balanceOf", walletAddress) var sUSDe_Balance = exchange.IO("api", sUSDe["address"], "balanceOf", walletAddress) if (!sDAI_Balance || !sUSDe_Balance) { Sleep(1000 * 5) continue } var tbl = {"type": "table", "title": "data", "cols": ["tokenName", "address", "idx", "decimals", "balance"], "rows": []} tbl["rows"].push([sDAI["name"], sDAI["address"], sDAI["idx"], sDAI["decimals"], toAmount(sDAI_Balance, sDAI["decimals"])]) tbl["rows"].push([sUSDe["name"], sUSDe["address"], sUSDe["idx"], sUSDe["decimals"], toAmount(sUSDe_Balance, sUSDe["decimals"])]) // 监控兑换价格,根据 DAI 入手成本价,计算实时利润等信息 var amountIn = 100000 var ret = getBuyProfit(poolAddress, sDAI, sUSDe, amountIn, entryPriceForDAI) if (!ret) { Sleep(1000 * 5) continue } var profit = ret["profit"] var amountOut = ret["amountOut"] var sDAI_sUSDe_price = ret["sDAI_sUSDe_price"] if (profit > 1000 && sDAI_Balance > amountIn) { Log("达到兑换条件,开始执行 sDAI -> sUSDe 兑换交易...") /* 兑换操作代码仅为教学演示,该功能请慎用,请先测试 executeTrade(poolAddress, sDAI, sUSDe, amountIn, 0.999*amountOut) */ } LogStatus(_D(), ", amountIn:", amountIn, ", amountOut:", amountOut, ", sDAI_sUSDe_price:", sDAI_sUSDe_price, ", profit:", profit, "\n`" + JSON.stringify(tbl) + "`") Sleep(1000 * 60) } }

END

De acuerdo con la idea de diseño de la estrategia original, el objetivo debería ser capturar condiciones extremas del mercado similares a las que se muestran en la figura.

img

Gracias por su lectura y apoyo.

Comment
All comments (0)
No data
No data
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)