gakonst / ethers-rs

Complete Ethereum & Celo library and wallet implementation in Rust. https://docs.rs/ethers

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ETHContractError(DecodingError(InvalidData))

YanOctavian opened this issue · comments

Version
lastest

cargo install cargo-tree
(see install here: https://github.com/sfackler/cargo-tree)

Then:

cargo tree | grep ethers

Platform
mac
Description
Enter your issue details here.
One way to structure the description:

[short summary of the bug]

I tried this code:

abigen!(
    ERC20Contract,
    "./crates/contract/json/ERC20.json",
    derives(serde::Deserialize, serde::Serialize)
);
let wallet: LocalWallet = "0xed0e10acdb4b9ad17a0d9ec1b6f92d9e70d9f9c0bbfc609eb1aa03a370aba489".parse::<LocalWallet>().unwrap();

    let provider =
        Provider::<ethers::providers::Http>::try_from("https://eth-goerli.api.onfinality.io/public")
            .unwrap();

    let client =
        SignerMiddleware::new_with_provider_chain(provider.clone(), wallet.clone()).await.unwrap();

    let a = Address::from_str("0x11612633Db3b966314E7B9DfB2D05289eC5b1B5E").unwrap();
    // 9651820
    let block_number = 9651820u64;
    let entry_point =
        ERC20Contract::new(a, Arc::new(client.clone()));
    let logs: Vec<TransferFilter> = entry_point
                .transfer_filter()
                .from_block(block_number)
                .to_block(block_number)
                .query()
                .await.unwrap();

[code sample that causes the bug]

I expected to see this happen: [explanation]

ETHContractError(DecodingError(InvalidData))

Instead, this happened: [explanation]


[
  {
    "inputs": [
      { "internalType": "string", "name": "name", "type": "string" },
      { "internalType": "string", "name": "symbol", "type": "string" }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "inputs": [
      { "internalType": "address", "name": "owner", "type": "address" },
      { "internalType": "address", "name": "spender", "type": "address" }
    ],
    "name": "allowance",
    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      { "internalType": "address", "name": "spender", "type": "address" },
      { "internalType": "uint256", "name": "amount", "type": "uint256" }
    ],
    "name": "approve",
    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      { "internalType": "address", "name": "account", "type": "address" }
    ],
    "name": "balanceOf",
    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      { "internalType": "address", "name": "spender", "type": "address" },
      {
        "internalType": "uint256",
        "name": "subtractedValue",
        "type": "uint256"
      }
    ],
    "name": "decreaseAllowance",
    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      { "internalType": "address", "name": "spender", "type": "address" },
      { "internalType": "uint256", "name": "addedValue", "type": "uint256" }
    ],
    "name": "increaseAllowance",
    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      { "internalType": "uint256", "name": "amount", "type": "uint256" }
    ],
    "name": "mint",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      { "internalType": "address", "name": "to", "type": "address" },
      { "internalType": "uint256", "name": "amount", "type": "uint256" }
    ],
    "name": "transfer",
    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      { "internalType": "address", "name": "from", "type": "address" },
      { "internalType": "address", "name": "to", "type": "address" },
      { "internalType": "uint256", "name": "amount", "type": "uint256" }
    ],
    "name": "transferFrom",
    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

hmm

  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },

this looks correct

weird that decoding this returns an error

https://goerli.etherscan.io/address/0x11612633Db3b966314E7B9DfB2D05289eC5b1B5E#events

could you try decoding this event manually?

decoding this event manually?

how decoding this event manually? Could you provide me with a code example, thank you very much

I write a custom event in the contract and it can be decoded, but the native events in ERC20 cannot be decoded.

the generated code of ERC20Contract should include an EthEvent type that supports decode, just to make the event data can be decoded via the generated event struct

use tokio;
use ethers::contract::{ContractFactory, Contract};
use ethers::providers::{Provider, Http};
use ethers::types::{Address, Filter};
use std::str::FromStr;
use std::sync::Arc;
use ethers::abi::{Abi, Log};
use ethers::contract::EthEvent;
use ethers::middleware::Middleware;
use ethers::types::U256;

#[derive(Debug, Clone, PartialEq, ethers::contract::EthEvent)]
pub struct Transfer {
    from: Address,
    to: Address,
    value: U256,
}

#[tokio::main]
async fn main() {
    let provider = Provider::<ethers::providers::Http>::try_from(
            "https://eth-goerli.api.onfinality.io/public"
        ).unwrap();
    let contract_address = Address::from_str("0x11612633Db3b966314E7B9DfB2D05289eC5b1B5E").unwrap();
    let contract = Contract::new(contract_address, Abi::default(), Arc::new(provider.clone()));
    let event = contract.event::<Transfer>();
    let mut f = Filter::new().from_block(9651800u64).to_block(9651900u64);
    let events:Vec<ethers::types::Log> = contract.client().get_logs(&f).await.unwrap();
    for log in events {
         if let Ok(decoded) = Transfer::decode_log(&log.into()) {
            println!("Transfer Event: {:?}", decoded);
            println!("From: {:?}", decoded.from);
            println!("To: {:?}", decoded.to);
            println!("Value: {:?}", decoded.value);
        }
    }

}

I tried to use this method to decode, but it didn't seem to work.

I tried to use this method to decode, but it didn't seem to work.

I tried to use this method to decode, but it didn't seem to work.

is this what's being generated?

because his lacks the indexed attributes

is this what's being generated?

because his lacks the indexed attributes

As a beginner of Ethereum, it takes time to understand this library. If you can give some hints in the above code, that would be great. thank you very much for your time

use tokio;
use ethers::contract::{ContractFactory, Contract};
use ethers::providers::{Provider, Http};
use ethers::types::{Address, Filter};
use std::str::FromStr;
use std::sync::Arc;
use ethers::abi::{Abi, Log};
use ethers::contract::EthEvent;
use ethers::middleware::Middleware;
use ethers::types::U256;

#[derive(Debug, Clone, PartialEq, ethers::contract::EthEvent)]
pub struct Transfer {
    #[ethevent(indexed)]
    from: Address,
    #[ethevent(indexed)]
    to: Address,
    value: U256,
}

#[tokio::main]
    let provider = Provider::<ethers::providers::Http>::try_from(
            "https://eth-goerli.api.onfinality.io/public"
        ).unwrap();
    let contract_address = Address::from_str("0x11612633Db3b966314E7B9DfB2D05289eC5b1B5E").unwrap();
    let contract = Contract::new(contract_address, Abi::default(), Arc::new(provider.clone()));
    let event = contract.event::<Transfer>();
    let mut f = Filter::new().from_block(9651800u64).to_block(9651900u64);
    let events:Vec<ethers::types::Log> = contract.client().get_logs(&f).await.unwrap();
    let b: Vec<Transfer> = contract.event_with_filter(f).query().await.unwrap();
    println!("{:?}", b);
}

is this what's being generated?
because his lacks the indexed attributes

As a beginner of Ethereum, it takes time to understand this library. If you can give some hints in the above code, that would be great. thank you very much for your time

it works. thank you very much

is this what's being generated?

because his lacks the indexed attributes

It seems to solve the problem in the block with only Transfer, but the same error is reported in the block with Approal at the same time