BTC
ETH
HTX
SOL
BNB
ดูตลาด
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

เชื่อมต่อกับ Chainlink ของเครื่อง Oracle แบบกระจายศูนย์เพื่อป้อนราคาและพัฒนาตัวอย่างแพลตฟอร์มการซ

Chainlink
特邀专栏作者
2020-11-17 05:17
บทความนี้มีประมาณ 11317 คำ การอ่านทั้งหมดใช้เวลาประมาณ 17 นาที
บทความนี้จะสอนวิธีใช้ Oracle ฟีดราคา Chainlink เพื่อพัฒนาแพลตฟอร์มการซื้อขาย DeFi ตัวเลือกการโทรอย่าง
สรุปโดย AI
ขยาย
บทความนี้จะสอนวิธีใช้ Oracle ฟีดราคา Chainlink เพื่อพัฒนาแพลตฟอร์มการซื้อขาย DeFi ตัวเลือกการโทรอย่าง

หมวดหมู่กว้างๆ ของ DeFi นั้นรวมถึงสถานการณ์แอปพลิเคชันสัญญาอัจฉริยะมากมาย เช่นการลงคะแนนแบบบล็อกเชนการขุดสภาพคล่องการขุดสภาพคล่องฟีดราคา Chainlinkฟีดราคา ChainlinkOracle ใช้ Solidity เพื่อพัฒนาแพลตฟอร์มการซื้อขาย DeFi ตัวเลือกการโทรอย่างง่ายบน Ethereum mainnet แน่นอน คุณสามารถปรับเปลี่ยนตัวอย่างนี้เล็กน้อยเพื่อพัฒนาแพลตฟอร์มการซื้อขายตัวเลือกใส่ แพลตฟอร์มนี้มีฟังก์ชันที่ทรงพลัง กล่าวคือ การโอนมูลค่าทั้งหมดจะดำเนินการผ่านสัญญาอัจฉริยะ และทั้งสองฝ่ายในธุรกรรมสามารถทำธุรกรรมได้โดยตรงโดยไม่ต้องผ่านคนกลาง ดังนั้น กระบวนการนี้จึงไม่เกี่ยวข้องกับบุคคลที่สาม มีเพียงสัญญาอัจฉริยะและฟีดราคา Chainlink แบบกระจายอำนาจ ซึ่งเป็นแอปพลิเคชัน DeFi ทั่วไป การพัฒนาแพลตฟอร์มการซื้อขายออปชันแบบกระจายอำนาจจะครอบคลุมสิ่งต่อไปนี้:

  • เปรียบเทียบสตริงใน Solidity

  • แปลงจำนวนเต็มเป็นจำนวนทศนิยมคงที่

  • สร้างและเริ่มต้นอินเทอร์เฟซโทเค็น เช่น LINK

  • โอนโทเค็นระหว่างผู้ใช้/สัญญาอัจฉริยะ

  • อนุมัติการโอนโทเค็น

  • SafeMath

  • อินเทอร์เฟซ ABI สัญญาอัจฉริยะ

  • ดำเนินการสถานะการทำธุรกรรมด้วยrequire()

  • Ethereum msg.Value และความแตกต่างจากธุรกรรมมูลค่าโทเค็น

  • แปลงระหว่าง int และ uint

  • ที่อยู่เจ้าหนี้

  • สุดท้าย ใช้อินเทอร์เฟซตัวรวบรวมข้อมูล Chainlink เพื่อรับข้อมูลราคา DeFi

และGitHubและRemixตรวจสอบรหัสที่เกี่ยวข้อง ก่อนที่เราจะเริ่มต้นอย่างเป็นทางการ เราจะแนะนำสั้น ๆ ว่าสัญญาออปชั่นคืออะไร สัญญาออปชั่นให้คุณมีตัวเลือกในการดำเนินการซื้อขายในราคาที่ตกลงกันภายในวันที่กำหนด โดยเฉพาะอย่างยิ่ง หากเนื้อหาของสัญญาออปชันคือการซื้อสินทรัพย์ เช่น หุ้นหรือโทเค็น จะเรียกว่าคอลออปชัน นอกจากนี้ โค้ดตัวอย่างในบทความนี้สามารถแก้ไขได้เล็กน้อยเพื่อใส่ตัวเลือก ตัวเลือกการขายนั้นตรงกันข้ามกับตัวเลือกการโทร และเนื้อหาของมันไม่ใช่การซื้อสินทรัพย์ แต่เพื่อขาย ต่อไปนี้เป็นคำนามเฉพาะที่เกี่ยวข้องกับตัวเลือก:

  • ราคาใช้สิทธิ์: ราคาซื้อ/ขายสินทรัพย์ที่ตกลงกัน

  • ค่าธรรมเนียมออปชัน: ค่าธรรมเนียมที่จ่ายให้กับผู้ขายเมื่อซื้อสัญญา

  • วันหมดอายุ: เวลาที่สัญญาสิ้นสุดลง

  • การประท้วง: การกระทำของผู้ซื้อที่ใช้สิทธิ์ในการซื้อหรือขายสินทรัพย์ในราคาใช้สิทธิ

