0
pragma solidity ^0.4.21;

contract Lottery {
  address public manager;
  address[] public players;

  constructor() public {
    manager = msg.sender;
  }

  function enter() public payable {
    require(msg.value > .01 ether);

    players.push(msg.sender);
  }

  function random() private view returns (uint) {
    return uint(keccak256(abi.encodePacked(block.difficulty, now, players)));
  }

  function pickWinner() public restricted {
    uint index = random() % players.length;

    players[index].transfer(address(this).balance);

    players = new address[](0);
  }

  function getPlayers() public view returns (address[]) {
    return players;
  }

  modifier restricted() {
    require(msg.sender == manager);
    _;
  }
}

I want o change the function

function enter() public payable {
    require(msg.value > .01 ether);

    players.push(msg.sender);
}

Instead of ether, user use our token/erc20 to enter the lottery

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100

1 Answers1

1

You can define an interface (in your contract) of the token contract. Since you're only going to be using the transferFrom() function, this is the only function that you need to define in the interface (no matter that the token contract contains other functions as well).

interface IERC20 {
    function transferFrom(address _from, address _to, uint256 _amount) external returns (bool);
}

The you can execute the transferFrom() function of the token, passing it arguments:

  • from: the user executing your enter() function
  • to: your contract
  • amount: Assuming the token has 18 decimals (most tokens do), you can use the ether helper unit, because it effectively calculates "0.01 * 10^18 (or 10^16, or 10000000000000000) of the token smallest units", which is 0.01 of the token. Otherwise, you'll need to recalculate this number based on the token decimals.
function enter() public payable {
    IERC20 token = IERC20(address(0x123)); // Insert the token contract address instead of `0x123`
    require(token.transferFrom(msg.sender, address(this), .01 ether));

    players.push(msg.sender);
}

Important: Mind that the user needs to approve() your contract to spend their tokens beforehand (from their address), otherwise the token transfer would fail. There's a security reason for that, read more about it in the bottom part of this answer.

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • Thank you for this, Can you give me an example to invoke user to approve token contract to use as their payment? – Lloyd Ramos May 24 '21 at 13:47
  • The user needs to execute the `approve()` function of the token contract (e.g. USDT), with arguments 1) your contract as the spender, 2) max amount of tokens that you're allowed to spend. Example: `approve(0x123, 1000)` - this will allow address `0x123` to spend `1000` token units (mind the decimals - if a token uses 18 decimals, this value would need to be 1000 * 10^18)... They can execute the function using their wallet software (only some have this feature) or some third party app. Or a webpage can prepare transaction executing the function and then just open a MetaMask window to confirm. – Petr Hejda May 24 '21 at 13:51
  • Sir one last question, can I change sa placeholder text of "payableAmount (BNB)" to payableAmount (TokenName)? – Lloyd Ramos May 24 '21 at 14:49
  • Where is the placeholder text? I can't see it in your question, nor the answer. – Petr Hejda May 24 '21 at 15:54