token - 通过合约发送代币时出现 SafeMath 错误
问题描述
在尝试通过合约发送代币时,我遇到了错误消息:“SafeMath:减法溢出。”
最初我只使用了传输功能。但是,正如我认为 msg.sender 只需将其令牌发送给其他用户(通过松露控制台,这没有问题)。然而,阅读 [this] 我得到的印象实际上是合约地址成为了 TokenContract 中的 msg.sender。因此,(仅作为账户而不是合约本身)我认为我必须先向合约发送代币,然后批准合约允许代表 msg.sender 发送代币,然后再转账。但是,我一直遇到 SafeMath 错误。
TokenContract(不是下面的接口)实现了我的代码最简单的版本如下:
contract ContractA {
function pay () public returns (bool) {
TokenContract tk = TokenContract("tokenContractAddress");
tk.transferFrom(msg.sender, address(this), 5);
tk.approve(address(this), 5);
tk.transfer("someAccount", 5);
return true;
}
}
interface TokenContract {
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount) external returns (bool);
}
contract TokenContract is ERC20, ERC20Detailed {
constructor() ERC20Detailed("Token", "TKN", 18) public {
_mint(msg.sender, 1000);
}
}
显然,我不希望出现 safeMath 错误。当我转帐并批准时。我只是期望与使用松露控制台时相同的行为。
解决方案
我假设地址调用ContractA
没有为合同设置津贴。
要求:
* 调用者必须sender
至少有 ' 的代币amount
。 https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.3.0/contracts/token/ERC20/ERC20.sol/** * @dev See `IERC20.transferFrom`. * * Emits an `Approval` event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of `ERC20`; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `value`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { _transfer(sender, recipient, amount); _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount)); return true; }
- 合约 A
approve
的调用者作为代币的津贴 - Caller of Contract A 调用
pay
函数,transferFrom
在先前设置的允许范围内将调用从用户转移到接收者。
如果您正在创建 ERC20 代币,您可能需要查看 OpenZeppelin Contracts 实现,看看这是否满足您的需求。有关详细信息,请参阅文档:https ://docs.openzeppelin.com/contracts/2.x/tokens#ERC20
如果您要转移各种 ERC20 代币,您可能需要考虑使用 SafeERC20 包装器进行这些调用:https ://docs.openzeppelin.com/contracts/2.x/api/token/erc20#SafeERC20
如果您需要 ERC20 的接口,您可能希望使用 IERC20:https ://docs.openzeppelin.com/contracts/2.x/api/token/erc20#IERC20
作为 ERC20 的替代方案,您可以考虑创建 ERC777 代币(无需在两个单独的交易中进行批准和 transferFrom)。有关详细信息,请参阅文档:https ://docs.openzeppelin.com/contracts/2.x/tokens#ERC777
如果您对使用 OpenZeppelin 有任何疑问,可以在社区论坛中提问:https ://forum.openzeppelin.com/
披露:我是 OpenZeppelin 的社区经理
推荐阅读
- c# - 如何修复减法、乘法和除法 C# 的代码
- javascript - 如何根据提交而不是合并的拉取请求配置发布起草者
- javascript - 设置间隔功能
- elasticsearch - 按数组项或空数组过滤
- python - 为什么 request.method 没有被调用?
- reactjs - 如何使用 TypeScript 以类型安全的方式访问 React 子元素道具?
- python - 如何从 CSV 解析日期时间?
- python - 如何将列附加到字典内的数据框
- plsql - 交互式网格:仅使用不基于表的 PL/SQL 处理
- java - 从 yml 加载属性文件作为 JUNIT 中的工厂 Bean