【问题标题】:Ethers js transferring ERC20 between contractsEthers js 在合约之间传输 ERC20
【发布时间】:2022-07-31 06:16:17
【问题描述】:

我有两份合约,第一份是 openzeppelin ERC20 代币,第二份是彩票合约,玩家可以在其中下注。

lottery.sol

pragma solidity ^0.8.4;
import "./Token.sol"; //import ERC20 token
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Lottery is Ownable {

Token token;
constructor(Token _token) public {
   token = _token;
}

// store information about player's bet
struct PlayersStruct {
   uint betAmount;
   uint betOnNumber;
}

mapping(address => PlayersStruct) public balances;

function enterLottery(string memory _betOnNumber) public payable {

    address player = msg.sender;
    uint amount = msg.value;

    // transfer token from player's wallet to lottery contract
    token.transferFrom(player, address(this), betAmount);

    balances[player].betAmount += amount ;
    balances[player].betOnNumber = _betOnNumber;

}

这就是我从 ReactJS 中调用它的方式

async function stakeBet() {
   const amount = ethers.utils.parseEther("10");
   const maxAmount = ethers.utils.parseEther("1000000");

  // approve token once so player can save on gas in future
  await token.approve(stakingContract.address, maxAmount);

  // bet 10 tokens on number 20
  await lottery.enterLottery(20, {value: amount,});
}

这段代码有两个问题:

  1. 我每次都必须批准合同,即使我批准的 maxAmount 高于投注金额。我如何让 Metamask 知道合同已经获得批准?
  2. ERC20代币通过后,转出的代币实际是ETH,而不是Token.sol中定义的ERC20代币,如何指定ERC20为转出的代币?

我正在 Kovan 测试网上进行测试。

【问题讨论】:

    标签: reactjs ethereum solidity ethers.js erc20


    【解决方案1】:

    在您的 stakeBet 函数中,您按顺序调用这些函数:

     await token.approve(stakingContract.address, maxAmount);
    
      // bet 10 tokens on number 20
      await lottery.enterLottery(20, {value: amount,});
    

    调用approve 时,实际上是在更新allowance 映射。让合同知道,您允许一定数量的地址用于允许的地址。应该这样实现:

    function approve(address _spender, uint _value)public returns (bool success){
            // allowance  tells how many tokens can be sent
            allowance[msg.sender][_spender]=_value;
            // This event must trigger when a successful call is made to the approve function.    
            emit Approval(msg.sender,_spender,_value);
            return true;
     }
    

    代币转移或硬币转移实际上是在更新合约内部的状态。使用approve 函数,您可以更新津贴。现在 token.transferFrom 应该这样实现:

    // my address is allowing your address for this much token
    mapping(address=>mapping(address=>uint)) public allowance;
    
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){
            // check the allowance
            require(_value <=allowance[_from][msg.sender]);
            // update the balances
            balanceOf[_to]+=_value;
            balanceOf[_from]-=_value;
            allowance[_from][msg.sender]-=_value;
            // emitting an event
            emit Transfer(_from,_to,_value);
            return true;
        }
    
    • ETH 不是 ERC20 代币。相反,您必须实施 WETH 代币并转移 WETH 代币。 WETH 是 eth 的包装版本。 https://weth.io/

    所有以太坊钱包地址都兼容 ERC20。此外,这意味着每次 ERC20 转账都可能发生在两个以太坊钱包地址或 ERC20 兼容地址之间。这通常包括所有与 EVM 兼容的区块链。您发送 weth 令牌,用户可以交换元掩码:

    【讨论】:

    • 谢谢。您的回答有助于第一部分。但我第二部分的意思是我想转移我的 ERC20 代币,但在批准后 Metamask 正在发送 ETH。这不是我想要的。我想发送我的硬币。
    【解决方案2】:

    对于第一部分,您已经完成了您打算做的事情,即您已将津贴设置为最大金额,以便用户不必为允许的通话交易付费() 每次。

    MetaMask 请求您同意向合约发送“betAmount”数量的代币的汽油费(以 ETH 为单位)。

    我是以太坊的新手,但我在项目中遇到过类似的情况。所以,这是根据我的理解。

    另外,对于第二个问题,正如我之前所说,MetaMask 要求您同意支付 gas 费用(它需要 ETH,但也必须进行代币的实际转移. 只是,一些 ETH 被用于“Gas Fee”。

    我有一篇非常好的文章讨论了同样的事情。 链接:https://medium.com/ethex-market/erc20-approve-allow-explained-88d6de921ce9

    你可以看到我刚才所说的演示。您可以看到 Gas 费用以 ETH 计入。此外,如果您之前没有将配额设置为最大值,则您必须支付 gas 费 两次才能使您的合同发生交易,首先调用approve() 以获得配额,然后才能获得转移到合约的代币“betAmount”数量。

    【讨论】:

      猜你喜欢
      • 2022-12-16
      • 2022-10-13
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      • 2021-09-17
      • 2023-01-08
      • 2022-01-01
      • 2020-09-14
      相关资源
      最近更新 更多