微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

智能合约不断听取价格馈送并在达到价格后立即执行的最佳方式是什么?

如何解决智能合约不断听取价格馈送并在达到价格后立即执行的最佳方式是什么?

我编写了一份智能合约,应该从 2 个地址下注,一个下注创建者和一个下注者。赌注是 ETH/USD 的价格(通过 ChainLink)。

让智能合约持续聆听 ETH/USD 价格的最佳方式是什么,以便每当价格达到投注的一方或另一方时,合约会自动generateBetoutcome() ?

pragma solidity ^0.8.4;

import "https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";

contract Bet {

    //bet status
    uint constant STATUS_WIN = 1;
    uint constant STATUS_LOSE = 2;
    uint constant STATUS_TIE = 3;
    uint constant STATUS_PENDING = 4;

    //game status
    uint constant STATUS_NOT_STARTED = 1;
    uint constant STATUS_STARTED = 2;
    uint constant STATUS_COMPLETE = 3;

    //general status
    uint constant STATUS_ERROR = 4;

    //the betting structure
    struct DoubleBet {
        uint guess;
        address addr;
        uint status;
    }

    //the 'game' structure
    struct Game {
        uint256 betAmount;
        uint outcome;
        uint status;
        DoubleBet creator;
        DoubleBet taker;
    }
    
    Game game;
    
    receive() external payable {
    }
    
    address payable owner;
    
        AggregatorV3Interface internal priceFeed;

    /**
     * Network: Kovan
     * Aggregator: ETH/USD
     * Address: 0x9326BFA02ADD2366b30bacB125260Af641031331
     */
    constructor() public {
        priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
    }
    
    function createBet(uint _guess) public payable {
      game = Game(msg.value,STATUS_STARTED,DoubleBet(_guess,msg.sender,STATUS_PENDING),DoubleBet(0,STATUS_NOT_STARTED));
      game.creator = DoubleBet(_guess,STATUS_PENDING);
    }

    function takeBet(uint _guess) public payable { 
      //requires the taker to make the same bet amount     
      require(msg.value == game.betAmount);
      game.taker = DoubleBet(_guess,STATUS_PENDING);
      generateBetoutcome();
    }
    
    function generateBetoutcome() private {
        game.outcome = uint(getThePrice());
        game.status = STATUS_COMPLETE;
        
        if (game.creator.guess == game.taker.guess) {
          game.creator.status = STATUS_TIE;
          game.taker.status = STATUS_TIE;
        } else if (game.creator.guess > game.outcome && game.taker.guess > game.outcome) {
          game.creator.status = STATUS_TIE;
          game.taker.status = STATUS_TIE;
        } else {
           if ((game.outcome - game.creator.guess) < (game.outcome - game.taker.guess)) {
             game.creator.status = STATUS_WIN;
             game.taker.status = STATUS_LOSE;
           } else if ((game.outcome - game.taker.guess) < (game.outcome - game.creator.guess)) {
             game.creator.status = STATUS_LOSE;
             game.taker.status = STATUS_WIN;
           } else {
             game.creator.status = STATUS_ERROR;
             game.taker.status = STATUS_ERROR;
             game.status = STATUS_ERROR;
           }
        }
    }
//returns - [<description>,'originator',<originator status>,'taker',<taker status>]
     function getBetoutcome() public view returns
     (string memory description,string memory originatorKey,uint originatorStatus,string memory takerKey,uint takerStatus) 
     {
        if (game.creator.status == STATUS_TIE || game.taker.status == STATUS_TIE) {
          description = "Both bets were the same or were over the number,the pot will be split";
        } else {
            if (game.creator.status == STATUS_WIN) {
             description = "Bet originator guess was closer to the number and will receive the pot";
           } else if (game.taker.status == STATUS_WIN) {
             description = "Bet taker guess was closer to the number and will receive the pot";
           } else {
             description = "UnkNown Bet Outcome";
           }
        }
        originatorKey = "creator";
        originatorStatus = game.creator.status;
        takerKey = "taker";
        takerStatus = game.taker.status;
     }

    /**
     * Returns the latest price
     */
    function getThePrice() public view returns (int) {
        (
            uint80 roundID,int price,uint startedAt,uint timeStamp,uint80 answeredInRound
        ) = priceFeed.latestRoundData();
        return price;
    }
    
    
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
    
    
    
    function getBalance() public view returns (uint balance) {
        return address(this).balance;
    }
    
    
}

解决方法

智能合约无法访问区块链本身之外的任何内容。 唯一的方法是使用 oracle

预言机只是一个普通软件(你可以用 C++、PHP 或 Java 或任何你喜欢的语言编写),它访问 ChainLink 上的 ETH/USD 价格等外部资源,然后根据你编写的逻辑调用一个满足条件时智能合约上的方法。

为了确保只有您的 oracle 可以调用该方法(例如调用 generateBetOutcome)并避免第三者因过早调用该方法而作弊,您可以编写代码来验证调用者是您的 oracle。>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。