O recurso está a ser carregado... Carregamento...

Introdução fácil ao desenvolvimento web3 baseado no Ethereum com o FMZ

Autora:Inventor quantificado - sonho pequeno, Criado: 2023-03-28 13:32:48, Atualizado: 2024-11-11 22:28:24

nome: token,type:address],name:approveZeroThenMax,outputs:[],stateMutability:payable,type:bytes,{inputs:[],stateMutability:payable,type:function,{inputs:{internalType:minimumbytes,addviewname:data,minimumtype:outputs],inputs:[internalType:address,type:token,type:address],inputs:[approveZeroThenMaxMinusOne,outputs:[],stateMutability:payable,type:byte,type:function,[],[inputs:[],[inputs:],[inputs:],[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:constructor},{anonymous:true,internalType:int24,name:addaddaddaddaddadd:true,internalType:address:address,name:owner,type:address:address: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:[addaddaddaddaddaddaddaddaddadd:true,internalType:uint24,name:uint24,name:inputs,inputs:addaddaddaddaddaddaddaddaddaddaddaddadd:true,internalType:type:

Var contractV3FactoryAddress = 0x1F98431c8aD98523631AE4a59f267346ea31F984 VAR contractV3SwapRouterV2Address = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45

Função toAmount (s, decimais) { Retorno Número (BigDecimal) (BigInt) (s) / (BigDecimal) (Math.pow) (10, decimais) (toString)) - Não.

Função para InnerAmount ((n, decimais) { retorno (BigDecimal(n) * BigDecimal(Math.pow(10, decimais))).toFixed(0) - Não.

função main (() { // ABI registrado no contrato da fábrica da Uniswapexchange.IO("abi", contratoV3FactoryEndereço, 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
}

Os principais dados de informações sobre preços são registrados em:sqrtPriceX96O campo, que precisa de ser calculado com base em dados de precisão de tokens da combinação de trocas em conjunto com o preço atual do pool de trocas, com base emUniswapA descrição na documentação é que nós implementamos uma função para calcular:

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)
    );
}

Com esta função, podemos calcular a combinação de tokens como1INCH/WETHA taxa é de 10.000, o preço atual do poço.

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)
}

Imprimir variáveispriceMostrar:price: 0.000203(Um 1 INCH para 0.000203 WETH)

Uniswap V3 Arquivo de classes de negociação

Os inventores da plataforma de negociação quantitativa divulgaram um pacote completoUniswapModeloO modelo de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código de código. A biblioteca de modelos tem muitos detalhes de design que vale a pena aprender:

  • Obtenção automática de informações de tokens Para obter uma descrição do código, quando o parâmetro do modelo éAutoFetchTokensQuando definido como verdadeiro, o programa de modelo acessa automaticamentehttps://tokens.coingecko.com/uniswap/all.jsonO link, obtém e processa automaticamente a informação de todos os tokens. Isso permite que você não tenha que adicionar manualmente um token no código da política (ou seja, você precisa usar o token).addToken(name, address)Adicionar um 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
                      }
                  }
              })
          }  
    
  • Adaptação de diferentes endereços de contratos com base nas configurações da cadeia O modelo foi configuradoChainTypeParâmetros que permitem a troca de várias cadeias:

      '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',
    

    Código de seleção:

          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)
              }
          }
    

    Método RPC para chamar Ethereumeth_chainIdConsultas atuaischainIdDe acordo comchainIdA partir de agora, o site está disponível para download gratuito e download gratuito.UniswapA lista de endereços dos contratos foi divulgada.USDTO endereço de um contrato pode variar de acordo com a cadeia.

    Código de seleção:

          // 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")
          }
    
  • Usando o Uniswap V3

    Neste modelo$.testUniswap()A função é uma função de teste de funções de modelo, cujo código fornece exemplos de como usar o modelo:

    $.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))
        
        // ...
    }
    

    Quando uma política faz referência ao "Uniswap V3 transaction library" (como fazer referência ao template library pode ser consultado na documentação da plataforma FMZ), é possível invocar funções que estão embutidas nesse template library.

    Criar um site chamadoexUma variável chamada "Uniswap V3 Transaction Library" é uma função de interface embalada.$.NewUniswapV3()Criar um objeto para atribuir valor aex

    let ex = $.NewUniswapV3()
    

    UtilizaçãoexFunções membros de objetosaddToken()Adicionar informações sobre os tokens.

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

    Se você quiser obter e imprimir o preço do pool de câmbio de um par de transações, você pode usarexFunções membros de objetosgetPrice()O que você pode escrever é:

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

    Se você quiser executar uma operação de conversão, você pode usarexFunções membros de objetosswapToken(), executar a troca:

      // 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'))
    

