Solidity智能合约transfer函数报uint256无sub成员是版本问题吗?
报错原因说明
- 核心原因:
sub()、add()并非uint256类型的原生成员方法,这类带溢出检查的安全算术方法是OpenZeppelin的SafeMath库提供的扩展方法,你的代码未引入SafeMath库、也未将库方法绑定到uint256类型,因此调用时会提示成员不存在。 - 该错误确实和Solidity版本直接相关:
- Solidity 0.8之前的版本(包含你使用的0.5.16):编译器默认不会做算术溢出/下溢检查,也没有内置安全算术方法,必须手动引入SafeMath库并绑定到uint256类型才能使用
sub()、add()这类链式调用方法。 - Solidity 0.8及之后的版本:编译器内置了算术溢出/下溢检查,运算溢出时会自动回滚交易,官方不再推荐使用SafeMath,原生uint256类型仍然没有
sub、add成员方法,直接使用-=、+=运算符即可满足安全需求。
- Solidity 0.8之前的版本(包含你使用的0.5.16):编译器默认不会做算术溢出/下溢检查,也没有内置安全算术方法,必须手动引入SafeMath库并绑定到uint256类型才能使用
修复方案
方案1:保留0.5.16版本,引入SafeMath库
pragma solidity ^0.5.16; // 内置精简版SafeMath库 library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } } // 将SafeMath方法绑定到uint256类型 using SafeMath for uint256; contract Token { string public name = "Token"; string public symbol = "TK"; uint256 public decimals = 18; uint256 public totalSupply; mapping(address => uint256) public balanceOf; constructor() public { totalSupply = 1000000 * (10 ** decimals); balanceOf[msg.sender] = totalSupply; } function transfer(address _to, uint256 _value) public returns(bool success){ require(balanceOf[msg.sender] >= _value, "Insufficient balance"); balanceOf[msg.sender] = balanceOf[msg.sender].sub(_value); balanceOf[_to] = balanceOf[_to].add(_value); return true; } }
方案2:升级到0.8+版本,直接使用原生运算符
pragma solidity ^0.8.0; contract Token { string public name = "Token"; string public symbol = "TK"; uint256 public decimals = 18; uint256 public totalSupply; mapping(address => uint256) public balanceOf; constructor() { totalSupply = 1000000 * (10 ** decimals); balanceOf[msg.sender] = totalSupply; } function transfer(address _to, uint256 _value) public returns(bool success){ require(balanceOf[msg.sender] >= _value, "Insufficient balance"); // 0.8+版本运算符自带溢出检查,无需额外调用安全方法 balanceOf[msg.sender] -= _value; balanceOf[_to] += _value; return true; } }
内容的提问来源于stack exchange,提问作者npkp
相关产品推荐
相关产品推荐