ไม่ว่าคุณกำลังพัฒนาการโทรหรือตัวเลือกการส่ง คุณต้องมีองค์ประกอบพื้นฐานของการนำเข้า ตัวสร้าง และตัวแปรส่วนกลาง

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 {

// ตัวดำเนินการที่ปลอดภัยล้น

using SafeMath for uint;

// อินเทอร์เฟซฟีดราคา

AggregatorV3Interface internal ethFeed;

AggregatorV3Interface internal linkFeed;

// อินเตอร์เฟสโทเค็น LINK

LinkTokenInterface internal LINK;

uint ethPrice;

uint linkPrice;

// คำนวณค่าแฮชของสตริงล่วงหน้า

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

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

address payable contractAddr;

// ตัวเลือกถูกจัดเก็บในรูปแบบของอาร์เรย์โครงสร้าง

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;

// ราคาฟีด Kovan: https://docs.chain.link/docs/reference-contracts

constructor() public {

// ฟีดราคา Kovan สำหรับ ETH/USD

ethFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);

//LINK/USD ราคาฟีด Kovan

linkFeed = AggregatorV3Interface(0x396c5E36DD0a0F5a5D33dae44368D4193f69a1F0);

// ที่อยู่โทเค็นลิงก์บน Kovan

LINK = LinkTokenInterface(0xa36085F69e2889c224210F603D836748e7dC0088);

contractAddr = payable(address(this));

}

เมื่อนำเข้า เราจำเป็นต้องเข้าถึงอินเทอร์เฟซตัวรวบรวมข้อมูลของ Chainlink เพื่อใช้งานฟังก์ชันฟีดราคา และเข้าถึงอินเทอร์เฟซโทเค็น LINK (หมายเหตุ: ที่นี่ เราจำเป็นต้องใช้ LINK เพื่อโอนเงิน ดังนั้น เราจำเป็นต้องใช้ฟังก์ชัน ERC20 ของสัญญาโทเค็น) . ในที่สุดเราก็นำเข้าSafeMath โดย OpenZeppelinสัญญาซึ่งเป็นการดำเนินการไลบรารีมาตรฐานที่ดำเนินการตรวจสอบโอเวอร์โฟลว์ในตัว ในขณะที่ Solidity ไม่รวมการตรวจสอบโอเวอร์โฟลว์ในตัวดำเนินการในตัว

ฟีดราคา Chainlink

ฟีดราคา Chainlink

// คืนค่า LINK ล่าสุด

function getLinkPrice() public view returns (uint) {

(

uint80 roundID,

int price,

uint startedAt,

uint timeStamp,

uint80 answeredInRound

) = linkFeed.latestRoundData();

//หากรอบนี้ยังไม่สิ้นสุด การประทับเวลาจะเป็น 0

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

//ราคาจะไม่ติดลบ คุณจึงแปลง int เป็น uint ได้

//ราคามีจุดทศนิยม 8 หลัก แล้วต้องบวก 10 หลักถึงจะเป็น 18 หลัก

return uint(price);

}

ชื่อระดับแรก

เขียนสัญญาตัวเลือกการโทร

// อนุญาตให้ผู้ใช้เขียนตัวเลือกการโทรที่ระงับ

// ประเภทโทเค็นที่ได้รับ, ราคาใช้สิทธิ์ (โทเค็นเป็นสกุลเงิน USD, มี 18 หลักหลังจุดทศนิยม), ค่าธรรมเนียมออปชั่น (เหมือนกับจุดทศนิยมของโทเค็น), วันหมดอายุ (ยูนิกซ์), โทเค็นในปริมาณสัญญา

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)); // ต้นทุนการใช้สิทธิเป็นอีเทอร์ ปรับจุดทศนิยม

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)));

}

}

