2

Looking at ChainLink ABI (using this tool) I see

{
"anonymous": false,
"inputs": [
  {
    "indexed": true,
    "name": "from",
    "type": "address"
  },
  {
    "indexed": true,
    "name": "to",
    "type": "address"
  },
  {
    "indexed": false,
    "name": "value",
    "type": "uint256"
  },
  {
    "indexed": false,
    "name": "data",
    "type": "bytes" <----- HERE
  }
],
"name": "Transfer",
"type": "event"
}

a fourth field "data" that results in signature Transfer(address,address,uint256,bytes) which translates to Keccak-256 hash of 0xe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16 which is different from 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef that I expect to look for.

At the same time Etherscan show the correct function hash. What I am doing wrong here? I am parsing the ABI and generating signatures for each event and this works fine for other ERC20 tokens from top 10.

"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" => array:4 [
"anonymous" => false
"inputs" => array:3 [
  0 => array:3 [
    "indexed" => true
    "name" => "from"
    "type" => "address"
  ]
  1 => array:3 [
    "indexed" => true
    "name" => "to"
    "type" => "address"
  ]
  2 => array:3 [
    "indexed" => false
    "name" => "value"
    "type" => "uint256"
  ]
]
"name" => "Transfer"
"type" => "event"
]

2 Answers 2

2

ERC-20 is a standard. It says what kind of functions and events the contract should have, in order to be ERC-20 compliant. It even dictates some small details about how the functions should be implemented.

The problem with such standards is that it's next to impossible to enforce their usage. In theory, lots of things should be done in a contract for it to be ERC-20 compatible. In reality, quite many contracts claim to be ERC-20 compatible even if they do some things differently.

One such different thing may be the event signature. The standard (https://eips.ethereum.org/EIPS/eip-20) says that the Transfer event has to have the signature you expected. But that's impossible to enforce.

You may claim that the token is then not ERC-20 compliant, and you might be right. Unfortunately, for most parties, it's close enough that they accept it as it is.

Furthermore, it's next to impossible to determine which contract is fully ERC-20 compliant and which is not. For example you can't be sure that the contract emits the same event every time - maybe every 100th time it emits a different event. Unless you analyze the source code by hand.

Simply put: you just have to accept the fact that some "ERC-20 compliant" tokens are only close enough.

7
  • Wow, that's strange! I really expect them to follow the standard at least for the main things like the Transfer event. Well then what does exactly etherscan is doing here if it's not looking for the event signatures? I looks like it only cares about function calls which indeed have the expected signature MethodID: 0xa9059cbb?
    – nforced
    Sep 22, 2021 at 16:55
  • It really depends on the third party. They decide how they determine whether a contract is ERC20 compliant or not. I really don't know how they determine it. Sep 22, 2021 at 17:03
  • Ok, I agree with everything you said, the only thing bugs me and I can't understand is why the signature on this LINK transaction log does not match the one on the LINK contract ABI with the forth parameter included. How it this possible? It has to be 0xe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16 but instead it's the "right" one 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef for Transfer(address,address,uint256), why?
    – nforced
    Sep 22, 2021 at 18:42
  • That's weird. The source code says 3 arguments, the ABI says 4. Sorry, don't really know. Sep 23, 2021 at 4:36
  • Reading the source Chainlink token supports EIP-667 transferAndCall.
    – Ismael
    Sep 23, 2021 at 6:00
1

The LINK token is actually not an ERC-20 token but an ERC-677 token.

This token standard has a function transferAndCall:
function transferAndCall(address receiver, uint amount, bytes data) returns (bool success)

This transfers tokens to receiver, via ERC20's transfer(address,uint256) function. It then logs an event Transfer(address,address,uint256,bytes). Once the transfer has succeeded and the event is logged, the token calls onTokenTransfer(address,uint256,bytes) on the receiver with the sender, the amount approved, and additional bytes data as parameters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.