Sumber dimuat naik... memuat...

Pengembangan web3 berasaskan Ethereum dengan FMZ

Penulis:Pencipta Kuantiti - Impian Kecil, Dicipta: 2023-03-28 13:32:48, Dikemas kini: 2024-11-11 22:28:24

nama: token,type:address],name:approveZeroThenMax,outputs:[],stateMutability:payable,type:bytes,{inputs:[],stateMutability:payable,type:function,{inputs:{internalType:byte,addminimumviewname:data,type:outputs],inputs:[internalType:address,name:token,type:address],approveZeroThenMaxMinusOne,outputs:[],stateMutability:payable,type:bytes,type:outputs,type:outputs,type:outputs,type:outputs,inputs, var abiPool = [inputs:[],stateMutability:nonpayable,type:constructor},{anonymous:true,internalType:int24,inputs:[indexed:true,internalType:address,name:owner,type:address},{indexed:true,internalType:int24,stateMutability:nonpayable,type:int24},{anonymous:true,addalType:int24,name:addaddaddaddaddaddUpperType:address,name:owner:type:type:addaddaddadd,type:address,type:address:address:address:address:address var abiFactory = [{inputs:[],stateMutability:nonpayable,type:int24},{anonymous:false,inputs:[{indexed:true,internalType:uint24,name:fee,type:uint24},{indexed:true,internalType:int24,name:tickSpacing,type:int24},{anonymous:FeeAuntmountbled,type:false,inputs:{addaddaddaddaddaddaddadd:true,internalType:uint24,name:inputs,name:inputs:[indexed:true,type:infunctionalType:internalType:uint24,type

var kontrakV3FactoryAlamat = 0x1F98431c8aD98523631AE4a59f267346ea31F984 var contractV3SwapRouterV2Address = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45

fungsi ke Jumlah (s, perpuluhan) { Kembali nombor (((BigDecimal(BigInt(s)) / BigDecimal ((Math.pow(10, perpuluhan))).toString()) { C: $ 00FFFF }

fungsi ke InnerAmount ((n, perpuluhan) { pulangan (BigDecimal(n) * BigDecimal(Math.pow(10, perpuluhan))).toFixed(0) { C: $ 00FFFF }

fungsi utama (() { // Pendaftaran ABI kontrak kilang Uniswapexchange.IO("abi", kontrakV3FactoryAlamat, abiFactory)

// 注册Uniswap路由合约的ABI
exchange.IO("abi", contractV3SwapRouterV2Address, abiRoute)

// 获取交易对的池地址
var tokenIn = {name : "1INCH", address: "0x111111111117dC0aa78b770fA6A738034120C302", decimals: exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "decimals")}
var tokenOut = {name : "WETH", address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", decimals: exchange.IO("api", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals")}
var poolAddress = exchange.IO("api", contractV3FactoryAddress, "getPool", tokenIn.address, tokenOut.address, 10000)

// 注册池合约ABI
exchange.IO("abi", poolAddress, abiPool)

var slot0 = exchange.IO("api", poolAddress, "slot0")
Log("slot0:", slot0)

}


获取到兑换池的价格信息,打印出代码中```slot0```变量:

```javascript
{
    "feeProtocol":0,
    "unlocked":true,
    "sqrtPriceX96":"1128983883551457130720648561",
    "tick":"-85025",
    "observationIndex":5,
    "observationCardinality":6,
    "observationCardinalityNext":6
}

Data maklumat harga utama dicatatkan disqrtPriceX96Bidang yang perlu dikira berdasarkan data ketepatan token dalam pautan pertukaran bersama dengan harga semasa kolam pertukaran, berdasarkanUniswapDalam dokumen ini, kita menerangkan bagaimana kita melaksanakan fungsi untuk mengira:

function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {
    // sqrtPriceX96 = sqrt(price) * 2^96
    [decimals0, decimals1, sqrtPriceX96] = [decimals0, decimals1, sqrtPriceX96].map(BigInt);
    const TWO = BigInt(2);
    const TEN = BigInt(10);
    const SIX_TENTH = BigInt(1000000);
    const Q192 = (TWO ** BigInt(96)) ** TWO;
    return (
        Number((sqrtPriceX96 ** TWO * TEN ** decimals0 * SIX_TENTH) / (Q192 * TEN ** decimals1)) /
        Number(SIX_TENTH)
    );
}

Gunakan fungsi ini untuk mengira kombinasi token sebagai1INCH/WETHPada bulan Disember tahun ini, Malaysia mencatatkan jumlah pelaburan sebanyak 10 juta dolar AS.

function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {
    // sqrtPriceX96 = sqrt(price) * 2^96
    [decimals0, decimals1, sqrtPriceX96] = [decimals0, decimals1, sqrtPriceX96].map(BigInt);
    const TWO = BigInt(2);
    const TEN = BigInt(10);
    const SIX_TENTH = BigInt(1000000);
    const Q192 = (TWO ** BigInt(96)) ** TWO;
    return (
        Number((sqrtPriceX96 ** TWO * TEN ** decimals0 * SIX_TENTH) / (Q192 * TEN ** decimals1)) /
        Number(SIX_TENTH)
    );
}

function main() {
    var tokenIn = {name : "1INCH", address: "0x111111111117dC0aa78b770fA6A738034120C302", decimals: exchange.IO("api", "0x111111111117dC0aa78b770fA6A738034120C302", "decimals")}
    var tokenOut = {name : "WETH", address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", decimals: exchange.IO("api", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals")}

    // 获取的slot0变量中"sqrtPriceX96":"1128983883551457130720648561",
    var price = computePoolPrice(tokenIn.decimals, tokenOut.decimals, "1128983883551457130720648561")
    Log("price:", price)
}

Pencetakan pembolehubahpriceTunjukkan:price: 0.0002031 INCH untuk 0.000203 WETH).

Uniswap V3

Pencipta platform perdagangan kuantitatif mendedahkan pembungkusanUniswapTemplat, telah mencapai fungsi seperti pertukaran, mendapatkan harga, memeriksa baki dompet, tidak perlu lagi menulis semula kod berdasarkan apa yang dijelaskan di atas, anda boleh membaca kod sumber templat ini untuk mempelajari lebih mendalam, membangunkan aplikasi ke arah Web3. Terdapat banyak perincian reka bentuk yang patut dipelajari dalam perpustakaan ini:

  • Mengambil maklumat token secara automatik Mengambil salah satu perenggan kod, apabila parameter templatAutoFetchTokensApabila ditetapkan sebagai benar, program templat akan diakses secara automatikhttps://tokens.coingecko.com/uniswap/all.jsonMenghubungkan, mendapatkan dan memproses semua maklumat token secara automatik. Dengan cara ini, anda tidak perlu menambahkan token secara manual dalam kod dasar (jika tidak, anda perlu menggunakannya)addToken(name, address)Tambah token) ‖

         if (AutoFetchTokens) {
              let res = JSON.parse(HttpQuery("https://tokens.coingecko.com/uniswap/all.json"))
              Log("fetch", res.tokens.length, "tokens from", res.name)
              res.tokens.forEach(function(token) {
                  if (token.chainId == chainId && token.symbol != "WETH") {
                      self.tokenInfo[token.symbol] = {
                          name: token.symbol,
                          decimals: token.decimals,
                          address: token.address
                      }
                  }
              })
          }  
    
  • Sesuaikan alamat kontrak yang berbeza mengikut tetapan rantai Templat ini telah disiapkanChainTypeParameter yang menyokong menukar pelbagai rantaian:

      'https://rpc.ankr.com/eth',
      'https://arb1.arbitrum.io/rpc',
      'https://mainnet.optimism.io/',
      'https://rpc.ankr.com/avalanche',
      'https://polygon-rpc.com',
      'https://rpc.ankr.com/celo',
    

    Kod pilihan:

          if (typeof(ChainType) === 'number') {
              let chainRpc = [
                  '',
                  'https://rpc.ankr.com/eth',
                  'https://arb1.arbitrum.io/rpc',
                  'https://mainnet.optimism.io/',
                  'https://rpc.ankr.com/avalanche',
                  'https://polygon-rpc.com',
                  'https://rpc.ankr.com/celo',
                  //'https://mainnet.aurora.dev',
                  //'https://bsc-dataseed.binance.org',
                  //'https://exchainrpc.okex.org'
              ][ChainType]
              if (chainRpc && chainRpc.length > 0) {
                  e.IO("base", chainRpc)
                  Log("change base rpc to", chainRpc)
              }
          }
    

    Kaedah RPC untuk memanggil Ethereumeth_chainIdSoalan semasachainIdMengikutchainIdUntuk menyesuaikan alamat WETH, anda perlu membuat senarai nama yang sesuai dengan alamat anda.UniswapAlamat kontrak:USDTDi samping itu, ia juga mempunyai alamat kontrak dan sebagainya (sebab kontrak pintar mungkin mempunyai alamat kontrak yang berbeza di rantaian yang berbeza).

    Kod pilihan:

          // https://docs.uniswap.org/contracts/v3/reference/deployments
          let WETHAddress = {
              1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // Ethereum
              3: "0xc778417E063141139Fce010982780140Aa0cD5Ab", // Ropsten
              4: "0xc778417E063141139Fce010982780140Aa0cD5Ab", // Rinkeby
              5: "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6", // Goerli
              42: "0xd0A1E359811322d97991E03f863a0C30C2cF029C", // Kovan
              10: "0x4200000000000000000000000000000000000006", // Optimism
              69: "0x4200000000000000000000000000000000000006", // Optimistic Kovan
              42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", // Arbitrum One
              421611: "0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681", // Arbitrum Rinkeby
              137: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", // Polygon
              80001: "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889", // Polygon Mumbai
          }
    
          let chainId = e.IO("api", "ETH", "eth_chainId")
          if (chainId) {
              chainId = Number(chainId)
              Log("chainId: ", chainId)
              let addr = WETHAddress[chainId]
              if (addr) {
                  Log("Register WETH address", addr)
                  self.addToken("ETH", addr)
              }
              if (chainId == 42220) {
                  // Celo Address
                  ContractV3Factory = '0xAfE208a311B21f13EF87E33A90049fC17A7acDEc'
                  ContractV3SwapRouterV2 = '0x5615CDAb10dc425a742d643d949a7F474C01abc4'
                  self.addToken('CELO', '0x471ece3750da237f93b8e339c536989b8978a438')
              } else if (chainId == 42161) {
                  self.addToken('USDT', '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9')
              }
          } else {
              panic("get chain Id error")
          }
    
  • Menggunakan Uniswap V3

    Di dalam templat ini$.testUniswap()Fungsi adalah fungsi untuk menguji fungsi templat, kodnya memberikan contoh panggilan bagaimana menggunakan templat:

    $.testUniswap = function() {
        let ex = $.NewUniswapV3()
        Log("walletAddress: ", ex.walletAddress)
        let tokenAddressMap = {
            "USDT": "0xdac17f958d2ee523a2206206994597c13d831ec7",
            "1INCH": "0x111111111117dC0aa78b770fA6A738034120C302",
            "USDC": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
            "DAI": "0x6b175474e89094c44da98b954eedeac495271d0f",
        }
        for (let name in tokenAddressMap) {
            ex.addToken(name, tokenAddressMap[name])
        }
    
        Log(ex.getPrice('ETH_USDT'))
        Log(ex.getPrice('1INCH_USDT'))
    
        // swap 0.01 ETH to USDT
        Log(ex.swapToken('ETH', 0.01, 'USDT'))
        let usdtBalance = ex.balanceOf('USDT')
        Log("balance of USDT", usdtBalance)
    
        // swap USDT to DAI then DAI to ETH
        Log(ex.swapToken('USDT', usdtBalance, 'DAI,ETH'))
    
        Log("balance of ETH", ex.getETHBalance())
    
        // Log(ex.sendETH('0x11111', 0.02))
        
        // ...
    }
    

    Apabila satu dasar merujuk kepada "Uniswap V3 Transaction Library", anda boleh memanggil fungsi yang terbungkus dalam library template ini.

    Membuat laman web bernamaexVariabel yang dipanggil "Uniswap V3 Exchange Library Template Wrapped Interface Function"$.NewUniswapV3()Mencipta objek yang diberi nilai kepadaex

    let ex = $.NewUniswapV3()
    

    PenggunaanexFungsi ahli objekaddToken()Tambah maklumat tentang Token.

      let tokenAddressMap = {
          "USDT": "0xdac17f958d2ee523a2206206994597c13d831ec7",
          "1INCH": "0x111111111117dC0aa78b770fA6A738034120C302",
          "USDC": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
          "DAI": "0x6b175474e89094c44da98b954eedeac495271d0f",
      }
      for (let name in tokenAddressMap) {
          ex.addToken(name, tokenAddressMap[name])
      }
    

    Jika anda ingin mendapatkan dan mencetak harga kumpulan pertukaran untuk pasangan dagangan, anda boleh menggunakanexFungsi ahli objekgetPrice()Saya tidak tahu apa yang akan berlaku.

      Log(ex.getPrice('ETH_USDT'))
      Log(ex.getPrice('1INCH_USDT'))
    

    Jika anda ingin menjalankan operasi pertukaran, anda boleh menggunakanexFungsi ahli objekswapToken(), melakukan pertukaran:

      // swap 0.01 ETH to USDT
      Log(ex.swapToken('ETH', 0.01, 'USDT'))
      let usdtBalance = ex.balanceOf('USDT')
      Log("balance of USDT", usdtBalance)
    
      // swap USDT to DAI then DAI to ETH
      Log(ex.swapToken('USDT', usdtBalance, 'DAI,ETH'))
    

Kejadian Pengundian

Dalam bab ini, kita akan belajar untuk membaca peristiwa yang dikeluarkan oleh kontrak pintar menggunakan platform dagangan kuantitatif pencipta, dan peristiwa yang dikeluarkan oleh kontrak pintar disimpan dalam log mesin maya Ethereum.

Eth_getLogs

Mencari peristiwa yang dikeluarkan oleh kontrak pintar yang memerlukan kaedah RPC Ethereumeth_getLogsUntuk mendapatkan data log pada rantaian, bagaimana untuk memanggil node Ethereum RPC telah dijelaskan dalam kursus sebelumnya. Sebagai contoh, kita dapatWETHPeristiwa kontrak boleh ditulis dengan kod yang menggunakan FMZ untuk mengesan peristiwa kontrak.Alat penyesuaianUjian, objek pertukaran dikonfigurasikan RPC nodes sebagai nodes Ethereum, yang dipanggileth_getLogsKami telah menetapkan tiga parameter untuk kaedah ini.fromBlocktoBlockaddressKami menggunakan parameter fromBlock dan toBlock untuk mengehadkan permintaan data dalam satu blok:

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 main() {
    // getBlockNumber
    var blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
    Log("blockNumber:", blockNumber)

    // get logs
    var fromBlock = "0x" + (toAmount(blockNumber, 0) - 1).toString(16)
    var toBlock = "0x" + toAmount(blockNumber, 0).toString(16)
    var params = {
        "fromBlock" : fromBlock,
        "toBlock" : toBlock,
        "address" : "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"   // WETH合约的地址
    }
    var logs = exchange.IO("api", "eth", "eth_getLogs", params)

    // 由于数据量比较大,如果使用Log函数打印,数据会被截断。使用return将完整数据返回在页面「函数结果」编辑框中
    return logs   
}

Untuk mendapatkan data log, kami telah mengabaikan beberapa perkara kerana kandungan data yang lebih besar:

[{
	"data": "0x00000000000000000000000000000000000000000000000001c1a55000000000",
	"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000006b75d8af000000e20b7a7ddf000ba900b4009a80", "0x000000000000000000000000bcb095c1f9c3dc02e834976706c87dee5d0f1fb6"],
	"transactionHash": "0x27f9bf5abe3148169b4b85a83e1de32bd50eb81ecc52e5af006157d93353e4c4",
	"transactionIndex": "0x0",
	"removed": false,
	"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
	"blockHash": "0x847be24a7b159c292bda030a011dfec89487b70e71eed486969b032d6ef04bad",
	"blockNumber": "0x109b1cc",
	"logIndex": "0x0"
}, {
	"data": "0x00000000000000000000000000000000000000000000000008ea20cdea027c00",
	"logIndex": "0x5",
	"topics": ["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c", "0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d"],
	"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
	"blockHash": "0x847be24a7b159c292bda030a011dfec89487b70e71eed486969b032d6ef04bad",
	"blockNumber": "0x109b1cc",
	"removed": false,
	"transactionHash": "0xace3afa02e8af5d1ef6fc1635fbdf7bee37624547937ea5272c23968dd034c09",
	"transactionIndex": "0x1"
},

...

{
	"blockNumber": "0x109b1cd",
	"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
	"data": "0x00000000000000000000000000000000000000000000000002c053531ab8a000",
	"logIndex": "0xd3",
	"removed": false,
	"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000001111111254eeb25477b68fb85ed929f73a960582", "0x000000000000000000000000252ba9b5916171dbdadd2cec7f91875a006955d0"],
	"transactionHash": "0x3012b82891f85b077cfe1c12cb9722b93c696ef2c37d67981ccddcc9c3396aca",
	"transactionIndex": "0x8d",
	"blockHash": "0xcd3d567c9bd02a4549b1de0dc638ab5523e847c3c156b096424f56c633000fd9"
}, {
	"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c", "0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],
	"transactionIndex": "0x91",
	"logIndex": "0xdb",
	"removed": false,
	"blockNumber": "0x109b1cd",
	"data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",
	"transactionHash": "0x6aa8d80daf42f442591e7530e31323d05e1d6dd9f9f9b9c102e157d89810c048",
	"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
	"blockHash": "0xcd3d567c9bd02a4549b1de0dc638ab5523e847c3c156b096424f56c633000fd9"
}, {
	"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
	"blockHash": "0xcd3d567c9bd02a4549b1de0dc638ab5523e847c3c156b096424f56c633000fd9",
	"blockNumber": "0x109b1cd",
	"logIndex": "0xde",
	"removed": false,
	"topics": ["0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65", "0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],
	"data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",
	"transactionHash": "0x6aa8d80daf42f442591e7530e31323d05e1d6dd9f9f9b9c102e157d89810c048",
	"transactionIndex": "0x91"
}]

Anda boleh lihat semua jenis peristiwa dalam data log, jika kita hanya mengambil perhatianTransferPeristiwa ini memerlukan pengumpulan data.TransferPeristiwa ini telah disaring.

Cari log

Log Ethereum dibahagikan kepada dua bahagian, satu, tematopics; 2, datadata

  • TopiktopicsDenganeth_getLogsDalam kes ini, kita akan melihat bagaimana anda boleh mengemas kini kod anda untuk digunakan di laman web kami.topicsData dalam bidang ini ialah:

    "topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c", "0x000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b"],  
    

    Yang initopicsNilai bagi medan (topik) adalah struktur aritmatika yang digunakan untuk menerangkan peristiwa. Ia menetapkan bahawa panjangnya tidak boleh melebihi 4. Kami menggunakan platform perdagangan kuantitatif pencipta.EncodeFungsi boleh mengira nilai hash tandatangan ini dengan menggunakan kod berikut:

    function main() {
        var eventFunction = "Transfer(address,address,uint256)"
        var eventHash = Encode("keccak256", "string", "hex", eventFunction)
        Log("eventHash:", "0x" + eventHash)
        // eventHash: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
    }
    

    MengiraTransfer(address,address,uint256)Perbezaankeccak256Nilai hash (hex code) ialah0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

    topicsNilai bidang adalah struktur aritmatika, elemen kedua dan ketiga adalah:

    • Panggilan alamatfrom
    • Alamat penerimaanto
  • Datadata

    dataData dalam bidang ini ialah:

    "data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",
    

    Beberapa parameter dalam peristiwa (parameter dalam kod Solidity kontrak pintar tanpa pengisytiharan diindeks) akan disimpan didataDi bahagian ini.

    Menganalisis data ini0x0000000000000000000000000000000000000000000000000164f2434262e1cc

    function toAmount(s, decimals) {
        return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
    }
    
    function main() {
        var value = "0x0000000000000000000000000000000000000000000000000164f2434262e1cc"
        Log(toAmount(value, 0) / 1e18)  // 0.10047146239950075
    }
    

    Di sini, anda boleh melihat data: 0.10047146239950075, dan kemudian anda boleh melihat data: 0.10047146239950075.dataData adalah jumlah pemindahan yang sepadan.


Setelah latihan, anda sudah bersedia. Kita boleh mula mencari log:

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 main() {
    // getBlockNumber
    var blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
    Log("blockNumber:", blockNumber)

    // get logs
    var fromBlock = "0x" + (toAmount(blockNumber, 0) - 1).toString(16)
    var toBlock = "0x" + toAmount(blockNumber, 0).toString(16)
    var params = {
        "fromBlock" : fromBlock,
        "toBlock" : toBlock,
        "address" : "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
    }
    var logs = exchange.IO("api", "eth", "eth_getLogs", params)

    // 遍历logs
    var eventFunction = "Transfer(address,address,uint256)"
    var eventHash = "0x" + Encode("keccak256", "string", "hex", eventFunction)
    Log("eventHash:", eventHash)

    var counter = 0
    for (var i = logs.length - 1; i >= 0 && counter < 10; i--) {
        if (logs[i].topics[0] == eventHash) {
            Log("Event Transfer, data:", toAmount(logs[i].data, 0) / 1e18, ", blockNumber:", toAmount(logs[i].blockNumber, 0), ", transactionHash:", logs[i].transactionHash,
              ", log:", logs[i])
            counter++
        }
    }
}

Dalamhttps://etherscan.io/Permintaan:

img

Hasil daripada menjalankan kod ujian dalam alat debugging FMZ:

img

Ia juga boleh diselesaikan mengikut keperluan semasa carian.fromtoData dalam bidang, contohnya:

function main() {
    var from = "0x00000000000000000000000012b791bb27b3a4ee958b5a435fea7d49ec076e9c"
    var address = "0x" + exchange.IO("encodePacked", "address", from)
    Log("address:", address)
}

Hasilnya:

Alamat: 0x12b791bb27b3a4ee958b5a435fea7d49ec076e9c

Peristiwa kontrak pengawasan

Oleh keranaAlat penyesuaianHanya boleh menguji kod untuk masa yang singkat, dan kandungan yang dikeluarkan hanya selepas pelaksanaan kod selesai, tidak dapat dipaparkan secara langsung, log output.

Di sini, kita menggunakan Ethereum untuk mendengar.USDTKontrak mata wang iniTransfer(address,address,uint256)Peristiwa, berdasarkan apa yang kita pelajari dalam kelas sebelumnya, kami merancang untuk menulis contoh yang terus mendengar peristiwa kontrak pintar:

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 addEventListener(contractAddress, event, callBack) {
    var self = {}
    self.eventHash = "0x" + Encode("keccak256", "string", "hex", event)
    self.contractAddress = contractAddress
    self.latestBlockNumber = 0
    self.fromBlockNumber = 0
    self.firstBlockNumber = 0
    /* TODO: test
    self.isFirst = true 
    */ 

    self.getBlockNumber = function() {
        var maxTry = 10
        for (var i = 0; i < maxTry; i++) {
            var ret = exchange.IO("api", "eth", "eth_blockNumber")
            if (ret) {
                return toAmount(ret, 0)
            }
            Sleep(5000)
        }
        throw "getBlockNumber failed"
    }

    self.run = function() {
        var currBlockNumber = self.getBlockNumber()
        var fromBlock = "0x" + self.fromBlockNumber.toString(16)
        var toBlock = "0x" + currBlockNumber.toString(16)
        var params = {

Lebih lanjut