BTC
ETH
HTX
SOL
BNB
Xem thị trường
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

Kết nối với máy tiên tri phi tập trung Chainlink để cung cấp giá và phát triển ví dụ về nền tảng giao dịch tùy chọn cuộc gọi DeFi

Chainlink
特邀专栏作者
2020-11-17 05:17
Bài viết này có khoảng 11317 từ, đọc toàn bộ bài viết mất khoảng 17 phút
Bài viết này sẽ hướng dẫn bạn cách sử dụng oracle nguồn cấp dữ liệu giá Chainlink để phát triển một nền tảng giao dịch DeFi tùy chọn cuộc gọi đơn giản với Solidity trên mạng chính Ethereum.
Tóm tắt AI
Mở rộng
Bài viết này sẽ hướng dẫn bạn cách sử dụng oracle nguồn cấp dữ liệu giá Chainlink để phát triển một nền tảng giao dịch DeFi tùy chọn cuộc gọi đơn giản với Solidity trên mạng chính Ethereum.

Danh mục rộng của DeFi bao gồm nhiều kịch bản ứng dụng hợp đồng thông minh, chẳng hạn nhưbỏ phiếu chuỗi khốiKhai thác thanh khoảnKhai thác thanh khoảnNguồn cấp dữ liệu giá ChainlinkNguồn cấp dữ liệu giá ChainlinkOracle sử dụng Solidity để phát triển một nền tảng giao dịch DeFi tùy chọn cuộc gọi đơn giản trên mạng chính Ethereum. Tất nhiên, bạn cũng có thể sửa đổi một chút ví dụ này để phát triển nền tảng giao dịch quyền chọn bán. Nền tảng này có một chức năng mạnh mẽ, đó là tất cả việc chuyển giá trị được thực hiện thông qua hợp đồng thông minh và cả hai bên tham gia giao dịch có thể trực tiếp thực hiện giao dịch mà không cần bên trung gian. Do đó, quá trình này không liên quan đến bất kỳ bên thứ ba nào, chỉ có hợp đồng thông minh và nguồn cấp dữ liệu giá Chainlink phi tập trung, là những ứng dụng DeFi điển hình nhất. Phát triển một nền tảng giao dịch quyền chọn phi tập trung sẽ bao gồm những điều sau:

  • So sánh các chuỗi trong Solidity

  • chuyển đổi một số nguyên thành một số thập phân cố định

  • Tạo và khởi tạo giao diện mã thông báo, chẳng hạn như LINK

  • Chuyển mã thông báo giữa người dùng/hợp đồng thông minh

  • Phê duyệt chuyển mã thông báo

  • SafeMath

  • Giao diện ABI hợp đồng thông minh

  • Thực hiện trạng thái giao dịch với yêu cầu ()

  • Ethereum msg.Value và sự khác biệt của nó với các giao dịch giá trị mã thông báo

  • Chuyển đổi giữa int và uint

  • địa chỉ phải trả

  • Cuối cùng, sử dụng giao diện tổng hợp dữ liệu Chainlink để lấy dữ liệu giá DeFi

GitHubRemixKiểm tra các mã có liên quan. Trước khi chính thức bắt đầu, chúng ta hãy giới thiệu ngắn gọn hợp đồng quyền chọn là gì. Hợp đồng quyền chọn cung cấp cho bạn tùy chọn để thực hiện giao dịch ở mức giá đã thỏa thuận vào một ngày nhất định. Cụ thể, nếu nội dung của hợp đồng quyền chọn là mua các tài sản như cổ phiếu hoặc mã thông báo, thì nó được gọi là quyền chọn mua. Ngoài ra, mã mẫu trong bài viết này có thể được sửa đổi một chút để đặt các tùy chọn. Quyền chọn bán trái ngược với quyền chọn mua và nội dung của nó không phải là mua một tài sản mà là bán nó. Sau đây là một số danh từ thích hợp liên quan đến các tùy chọn:

  • Giá thực hiện: giá mua/bán đã thỏa thuận của tài sản

  • Phí quyền chọn: Phí trả cho người bán khi mua hợp đồng

  • Expiration Date: Thời điểm hợp đồng kết thúc

  • Đình công: Hành động của người mua thực hiện quyền mua hoặc bán một tài sản với giá đình công

