通过合约发送代币时出现 SafeMath 错误
SafeMath error on sending tokens via contract
在尝试通过合约发送代币时,我 运行 收到错误消息:"SafeMath: subtraction overflow."
最初我只使用传输功能。然而,正如我认为 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
的地址没有为合约设置津贴。
Requirements:
* the caller must have allowance for sender
's tokens of at least 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
代币的津贴
- 合约 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 代币(无需在两个单独的交易中执行 approve 和 transferFrom)。详情见文档:https://docs.openzeppelin.com/contracts/2.x/tokens#ERC777
如果您对使用 OpenZeppelin 有任何疑问,可以在社区论坛中提问:https://forum.openzeppelin.com/
披露:我是 OpenZeppelin 的社区经理
在尝试通过合约发送代币时,我 运行 收到错误消息:"SafeMath: subtraction overflow."
最初我只使用传输功能。然而,正如我认为 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
的地址没有为合约设置津贴。
Requirements:
* the caller must have allowance forsender
's tokens of at leastamount
. 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 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 代币(无需在两个单独的交易中执行 approve 和 transferFrom)。详情见文档:https://docs.openzeppelin.com/contracts/2.x/tokens#ERC777
如果您对使用 OpenZeppelin 有任何疑问,可以在社区论坛中提问:https://forum.openzeppelin.com/
披露:我是 OpenZeppelin 的社区经理