Incidentes de busca

Neste capítulo, aprenderemos a ler os eventos de lançamento de contratos inteligentes usando a plataforma de negociação quantitativa dos inventores, que são armazenados nos registros do Ethereum Virtual Machine.

Eth_getLogs

Os eventos de consulta de contratos inteligentes são liberados usando o método RPC do Ethereumeth_getLogsO que é mais importante é que você tenha acesso aos dados de logs da cadeia, como foi explicado em nossos cursos anteriores sobre como chamar os nós do Ethereum RPC. Por exemplo, nós conseguimosWETHOs eventos contratados podem ser codificados usando o FMZ.Ferramentas de depuraçãoTestes, os objetos de troca são configurados para que os nós RPC sejam os nodes da rede Ethereum que estão sendo chamadoseth_getLogsQuando o método é definido, temos três parâmetros.fromBlocktoBlockaddressUsamos os parâmetros fromBlock e toBlock para consultar dados limitados dentro de um bloco:

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   
}

Para acessar os dados dos logs, por causa do grande volume de dados, nós omitimos alguns deles:

[{
	"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"
}]

Podemos ver que há uma grande variedade de eventos nos dados de logs, se apenas nos interessarmosTransferO evento precisa de usar esses dados.TransferO incidente foi filtrado.

Pesquisa de logs

Os logs do Ethereum são divididos em duas partes, uma e uma temática.topics; 2, dadosdata

  • TemáticatopicsCom oeth_getLogsO resultado da execução do código do teste do capítulo é um exemplo.topicsOs dados dos campos são:

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

    Esta étopicsO valor do campo (tema) é uma estrutura de matriz usada para descrever eventos. Especifica que seu tamanho não pode exceder 4 e que o primeiro elemento é o hash de assinatura do evento. No inventor quantidade de plataforma de negociação, usamosEncodeA função pode calcular esse hash de assinatura usando o seguinte código:

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

    CalcularTransfer(address,address,uint256)Não.keccak256O hash (hex code) é:0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

    topicsO valor do campo é uma estrutura de matrizes, com o segundo e o terceiro elementos:

    • Endereço enviadofrom
    • Endereço de recepçãoto
  • Dadosdata

    dataOs dados dos campos são:

    "data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",
    

    Alguns parâmetros do evento (parâmetros no código Solidity do smart contract sem declarações indexadas) são armazenados emdataO que é que ele está a fazer?

    Analisar os dados0x0000000000000000000000000000000000000000000000000164f2434262e1cc

    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
    }
    

    O resultado é: 0.10047146239950075, o que significa que o número de pessoas que estão usando o aplicativo é de 0.10047146239950075.dataOs dados correspondem ao valor da transferência.


A partir de agora, podemos começar a pesquisar os diários:

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++
        }
    }
}

Emhttps://etherscan.io/A pergunta é:

img

Resultados do teste de código em FMZ Debug Tool:

img

A partir daí, você pode fazer uma análise de acordo com o que você precisa quando você está procurando.fromtoOs dados dos campos, por exemplo:

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

Os resultados:

Endereço: 0x12b791bb27b3a4ee958b5a435fea7d49ec076e9c

Incidentes com contratos de espionagem

Por causa doFerramentas de depuraçãoO código é testado por um curto período de tempo e o conteúdo é exportado após a execução do código, não pode ser exibido em tempo real. O conteúdo desta seção é testado usando a plataforma de negociação quantitativa do inventor.

Aqui nós usamos o Ethereum para escutar.USDTO contrato de moedaTransfer(address,address,uint256)A partir do que aprendemos na aula anterior, nós projetamos um exemplo de um evento de contrato inteligente que é monitorado continuamente:

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 = {

Mais.