Cho dù bạn đang phát triển một cuộc gọi hay một cuộc gọi, bạn cần các yếu tố cơ bản của nhập khẩu, hàm tạo và biến toàn cục.

pragma solidity ^0.6.7;

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

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

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol";

contract chainlinkOptions {

// tràn toán tử an toàn

using SafeMath for uint;

// giao diện nguồn cấp giá

AggregatorV3Interface internal ethFeed;

AggregatorV3Interface internal linkFeed;

// Giao diện mã thông báo LINK

LinkTokenInterface internal LINK;

uint ethPrice;

uint linkPrice;

// Tính toán trước giá trị băm của chuỗi

bytes32 ethHash = keccak256(abi.encodePacked("ETH"));

bytes32 linkHash = keccak256(abi.encodePacked("LINK"));

address payable contractAddr;

// Các tùy chọn được lưu trữ dưới dạng một mảng cấu trúc

struct option {

uint strike; //Price in USD (18 decimal places) option allows buyer to purchase tokens at

uint premium; //Fee in contract token that option writer charges

uint expiry; //Unix timestamp of expiration time

uint amount; //Amount of tokens the option contract is for

bool exercised; //Has option been exercised

bool canceled; //Has option been canceled

uint id; //Unique ID of option, also array index

uint latestCost; //Helper to show last updated cost to exercise

address payable writer; //Issuer of option

address payable buyer; //Buyer of option

}

option[] public ethOpts;

option[] public linkOpts;

// Giá thức ăn Kovan: https://docs.chain.link/docs/reference-contracts

constructor() public {

// Nguồn cấp dữ liệu giá Kovan cho ETH/USD

ethFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);

// LIÊN KẾT/USD giá thức ăn Kovan

linkFeed = AggregatorV3Interface(0x396c5E36DD0a0F5a5D33dae44368D4193f69a1F0);

//Địa chỉ mã thông báo liên kết trên Kovan

LINK = LinkTokenInterface(0xa36085F69e2889c224210F603D836748e7dC0088);

contractAddr = payable(address(this));

}

Khi nhập, chúng tôi cần truy cập giao diện tổng hợp dữ liệu của Chainlink để nhận ra chức năng cấp giá và truy cập giao diện mã thông báo LINK (Lưu ý: Ở đây chúng tôi cần sử dụng LINK để chuyển tiền, vì vậy chúng tôi cần sử dụng chức năng ERC20 của hợp đồng mã thông báo) . Cuối cùng, chúng tôi nhập khẩuSafeMath của OpenZeppelinHợp đồng, là các hoạt động thư viện tiêu chuẩn thực hiện kiểm tra tràn tích hợp, trong khi Solidity không bao gồm kiểm tra tràn trong các toán tử tích hợp sẵn của nó.

Nguồn cấp dữ liệu giá Chainlink

Nguồn cấp dữ liệu giá Chainlink

//Trả về giá LIÊN KẾT mới nhất

function getLinkPrice() public view returns (uint) {

(

uint80 roundID,

int price,

uint startedAt,

uint timeStamp,

uint80 answeredInRound

) = linkFeed.latestRoundData();

// Nếu vòng này chưa kết thúc, dấu thời gian là 0

require(timeStamp > 0, "Round not complete");

// Giá sẽ không bao giờ âm, vì vậy bạn có thể chuyển đổi int thành uint

// Giá có 8 chữ số sau dấu thập phân, sau đó cần cộng 10 chữ số để thành 18 chữ số.

return uint(price);

}

tiêu đề cấp đầu tiên

Viết hợp đồng quyền chọn mua

//Cho phép người dùng viết các tùy chọn cuộc gọi được tổ chức

// Loại mã thông báo đã nhận, giá thực hiện (mã thông báo có mệnh giá bằng đô la Mỹ, với 18 chữ số sau dấu thập phân), phí tùy chọn (giống như dấu thập phân của mã thông báo), ngày hết hạn (unix), số lượng mã thông báo trong hợp đồng

