Im unable to get top 3 winners address and cannt transfer the reward Once Betting Result is out Top 3 people will get rewards of total pool amount. Transfer 80% to Top 3 of total collected bet and keep 20% on treasury pool give code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

contract NFTBettingGame is ERC721, ERC721URIStorage, Ownable {
uint256 public constant MAX_NFTS = 5;
uint256 public constant BETTING_FEE = 0.01 ether;
uint256 public totalBets;
uint256 public pot;
address payable public winner;
bool public bettingClosed = false;
uint256 public tokenIdList;
uint256 public totalSupply;
uint256 public constant TREASURY_FEE_PERCENTAGE = 5;
uint public treasuryPool;
uint256 private _totalBetAmount;
string public _uri;

mapping(address => uint256) public betAmount;
mapping(address => bool) public hasMinted;
mapping(uint256 => mapping(address => uint256)) public betAmounts;
mapping(address => uint256[]) public winners;

using Counters for Counters.Counter;

Counters.Counter private currentTokenId;

string public baseTokenURI;

constructor(string memory uri) ERC721("NFTBETTING", "BET") {
    _uri = uri;
    // baseTokenURI = "" ;
}

function mintTo(address recipient) public returns (uint256) {
    currentTokenId.increment();
    uint256 newItemId = currentTokenId.current();
    _safeMint(recipient, newItemId);
    return newItemId;
}

function _baseURI() internal view virtual override returns (string memory) {
    return baseTokenURI;
}

function setBaseTokenURI(string memory _baseTokenURI) public {
    baseTokenURI = _baseTokenURI;
}

function mintNFT() public payable {
    require(
        msg.value >= BETTING_FEE,
        "Not enough ether to participate in the game"
    );
    require(totalSupply < MAX_NFTS, "Maximum NFTs have been minted");
    require(hasMinted[msg.sender] == false, "You already minted an NFT");

    uint256 tokenId = currentTokenId.current();
    currentTokenId.increment();

    totalBets++;
    pot += msg.value;
    betAmount[msg.sender] = msg.value;
    tokenIdList.push(totalSupply);
    totalSupply++;
    hasMinted[msg.sender] = true;
    _safeMint(msg.sender, tokenId);
    _setTokenURI(tokenId, _uri);
}

function placeBet(uint256 tokenId) public payable {
    require(bettingClosed == false, "Betting is closed");
    require(totalSupply == MAX_NFTS, "All NFTs have been minted");
    require(winner == address(0), "Winner has already been chosen");
    require(ownerOf(tokenId) != address(0), "Invalid NFT token ID");

    uint256 betAmount = msg.value;
    require(betAmount > 0, "Bet amount must be greater than 0");

    pot += betAmount;
    betAmounts[tokenId][msg.sender] += betAmount;
}

function closeBetting() public onlyOwner {
    require(totalSupply == MAX_NFTS, "Not all NFTs have been minted");
    require(bettingClosed == false, "Betting is already closed");
    bettingClosed = true;
}

function contains(
    uint256[] memory array,
    uint256 value
) private pure returns (bool) {
    for (uint256 i = 0; i < array.length; i++) {
        if (array[i] == value) {
            return true;
        }
    }
    return false;
}

function chooseWinner()
    public
    onlyOwner
    returns (address payable[3] memory)
{
    require(totalSupply == MAX_NFTS, "Not all NFTs have been minted");
    require(bettingClosed == true, "Betting is still open");
    require(winner == address(0), "Winner has already been picked");

    address payable[3] memory topWinners;
    uint256[3] memory topWinnersAmount;
    uint256 totalBetAmount = 0;

    for (uint256 i = 0; i < tokenIdList.length; i++) {
        address tokenOwner = ownerOf(tokenIdList[i]);

        if (tokenOwner == address(0)) {
            for (uint256 j = 0; j < 3; j++) {
                uint256 amount = betAmounts[tokenIdList[i]][msg.sender];
                if (amount > topWinnersAmount[j]) {
                    for (uint256 k = 2; k > j; k--) {
                        topWinners[k] = topWinners[k - 1];
                        topWinnersAmount[k] = topWinnersAmount[k - 1];
                    }
                    topWinners[j] = payable(msg.sender);
                    topWinnersAmount[j] = amount;
                    break;
                }
            }
            totalBetAmount += betAmounts[tokenIdList[i]][msg.sender];
        }
    }

    uint256 rewardPool = (pot * 8) / 3;
    uint256 remainingPool = rewardPool;
    for (uint256 i = 0; i < 3; i++) {
        if (topWinnersAmount[i] == 0) {
            break;
        }

        uint256 reward = (rewardPool * topWinnersAmount[i]) /
            totalBetAmount;
        _transfer(address(this), topWinners[i], reward);
        remainingPool -= reward;
    }

    uint256 treasuryAmount = (remainingPool * 2) / 3;
    uint256 winnerReward = remainingPool - treasuryAmount;
    if (tokenIdList.length > 0) {
        winner = payable(
            ownerOf(tokenIdList[random() % tokenIdList.length])
        );
        winner.transfer(winnerReward);
    }

    treasuryPool += treasuryAmount + remainingPool;

    return topWinners;
}

function random() private view returns (uint256) {
    return
        uint256(
            keccak256(
                abi.encodePacked(
                    block.difficulty,
                    block.timestamp,
                    tokenIdList
                )
            )
        );
}

function refundBets() public {
    require(bettingClosed == true, "Betting is still open");
    require(winner != address(0), "Winner has not been picked yet");
    require(msg.sender != winner, "Winner cannot refund their bet");

    uint256 amount = betAmount[msg.sender];
    require(amount > 0, "You did not participate in the betting");

    betAmount[msg.sender] = 0;
    payable(msg.sender).transfer(amount);
}

}

What error do you get when you try to get call function?
Can you share us failed tx link?

I want the top 3 winners, but it only gives one winner, and it transfers to the one winner, not the top 3 winners.

only the owner can call this function.
int256 amount = betAmounts[tokenIdList[i]][msg.sender];
msg.sender = always the owner, so will return 0 for almost all bets unless the owner made a bet

topWinners[j] = payable(msg.sender);
so topWinners[j] = always the owner

So pretty much the only possible winner is the owner of the contract, noone else

btw: this is absolutely NOT how you get a random number on the blockchain :slight_smile: the outcome of this function is easily to predicted

But I don't want that contract owner to be the winner.?

According to your code, the owner is the ONLY possible winner. Noone else can win