Every time I try to transfer tokens from the user to the smart contract, I get the following revert
error:
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Here is my code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
contract Hilo {
uint public fee;
uint256 public maxBet;
uint256 public minBet;
address public owner;
IERC20 public immutable token;
constructor(address _tradeToken, uint initialFee, uint256 initalMaxBet, uint256 initalMinBet) {
fee = initialFee;
maxBet = initalMaxBet;
minBet = initalMinBet;
owner = msg.sender;
token = IERC20(_tradeToken);
}
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
// Underscore is a special character only used inside
// a function modifier and it tells Solidity to
// execute the rest of the code.
_;
}
function changeFee(uint newFee) public onlyOwner {
fee = newFee;
}
function changeMaxBet(uint newMaxBet) public onlyOwner {
maxBet = newMaxBet;
}
function changeMinBet(uint newMinBet) public onlyOwner {
maxBet = newMinBet;
}
function bet(uint card, string memory choice, uint256 amount, uint256 multiplier) external returns (uint nextCard) {
require(amount <= maxBet, "amount is greater than the maxBet");
require(amount >= minBet, "amount is smaller than minBet");
uint256 newAmount = amount * (fee / 1000);
require(token.balanceOf(msg.sender) >= newAmount, "Token transfer failed.");
token.transferFrom(msg.sender, address(this), newAmount);
uint next = uint(keccak256(abi.encodePacked(block.timestamp, block.difficulty,
msg.sender))) % 13 + 1;
if (keccak256(abi.encodePacked(choice)) == keccak256(abi.encodePacked('L'))) {
if (card > next) {
token.transfer(msg.sender, amount * (multiplier / 100));
return next;
}
} else if (keccak256(abi.encodePacked(choice)) == keccak256(abi.encodePacked('H'))) {
if (card < next) {
token.transfer(msg.sender, amount * (multiplier / 100));
return next;
}
}
return next;
}
}
I am using remix with a VM. And my token is successfully deployed as far as I am concerned. This error happens whenever I call any transfer
or transferFrom
method using the token
variable.
The code works fine when I remove the transfer methods but fails when I use them. I tried calling the transferFrom method directly from the ERC20 contract and it worked fine after approving the transaction. Also not sure if this is an allowance error but I have been told that if it was that type of error, then that would be the error message.
Any help is much appreciated!
Add the below function to your Hilo
smart contract.
receive() external payable {}
From solidity
v0.6
, the above fallback function is required for a smart contract to receive ether without any calldata and has value (amount of ether).
The above is applicable when you try to transfer to a deployed contract.
If you need to transfer ether to the smart contract when you create it, update your constructor to:
constructor(address _tradeToken, uint initialFee, uint256 initalMaxBet, uint256 initalMinBet) public payable {
fee = initialFee;
maxBet = initalMaxBet;
minBet = initalMinBet;
owner = msg.sender;
token = IERC20(_tradeToken);
}
This is because when you create the smart contract, it's the constructor that's called, and not the fallback. Hence you need to mark the constructor as payable
to receive ether during contract creation.