function writeOption(string memory token, uint strike, uint premium, uint expiry, uint tknAmt) public payable {

bytes32 tokenHash = keccak256(abi.encodePacked(token));

require(tokenHash == ethHash || tokenHash == linkHash, "Only ETH and LINK tokens are supported");

updatePrices();

if (tokenHash == ethHash) {

require(msg.value == tknAmt, "Incorrect amount of ETH supplied");

uint latestCost = strike.mul(tknAmt).div(ethPrice.mul(10**10)); // Chi phí tập thể dục bằng ether, điều chỉnh dấu thập phân

ethOpts.push(option(strike, premium, expiry, tknAmt, false, false, ethOpts.length, latestCost, msg.sender, address(0)));

} else {

require(LINK.transferFrom(msg.sender, contractAddr, tknAmt), "Incorrect amount of LINK supplied");

uint latestCost = strike.mul(tknAmt).div(linkPrice.mul(10**10));

linkOpts.push(option(strike, premium, expiry, tknAmt, false, false, linkOpts.length, latestCost, msg.sender, address(0)));

}

}

Mô tả hình ảnh


Viết hợp đồng tùy chọn LINK cho mã thông báo LINK, đặt thời gian hết hạn Unix, giá thực hiện là 10 đô la và phí tùy chọn là 0,1 LINK.

tiêu đề cấp đầu tiên

Giao diện hợp đồng ABI

Khi bạn xem hợp đồng trên Etherscan, sẽ có hai tab, đó là: Đọc hợp đồng và Viết hợp đồng. Bạn có thể sử dụng hai tab này để tương tác với hợp đồng. Ví dụ: Hợp đồng mạng chính mã thông báo LINK. Etherscan biết những chức năng này là gì và cách gọi chúng thông qua ABI của hợp đồng. Sử dụng định dạng JSON để gọi ABI và chỉ định các tham số gọi hàm. Nó có thể được gọi trực tiếp trên mạng chính, nhưng hợp đồng LINK trên Kovan cần nhập mô-đun này. bạn có thể vàoLinkTokenMô tả hình ảnh

Mô tả hình ảnh

tiêu đề cấp đầu tiên

mua tùy chọn cuộc gọi

// Để mua tùy chọn cuộc gọi, bạn cần mã thông báo, ID tùy chọn và thanh toán

function buyOption(string memory token, uint ID) public payable {

bytes32 tokenHash = keccak256(abi.encodePacked(token));

require(tokenHash == ethHash || tokenHash == linkHash, "Only ETH and LINK tokens are supported");

updatePrices();

if (tokenHash == ethHash) {

require(!ethOpts[ID].canceled && ethOpts[ID].expiry > now, "Option is canceled/expired and cannot be bought");

// Người mua trả phí quyền chọn

require(msg.value == ethOpts[ID].premium, "Incorrect amount of ETH sent for premium");

// Người bán nhận được phí quyền chọn

ethOpts[ID].writer.transfer(ethOpts[ID].premium);

ethOpts[ID].buyer = msg.sender;

} else {

require(!linkOpts[ID].canceled && linkOpts[ID].expiry > now, "Option is canceled/expired and cannot be bought");

//Chuyển phí quyền chọn từ người mua sang người bán

require(LINK.transferFrom(msg.sender, linkOpts[ID].writer, linkOpts[ID].premium), "Incorrect amount of LINK sent for premium");

linkOpts[ID].buyer = msg.sender;

}

}

tiêu đề cấp đầu tiên

tùy chọn tập thể dục

// Tùy chọn cuộc gọi thực hiện, cần mã thông báo, ID tùy chọn và thanh toán

