按关键词阅读:
Chainlink喂价//返回最新的LINK价格
function getLinkPrice public view returns (uint) {
(
uint80 roundID,
int price,
uint startedAt,
uint timeStamp,
uint80 answeredInRound
) = linkFeed.latestRoundData;
//如果这轮还没有结束 , 则timestamp是0
require(timeStamp > 0, "Round not complete");
//价格永远不会是负数 , 因此可以将int转换成uint
//价格小数点后有8位 , 之后需要增加10位变成18位 。
return uint(price);
}
我们首先实现的是两个getter函数 , 获取以太币和LINK喂价 。 以太币的函数与上方LINK函数一样 , 唯一不同的是接入以太币喂价 。 这会调用latestRoundData函数查看我们初始化的喂价 , 并且会自动返回最新的去中心化市场聚合价格数据 。 因为这是一个view函数 , 所以甚至连gas费也用不着!我们对默认喂价getter函数做了一个调整 , 将价格从int转换成uint , 以匹配之后使用uint的函数 。 这里要注意一点 , 这样转换是ok的 , 因为价格永远不可能是负数 , 所以不会用到int的符号位 。 在类型之间转换的时候需要考虑到这些细节 。
写一个看涨期权合约//允许用户写保持看涨期权
//接收的通证类型 , 行权价格(通证以美元计价 , 小数点后保留18位) , 期权费用(与通证小数点位数一样) , 到期日(unix) , 合约中的通证数量
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 =http://kandian.youth.cn/index/= 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)));
}
}
初始设置完成并接入喂价后 , 我们接下来就可以调用函数了 , 先来写一个期权合约 。 卖家调用writeOption函数 , 并填入期权具体的参数 , 小数点后保留18位 。 这里必须要明确小数点位数 , 以确保合约中使用的所有参数都格式统一 。 比如 , 整数777没有小数点 , 但是如果我们规定的逻辑是保留两位小数 , 则表示成7.77 。 我们这里的规则是小数点后保留18位 , 因为以太币和LINK都是18位小数 。 如果小数点后不到18位 , 则可以添加0变成18位 。 接下来 , 我们就可以第一次使用之前计算出的以太币和LINK字符串哈希值 。 为了明确卖家的期权合约针对的是什么通证 , 我们需要比较字符串 。 然而Solidity不支持在字符串之间进行==操作 , 因为其长度是动态的 。 我们不需要写一个函数一个个字节地比较字符串 , 而只需用keccak256哈希函数计算每个字符串的32位哈希值 , 并直接对比 。 只要哈希值一样 , 字符串就一样 。 现在我们知道卖家用的是哪种通证 , 就可以有的放矢了 。 如果是以太币 , 我们就可以用msg.value确认转账到期权合约的以太币数量是否正确 。 我们可以用require函数严格执行 。 如果require的第一个字段为false , 则交易会被拒绝 , 无法进行下去 。 这样一来 , 我们可以确保所有期权合约的转账都完全符合之前约定的金额(tknAmnt) 。 检查通过后 , 我们就可以创建期权合约 , 提供所有必须的字段生成结构 。 基于当前以太币价格 , 使用SafeMath函数而非内置操作符计算当前行使期权的费用(LatestCost) 。 使用Chainlink的updatePrices helper函数获取当前价格 , 这个函数会更新全局以太币和LINK价格 。 注意ethPrice要乘以10的10次方 。 这样做是因为Chainlink喂价返回的是8位小数的美元价格 , 但正如上文所述 , 我们现在的标准是18位小数 。 所以添加10个零可以将其调整成18位小数 , 符合以太币和LINK通证的格式 。 最后 , 我们将期权的结构压入ethOpts的数组中 , 这样期权合约就写完了 , 而且里面有足够的资金 。
文章插图
针对一枚LINK通证写一个LINK期权合约 , 设定Unix到期时间 , 行权价格为10美元 , 期权费用为0.1个LINK 。
如果是LINK期权合约 , 那么就需要做一些修改了 。 Msg.value只提供交易中以太币的金额 。 因此如果要确保LINK的金额充足 , 我们需要直接接入LINK通证合约 。 我们之前已经导入并初始化了LINK通证接口 , 因此可以访问所有LINK通证函数 , 其中一个是transferFrom , 这个函数可以将LINK从一个地址转移到另一个地址 。 当然 , 我们不能让任何合约都可以随便转移你的LINK资产 , 所以必须首先调用LINK的approve函数 , 并具体说明允许转移的LINK数量以及转移到的合约地址 。
稿源:(未知)
【傻大方】网址:http://www.shadafang.com/c/111J2I3H020.html
标题:接入去中心化预言机Chainlink喂价开发DeFi看涨期权交易平台实例( 二 )