Thanks for your response.
I should have mentioned, I had also tried transfer
, which ends up in ERC20: transfer amount exceeds balance
I checked the balanceOf
the contract before calling endGame
to confirm the balance is as expected.
However if the balance were incorrect, it would have been caught at
uint256 _pot = g.pot;
uint256 _balance = g.token.balanceOf(address(this));
require(
g.pot <= _balance,
"Not enough of game token in reserve"
);
Full function
function endGame(
uint256 _gameNumber
) external onlyRole(CALLER_ROLE) {
Game storage g = games[_gameNumber];
require(
g.maxPlayers > 0,
"Invalid game"
);
require(
g.status == true,
"Game already ended"
);
uint256 _pot = g.pot;
uint256 _balance = g.token.balanceOf(address(this));
require(
g.pot <= _balance,
"Not enough of game token in reserve"
);
// Close game
g.status = false;
// Pick winner
uint256 _rand = _randModulus(100);
uint256 _total = g.tickets.length - 1;
uint256 _index = _rand % _total;
g.winnerAddress = g.tickets[_index];
// Send pot to winner
g.token.transfer(g.winnerAddress, _pot);
// @todo Trim superfluous game data for gas saving
totalGamesEnded++;
// Fire `GameEnded` event
emit GameEnded(
g.tokenAddress,
g.winnerAddress,
g.number,
_pot
);
}
I've included buyTicket
to show that pot
is increased (it's done this way to allow multiple games to run)
function buyTicket(
uint256 _gameNumber,
uint256 _numberOfTickets
) external {
Game storage g = games[_gameNumber];
require(
g.maxPlayers >= 0,
"Invalid game"
);
require(
g.status == true,
"Game already ended"
);
require(
_numberOfTickets > 0,
"Buy at least 1 ticket"
);
// Ensure player has enough tokens to play
uint256 _totalCost = g.ticketPrice * _numberOfTickets;
require(
g.token.allowance(msg.sender, address(this)) >= _totalCost,
"Insufficent game token allowance"
);
// Marker for new player logic
bool _isNewPlayer = false;
// Current number of tickets that this player has
uint256 _playerTicketCount = g.players[msg.sender];
// First time player has entered the game
if (_playerTicketCount == 0) {
if (g.playerCount == g.maxPlayers) {
revert("Too many players in game");
}
_isNewPlayer = true;
}
// Check the new player ticket count
uint256 _playerTicketNextCount = _playerTicketCount + _numberOfTickets;
require(
_playerTicketNextCount <= g.maxTicketsPlayer,
"Exceeds max player tickets, try lower value"
);
// Transfer `_totalCost` of `gameToken` from player, this this contract
// _safeTransferFrom(g.token, msg.sender, address(this), _totalCost);
g.token.transferFrom(msg.sender, address(this), _totalCost);
// Add total ticket cost to pot
g.pot += _totalCost;
// If a new player (currently has no tickets)
if (_isNewPlayer) {
// Increase game total player count
g.playerCount++;
// Used for iteration on game player mapping, when resetting game
g.playersIndex.push(msg.sender);
}
// Update number of tickets purchased by player
g.players[msg.sender] = _playerTicketNextCount;
// Add each of the tickets to an array, a random index of this array
// will be selected as winner.
uint256 _i;
while (_i != _numberOfTickets) {
g.tickets.push(msg.sender);
_i++;
}
// Increase total number of game player tickets
g.ticketCount += _numberOfTickets;
// Fire `TicketBought` event
emit TicketBought(
msg.sender,
g.number,
g.playerCount,
g.ticketCount
);
}