在尝试通过合同发送令牌时,我遇到错误消息:“ 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错误。当我转帐并批准时。我只是期望与使用松露控制台时的行为相同。
答案 0 :(得分:3)
我假设调用ContractA
的地址没有为合同设置津贴。
要求:
*呼叫者必须允许至少sender
的{{1}}令牌使用。 https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.3.0/contracts/token/ERC20/ERC20.solamount
/**
* @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;
}
对该代币进行配额approve
函数,并调用pay
在先前设置的限额内从用户转移到接收者。如果您正在创建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的社区经理