blockchain - 智能合约不断听取价格信息并在达到价格后立即执行的最佳方式是什么?
问题描述
我编写了一个智能合约,该合约应该从 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, 0, STATUS_STARTED, DoubleBet(_guess, msg.sender, STATUS_PENDING), DoubleBet(0, msg.sender, STATUS_NOT_STARTED));
game.creator = DoubleBet(_guess, msg.sender, 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, msg.sender, 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
)并通过过早调用该方法来避免第 3 方作弊,您可以编写代码来验证调用者是您的 oracle。
推荐阅读
- r - 由于未使用的参数错误(SRS_string = from$wkt),无法将 sf 对象转换为 sp 对象
- javascript - 如何使用 StencilJS 处理全宽
- java - 将枚举值传递给 Quarkus-Qute 中的模板扩展方法
- symfony - api平台ManyToMany坚持
- java - 如何跟踪三列Java中每一列的总和
- python-3.x - Heroku 应用部署失败,原因不明
- c++ - 使用放置 new 在另一个函数中使用 args 调用构造函数
- java - Java和NodeJS中的变量“long”类型
- python - 当我尝试将图像上传到 /media/ 目录时出现“权限被拒绝”,DJANGO
- android - SQLite GROUP BY 偏好某个值