You're going in the right direction checking the Transfer()
event logs. Even though both ERC20 and ERC721 use the same event signature, the ERC721 (NFT) standard defines the 3rd topic (token ID) as indexed
, which stores its value in the set of indexed topics. While the ERC20 defines the 3rd topic (amount) as non-indexed, making the total length of indexed topics set just 2.
I picked a random transaction that contains event logs of both ERC20 and ERC721 transfers. Looks like the logic behind it is payment in the form of an ERC20 token to mint a new ERC721 token.
Note: I'm not a Java dev, so I'll use a JS code in my answer that you can hopefully use as a reference to find the correct syntax and methods in the Java implementation of the Web3 library.
const Web3 = require("web3");
const web3 = new Web3("<provider_url>");
// keccak256 of string "Transfer(address,address,uint256)"
const TRANSFER_SIGNATURE = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
async function run() {
const txHash = "0xfb4dc20b4a8d0b72442a396aced0fc537de757c6aac69609ab3d09d19f9c9aa8";
const txReceipt = await web3.eth.getTransactionReceipt(txHash);
for (let log of txReceipt.logs) {
if (_isERC20Log(log)) {
// Unindexed topics are concatenated in the `data` field.
// There's only one unindexed topic in this case,
// so you don't need to do any parsing and just use the whole value.
const amount = web3.utils.hexToNumberString(log.data);
console.log("ERC20 token amount: ", amount);
console.log("ERC20 token contract: ", log.address);
} else if (_isERC721Log(log)) {
// 3rd indexed topic
// index 0 of the array is the event signature, see `_isERC721Log()`
const tokenId = web3.utils.hexToNumberString(log.topics[3]);
console.log("ERC721 token ID: ", tokenId);
console.log("ERC721 token contract: ", log.address);
}
}
}
function _isERC20Log(log) {
return (
log.topics[0] == TRANSFER_SIGNATURE
&& log.topics.length == 3 // index 0 is the signature, and then 2 indexed topics
);
}
function _isERC721Log(log) {
return (
log.topics[0] == TRANSFER_SIGNATURE
&& log.topics.length == 4 // index 0 is the signature, and then 3 indexed topics
);
}
run();
Output:
ERC20 token amount: 40000000000000000000
ERC20 token contract: 0x54a7cee7B02976ACE1bdd4aFad87273251Ed34Cf
ERC721 token ID: 12013
ERC721 token contract: 0x41cB4a771FdD019ADBF4685bd4885fbBeedE1784