function exercise(string memory token, uint ID) public payable {

//Nếu quyền chọn chưa hết hạn và chưa được thực hiện thì người sở hữu quyền chọn được phép thực hiện

// Để thực hiện quyền chọn, người mua cần trả cho người bán giá thực hiện * số lượng và nhận số lượng token đã thỏa thuận trong hợp đồng

bytes32 tokenHash = keccak256(abi.encodePacked(token));

require(tokenHash == ethHash || tokenHash == linkHash, "Only ETH and LINK tokens are supported");

if (tokenHash == ethHash) {

require(ethOpts[ID].buyer == msg.sender, "You do not own this option");

require(!ethOpts[ID].exercised, "Option has already been exercised");

require(ethOpts[ID].expiry > now, "Option is expired");

//đáp ứng điều kiện thì thanh toán

updatePrices();

// Phí thực hiện

uint exerciseVal = ethOpts[ID].strike*ethOpts[ID].amount;

// Kết nối với Chainlink để cung cấp giá và chuyển đổi nó thành Ethereum

uint equivEth = ExerciseVal.div(ethPrice.mul(10**10)); //Chuyển đổi 8 chữ số thập phân của giá nguồn cấp dữ liệu thành 18

// Người mua trả ether tương đương với giá thực hiện * số lượng để thực hiện tùy chọn.

require(msg.value == equivEth, "Incorrect LINK amount sent to exercise");

// Trả phí thực hiện cho người bán

ethOpts[ID].writer.transfer(equivEth);

// Thanh toán cho người mua số lượng ether theo hợp đồng

msg.sender.transfer(ethOpts[ID].amount);

ethOpts[ID].exercised = true;

} else {

require(linkOpts[ID].buyer == msg.sender, "You do not own this option");

require(!linkOpts[ID].exercised, "Option has already been exercised");

require(linkOpts[ID].expiry > now, "Option is expired");

updatePrices();

uint exerciseVal = linkOpts[ID].strike*linkOpts[ID].amount;

uint equivLink = exerciseVal.div(linkPrice.mul(10**10));

// Người mua thực hiện quyền chọn và trả phí thực hiện cho người bán

require(LINK.transferFrom(msg.sender, linkOpts[ID].writer, equivLink), "Incorrect LINK amount sent to exercise");

// Thanh toán số lượng hợp đồng của mã thông báo LINK cho người bán

require(LINK.transfer(msg.sender, linkOpts[ID].amount), "Error: buyer was not paid");

linkOpts[ID].exercised = true;

}

}

Mô tả hình ảnh

Ví dụ: Kết quả Remix xuất ra khi giao dịch không thỏa mãn một hoặc nhiều điều kiện.

Nếu các điều kiện được đáp ứng, phí thực hiện sẽ được trả cho người bán và số lượng mã thông báo theo hợp đồng sẽ được trả cho người mua. Khi thực hiện quyền chọn, người mua cần mua từng mã thông báo với giá thực hiện. Tuy nhiên, giá thực hiện được tính bằng USD, trong khi quy mô hợp đồng được tính bằng Ether hoặc LINK. Do đó, chúng tôi cần truy cập nguồn cấp dữ liệu giá Chainlink để tính toán số lượng ETH hoặc LINK tương đương với phí thực hiện. Sau khi chuyển đổi sang ETH hoặc LINK tương đương, chúng tôi có thể bắt đầu chuyển. Khi chuyển tiền, bạn cần sử dụng phương pháp đã đề cập ở trên, tức là tiền ether sẽ gọi hàm msg.value/address.transfer và LINK sẽ gọi hàm transferFrom().

tiêu đề cấp đầu tiên

Hủy hợp đồng/xóa tiền

// Cho phép người bán hủy hợp đồng hoặc lấy lại tiền từ các tùy chọn không đóng giao dịch thành công.

function cancelOption(string memory token, uint ID) public payable {

bytes32 tokenHash = keccak256(abi.encodePacked(token));

require(tokenHash == ethHash || tokenHash == linkHash, "Only ETH and LINK tokens are supported");

if (tokenHash == ethHash) {

require(msg.sender == ethOpts[ID].writer, "You did not write this option");

// không được hủy hoặc mua

require(!ethOpts[ID].canceled && ethOpts[ID].buyer == address(0), "This option cannot be canceled");

ethOpts[ID].writer.transfer(ethOpts[ID].amount);

ethOpts[ID].canceled = true;

} else {

require(msg.sender == linkOpts[ID].writer, "You did not write this option");

require(!linkOpts[ID].canceled && linkOpts[ID].buyer == address(0), "This option cannot be canceled");

require(LINK.transferFrom(address(this), linkOpts[ID].writer, linkOpts[ID].amount), "Incorrect amount of LINK sent");

linkOpts[ID].canceled = true;

}

}

