【问题标题】:Smart Contract can not add transfer function inside the contract智能合约不能在合约内部添加转账功能
【发布时间】:2021-11-11 17:46:33
【问题描述】:

如何使用 openZeppelin 向用户添加合约上的转账功能?

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TokenSample is ERC20 {
    constructor() ERC20("TokenSample", "SMPL") {
        _mint(msg.sender, 21000000 * 10 ** decimals());
    }
}

当我部署上述合约时,我得到一个带有 2 个参数(收件人、金额)的转账表格。没关系。

但由于一个原因,我需要在合约内部实现自己的传输函数。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TokenSample is ERC20 {
    constructor() ERC20("TokenSample", "SMPL") {
        _mint(msg.sender, 21000000 * 10 ** decimals());
    }

 function getToken(uint256 _amount) external returns(bool)  {
   // my internal logic here
   transfer(msg.sender, _amount);
    return true;
 }
}

从代码中我得到错误:ERC20:转账金额超过余额

我不太确定,但我来宾是因为令牌属于所有者而不属于合同。实现该 getToken 方法的正确方法是什么?

【问题讨论】:

    标签: solidity smartcontracts


    【解决方案1】:

    transfer amount exceeds balance 错误消息来自失败的检查发件人是否有足够的余额。来源:OpenZeppelin GitHub 上的ERC20.sol

    如果transfer() 函数是从合约函数中调用的(而不是由用户直接调用),则发送者就是合约。

    所以合同中的这一行

    transfer(msg.sender, _amount);
    

    正在尝试从合约地址向用户发送_amount的令牌(执行getToken()函数)。当它试图转移比发送者(合约)拥有的更多的代币时,它会失败并显示此错误消息。


    通过这种方式,您可以向用户铸造新代币(增加总供应量)。

    function getToken(uint256 _amount) external {
        // TODO your own logic here
        _mint(msg.sender, _amount);
    }
    

    如果你想在部署期间将一些代币铸造到合约地址,你可以使用address(this)作为接收者,它代表当前的合约地址。

    constructor() {
        // mint 10M tokens to the contract
        _mint(address(this), 10000000 * 10 ** decimals());
        
        // mint 21M tokens to the owner
        _mint(msg.sender, 21000000 * 10 ** decimals());
    
        // total supply is now 31M, where the contract owns 10M and the owner owns 21M
    }
    

    【讨论】:

    • 那么如何让发送者通过调用getToken方法获取token呢?发送
    • @Yusnee 如果您希望用户从合约余额中接收代币(不改变总供应量),您需要先向合约发送(或铸造)一些余额...如果您希望他们获得新铸造的代币(增加总供应量),您可以使用内部 _mint() 函数。我用后者的一个例子更新了我的答案。
    • 是的,我尝试了 _min,但它增加了总供应量。我想保持总供应量。我的更多问题是:为什么使用 openZeppelin 使令牌属于所有者而不是合同?顺便说一句,在上述情况下,我是否必须让所有者将所有代币发送到合约?
    • @Yusnee 我现在明白你的意思了。您也可以在部署期间为合约铸造代币。我也用一个例子更新了答案。
    • 好的。但这不是关于总供应量,而是发送者如何获得令牌。根据您的意见,我的想法是,我可以使用 _mint,但要限制铸币总量,使其成为最后的最大供应量。
    猜你喜欢
    • 1970-01-01
    • 2022-12-06
    • 2018-09-23
    • 2022-08-03
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    相关资源
    最近更新 更多