在尝试通过合约发送代币时,我遇到了错误消息:"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
的地址没有为合同设置限额。
要求:
* 调用方必须允许至少amount
sender
的令牌。 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
代币的津贴 - 合约 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的社区经理