以太坊js在合约之间传输ERC20

问题描述 投票:0回答:2

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

彩票.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 smartcontracts ethers.js
2个回答
3
投票

在您的

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 令牌,用户可以交换元掩码:


1
投票

对于第1部分,你已经完成了你想要做的事情,即你已经将限额设置为最大金额,这样用户就不必为每次调用allow()交易而付费。

MetaMask 正在征求您的许可,以向合约发送“betAmount”数量的代币,以支付燃气费(以 ETH 为单位)。

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

另外,对于第二个问题,正如我之前所说,MetaMask 正在请求您支付 Gas 费(以 ETH 形式支付,但代币的实际转移也必须发生)。仅需要一定数量的 ETH用于“Gas 费”。

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

你可以看我刚才说的演示。您可以看到,gas 费用是以 ETH 形式收取的。另外,如果您没有提前将限额设置为最大值,则您必须支付两次gas费用才能使您的合约发生交易,首先调用approve()以获得限额,然后获取“betAmount”金额转移到合约的代币。

© www.soinside.com 2019 - 2024. All rights reserved.