คำอธิบายภาพ


เขียนสัญญาออปชั่น LINK สำหรับโทเค็น LINK ตั้งเวลาหมดอายุของ Unix ราคาใช้สิทธิ์คือ $10 และค่าธรรมเนียมออปชันคือ 0.1 LINK

ชื่อระดับแรก

อินเตอร์เฟสสัญญา ABI

เมื่อคุณดูสัญญาบน Etherscan จะมีแท็บสองแท็บ ได้แก่: อ่านสัญญาและเขียนสัญญา คุณสามารถใช้สองแท็บนี้เพื่อโต้ตอบกับสัญญาได้ ตัวอย่างเช่น: สัญญาเครือข่ายหลักของโทเค็น LINK Etherscan รู้ว่าฟังก์ชันเหล่านี้คืออะไรและจะเรียกใช้งานผ่าน ABI ของสัญญาได้อย่างไร ใช้รูปแบบ JSON เพื่อเรียก ABI และระบุพารามิเตอร์การเรียกใช้ฟังก์ชัน สามารถเรียกได้โดยตรงบนเครือข่ายหลัก แต่สัญญา LINK บน Kovan จำเป็นต้องนำเข้าโมดูลนี้ คุณสามารถเข้าไปLinkTokenคำอธิบายภาพ

คำอธิบายภาพ

ชื่อระดับแรก

ซื้อตัวเลือกการโทร

//หากต้องการซื้อตัวเลือกการโทร คุณต้องใช้โทเค็น รหัสตัวเลือก และการชำระเงิน

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");

//ผู้ซื้อจ่ายออปชั่นพรีเมี่ยม

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

// ผู้ขายได้รับค่าธรรมเนียมออปชัน

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");

// โอนพรีเมี่ยมออปชั่นจากผู้ซื้อไปยังผู้ขาย

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

linkOpts[ID].buyer = msg.sender;

}

}

ชื่อระดับแรก

ตัวเลือกการออกกำลังกาย

// ตัวเลือกการโทรออก, ต้องการโทเค็น, ID ตัวเลือกและการชำระเงิน

function exercise(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(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");

//ตรงตามเงื่อนไขชำระเงิน

updatePrices();

// ค่าใช้สิทธิ

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

//เชื่อมต่อกับ Chainlink เพื่อป้อนราคาและแปลงเป็น Ethereum

uint equivEth = exerciseVal.div(ethPrice.mul(10**10)); //แปลงทศนิยม 8 ตำแหน่งของราคาฟีดเป็น 18

//ผู้ซื้อจ่ายอีเธอร์เทียบเท่ากับราคาใช้สิทธิ์*ปริมาณเพื่อใช้ออปชั่น

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

//ชำระค่าธรรมเนียมการใช้สิทธิ์ให้กับผู้ขาย

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

// ชำระเงินให้ผู้ซื้อตามจำนวนสัญญาของอีเธอร์

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));

//ผู้ซื้อใช้สิทธิและชำระค่าธรรมเนียมการใช้สิทธิให้ผู้ขาย

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

// ชำระเงินตามสัญญาของโทเค็น LINK ให้กับผู้ขาย

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

linkOpts[ID].exercised = true;

}

}

คำอธิบายภาพ

ตัวอย่าง: ผลลัพธ์ของเอาต์พุต Remix เมื่อธุรกรรมไม่ตรงตามเงื่อนไขตั้งแต่หนึ่งข้อขึ้นไป

หากตรงตามเงื่อนไข ค่าธรรมเนียมการใช้สิทธิ์จะจ่ายให้กับผู้ขาย และจำนวนสัญญาของโทเค็นจะจ่ายให้กับผู้ซื้อ เมื่อใช้ตัวเลือก ผู้ซื้อจำเป็นต้องซื้อแต่ละโทเค็นในราคาใช้สิทธิ อย่างไรก็ตาม ราคาใช้สิทธิ์เป็นสกุลเงิน USD ในขณะที่ขนาดสัญญาเป็น Ether หรือ LINK ดังนั้นเราจึงจำเป็นต้องเข้าถึงฟีดราคา Chainlink เพื่อคำนวณจำนวน ETH หรือ LINK ที่เทียบเท่ากับค่าธรรมเนียมการใช้สิทธิ์ หลังจากแปลงเป็น ETH หรือ LINK ที่เทียบเท่าแล้ว เราสามารถเริ่มโอนได้ เมื่อทำการโอนเงิน คุณต้องใช้วิธีการที่กล่าวถึงข้างต้น กล่าวคือ สกุลเงินอีเทอร์จะเรียกใช้ฟังก์ชัน msg.value/address.transfer และ LINK จะเรียกใช้ฟังก์ชัน TransferFrom()

