Summary
Wrapping the native asset (e.g. WETH.deposit()) produces no tokenTransfers entry in Blockbook, because canonical wrapped-native contracts (WETH9 and its ports) mint without emitting an ERC-20 Transfer event — they emit Deposit(address indexed dst, uint256 wad) instead. Blockbook's log parser only recognizes Transfer / TransferSingle / TransferBatch, so:
- the wrap transaction is indexed as a plain ETH send to the contract, with no indication the address received WETH,
- token auto-discovery never happens — the address↔contract association is built from token transfers only, so an address whose only WETH interaction is wrapping never gets WETH into its
tokens list and its WETH balance stays invisible until some unrelated Transfer event touches the address,
- the same applies to unwrapping:
withdraw() emits Withdrawal(address indexed src, uint256 wad), also ignored, and per-address transfers counts for WETH exclude all wraps/unwraps.
In clients this means e.g. Trezor Suite renders a wrap as nothing but an outgoing ETH payment to an unknown contract — there is no "received X WETH" line to show, while Etherscan displays the same tx as "Wrap 0.000123 ETH into 0.000123 WETH" (it parses the Deposit event itself).
Temporary fix for Trezor Suite trezor/trezor-suite#30797, trezor/trezor-suite#29875
Examples
Both are deposit() (0xd0e30db0) calls sending ETH to WETH 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2.
/api/v2/tx-specific/0xdb59b3… shows the receipt contains exactly one log — the Deposit event, no Transfer:
"logs": [{
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"topics": [
"0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c",
"0x0000000000000000000000009ea3721b5bf3b64b4418c38b603154d2d597fae3"
],
"data": "0x00000000000000000000000000000000000000000000000000038d7ea4c68000"
}]
/api/v2/tx/… consequently returns no tokenTransfers field at all for either tx (verified on both), even though parsedData correctly identifies the call as deposit().
(The example address does show WETH in tokens today, but only because later swap/send txs emitted real Transfer events; an address that only ever wraps gets nothing.)
Root cause
contractGetTransfersFromLog dispatches solely on the three transfer topics and continues on everything else:
|
func contractGetTransfersFromLog(logs []*bchain.RpcLog, txid string) bchain.TokenTransfers { |
|
var r bchain.TokenTransfers |
|
for _, l := range logs { |
|
tl := len(l.Topics) |
|
if tl > 0 { |
|
signature := l.Topics[0] |
|
var tt *bchain.TokenTransfer |
|
var err error |
|
if signature == tokenTransferEventSignature { |
|
tt, err = processTransferEvent(l) |
|
} else if signature == tokenERC1155TransferSingleEventSignature { |
|
tt, err = processERC1155TransferSingleEvent(l) |
|
} else if signature == tokenERC1155TransferBatchEventSignature { |
|
tt, err = processERC1155TransferBatchEvent(l) |
|
} else { |
|
continue |
|
} |
|
if err != nil { |
|
glog.Warningf("contractGetTransfersFromLog: skipping unparseable log of contract %s, tx %s: %v", l.Address, txid, err) |
|
continue |
|
} |
|
if tt != nil { |
|
r = append(r, tt) |
|
} |
|
} |
|
} |
|
return r |
WETH9 deposit()/withdraw() mint/burn without Transfer:
function deposit() public payable {
balanceOf[msg.sender] += msg.value;
Deposit(msg.sender, msg.value);
}
Suggested fix
Translate the wrapped-native contract's events into synthetic mint/burn token transfers:
Deposit(dst, wad) → TokenTransfer{from: 0x0, to: dst, value: wad}
Withdrawal(src, wad) → TokenTransfer{from: src, to: 0x0, value: wad}
Since any contract can emit events with these signatures (same spoofing concern as #1225), the translation should be restricted to the canonical wrapped-native contract per chain, e.g. a per-coin config field (wrappedNativeContract). That would cover WETH on Ethereum and the same WETH9-pattern contracts on other EVM chains Blockbook indexes (WBNB, WPOL, WXDAI, …).
Summary
Wrapping the native asset (e.g.
WETH.deposit()) produces notokenTransfersentry in Blockbook, because canonical wrapped-native contracts (WETH9 and its ports) mint without emitting an ERC-20Transferevent — they emitDeposit(address indexed dst, uint256 wad)instead. Blockbook's log parser only recognizesTransfer/TransferSingle/TransferBatch, so:tokenslist and its WETH balance stays invisible until some unrelatedTransferevent touches the address,withdraw()emitsWithdrawal(address indexed src, uint256 wad), also ignored, and per-addresstransferscounts for WETH exclude all wraps/unwraps.In clients this means e.g. Trezor Suite renders a wrap as nothing but an outgoing ETH payment to an unknown contract — there is no "received X WETH" line to show, while Etherscan displays the same tx as "Wrap 0.000123 ETH into 0.000123 WETH" (it parses the
Depositevent itself).Temporary fix for Trezor Suite trezor/trezor-suite#30797, trezor/trezor-suite#29875
Examples
Both are
deposit()(0xd0e30db0) calls sending ETH to WETH0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2./api/v2/tx-specific/0xdb59b3…shows the receipt contains exactly one log — theDepositevent, noTransfer:/api/v2/tx/…consequently returns notokenTransfersfield at all for either tx (verified on both), even thoughparsedDatacorrectly identifies the call asdeposit().(The example address does show WETH in
tokenstoday, but only because later swap/send txs emitted realTransferevents; an address that only ever wraps gets nothing.)Root cause
contractGetTransfersFromLogdispatches solely on the three transfer topics andcontinues on everything else:blockbook/bchain/coins/eth/contract.go
Lines 274 to 300 in 89963a3
WETH9
deposit()/withdraw()mint/burn withoutTransfer:Suggested fix
Translate the wrapped-native contract's events into synthetic mint/burn token transfers:
Deposit(dst, wad)→TokenTransfer{from: 0x0, to: dst, value: wad}Withdrawal(src, wad)→TokenTransfer{from: src, to: 0x0, value: wad}Since any contract can emit events with these signatures (same spoofing concern as #1225), the translation should be restricted to the canonical wrapped-native contract per chain, e.g. a per-coin config field (
wrappedNativeContract). That would cover WETH on Ethereum and the same WETH9-pattern contracts on other EVM chains Blockbook indexes (WBNB, WPOL, WXDAI, …).