• 深入解析Pancakeswap Prediction|博饼预测玩法


    常见问题

    • 领取奖金有时间限制吗?
      没有时间限制,可以在任何时间来领取。
    • 利息是如何计算的?
      上行池的支付比率=两个池的总价值÷上行池的价值
      下行池的支付比率=两个池的总价值÷下行池的价值
      例如,如果一轮的下线有15BNB,而总奖金池为150BNB,下线支付比率将为(150/15)=10x。
      支付金额=支付比率×头寸×(1-库务费)
      在上述情况下,如果一轮以下跌结果结束,如果您向下跌头寸承诺2 BNB,您将获得(2*10)×(1-0.03)=19.4 BNB的赔付。您的利润将为174亿英镑(19.4-2英镑)。
      财政费目前设定为3%:这可能会有变化,将在PancakeSwap的官方沟通渠道上公布。国库费用用于回购和烧掉蛋糕代币。
    • 手续费是如何计算的?
      每轮总奖金的3%将被燃烧。

    代码解析

        /**
         * @notice 看跌
         * @param epoch: epoch 轮数
         * @param amount: 代币竞猜数量 wei
         */
        function betBear(uint256 epoch, uint256 amount) external whenNotPaused nonReentrant notContract {
            require(epoch == currentEpoch, "Bet is too early/late");
            require(_bettable(epoch), "Round not bettable");
            require(amount >= minBetAmount, "Bet amount must be greater than minBetAmount");
            require(ledger[epoch][msg.sender].amount == 0, "Can only bet once per round");
            //对面无竞猜 不可下注
            if(roundsNumber[epoch][Position.Bear] > 0 && (roundsNumber[epoch][Position.Bull] == 0)){
                return;
            }
            //代币转入合约中
            tokens.safeTransferFrom(msg.sender, address(this), amount);
            //更新竞猜对象内容
            Round storage round = rounds[epoch];
            round.totalAmount = round.totalAmount + amount;
            round.bearAmount = round.bearAmount + amount;
    
            // 更新用户数据
            BetInfo storage betInfo = ledger[epoch][msg.sender];
            betInfo.position = Position.Bear;
            betInfo.amount = amount;
            userRounds[msg.sender].push(epoch);
    
            player[msg.sender] = true;
            roundsNumber[epoch][Position.Bear] += 1;
    		//记录日志
            emit BetBear(msg.sender, epoch, amount);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    	/**
         * @notice 看涨
         * @param epoch: 轮数
         * @param amount: 代币竞猜数量 wei
         */
        function betBull(uint256 epoch, uint256 amount) external payable whenNotPaused nonReentrant notContract {
            require(epoch == currentEpoch, "Bet is too early/late");
            require(_bettable(epoch), "Round not bettable");
            require(amount >= minBetAmount, "Bet amount must be greater than minBetAmount");
            require(ledger[epoch][msg.sender].amount == 0, "Can only bet once per round");
            if(roundsNumber[epoch][Position.Bull] > 0 && (roundsNumber[epoch][Position.Bear] == 0)){
                return;
            }
    
            tokens.safeTransferFrom(msg.sender, address(this), amount);
            Round storage round = rounds[epoch];
            round.totalAmount = round.totalAmount + amount;
            round.bullAmount = round.bullAmount + amount;
    
            // Update user data
            BetInfo storage betInfo = ledger[epoch][msg.sender];
            betInfo.position = Position.Bull;
            betInfo.amount = amount;
            userRounds[msg.sender].push(epoch);
            
            player[msg.sender] = true;
            roundsNumber[epoch][Position.Bull] += 1;
    
            emit BetBull(msg.sender, epoch, amount);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    	/**
         * @notice 开始下一轮n,锁定第n-1轮的价格,结束第n-2轮
         * @dev 只有管理员账户可以操作
         */
        function executeRound() external whenNotPaused onlyOperator {
            require(
                genesisStartOnce && genesisLockOnce,
                "Can only run after genesisStartRound and genesisLockRound is triggered"
            );
    
            (uint80 currentRoundId, int256 currentPrice) = _getPriceFromOracle();
    
            oracleLatestRoundId = uint256(currentRoundId);
    
            // CurrentEpoch refers to previous round (n-1)
            _safeLockRound(currentEpoch, currentRoundId, currentPrice);
            _safeEndRound(currentEpoch - 1, currentRoundId, currentPrice);
            _calculateRewards(currentEpoch - 1);
    
            // Increment currentEpoch to current round (n)
            currentEpoch = currentEpoch + 1;
            _safeStartRound(currentEpoch);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    	/**
         * @notice 开始回合
         * @dev Callable by admin or operator
         */
        function genesisStartRound() external whenNotPaused onlyOperator {
            require(!genesisStartOnce, "Can only run genesisStartRound once");
    
            currentEpoch = currentEpoch + 1;
            _startRound(currentEpoch);
            genesisStartOnce = true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    	/**
         * @notice 领取全部奖励
         * @param epochs: 有奖励轮数数组
         */
        function claim(uint256[] calldata epochs) external nonReentrant notContract {
            uint256 reward; // Initializes reward
            uint256 rcm1Amt;
            uint256 rcm2Amt;
            uint256 rcm3Amt;
            uint256 marketAmt;
    
            for (uint256 i = 0; i < epochs.length; i++) {
                require(rounds[epochs[i]].times.startTimestamp != 0, "Round has not started");
                require(block.timestamp > rounds[epochs[i]].times.closeTimestamp, "Round has not ended");
    
                uint256 addedReward = 0;
    
                // 竞猜有效
                if (rounds[epochs[i]].oracleCalled) {
                    // 猜对
                    if(claimable(epochs[i], msg.sender)){
                        Round memory round = rounds[epochs[i]];
                        //轮空
                        if(round.isBet){
                            require(refundable(epochs[i], msg.sender), "Not eligible for refund");
                            addedReward = ledger[epochs[i]][msg.sender].amount;
                            recommendOtherAmt[msg.sender] = ledger[epochs[i]][msg.sender].amount * failureFee / 10000;
                        }else{
                            addedReward = (ledger[epochs[i]][msg.sender].amount * round.rewardAmount) / round.rewardBaseCalAmount;
                            marketAmt = addedReward / (10000 - totalFee) * marketFee / 10000000;
                            rcm1Amt = addedReward / (10000 - totalFee) * recommend1Fee / 10000000;
                            rcm2Amt = addedReward / (10000 - totalFee) * recommend2Fee / 10000000;
                            rcm3Amt = addedReward / (10000 - totalFee) * recommend3Fee / 10000000;
                            distributionProfit(rcm1Amt, rcm2Amt, rcm3Amt, marketAmt, msg.sender);
                        }
                    //猜错    
                    }else if(isLotteryFailure(epochs[i], msg.sender)){
                        recommendOtherAmt[msg.sender] = ledger[epochs[i]][msg.sender].amount * failureFee / 10000;
                    }
                }
                // 竞猜无效 退还金额
                else {
                    require(refundable(epochs[i], msg.sender), "Not eligible for refund");
                    addedReward = ledger[epochs[i]][msg.sender].amount;
                }
    
                ledger[epochs[i]][msg.sender].claimed = true;
                reward += addedReward;
    
                emit Claim(msg.sender, epochs[i], addedReward);
            }
    		//发放收益
            if (reward > 0) {
                _safeTransfeTokens(tokens, address(msg.sender), reward);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    其他问题

    • 如果没有人进入相反的预测会发生什么?
      如果一轮中只有一方持仓,那么该方就输了,损失的资金将被送到总奖池。
      例如:用户A进入向上位置,没有其他人进入向下位置。用户A输了,并且没有相反的头寸可供支付奖金。资金被送到总奖池。
    • 如果锁定价格和收盘价格完全相同,会发生什么情况?
      在锁定价格与收盘价格完全相同的极少数情况下,没有人获胜,所有进入头寸的资金都将被送到财政部,用于烧掉蛋糕回购。
    • 我可以改变或取消我的竞猜吗?
      不,一旦你进入一个位置,你就不能改变方向
  • 相关阅读:
    Ai4science学习、教育和更多
    Httpd启动报错 Couldn‘t create the ssl-cache 的解决办法
    leetcode 61. 旋转链表
    分享关于职场心态
    Linux命令行如何设置MySQL远程连接
    React学习(三)— React State和生命周期
    0基础学习PyFlink——用户自定义函数之UDTF
    作为优秀的DBA,究竟需要掌握多少种数据库?
    ESP8266-Arduino编程实例-MMA7455L加速计驱动
    SpringBean生命周期
  • 原文地址:https://blog.csdn.net/zgsdzczh/article/details/126288954