ชื่อระดับแรก

ยกเลิกสัญญา/ลบกองทุน

// อนุญาตให้ผู้ขายยกเลิกสัญญาหรือรับเงินคืนจากตัวเลือกที่ปิดการซื้อขายไม่สำเร็จ

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");

// ต้องไม่ถูกยกเลิกหรือซื้อแล้ว

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;

}

}

//อนุญาตให้ผู้ขายแลกเงินจากออปชันที่หมดอายุ ค้างชำระ และไม่ถูกยกเลิก

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");

//ต้องหมดอายุ ไม่ใช้สิทธิ์ และไม่ถูกยกเลิก

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);

// แก้ไขค่าสถานะการยกเลิกเป็นจริงเพื่อหลีกเลี่ยงการแลกหลายรายการ

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;

}

}

เนื่องจากตลาดผันผวน ผู้ขายอาจยกเลิกสัญญาออปชันและไถ่ถอนเงินของตนหากยังไม่ได้ขายออปชัน ในทำนองเดียวกัน หากออปชันหมดอายุโดยไม่ได้ใช้งาน ผู้ขายก็ต้องการไถ่ถอนเงินในสัญญาอย่างแน่นอน ดังนั้นเราจึงเพิ่มฟังก์ชัน cancelOption() และ retrieveExpiredFunds()

จุดที่สำคัญที่สุดของฟังก์ชันทั้งสองนี้คือต้องตรงตามเงื่อนไขการแลกรับจึงจะเรียกได้สำเร็จ ผู้ขายต้องปฏิบัติตามเงื่อนไขบางประการเพื่อแลกเงิน และสามารถแลกได้เพียงครั้งเดียวเท่านั้น ผู้ขายไม่สามารถยกเลิกสัญญาที่ขายไปแล้วได้ ดังนั้น เราจำเป็นต้องยืนยันว่าที่อยู่ของผู้ซื้อยังคงเป็นค่าเริ่มต้น 0 นอกจากนี้ เรายังจำเป็นต้องยืนยันว่าตัวเลือกนั้นไม่ได้ถูกยกเลิก แล้วจึงขอคืนเงิน หากแลกเงินหลังจากออปชันหมดอายุ สถานการณ์จะแตกต่างออกไปเล็กน้อย ในกรณีนี้ ออปชันอาจถูกขายแต่ไม่ได้ใช้สิทธิ์ และควรคืนเงินให้กับผู้ขาย เราต้องการยืนยันว่าสัญญาหมดอายุและยังไม่ได้ใช้สิทธิ จากนั้นตั้งค่าสถานะการยกเลิกของตัวเลือกเป็น "จริง" เพื่อคืนเงินหากตรงตามเงื่อนไข

ฉันหวังว่าบทความนี้จะช่วยคุณพัฒนากรณีการใช้งาน Chainlink บน mainnet ได้ทันที และช่วยให้คุณเข้าใจถึงความสามารถเฉพาะของ Solidity หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับคุณสมบัติของ Chainlink ลองดูChainlink VRF(ฟังก์ชันสุ่มตรวจสอบได้) หรือดูบริการสั่งซื้อ Chainlink Fairเรียนรู้ว่า Chainlink แก้ปัญหาการทำงานของนักขุดได้อย่างไร

และเข้าร่วมกับเราได้ที่เอกสารประกอบสำหรับนักพัฒนาและเข้าร่วมกับเราได้ที่Discordติดต่อเรา.คลิกที่นี่ติดต่อเรา.

Chainlink
DeFi
开发者
期权
ยินดีต้อนรับเข้าร่วมชุมชนทางการของ Odaily
กลุ่มสมาชิก
https://t.me/Odaily_News
กลุ่มสนทนา
https://t.me/Odaily_CryptoPunk
บัญชีทางการ
https://twitter.com/OdailyChina
กลุ่มสนทนา
https://t.me/Odaily_CryptoPunk
ค้นหา
สารบัญบทความ
คลังบทความของผู้เขียน
Chainlink
ดาวน์โหลดแอพ Odaily พลาเน็ตเดลี่
ให้คนบางกลุ่มเข้าใจ Web3.0 ก่อน
IOS
Android