리소스 로딩... 로딩...

FMZ를 사용하여 에테리움 기반의 웹3 개발에 대한 쉬운 입문

저자:발명가들의 수량화 - 작은 꿈, 창작: 2023-03-28 13:32:48, 업데이트: 2024-11-11 22:28:24

name:token,type:address],name:approveZeroThenMax,outputs:[],stateMutability:payable,type:bytefunction,{inputs:[],stateMutability:payable,type:function,{inputs:[stateMutability:payable,type:function},{inputs:[internalType:addminimumbytes,type:addviewadddata,typeaddress,name:token,type:address],name:approveZeroThenMaxMinusOne,outputs:[],stateMutability:payable,type:type:bytefunction,{inputsinputs:[],stateMutability:[internalType:,type var abiPool = [inputs:[],stateMutability:nonpayable,type:constructor},{anonymous:true,addalType:int24,inputs:[indexed:true,internalType:address,name:owner,type:address},{indexed:true,internalType:[inputs:[],stateMutability:nonpayable,type:int24},{anonymous:true,internalType:int24,inputs:[added:true,internalType:address:address,name:owner,type: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,stateMutability:nonpayable,type:int24},{anonymous:FeeAuntmountbled,type:false,inputs:{addaddaddaddaddaddaddaddaddaddfalse:true,internalType:uint24,name:fee,type:uint24},{indexed:true,internalType:type:uint24,inputs

0x1F98431c8aD98523631AE4a59f267346ea31F984 var contractV3SwapRouterV2Address = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45

함수 toAmount ((s, 소수점) { 반환 번호 (BigDecimal) / BigDecimal (Math.pow), 10개의 소수점 (decimal) ♪ ♪

함수 toInnerAmount ((n, 소수점) { 반환 (BigDecimal(n) * BigDecimal(Math.pow(10, 소수))).toFixed(0) ♪ ♪

function main (() { // 유니스랩 공장 계약에 등록된 ABIexchange.IO("abi", 계약V3Factory주소, 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
}

그 중 주요 가격 정보 데이터는sqrtPriceX96이 필드는 교환 조합의 토큰 정밀 데이터와 함께 교환 풀의 현재 가격을 계산해야 합니다.Uniswap이 문서는 우리가 계산을 위해 함수를 구현한 것을 설명합니다.

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

이 함수를 사용해서1INCH/WETH, , , , , , .

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

인쇄 변수price표시:price: 0.0002031 인치에 0.000203 WETH가 있습니다.

Uniswap V3 거래 클래식 라이브러리

발명가 양적 거래 플랫폼은 포장 된 것을 공개했습니다.Uniswap템플릿이 템플릿의 소스 코드를 더 깊이 학습하고 웹 3 방향으로 응용 프로그램을 개발할 수 있습니다. 이 템플릿 라이브러리에는 많은 디자인 세부 사항이 있습니다.

  • 토큰 정보를 자동으로 얻습니다. 예를 들어, 이 템플릿의 변수에서AutoFetchTokenstrue로 설정하면 템플릿 프로그램이 자동으로 접속합니다.https://tokens.coingecko.com/uniswap/all.json링크, 취득 및 자동으로 모든 토큰의 정보를 처리합니다. 이렇게하면 정책 코드에서 수동으로 토큰을 추가하지 않고 사용할 수 있습니다.addToken(name, address)토큰을 추가합니다.

         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
                      }
                  }
              })
          }  
    
  • 체인 설정에 따라 다른 계약 주소를 조정합니다 이 템플릿은 설정되었습니다.ChainType여러 개의 체인 전환을 지원하는 매개 변수:

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

    코드:

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

    에테리움의 RPC 방법eth_chainId현재 검색chainId그리고,chainId이 글은 WETH의 주소와 일치합니다.Uniswap이 글은 전 세계 유동인물 거래소에서 공개된 글입니다.USDT이 경우, 다른 체인에서 다른 계약 주소를 가질 수 있습니다.

    코드:

          // 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")
          }
    
  • "Uniswap V3 트레이드 클래스 라이브러리"를 이용합니다.

    이 템플릿에서$.testUniswap()함수는 템플릿 함수를 테스트하는 함수이며, 코드는 템플릿을 사용하는 방법에 대한 호출 예제를 제공합니다.

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

    어떤 정책이 "Uniswap V3 트랜잭션 클래스 라이브러리"를 참조할 때, 이 템플릿 클래스 라이브러리에 포괄된 함수를 호출할 수 있다.

    이 프로젝트의 주제는ex"Uniswap V3 트랜잭션 클래스 라이브러리" 템플릿을 호출하는 변수를 포괄한 인터페이스 함수$.NewUniswapV3()하나의 객체에 값을 부여하는 것ex

    let ex = $.NewUniswapV3()
    

    사용ex객체의 멤버 함수addToken()이 트로킹은 트로킹에 대한 정보를 추가합니다.

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

    만약 당신이 거래 쌍의 교환 풀 가격을 얻고 인쇄하려면ex객체의 멤버 함수getPrice()이 글은 다음과 같습니다.

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

    만약 당신이 이식 작업을 수행하고 싶다면ex객체의 멤버 함수swapToken()이 모든 것은

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

수색 사건

이 장에서는 발명자의 양적 거래 플랫폼을 사용하여 스마트 계약에 의해 출시되는 이벤트를 읽는 법을 배우게 될 것입니다.

eth_getLogs

이더리움의 RPC 방법을 사용하는 스마트 계약의 공개 이벤트를 검색합니다.eth_getLogs에테리움의 RPC 노드를 호출하는 방법에 대한 설명은 이전 강의에서 설명했습니다. 예를 들어,WETH계약된 이벤트는 FMZ를 사용하여 코드를 작성할 수 있습니다.디뷰팅 도구테스트, 거래소 객체 구성 RPC 노드는 에테리움 네트워크 노드, 호출eth_getLogs이 방법은 3개의 매개 변수를 지정합니다.fromBlocktoBlockaddress우리는 fromBlock와 toBlock를 사용하여 블록 내의 데이터를 제한적으로 검색합니다.

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   
}

로그 데이터에 접근하기 위해, 더 많은 데이터로 인해, 우리는 몇 가지 내용을 생략했습니다:

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

로그 데이터에 있는 모든 종류의 이벤트를 볼 수 있습니다Transfer이 자료를 이용해서Transfer이 사건은 필터링되어 있습니다.

로그 검색

이더리움 로그는 두 부분으로 나뉘어 있습니다.topics2 데이터data

  • 주제topics그리고eth_getLogs이 프로젝트의 주요 목표는 개발자들에 대한 신뢰를 높이고,topics필드의 데이터는 다음과 같습니다:

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

    이것은topics(주제) 필드의 값은 행렬 구조로, 이벤트를 설명하기 위해 사용된다. 그것의 ((열열) 길이가 4을 초과할 수 없도록 규정한다. 첫 번째 요소는 이벤트의 서명 해시 값이다. 우리는 발명가들의 양적 거래 플랫폼을 사용했습니다.Encode이 함수는 다음과 같은 코드를 사용하여 서명 해시 값을 계산할 수 있습니다.

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

    계산해 보세요.Transfer(address,address,uint256)이 모든 것은keccak256해시 값 (hex 코딩) 은0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

    topics필드의 값은 배열 구조이며, 두 번째 요소와 세 번째 요소는 다음과 같습니다.

    • 주소 발송from
    • 수신 주소to
  • 데이터data

    data필드의 데이터는 다음과 같습니다:

    "data": "0x0000000000000000000000000000000000000000000000000164f2434262e1cc",
    

    이 사건의 일부 매개 변수 (스마트 컨트랙트의 솔리디티 코드 내의 매개 변수에는 인덱스 된 선언이 없습니다) 는data이 부분에는

    이 데이터를 분석합니다.0x0000000000000000000000000000000000000000000000000164f2434262e1cc

    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
    }
    

    이 자료는 0.10047146239950075입니다.data이 자료는 송금 금액에 해당합니다.


이 문서의 내용을 설명하고, 연습하고, 준비할 수 있습니다.

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

이쪽에서https://etherscan.io/이 문서를 검색하세요:

img

FMZ 디뷰팅 도구에서 테스트 코드가 실행되는 결과:

img

검색시 필요에 따라 분석할 수도 있습니다.fromto필드의 데이터, 예를 들어:

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

이 프로젝트의 결과는:

주소: 0x12b791bb27b3a4ee958b5a435fea7d49ec076e9c

경청 계약 사건

그 이유는디뷰팅 도구코드는 짧은 시간 동안 테스트 할 수 있으며 코드가 실행된 후에만 출력을 할 수 있으며 실시간으로 표시, 출력 로그를 할 수 없습니다. 이 섹션의 내용은 우리는 발명자의 양적 거래 플랫폼을 사용하여 실제 디스크를 생성하여 테스트합니다.

여기 우리는 에테리움을 사용하고 있습니다.USDT이 통화 계약은Transfer(address,address,uint256)우리는 지난 수업에서 배운 내용에 따라 스마트 컨트랙트 이벤트에 대한 지속적인 경청의 예를 작성했습니다.

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

더 많은