ERC20 如何將代幣從合約轉移到賬戶?
該合約創建了代幣並將其儲存在自己的地址(合約地址)中。
我想實現一個將令牌從這個合約地址轉移到帳戶地址的功能。
pragma solidity ^0.8.4; import "@openzeppelin/contracts@4.5.0/token/ERC20/ERC20.sol"; contract MyToken is ERC20 { constructor() ERC20("MyToken", "MTK") { _mint(address(this), 500 * 10 ** decimals()); } function testTra(address _to, uint _amount) public{ transfer(_to,_amount); } }
它沒有用,它顯示 remix ide 中的錯誤。
ERC20: transfer amount exceeds balance
此外,當我檢查合約地址的 balanceOf 時,它顯示它有代幣。
基本上,我想要的是一個使用者呼叫
testTra()
來獲得 ERC20 代幣的獎勵。使用者如何從 MyToken 合約中接收代幣?
根據 OpenZeppelin 文件(OpenZeppelin),傳遞函式必須滿足以下條件:
- 收件人不能是零地址。
- 呼叫者必須至少有一個餘額。
呼叫者表示 msg.sender。現在當有人呼叫你的合約時,他們的地址就是 msg.sender。當呼叫 transfer 函式時,它會檢查 msg.sender 是否有足夠的餘額。然而,所有的代幣餘額實際上都在合約地址中,這就是為什麼 msg.sender 的餘額為 0。因此交易失敗。
所以簡而言之,當人 A 呼叫你的 testTra 函式時,合約會嘗試將人 A 的餘額發送到*_to*參數中指定的地址。
你的邏輯問題是,如果你為合約地址鑄造代幣,你就不能對這些代幣做任何事情,因為在這種情況下你的合約永遠不會是 msg.sender 。因此,您既不能在 testTra 函式中給予津貼,也不能使用 transferFrom 或 transfer。但是,您可以做的是使用另一個地址(如另一個智能合約)作為代幣管理器並將代幣鑄造到該地址。
pragma solidity ^0.8.4; import "@openzeppelin/contracts@4.5.0/token/ERC20/ERC20.sol"; contract MyToken is ERC20 { constructor(address _manager) ERC20("MyToken", "MTK") { _mint(_manager, 500 * 10 ** decimals()); } function testTra(address _to, uint _amount) external{ transfer(_to,_amount); } } contract ManagerContract { address public myTokenAddress; address public owner; constructor(){ owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner); _; } modifier addressIsNotEmpty() { require(myTokenAddress != address(0), "Address is empty!"); _; } function setMyTokenAddress(address _myTokenAddress) public onlyOwner { myTokenAddress = _myTokenAddress; } function testTra(address _to, uint _amount) public addressIsNotEmpty { (bool success, ) = myTokenAddress.call(abi.encodeWithSignature("testTra(address,uint256)",_to,_amount)); } }
將會發生的是,您首先部署您的 ManagerContract。然後您將通過在建構子中提供 ManagerContract 的地址來部署 TokenContract。之後,您將使用 TokenContract 的地址呼叫 setMyTokenAddress 函式。通過這種方式,使用者現在必須呼叫管理器合約中的 testTra 函式來獲取代幣。之後,使用者可以正常與 TokenContract 互動。