通过合约发送代币时出现 SafeMath 错误



在尝试通过合约发送代币时,我遇到了错误消息:"SafeMath:减法溢出。

最初我只使用传输功能。但是,正如我认为msg.sender只需要将其令牌发送给其他用户(通过松露控制台,这没有问题(。然而,读到这里,我的印象是,实际上是合约地址变成了TokenContract中的msg.sender。因此,(作为账户而不是合约本身(我认为我必须先向合约发送代币,然后批准允许合约代表msg.sender发送代币,然后转移资金。但是,我一直有SafeMath错误。

令牌合约(不是下面的接口(实现了我的代码的最简单版本如下:

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);
}
}

显然,我希望不会出现安全数学错误。因为我转账并批准。我只是期望与使用松露控制台时相同的行为。

我假设呼叫ContractA的地址没有为合同设置限额。

要求:
* 调用方必须允许至少amountsender的令牌。 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;
}
  1. 合约A的调用方approve代币的津贴
  2. 合约 A 的调用方调用pay函数,该函数调用transferFrom以在先前设置的限额内从用户转移到接收方。

如果您正在创建ERC20代币,您可能需要查看OpenZeppelin合约的实现,看看这是否满足您的需求。有关详细信息,请参阅文档: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令牌(无需在两个单独的交易中进行批准和转移(。有关详细信息,请参阅文档:https://docs.openzeppelin.com/contracts/2.x/tokens#ERC777

如果您对使用 OpenZeppelin 有疑问,可以在社区论坛中提问:https://forum.openzeppelin.com/

披露:我是OpenZeppelin的社区经理

最新更新