//Cho phép người bán đổi tiền từ các tùy chọn đã hết hạn, chưa thanh toán và không bị hủy.

function retrieveExpiredFunds(string memory token, uint ID) public payable {

bytes32 tokenHash = keccak256(abi.encodePacked(token));

require(tokenHash == ethHash || tokenHash == linkHash, "Only ETH and LINK tokens are supported");

if (tokenHash == ethHash) {

require(msg.sender == ethOpts[ID].writer, "You did not write this option");

// Phải hết hạn, không được thực hiện và không bị hủy bỏ.

require(ethOpts[ID].expiry <= now && !ethOpts[ID].exercised && !ethOpts[ID].canceled, "This option is not eligible for withdraw");

ethOpts[ID].writer.transfer(ethOpts[ID].amount);

//Sửa đổi cờ hủy thành đúng để tránh nhiều lần quy đổi

ethOpts[ID].canceled = true;

} else {

require(msg.sender == linkOpts[ID].writer, "You did not write this option");

require(linkOpts[ID].expiry <= now && !linkOpts[ID].exercised && !linkOpts[ID].canceled, "This option is not eligible for withdraw");

require(LINK.transferFrom(address(this), linkOpts[ID].writer, linkOpts[ID].amount), "Incorrect amount of LINK sent");

linkOpts[ID].canceled = true;

}

}

Khi thị trường biến động, người bán có thể hủy hợp đồng quyền chọn và mua lại tiền của họ nếu quyền chọn chưa được bán. Tương tự như vậy, nếu một quyền chọn hết hạn mà không được thực hiện, người bán chắc chắn sẽ muốn mua lại số tiền trong hợp đồng. Do đó, chúng tôi đã thêm các hàm cancelOption() và retrieveExpiredFunds()

Điểm quan trọng nhất của hai chức năng này là các điều kiện quy đổi phải được đáp ứng để gọi thành công. Người bán phải đáp ứng các điều kiện nhất định để đổi tiền và chỉ có thể đổi một lần. Người bán không thể hủy hợp đồng đã được bán, vì vậy chúng tôi cần xác nhận rằng địa chỉ của người mua vẫn là giá trị ban đầu 0. Ngoài ra, chúng tôi cũng cần xác nhận rằng tùy chọn chưa bị hủy và sau đó hoàn lại tiền. Nếu tiền được mua lại sau khi tùy chọn hết hạn, tình hình sẽ hơi khác một chút. Trong trường hợp này, quyền chọn có thể đã được bán nhưng không được thực hiện và tiền vẫn phải được trả lại cho người bán. Chúng tôi muốn xác nhận rằng hợp đồng đã hết hạn và chưa được thực hiện. Sau đó, cũng đặt cờ hủy của tùy chọn thành true để hoàn lại tiền nếu điều kiện được đáp ứng.

Tôi hy vọng bài viết này sẽ giúp bạn phát triển các trường hợp sử dụng Chainlink trên mainnet ngay lập tức và giúp bạn hiểu về các khả năng độc đáo của Solidity. Nếu bạn muốn tìm hiểu thêm về các tính năng của Chainlink, hãy xemChainlink VRF(chức năng ngẫu nhiên có thể kiểm chứng) hoặc xemDịch vụ đặt hàng công bằng Chainlink, hãy tìm hiểu cách Chainlink giải quyết vấn đề chạy trước của công cụ khai thác.

và tham gia với chúng tôi tạitài liệu dành cho nhà phát triểnvà tham gia với chúng tôi tạiDiscordliên hệ chúng tôi.bấm vào đâyliên hệ chúng tôi.

Chainlink
DeFi
开发者
期权
Chào mừng tham gia cộng đồng chính thức của Odaily
Nhóm đăng ký
https://t.me/Odaily_News
Nhóm trò chuyện
https://t.me/Odaily_CryptoPunk
Tài khoản chính thức
https://twitter.com/OdailyChina
Nhóm trò chuyện
https://t.me/Odaily_CryptoPunk