Diff
checker
文本
文本
圖像
文檔
Excel
文件夾
Legal
Enterprise
桌面版
定價
登入
下載 Diffchecker 桌面版
比較文本
尋找兩個文字檔案之間的差異
工具
歷史
即時編輯器
摺疊未變更行
關閉換行
檢視
拆分
統一
比對精度
智能
單詞
字符
語法突出顯示
選擇語法
忽略
文字轉換
前往第一個差異
編輯輸入
Diffchecker Desktop
執行Diffchecker最安全的方式。取得Diffchecker桌面應用程式:您的差異永遠不會離開您的電腦!
取得桌面版
PriceCalculatorBSC.sol
建立於
5 年前
差異永不過期
清除
匯出
分享
解釋
8 刪除
行
總計
刪除
字符
總計
刪除
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
144 行
全部複製
48 新增
行
總計
新增
字符
總計
新增
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
185 行
全部複製
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
pragma experimental ABIEncoderV2;
/*
/*
___ _ _
___ _ _
| _ )_ _ _ _ _ _ _ _ | | | |
| _ )_ _ _ _ _ _ _ _ | | | |
| _ \ || | ' \| ' \ || | |_| |_|
| _ \ || | ' \| ' \ || | |_| |_|
|___/\_,_|_||_|_||_\_, | (_) (_)
|___/\_,_|_||_|_||_\_, | (_) (_)
|__/
|__/
*
*
* MIT License
* MIT License
* ===========
* ===========
*
*
* Copyright (c) 2020 BunnyFinance
* Copyright (c) 2020 BunnyFinance
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in all
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/
*/
import "@pancakeswap/pancake-swap-lib/contracts/token/BEP20/IBEP20.sol";
import "@pancakeswap/pancake-swap-lib/contracts/token/BEP20/IBEP20.sol";
複製
已複製
複製
已複製
import "@pancakeswap/pancake-swap-lib/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "../../interfaces/IPancakePair.sol";
import "../../interfaces/IPancakePair.sol";
import "../../interfaces/IPancakeFactory.sol";
import "../../interfaces/IPancakeFactory.sol";
import "../../interfaces/AggregatorV3Interface.sol";
import "../../interfaces/AggregatorV3Interface.sol";
import "../../interfaces/IPriceCalculator.sol";
import "../../interfaces/IPriceCalculator.sol";
複製
已複製
複製
已複製
import "../../library/HomoraMath.sol";
contract PriceCalculatorBSC is IPriceCalculator, OwnableUpgradeable {
contract PriceCalculatorBSC is IPriceCalculator, OwnableUpgradeable {
using SafeMath for uint;
using SafeMath for uint;
複製
已複製
複製
已複製
using HomoraMath for uint;
address public constant WBNB = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
address public constant WBNB = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
address public constant CAKE = 0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82;
address public constant CAKE = 0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82;
address public constant BUNNY = 0xC9849E6fdB743d08fAeE3E34dd2D1bc69EA11a51;
address public constant BUNNY = 0xC9849E6fdB743d08fAeE3E34dd2D1bc69EA11a51;
address public constant VAI = 0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7;
address public constant VAI = 0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7;
address public constant BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56;
address public constant BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56;
複製
已複製
複製
已複製
address public constant BUNNY_BNB_V1 = 0x7Bb89460599Dbf32ee3Aa50798BBcEae2A5F7f6a;
address public constant BUNNY_BNB_V2 = 0x5aFEf8567414F29f0f927A0F2787b188624c10E2;
IPancakeFactory private constant factory = IPancakeFactory(0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73);
IPancakeFactory private constant factory = IPancakeFactory(0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73);
複製
已複製
複製
已複製
AggregatorV3Interface private constant bnbPriceFeed = AggregatorV3Interface(0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeE);
/* ========== STATE VARIABLES ========== */
/* ========== STATE VARIABLES ========== */
mapping(address => address) private pairTokens;
mapping(address => address) private pairTokens;
複製
已複製
複製
已複製
mapping(address => address) private tokenFeeds;
/* ========== INITIALIZER ========== */
/* ========== INITIALIZER ========== */
function initialize() external initializer {
function initialize() external initializer {
__Ownable_init();
__Ownable_init();
setPairToken(VAI, BUSD);
setPairToken(VAI, BUSD);
}
}
/* ========== Restricted Operation ========== */
/* ========== Restricted Operation ========== */
function setPairToken(address asset, address pairToken) public onlyOwner {
function setPairToken(address asset, address pairToken) public onlyOwner {
pairTokens[asset] = pairToken;
pairTokens[asset] = pairToken;
}
}
複製
已複製
複製
已複製
function setTokenFeed(address asset, address feed) public onlyOwner {
tokenFeeds[asset] = feed;
}
/* ========== Value Calculation ========== */
/* ========== Value Calculation ========== */
function priceOfBNB() view public returns (uint) {
function priceOfBNB() view public returns (uint) {
複製
已複製
複製
已複製
(, int price, , ,) =
bnbPriceFeed
.latestRoundData();
(, int price, , ,) =
AggregatorV3Interface(tokenFeeds[WBNB])
.latestRoundData();
return uint(price).mul(1e10);
return uint(price).mul(1e10);
}
}
function priceOfCake() view public returns (uint) {
function priceOfCake() view public returns (uint) {
複製
已複製
複製
已複製
(,
u
int
cakePriceInUSD
) =
valueOfAsset(
CAKE
, 1e18
);
(,
int
price, , ,
) =
AggregatorV3Interface(tokenFeeds[
CAKE
]).latestRoundData(
);
return
cakePriceInUSD
;
return
uint(price).mul(1e10)
;
}
}
function priceOfBunny() view public returns (uint) {
function priceOfBunny() view public returns (uint) {
(, uint bunnyPriceInUSD) = valueOfAsset(BUNNY, 1e18);
(, uint bunnyPriceInUSD) = valueOfAsset(BUNNY, 1e18);
return bunnyPriceInUSD;
return bunnyPriceInUSD;
}
}
function pricesInUSD(address[] memory assets) public view override returns (uint[] memory) {
function pricesInUSD(address[] memory assets) public view override returns (uint[] memory) {
uint[] memory prices = new uint[](assets.length);
uint[] memory prices = new uint[](assets.length);
for (uint i = 0; i < assets.length; i++) {
for (uint i = 0; i < assets.length; i++) {
(, uint valueInUSD) = valueOfAsset(assets[i], 1e18);
(, uint valueInUSD) = valueOfAsset(assets[i], 1e18);
prices[i] = valueInUSD;
prices[i] = valueInUSD;
}
}
return prices;
return prices;
}
}
function valueOfAsset(address asset, uint amount) public view override returns (uint valueInBNB, uint valueInUSD) {
function valueOfAsset(address asset, uint amount) public view override returns (uint valueInBNB, uint valueInUSD) {
if (asset == address(0) || asset == WBNB) {
if (asset == address(0) || asset == WBNB) {
複製
已複製
複製
已複製
return _oracleValueOf(WBNB, amount);
} else if (asset == BUNNY || asset == BUNNY_BNB_V1 || asset == BUNNY_BNB_V2) {
return _unsafeValueOfAsset(asset, amount);
} else if (keccak256(abi.encodePacked(IPancakePair(asset).symbol())) == keccak256("Cake-LP")) {
return _getPairPrice(asset, amount);
} else {
return _oracleValueOf(asset, amount);
}
}
function _oracleValueOf(address asset, uint amount) private view returns (uint valueInBNB, uint valueInUSD) {
(, int price, , ,) = AggregatorV3Interface(tokenFeeds[asset]).latestRoundData();
valueInUSD = uint(price).mul(1e10).mul(amount).div(1e18);
valueInBNB = valueInUSD.mul(1e18).div(priceOfBNB());
}
function _getPairPrice(address pair, uint amount) private view returns (uint valueInBNB, uint valueInUSD) {
address token0 = IPancakePair(pair).token0();
address token1 = IPancakePair(pair).token1();
uint totalSupply = IPancakePair(pair).totalSupply();
(uint r0, uint r1, ) = IPancakePair(pair).getReserves();
uint sqrtK = HomoraMath.sqrt(r0.mul(r1)).fdiv(totalSupply);
(uint px0,) = _oracleValueOf(token0, 1e18);
(uint px1,) = _oracleValueOf(token1, 1e18);
uint fairPriceInBNB = sqrtK.mul(2).mul(HomoraMath.sqrt(px0)).div(2**56).mul(HomoraMath.sqrt(px1)).div(2**56);
valueInBNB = fairPriceInBNB.mul(amount).div(1e18);
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
}
function _unsafeValueOfAsset(address asset, uint amount) private view returns (uint valueInBNB, uint valueInUSD) {
if (asset == address(0) || asset == WBNB) {
valueInBNB = amount;
valueInBNB = amount;
valueInUSD = amount.mul(priceOfBNB()).div(1e18);
valueInUSD = amount.mul(priceOfBNB()).div(1e18);
}
}
else if (keccak256(abi.encodePacked(IPancakePair(asset).symbol())) == keccak256("Cake-LP")) {
else if (keccak256(abi.encodePacked(IPancakePair(asset).symbol())) == keccak256("Cake-LP")) {
if (IPancakePair(asset).totalSupply() == 0) return (0, 0);
if (IPancakePair(asset).totalSupply() == 0) return (0, 0);
(uint reserve0, uint reserve1, ) = IPancakePair(asset).getReserves();
(uint reserve0, uint reserve1, ) = IPancakePair(asset).getReserves();
if (IPancakePair(asset).token0() == WBNB) {
if (IPancakePair(asset).token0() == WBNB) {
valueInBNB = amount.mul(reserve0).mul(2).div(IPancakePair(asset).totalSupply());
valueInBNB = amount.mul(reserve0).mul(2).div(IPancakePair(asset).totalSupply());
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
} else if (IPancakePair(asset).token1() == WBNB) {
} else if (IPancakePair(asset).token1() == WBNB) {
valueInBNB = amount.mul(reserve1).mul(2).div(IPancakePair(asset).totalSupply());
valueInBNB = amount.mul(reserve1).mul(2).div(IPancakePair(asset).totalSupply());
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
} else {
} else {
(uint token0PriceInBNB,) = valueOfAsset(IPancakePair(asset).token0(), 1e18);
(uint token0PriceInBNB,) = valueOfAsset(IPancakePair(asset).token0(), 1e18);
valueInBNB = amount.mul(reserve0).mul(2).mul(token0PriceInBNB).div(1e18).div(IPancakePair(asset).totalSupply());
valueInBNB = amount.mul(reserve0).mul(2).mul(token0PriceInBNB).div(1e18).div(IPancakePair(asset).totalSupply());
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
}
}
}
}
else {
else {
address pairToken = pairTokens[asset] == address(0) ? WBNB : pairTokens[asset];
address pairToken = pairTokens[asset] == address(0) ? WBNB : pairTokens[asset];
address pair = factory.getPair(asset, pairToken);
address pair = factory.getPair(asset, pairToken);
if (IBEP20(asset).balanceOf(pair) == 0) return (0, 0);
if (IBEP20(asset).balanceOf(pair) == 0) return (0, 0);
(uint reserve0, uint reserve1, ) = IPancakePair(pair).getReserves();
(uint reserve0, uint reserve1, ) = IPancakePair(pair).getReserves();
if (IPancakePair(pair).token0() == pairToken) {
if (IPancakePair(pair).token0() == pairToken) {
valueInBNB = reserve0.mul(amount).div(reserve1);
valueInBNB = reserve0.mul(amount).div(reserve1);
} else if (IPancakePair(pair).token1() == pairToken) {
} else if (IPancakePair(pair).token1() == pairToken) {
valueInBNB = reserve1.mul(amount).div(reserve0);
valueInBNB = reserve1.mul(amount).div(reserve0);
} else {
} else {
return (0, 0);
return (0, 0);
}
}
if (pairToken != WBNB) {
if (pairToken != WBNB) {
(uint pairValueInBNB,) = valueOfAsset(pairToken, 1e18);
(uint pairValueInBNB,) = valueOfAsset(pairToken, 1e18);
valueInBNB = valueInBNB.mul(pairValueInBNB).div(1e18);
valueInBNB = valueInBNB.mul(pairValueInBNB).div(1e18);
}
}
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18);
}
}
}
}
}
}
已保存差異
原始文本
開啟檔案
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; /* ___ _ _ | _ )_ _ _ _ _ _ _ _ | | | | | _ \ || | ' \| ' \ || | |_| |_| |___/\_,_|_||_|_||_\_, | (_) (_) |__/ * * MIT License * =========== * * Copyright (c) 2020 BunnyFinance * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ import "@pancakeswap/pancake-swap-lib/contracts/token/BEP20/IBEP20.sol"; import "@pancakeswap/pancake-swap-lib/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../interfaces/IPancakePair.sol"; import "../../interfaces/IPancakeFactory.sol"; import "../../interfaces/AggregatorV3Interface.sol"; import "../../interfaces/IPriceCalculator.sol"; contract PriceCalculatorBSC is IPriceCalculator, OwnableUpgradeable { using SafeMath for uint; address public constant WBNB = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c; address public constant CAKE = 0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82; address public constant BUNNY = 0xC9849E6fdB743d08fAeE3E34dd2D1bc69EA11a51; address public constant VAI = 0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7; address public constant BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56; IPancakeFactory private constant factory = IPancakeFactory(0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73); AggregatorV3Interface private constant bnbPriceFeed = AggregatorV3Interface(0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeE); /* ========== STATE VARIABLES ========== */ mapping(address => address) private pairTokens; /* ========== INITIALIZER ========== */ function initialize() external initializer { __Ownable_init(); setPairToken(VAI, BUSD); } /* ========== Restricted Operation ========== */ function setPairToken(address asset, address pairToken) public onlyOwner { pairTokens[asset] = pairToken; } /* ========== Value Calculation ========== */ function priceOfBNB() view public returns (uint) { (, int price, , ,) = bnbPriceFeed.latestRoundData(); return uint(price).mul(1e10); } function priceOfCake() view public returns (uint) { (, uint cakePriceInUSD) = valueOfAsset(CAKE, 1e18); return cakePriceInUSD; } function priceOfBunny() view public returns (uint) { (, uint bunnyPriceInUSD) = valueOfAsset(BUNNY, 1e18); return bunnyPriceInUSD; } function pricesInUSD(address[] memory assets) public view override returns (uint[] memory) { uint[] memory prices = new uint[](assets.length); for (uint i = 0; i < assets.length; i++) { (, uint valueInUSD) = valueOfAsset(assets[i], 1e18); prices[i] = valueInUSD; } return prices; } function valueOfAsset(address asset, uint amount) public view override returns (uint valueInBNB, uint valueInUSD) { if (asset == address(0) || asset == WBNB) { valueInBNB = amount; valueInUSD = amount.mul(priceOfBNB()).div(1e18); } else if (keccak256(abi.encodePacked(IPancakePair(asset).symbol())) == keccak256("Cake-LP")) { if (IPancakePair(asset).totalSupply() == 0) return (0, 0); (uint reserve0, uint reserve1, ) = IPancakePair(asset).getReserves(); if (IPancakePair(asset).token0() == WBNB) { valueInBNB = amount.mul(reserve0).mul(2).div(IPancakePair(asset).totalSupply()); valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } else if (IPancakePair(asset).token1() == WBNB) { valueInBNB = amount.mul(reserve1).mul(2).div(IPancakePair(asset).totalSupply()); valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } else { (uint token0PriceInBNB,) = valueOfAsset(IPancakePair(asset).token0(), 1e18); valueInBNB = amount.mul(reserve0).mul(2).mul(token0PriceInBNB).div(1e18).div(IPancakePair(asset).totalSupply()); valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } } else { address pairToken = pairTokens[asset] == address(0) ? WBNB : pairTokens[asset]; address pair = factory.getPair(asset, pairToken); if (IBEP20(asset).balanceOf(pair) == 0) return (0, 0); (uint reserve0, uint reserve1, ) = IPancakePair(pair).getReserves(); if (IPancakePair(pair).token0() == pairToken) { valueInBNB = reserve0.mul(amount).div(reserve1); } else if (IPancakePair(pair).token1() == pairToken) { valueInBNB = reserve1.mul(amount).div(reserve0); } else { return (0, 0); } if (pairToken != WBNB) { (uint pairValueInBNB,) = valueOfAsset(pairToken, 1e18); valueInBNB = valueInBNB.mul(pairValueInBNB).div(1e18); } valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } } }
更改後文本
開啟檔案
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; /* ___ _ _ | _ )_ _ _ _ _ _ _ _ | | | | | _ \ || | ' \| ' \ || | |_| |_| |___/\_,_|_||_|_||_\_, | (_) (_) |__/ * * MIT License * =========== * * Copyright (c) 2020 BunnyFinance * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ import "@pancakeswap/pancake-swap-lib/contracts/token/BEP20/IBEP20.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "../../interfaces/IPancakePair.sol"; import "../../interfaces/IPancakeFactory.sol"; import "../../interfaces/AggregatorV3Interface.sol"; import "../../interfaces/IPriceCalculator.sol"; import "../../library/HomoraMath.sol"; contract PriceCalculatorBSC is IPriceCalculator, OwnableUpgradeable { using SafeMath for uint; using HomoraMath for uint; address public constant WBNB = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c; address public constant CAKE = 0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82; address public constant BUNNY = 0xC9849E6fdB743d08fAeE3E34dd2D1bc69EA11a51; address public constant VAI = 0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7; address public constant BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56; address public constant BUNNY_BNB_V1 = 0x7Bb89460599Dbf32ee3Aa50798BBcEae2A5F7f6a; address public constant BUNNY_BNB_V2 = 0x5aFEf8567414F29f0f927A0F2787b188624c10E2; IPancakeFactory private constant factory = IPancakeFactory(0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73); /* ========== STATE VARIABLES ========== */ mapping(address => address) private pairTokens; mapping(address => address) private tokenFeeds; /* ========== INITIALIZER ========== */ function initialize() external initializer { __Ownable_init(); setPairToken(VAI, BUSD); } /* ========== Restricted Operation ========== */ function setPairToken(address asset, address pairToken) public onlyOwner { pairTokens[asset] = pairToken; } function setTokenFeed(address asset, address feed) public onlyOwner { tokenFeeds[asset] = feed; } /* ========== Value Calculation ========== */ function priceOfBNB() view public returns (uint) { (, int price, , ,) = AggregatorV3Interface(tokenFeeds[WBNB]).latestRoundData(); return uint(price).mul(1e10); } function priceOfCake() view public returns (uint) { (, int price, , ,) = AggregatorV3Interface(tokenFeeds[CAKE]).latestRoundData(); return uint(price).mul(1e10); } function priceOfBunny() view public returns (uint) { (, uint bunnyPriceInUSD) = valueOfAsset(BUNNY, 1e18); return bunnyPriceInUSD; } function pricesInUSD(address[] memory assets) public view override returns (uint[] memory) { uint[] memory prices = new uint[](assets.length); for (uint i = 0; i < assets.length; i++) { (, uint valueInUSD) = valueOfAsset(assets[i], 1e18); prices[i] = valueInUSD; } return prices; } function valueOfAsset(address asset, uint amount) public view override returns (uint valueInBNB, uint valueInUSD) { if (asset == address(0) || asset == WBNB) { return _oracleValueOf(WBNB, amount); } else if (asset == BUNNY || asset == BUNNY_BNB_V1 || asset == BUNNY_BNB_V2) { return _unsafeValueOfAsset(asset, amount); } else if (keccak256(abi.encodePacked(IPancakePair(asset).symbol())) == keccak256("Cake-LP")) { return _getPairPrice(asset, amount); } else { return _oracleValueOf(asset, amount); } } function _oracleValueOf(address asset, uint amount) private view returns (uint valueInBNB, uint valueInUSD) { (, int price, , ,) = AggregatorV3Interface(tokenFeeds[asset]).latestRoundData(); valueInUSD = uint(price).mul(1e10).mul(amount).div(1e18); valueInBNB = valueInUSD.mul(1e18).div(priceOfBNB()); } function _getPairPrice(address pair, uint amount) private view returns (uint valueInBNB, uint valueInUSD) { address token0 = IPancakePair(pair).token0(); address token1 = IPancakePair(pair).token1(); uint totalSupply = IPancakePair(pair).totalSupply(); (uint r0, uint r1, ) = IPancakePair(pair).getReserves(); uint sqrtK = HomoraMath.sqrt(r0.mul(r1)).fdiv(totalSupply); (uint px0,) = _oracleValueOf(token0, 1e18); (uint px1,) = _oracleValueOf(token1, 1e18); uint fairPriceInBNB = sqrtK.mul(2).mul(HomoraMath.sqrt(px0)).div(2**56).mul(HomoraMath.sqrt(px1)).div(2**56); valueInBNB = fairPriceInBNB.mul(amount).div(1e18); valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } function _unsafeValueOfAsset(address asset, uint amount) private view returns (uint valueInBNB, uint valueInUSD) { if (asset == address(0) || asset == WBNB) { valueInBNB = amount; valueInUSD = amount.mul(priceOfBNB()).div(1e18); } else if (keccak256(abi.encodePacked(IPancakePair(asset).symbol())) == keccak256("Cake-LP")) { if (IPancakePair(asset).totalSupply() == 0) return (0, 0); (uint reserve0, uint reserve1, ) = IPancakePair(asset).getReserves(); if (IPancakePair(asset).token0() == WBNB) { valueInBNB = amount.mul(reserve0).mul(2).div(IPancakePair(asset).totalSupply()); valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } else if (IPancakePair(asset).token1() == WBNB) { valueInBNB = amount.mul(reserve1).mul(2).div(IPancakePair(asset).totalSupply()); valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } else { (uint token0PriceInBNB,) = valueOfAsset(IPancakePair(asset).token0(), 1e18); valueInBNB = amount.mul(reserve0).mul(2).mul(token0PriceInBNB).div(1e18).div(IPancakePair(asset).totalSupply()); valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } } else { address pairToken = pairTokens[asset] == address(0) ? WBNB : pairTokens[asset]; address pair = factory.getPair(asset, pairToken); if (IBEP20(asset).balanceOf(pair) == 0) return (0, 0); (uint reserve0, uint reserve1, ) = IPancakePair(pair).getReserves(); if (IPancakePair(pair).token0() == pairToken) { valueInBNB = reserve0.mul(amount).div(reserve1); } else if (IPancakePair(pair).token1() == pairToken) { valueInBNB = reserve1.mul(amount).div(reserve0); } else { return (0, 0); } if (pairToken != WBNB) { (uint pairValueInBNB,) = valueOfAsset(pairToken, 1e18); valueInBNB = valueInBNB.mul(pairValueInBNB).div(1e18); } valueInUSD = valueInBNB.mul(priceOfBNB()).div(1e18); } } }
尋找差異