Ethers js передает ERC20 между контрактами

У меня есть 2 контракта, первый — это токен openzeppelin ERC20, а второй — лотерейный контракт, где игроки могут делать ставки на число.

лотерея.соль

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,});
}

Есть 2 проблемы с этим кодом:

  1. Я должен одобрять контракт каждый раз, даже если я одобряю maxAmount выше, чем сумма ставки. Как мне сообщить Metamask, что контракт уже утвержден?
  2. После утверждения токена ERC20 токен для передачи на самом деле является токеном ETH, а не токеном ERC20, определенным в Token.sol. Как мне указать, что ERC20 — это токен для передачи?

Я тестирую в тестовой сети Kovan.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
145
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В вашей функции stakeBet вы вызываете эти функции по порядку:

 await token.approve(stakingContract.address, maxAmount);

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

Когда вы вызываете утверждение, вы фактически обновляете сопоставление 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/

Все адреса кошельков Ethereum совместимы с ERC20. Более того, это означает, что каждый перевод ERC20 может происходить между двумя адресами кошелька Ethereum или адресами, совместимыми с ERC20. Обычно это включает в себя все блокчейны, совместимые с EVM. Вы отправляете токен weth, и пользователь может поменяться местами в метамаске:

Спасибо. Ваш ответ помогает с 1-й частью. Но что я имел в виду во второй части, так это то, что я хочу передать свой токен ERC20, но после одобрения Metamask отправляет ETH. Это не то, чего я хочу. Я хочу отправить свою монету.

Radim 16.03.2022 10:09

Для 1-я часть вы сделали то, что намеревались сделать, т. е. вы установили разрешение на максимальную сумму, чтобы пользователю не приходилось каждый раз платить за вызывающую транзакцию для allow().

MetaMask запрашивает ваше разрешение на комиссию за газ (в ETH) за отправку токенов на сумму «betAmount» в контракт.

Я новичок в эфириуме, но сталкивался с подобными обстоятельствами в своих проектах. Так это в моем понимании.

Кроме того, для 2-я проблема, как я уже говорил ранее, MetaMask запрашивает ваше разрешение на оплату комиссии за газ (которую он берет в ETH, но фактическая передача токенов также должна иметь место. Только некоторое количество ETH тратится на «Газовые сборы».

У меня есть очень хорошая статья, обсуждающая то же самое. Ссылка: https://medium.com/ethex-market/erc20-approve-allow-explained-88d6de921ce9

Вы можете увидеть демонстрацию того, что я только что сказал. Вы можете видеть, что плата за газ взимается в ETH. Кроме того, если бы вы не установили лимит раньше на максимум, вам пришлось бы заплатить плата за газ два раза за транзакцию с вашим контрактом, сначала для вызова Approval() для лимита, а затем для получения количества переданных токенов «betAmount». к контракту.

Другие вопросы по теме