On June 24th, SECBIT team conducted a comprehensive analysis on ATN Token bug and found numerous ERC827 contracts sharing the same trouble, part of which referred to the ERC827 template offered by OpenZeppelin. One member of SECBIT team, p0n1 reported this problem to OpenZeppelin in seconds along with solution that has been accepted afterwards. OpenZeppelin has removed the ERC827 template on GitHub as well.
For now, this issue is under discussion in the community and we are actively looking for valid solutions.
EIP827 is one proposal on ERC827 token standard of many drafts on Ethereum extending ERC20 standard. ERC827 implements three additional interfaces based on ERC20: transferAndCall()
, transferFromAndCall()
, approveAndCall()
.
function transferAndCall(address _to, uint256 _value, bytes _data) public payable returns (bool) {
require(_to != address(this));
require(super.transfer(_to, _value));
require(_to.call(_data));
return true;
}
function transferFromAndCall(
address _from, address _to, uint256 _value, bytes _data
) public payable returns (bool) {
require(_to != address(this));
require(super.transferFrom(_from, _to, _value));
require(_to.call(_data));
return true;
}
function approveAndCall(address _spender, uint256 _value, bytes _data) public payable returns (bool) {
require(_spender != address(this));
require(super.approve(_spender, _value));
require(_spender.call(_data));
return true;
}
All these functions has a call()
operation allowing users to call functions on any addresses via this contract arbitrarily, e.g. transferAndCall()
would call the function with _to
address after finishing a transaction, and _data
is determined by the caller. A hacker would have no difficulty capturing the identity of current contract and conducting any operations on to
contract, such as stealing tokens or bypassing authority checks. Here is a detailed description.
Some of these buggy contracts referred to the sample code by OpenZeppelin, and SECBIT team raised an issue on the official GitHub page immediately.
The ERC827 implementation has been removed from OpenZeppelin repository, and p0n1 reached a consensus with OpenZeppelin after further discussion that immature drafts should reside in an isolate directory marked a unstable draft with issue discussion link provided
. The author of EIP827 responded soon afterwards.
The description and affected contracts of this issue has been indexed in A Collection of Vulnerabilities in ERC20 Smart Contracts With Tokens Affected maintained by SECBIT and Loopring. We would keep updating this repository and welcome your cooperation.
Description and Contracts Affected: https://github.com/sec-bit/awesome-buggy-erc20-tokens/blob/master/ERC20_token_issue_list.md#a16-custom-call-abuse
ERC827 implementation has been transferred to a new repository.
Repo Address https://github.com/windingtree/erc827
Further discussion and improvements would be conducted within this field.
SECBIT team would also join in developing ERC827 to enhance the Ethereum ecosystem. In the mean time, please take extreme care when deploying contracts, especially those which are new and immature. Developers should test and assess their code adequately, also contact professional auditing teams if necessary.
[1] ERC827 Token Standard (ERC20 Extension) ethereum/EIPs#827
[2] SECBIT: ERC223及ERC827实现代码欠缺安全考虑 —— ATN Token中的CUSTOM_CALL漏洞深入分析 https://mp.weixin.qq.com/s/kgo_FA1lCvuglC9cG-V2cQ
[3] ERC827: abuse of CUSTOM_CALL will cause unexpected result #1044 OpenZeppelin/openzeppelin-contracts#1044 (comment)
[4] A Collection of Vulnerabilities in ERC20 Smart Contracts With Tokens Affected https://github.com/sec-bit/awesome-buggy-erc20-tokens
[5] Token Contract Risk - A Joint Open Source Project by Loopring & SECBIT https://medium.com/loopring-protocol/token-contract-risk-list-a-joint-open-source-project-by-loopring-secbit
[6] ERC827 Token Standard https://github.com/windingtree/erc827
All data above comes from SECBIT, please send emails to [email protected] if interested.