检测erc20代币交易的正确方式是什么?
发布于 3 个月前 作者 suyhuai 813 次浏览 来自 以太坊

由于我想确认一笔erc20代币交易是否成功,并获取代币转出地址和转入地址, 所以我目前尝试了以下的方式:

a. 一开始我以为和eth确认方式一样,后来发现代币交易的to字段是合约地址,真实的转入地址是在input字段中. 因此我去解析input字段, 找到凡是调用transfer函数的交易(不同的合约貌似transfer函数名hash不同,我在https://tokenstandard.codetract.io/网站上找到我要观察的合约的transfer函数名hash),找到之后在从input中继续解析转入地址和金额.

b. 后来了解到代币交易还有被动方式,就是调用的是transferFrom之类的函数,所以前一种方式可能会遗漏一些交易,可靠的方式是获取交易的receipt信息,根据receipt中的信息,拿到交易是否成功,并能在logs中获取到真实的token from地址和to地址. 但是这样,解析一个区块的所有交易就比较慢了,因为每一个交易都要做一次getTransactionReceipt的rpc调用.

我现在的问题是:

  1. 是否只有receipt才能作为交易信息的最终依据?能不能通过区块中携带的信息就完成token交易的所有判断和信息获取?
  2. erc20代币交易中, msg.sender地址和token的from地址一定是一样的吗?
  3. 之前了解到,需要通过getCode来判断区块交易信息中的to地址是普通地址还是合约地址,这样也比较消耗时间和性能, 有其他更好的方式推荐吗?

希望有经验的朋友们,帮忙解答一下,多谢

4 回复
  1. 根据合约的实现不同,receipt的状态也不一定能够代表转账绝对成功,例如一下代码:
function transfer(address _to, uint256 _value) returns (bool success) {
        //Default assumes totalSupply can't be over max (2^256 - 1).
        //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
        //Replace the if with this one instead.
        //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
        if (balances[msg.sender] >= _value && _value > 0) {
            balances[msg.sender] -= _value;
            balances[_to] += _value;
            Transfer(msg.sender, _to, _value);
            return true;
        } else { return false; }
}

这段代码即使没有成功,receipt的status字段也是0x1。

个人认为可以通过检测Transfer事件来进行判断,一般该事件是只有在交易成功完成后才会生成,然后解析Transfer事件的参数来获取具体的交易金额,from,to等,感觉这种方式也挺花时间的。

@manxiaqu 检测Transfer事件就是检测receipt中的logs信息对吧? 是否可以理解为,即使status字段为0x1,但是logs中没有transfer事件,也认为是失败.

getTransactionReceipt 过滤Event log

回到顶部