Smart contract receive multiple ERC20 tokens and then pay out them out using transfer(address(this).balance)?

How can I let my smart contract receive any erc-20 tokens and pay them out when the paywinner function is called?

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.11;

import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";

contract Ownable_Page_Lottery is VRFConsumerBase {
    address public owner;
    address payable[] public players;
    uint public lotteryId;
    mapping (uint => address payable) public lotteryHistory;

    bytes32 internal keyHash; // identifies which Chainlink oracle to use
    uint internal fee;        // fee to get random number
    uint public randomResult;

    constructor()
        VRFConsumerBase(
            0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B, // VRF coordinator
            0x01BE23585060835E02B77ef475b0Cc51aA1e0709  // LINK token address
        ) {
            keyHash = 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311;
            fee = 0.1 * 10 ** 18;    // 0.1 LINK

            owner = msg.sender;
            lotteryId = 1;
        }

    

    function getRandomNumber() public returns (bytes32 requestId) {
        require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK in contract");
        return requestRandomness(keyHash, fee);
    }

    function fulfillRandomness(bytes32 requestId, uint randomness) internal override {
        randomResult = randomness;
        payWinner();
    }

    function getWinnerByLottery(uint lottery) public view returns (address payable) {
        return lotteryHistory[lottery];
    }

    function getBalance() public view returns (uint) {
        return address(this).balance;
    }

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

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

        // address of player entering lottery
        players.push(payable(msg.sender));
    }

    function pickWinner() public onlyowner {
        getRandomNumber();
    }

    function payWinner() public {
        uint index = randomResult % players.length;
        players[index].transfer(address(this).balance);

        lotteryHistory[lotteryId] = players[index];
        lotteryId++;
        
        // reset the state of the contract
        players = new address payable[](0);
    }

    modifier onlyowner() {
      require(msg.sender == owner);
      _;
    }

    receive () external payable {}
}

I would also love for this to be able to receive 721 tokens and pay them out using the pay winner function also but erc20 is a good start. I appreciate even any advise on where to look.

Thank you!

you need to instance of ERC20 and use this function.
tokenInst.transferFrom(msg.sender, address(this), totalPay);

Thank you for your response! Excuse my ignorance, when you say an instance of erc20 does that mean to have the IERC-20 interface in my contract?

I have copied the function below, is this how you would implement it to send the erc20 balance as well as the ether balance held in the contract?

function payWinner() public {
        uint index = randomResult % players.length;
        players[index].transfer(address(this).balance);

        tokenInst.transferFrom(players[index], address(this), totalPay); //Transfer erc20 tokens to the winner 

        lotteryHistory[lotteryId] = players[index];
        lotteryId++;
        
        // reset the state of the contract
        players = new address payable[](0);
    }

Yes you need to create an interface with the transfer function.
you can implement the interface in your contract like this:

[interface name] token = [interface name]([address of token])

token.transfer(msg.sender, address(this), amount)

Don't use transferfrom this from a contract to an eoa

My project was a little different - it had to only accept multiple tokens and store them. I had 2 issues - testing the smart contract on rinkeby testnet was unconsistent, so i switched to goerli and also i started to use safetransferfrom and safetransfer.
im using remix and here is how to use it:

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

contract TestContract {

    using SafeERC20 for IERC20;

// you can use the safetransfer etc

hope this helps out with recieving tokens :smile: