【问题标题】:A Lottery Solidity Contract to use custom token as payment instead of ether使用自定义代币代替以太币作为支付方式的 Lottery Solidity 合约
【发布时间】:2023-01-16 05:55:39
【问题描述】:

我正在构建一个彩票 dapp,我需要一些帮助来解决一个问题:我想使用我的自定义令牌而不是以太币来购买彩票。

以下是彩票合约:

pragma solidity >=0.7.0 <0.9.0;

contract Lottery {
    uint256 public constant ticketPrice = 0.01 ether;
    uint256 public constant maxTickets = 100; // maximum tickets per lottery
    uint256 public constant ticketCommission = 0.001 ether; // commission per ticket
    uint256 public constant duration = 30 minutes; // The duration set for the lottery

    uint256 public expiration; // Timeout in case That the lottery was not carried out.
    address public lotteryOperator; // the creator of the lottery
    uint256 public operatorTotalCommission = 0; // the total commission balance
    address public lastWinner; // the last winner of the lottery
    uint256 public lastWinnerAmount; // the last winner amount of the lottery
    address public allWinners; // get all lottery winners
    uint256 public lotteryId; // get lotteryID
    address payable[] public players; // return all Players

    mapping(address => uint256) public winnings; // maps the winners to there winnings
    address[] public tickets; //array of purchased Tickets

    // modifier to check if caller is the lottery operator
    modifier isOperator() {
        require(
            (msg.sender == lotteryOperator),
            "Caller is not the lottery operator"
        );
        _;
    }

    // modifier to check if caller is a winner
    modifier isWinner() {
        require(IsWinner(), "Caller is not a winner");
        _;
    }

    constructor() {
        lotteryOperator = msg.sender;
        expiration = block.timestamp + duration;
        lotteryId = 0;
    }
    
    // return all winners
    function getWinners() public view returns (address[] memory) {
        return allWinners;
    }

    // return all the tickets
    function getTickets() public view returns (address[] memory) {
        return tickets;
    }

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

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

    function getWinningsForAddress(address addr) public view returns (uint256) {
        return winnings[addr];
    }

    function getLotteryId() public view returns(uint256) {
        return lotteryId;
    }

    function BuyTickets() public payable {
        require(
            msg.value % ticketPrice == 0,
            string.concat(
                "the value must be multiple of ",
                Strings.toString(ticketPrice),
                " Ether"
            )
        );
        uint256 numOfTicketsToBuy = msg.value / ticketPrice;
        players.push(payable(msg.sender));

        require(
            numOfTicketsToBuy <= RemainingTickets(),
            "Not enough tickets available."
        );

        for (uint256 i = 0; i < numOfTicketsToBuy; i++) {
            tickets.push(msg.sender);
        }
    }

    function DrawWinnerTicket() public isOperator {
        require(tickets.length > 0, "No tickets were purchased");

        bytes32 blockHash = blockhash(block.number - tickets.length);
        uint256 randomNumber = uint256(
            keccak256(abi.encodePacked(block.timestamp, blockHash))
        );
        uint256 winningTicket = randomNumber % tickets.length;

        address winner = tickets[winningTicket];
        lastWinner = winner;
        winnings[winner] += (tickets.length * (ticketPrice - ticketCommission));
        lastWinnerAmount = winnings[winner];
        operatorTotalCommission += (tickets.length * ticketCommission);
        delete tickets;
        expiration = block.timestamp + duration;
    }

    function restartDraw() public isOperator {
        require(tickets.length == 0, "Cannot Restart Draw as Draw is in play");

        delete tickets;
        expiration = block.timestamp + duration;
    }

    function checkWinningsAmount() public view returns (uint256) {
        address payable winner = payable(msg.sender);

        uint256 reward2Transfer = winnings[winner];

        return reward2Transfer;
    }

    function WithdrawWinnings() public isWinner {
        address payable winner = payable(msg.sender);

        uint256 reward2Transfer = winnings[winner];
        winnings[winner] = 0;

        winner.transfer(reward2Transfer);
    }

    function RefundAll() public {
        require(block.timestamp >= expiration, "the lottery not expired yet");

        for (uint256 i = 0; i < tickets.length; i++) {
            address payable to = payable(tickets[i]);
            tickets[i] = address(0);
            to.transfer(ticketPrice);
        }
        delete tickets;
    }

    function WithdrawCommission() public isOperator {
        address payable operator = payable(msg.sender);

        uint256 commission2Transfer = operatorTotalCommission;
        operatorTotalCommission = 0;

        operator.transfer(commission2Transfer);
    }

    function IsWinner() public view returns (bool) {
        return winnings[msg.sender] > 0;
    }

    function CurrentWinningReward() public view returns (uint256) {
        return tickets.length * ticketPrice;
    }

    function RemainingTickets() public view returns (uint256) {
        return maxTickets - tickets.length;
    }
}

我尝试了以下“解决方案”,因为我只需要玩家购买门票但无法正常工作。因为我只需要 BuyTickets 函数来使用我的令牌,所以我有 IERC200 令牌地址。

function BuyTickets() public payable {

        IERC20 token = IERC20(address(0x123)); // Insert the token contract address 
        
        require(
            token.transferFrom(
            msg.sender, 
            address (players),
            msg.value % ticketPrice == 0,
            string.concat(
                "the value must be multiple of ",
                Strings.toString(ticketPrice),
                " Ether"
            );
        );

        uint256 numOfTicketsToBuy = msg.value / ticketPrice;
        players.push(payable(msg.sender));

        require(
            numOfTicketsToBuy <= RemainingTickets(),
            "Not enough tickets available."
        );

        for (uint256 i = 0; i < numOfTicketsToBuy; i++) {
            tickets.push(msg.sender);
        }
    }

任何帮助,将不胜感激。谢谢

【问题讨论】:

  • 你能明确你的问题吗?您是否收到 ERC20 批准的问题?
  • 它只适用于原生链代币。例如,如果我选择 BSC,它只允许我使用 BNB。我想使用 BSC 链中的另一个令牌而不是 BNB。
  • 这是用于前端 BuyTickets 的函数: } ]);
  • 我认为问题在那里,但无法弄清楚如何解决。谢谢

标签: next.js solidity


【解决方案1】:

您在第一个 require 语句中缺少 token.transferFrom 的右括号。还要确保您的合同中某处有 IERC20。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-12
    • 1970-01-01
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2021-07-17
    • 1970-01-01
    相关资源
    最近更新 更多