0

I recently published an ERC-20 token on mainnet and all is working well. Now I am attempting to write a Faucet smart contract in order to distribute coins to whoever asks for them. Note that this wouldn't be a faucet that mints new tokens directly from the Token contract but one that I can preload with tokens (via sending to the faucet from my wallet).

I've put together a smart contract for the faucet from various sources and everything works fine except for the 'withdraw' function. I am getting the following error:

truffle(development)> FaucetDeployed.withdraw()
Uncaught Error: Returned error: VM Exception while processing transaction: revert
    at evalmachine.<anonymous>:0:16
    at sigintHandlersWrap (vm.js:273:12)
    at Script.runInContext (vm.js:142:14)
    at runScript (C:\Users\Jonathan\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\console.js:364:1)
    at Console.interpret (C:\Users\Jonathan\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\console.js:379:1)
    at bound (domain.js:421:15)
    at REPLServer.runBound [as eval] (domain.js:432:12)
    at REPLServer.onLine (repl.js:909:10)
    at REPLServer.emit (events.js:400:28)
    at REPLServer.emit (domain.js:475:12)
    at REPLServer.Interface._onLine (readline.js:434:10)
    at REPLServer.Interface._normalWrite (readline.js:588:12)
    at Socket.ondata (readline.js:246:10)
    at Socket.emit (events.js:400:28) {
  data: {
    '0xf08ce8522dce0fb4c19ac791e5a7960055e1ad0e106761efa8f411c1cc9e23c9': { error: 'revert', program_counter: 677, return: '0x' },
    stack: 'c: VM Exception while processing transaction: revert\n' +
      '    at Function.c.fromResults (C:\\Users\\Jonathan\\AppData\\Roaming\\npm\\node_modules\\ganache-cli\\build\\ganache-core.node.cli.js:4:192416)\n' +
      '    at w.processBlock (C:\\Users\\Jonathan\\AppData\\Roaming\\npm\\node_modules\\ganache-cli\\build\\ganache-core.node.cli.js:42:50915)\n' +
      '    at runMicrotasks (<anonymous>)\n' +
      '    at processTicksAndRejections (internal/process/task_queues.js:95:5)',
    name: 'c'

Here's my Faucet smart contract code:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

contract Faucet {
    address payable owner;
    IERC20 private _token;
    uint256 public withdrawalAmount = 50 * (10 ** 18);

    event Withdrawal(address indexed to, uint amount);
    event Deposit(address indexed from, uint amount);

    constructor (IERC20 token) {
        _token = token;
        owner = payable(msg.sender);
    }

    // Accept any incoming amount
    receive() external payable {
        emit Deposit(msg.sender, msg.value);
    }

    // Give out ether to anyone who asks
    function withdraw() public {
        // Limit withdrawal amount to 1,000 tokens
        require(
            withdrawalAmount <= 1000 * (10 ** 18),
            "Request exceeds maximum withdrawal amount of 1000 ICHC"
          );

        require(
            _token.balanceOf(address(this)) >= withdrawalAmount,
            "Insufficient balance in faucet for withdrawal request"
        );

        require(
            msg.sender != address(0),
            "Request must not originate from a zero account"
        );

        // Send the amount to the address that requested it
        _token.transfer(msg.sender, withdrawalAmount);
    }

    // setter for withdrawl amount
    function setWithdrawalAmount(uint256 amount) public onlyOwner {
        // Limit max withdrawal amount to 10,000 tokens
        require(amount <= 10000 * (10 ** 18));
        withdrawalAmount = amount * (10 ** 18);
    }

    // Contract destructor
    function destroy() public onlyOwner {
        selfdestruct(owner);
    }

    // Access control modifier
    modifier onlyOwner {
        require(msg.sender == owner, "Only the contract owner can call this function");
        _;
    }
}

I'm deploying it as well as the ERC20 token to a local ganache blockchain via 'truffle migrate'. Then I test it using the following commands in the truffle console:

Setup:

Faucet.deployed().then(i=>{FaucetDeployed = i});
MyToken.deployed().then(s=>{ token = s });

Load Faucet with tokens:

token.transfer("0x55b9bCF39F78ef22E452d54957366cCBFffaF85E","300000000000000000000")

Check Faucet balance:

token.balanceOf("0x55b9bCF39F78ef22E452d54957366cCBFffaF85E").then((b)=> { balf = b })
balf.toString() // shows "300000000000000000000"

Attempt to withdrawal from Faucet:

FaucetDeployed.withdraw()

This results in the error at the top of this post. I have tried removing all the require statements, but same result. I'm sure I'm overlooking something really dumb. Can anyone spot what I'm doing wrong? I appreciate any advice - thanks!

  • Jonathan
jspru
  • 1,060
  • 1
  • 9
  • 17
  • How do you set `token` in `constructor`?! Try this code: `constructor (address tokenAddress)` and next line: `_token = IERC20(tokenAddress)` – Ahmad Gorji Nov 04 '21 at 15:15
  • Thanks Ahmad. The 'token' argument in the constructor inherits it's type from the imported IERC20 contract. I pass in the token address when deploying the faucet contract. – jspru Nov 04 '21 at 15:36
  • Ahmad - I just tried your approach but unfortunately getting the same error. Thanks for the suggestion. – jspru Nov 04 '21 at 15:46
  • Could you please deploy both token and faucet contract on rinkeby testnet to see what error does it throw?! I am not familiar with truffle. – Ahmad Gorji Nov 04 '21 at 18:04
  • I tried a simple token and your faucet contract on Rinkeby testnet but it throws no error and works fine – Ahmad Gorji Nov 04 '21 at 18:24
  • Hi Ahmad. Ok I will try deploying to Rinkeby. My testing so far has only been with a local Ganache instance so maybe there is some problem in local Ganache where 'msg.sender' is not set properly or something similar (?) I am not sure how to invoke contract functions in Rinkeby but I will research it a bit an try it out. Thanks. – jspru Nov 04 '21 at 18:59
  • It works on Rinkeby! So there is some problem with testing locally with Ganache / Truffle and seems like the code was fine. Takeaway: only test very simple stuff in local env. Do you want to reply to the main question so I can mark your answer as accepted? Thanks for the help. – jspru Nov 04 '21 at 21:43
  • It is likely some errors which happens on local test networks like Ganache or Truffle, do not happen in testnets or mainnet. No there is no need for that to have accepted answer, when someone search for the problem, it should read all the comments too – Ahmad Gorji Nov 05 '21 at 08:25

0 Answers0