Diff
checker
文本
文本
圖像
文檔
Excel
文件夾
Legal
Enterprise
桌面版
定價
登入
下載 Diffchecker 桌面版
比較文本
尋找兩個文字檔案之間的差異
工具
歷史
顯示
檢視
拆分
統一
即時編輯器
隱藏空白變更
摺疊未變更行
關閉換行
比對精度
智能
語法
無
變更外觀
處理
忽略
文字轉換
前往第一個差異
編輯輸入
Diffchecker Desktop
執行Diffchecker最安全的方式。取得Diffchecker桌面應用程式:您的差異永遠不會離開您的電腦!
取得桌面版
VaultSushiFlipToFlip.sol
建立於
5 年前
差異永不過期
清除
匯出
分享
解釋
0 刪除
行
總計
刪除
字符
總計
刪除
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
310 行
全部複製
17 新增
行
總計
新增
字符
總計
新增
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
327 行
全部複製
// 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/SafeBEP20.sol";
import "@pancakeswap/pancake-swap-lib/contracts/token/BEP20/SafeBEP20.sol";
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/math/Math.sol";
import {PoolConstant} from "../library/PoolConstant.sol";
import {PoolConstant} from "../library/PoolConstant.sol";
import "../interfaces/IUniswapV2Pair.sol";
import "../interfaces/IUniswapV2Pair.sol";
import "../interfaces/IUniswapV2Factory.sol";
import "../interfaces/IUniswapV2Factory.sol";
import "../interfaces/IStrategy.sol";
import "../interfaces/IStrategy.sol";
import "../interfaces/ISushiMiniChefV2.sol";
import "../interfaces/ISushiMiniChefV2.sol";
import "../interfaces/IZap.sol";
import "../interfaces/IZap.sol";
import "./VaultController.sol";
import "./VaultController.sol";
contract VaultSushiFlipToFlip is VaultController, IStrategy {
contract VaultSushiFlipToFlip is VaultController, IStrategy {
using SafeBEP20 for IBEP20;
using SafeBEP20 for IBEP20;
using SafeMath for uint256;
using SafeMath for uint256;
/* ========== CONSTANTS ============= */
/* ========== CONSTANTS ============= */
IBEP20 private constant SUSHI = IBEP20(0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a);
IBEP20 private constant SUSHI = IBEP20(0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a);
IBEP20 private constant WMATIC = IBEP20(0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270);
IBEP20 private constant WMATIC = IBEP20(0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270);
PoolConstant.PoolTypes public constant override poolType = PoolConstant.PoolTypes.FlipToFlip;
PoolConstant.PoolTypes public constant override poolType = PoolConstant.PoolTypes.FlipToFlip;
ISushiMiniChefV2 private constant SUSHI_MINI_CHEF = ISushiMiniChefV2(0x0769fd68dFb93167989C6f7254cd0D766Fb2841F);
ISushiMiniChefV2 private constant SUSHI_MINI_CHEF = ISushiMiniChefV2(0x0769fd68dFb93167989C6f7254cd0D766Fb2841F);
IZap private constant zap = IZap(0x93bCE7E49E26AF0f87b74583Ba6551DF5E4867B7);
IZap private constant zap = IZap(0x93bCE7E49E26AF0f87b74583Ba6551DF5E4867B7);
uint private constant DUST = 1000;
uint private constant DUST = 1000;
/* ========== STATE VARIABLES ========== */
/* ========== STATE VARIABLES ========== */
uint public override pid;
uint public override pid;
address private _token0;
address private _token0;
address private _token1;
address private _token1;
uint public totalShares;
uint public totalShares;
mapping (address => uint) private _shares;
mapping (address => uint) private _shares;
mapping (address => uint) private _principal;
mapping (address => uint) private _principal;
mapping (address => uint) private _depositedAt;
mapping (address => uint) private _depositedAt;
uint public sushiHarvested;
uint public sushiHarvested;
uint public wmaticHarvested;
uint public wmaticHarvested;
複製
已複製
複製
已複製
uint public totalBalance;
/* ========== MODIFIER ========== */
/* ========== MODIFIER ========== */
modifier updateSushiHarvested {
modifier updateSushiHarvested {
uint _before = SUSHI.balanceOf(address(this));
uint _before = SUSHI.balanceOf(address(this));
uint _beforeWmatic = WMATIC.balanceOf(address(this));
uint _beforeWmatic = WMATIC.balanceOf(address(this));
_;
_;
uint _after = SUSHI.balanceOf(address(this));
uint _after = SUSHI.balanceOf(address(this));
uint _afterWmatic = WMATIC.balanceOf(address(this));
uint _afterWmatic = WMATIC.balanceOf(address(this));
sushiHarvested = sushiHarvested.add(_after).sub(_before);
sushiHarvested = sushiHarvested.add(_after).sub(_before);
wmaticHarvested = wmaticHarvested.add(_afterWmatic).sub(_beforeWmatic);
wmaticHarvested = wmaticHarvested.add(_afterWmatic).sub(_beforeWmatic);
}
}
/* ========== INITIALIZER ========== */
/* ========== INITIALIZER ========== */
function initialize(uint _pid, address _token) external initializer {
function initialize(uint _pid, address _token) external initializer {
__VaultController_init(IBEP20(_token));
__VaultController_init(IBEP20(_token));
_stakingToken.safeApprove(address(SUSHI_MINI_CHEF), uint(- 1));
_stakingToken.safeApprove(address(SUSHI_MINI_CHEF), uint(- 1));
pid = _pid;
pid = _pid;
SUSHI.safeApprove(address(zap), uint(- 1));
SUSHI.safeApprove(address(zap), uint(- 1));
WMATIC.safeApprove(address(zap), uint(- 1));
WMATIC.safeApprove(address(zap), uint(- 1));
}
}
已保存差異
原始文本
開啟檔案
// 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/SafeBEP20.sol"; import "@openzeppelin/contracts/math/Math.sol"; import {PoolConstant} from "../library/PoolConstant.sol"; import "../interfaces/IUniswapV2Pair.sol"; import "../interfaces/IUniswapV2Factory.sol"; import "../interfaces/IStrategy.sol"; import "../interfaces/ISushiMiniChefV2.sol"; import "../interfaces/IZap.sol"; import "./VaultController.sol"; contract VaultSushiFlipToFlip is VaultController, IStrategy { using SafeBEP20 for IBEP20; using SafeMath for uint256; /* ========== CONSTANTS ============= */ IBEP20 private constant SUSHI = IBEP20(0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a); IBEP20 private constant WMATIC = IBEP20(0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270); PoolConstant.PoolTypes public constant override poolType = PoolConstant.PoolTypes.FlipToFlip; ISushiMiniChefV2 private constant SUSHI_MINI_CHEF = ISushiMiniChefV2(0x0769fd68dFb93167989C6f7254cd0D766Fb2841F); IZap private constant zap = IZap(0x93bCE7E49E26AF0f87b74583Ba6551DF5E4867B7); uint private constant DUST = 1000; /* ========== STATE VARIABLES ========== */ uint public override pid; address private _token0; address private _token1; uint public totalShares; mapping (address => uint) private _shares; mapping (address => uint) private _principal; mapping (address => uint) private _depositedAt; uint public sushiHarvested; uint public wmaticHarvested; /* ========== MODIFIER ========== */ modifier updateSushiHarvested { uint _before = SUSHI.balanceOf(address(this)); uint _beforeWmatic = WMATIC.balanceOf(address(this)); _; uint _after = SUSHI.balanceOf(address(this)); uint _afterWmatic = WMATIC.balanceOf(address(this)); sushiHarvested = sushiHarvested.add(_after).sub(_before); wmaticHarvested = wmaticHarvested.add(_afterWmatic).sub(_beforeWmatic); } /* ========== INITIALIZER ========== */ function initialize(uint _pid, address _token) external initializer { __VaultController_init(IBEP20(_token)); _stakingToken.safeApprove(address(SUSHI_MINI_CHEF), uint(- 1)); pid = _pid; SUSHI.safeApprove(address(zap), uint(- 1)); WMATIC.safeApprove(address(zap), uint(- 1)); } /* ========== VIEW FUNCTIONS ========== */ function totalSupply() external view override returns (uint) { return totalShares; } function balance() public view override returns (uint amount) { (amount,) = SUSHI_MINI_CHEF.userInfo(pid, address(this)); } function balanceOf(address account) public view override returns(uint) { if (totalShares == 0) return 0; return balance().mul(sharesOf(account)).div(totalShares); } function withdrawableBalanceOf(address account) public view override returns (uint) { return balanceOf(account); } function sharesOf(address account) public view override returns (uint) { return _shares[account]; } function principalOf(address account) public view override returns (uint) { return _principal[account]; } function earned(address account) public view override returns (uint) { if (balanceOf(account) >= principalOf(account) + DUST) { return balanceOf(account).sub(principalOf(account)); } else { return 0; } } function depositedAt(address account) external view override returns (uint) { return _depositedAt[account]; } function rewardsToken() external view override returns (address) { return address(_stakingToken); } function priceShare() external view override returns(uint) { if (totalShares == 0) return 1e18; return balance().mul(1e18).div(totalShares); } /* ========== MUTATIVE FUNCTIONS ========== */ function deposit(uint _amount) public override { _depositTo(_amount, msg.sender); } function depositAll() external override { deposit(_stakingToken.balanceOf(msg.sender)); } function withdrawAll() external override { uint amount = balanceOf(msg.sender); uint principal = principalOf(msg.sender); uint depositTimestamp = _depositedAt[msg.sender]; totalShares = totalShares.sub(_shares[msg.sender]); delete _shares[msg.sender]; delete _principal[msg.sender]; delete _depositedAt[msg.sender]; amount = _withdrawTokenWithCorrection(amount); uint profit = amount > principal ? amount.sub(principal) : 0; uint withdrawalFee = canMint() ? _minter.withdrawalFee(principal, depositTimestamp) : 0; uint performanceFee = canMint() ? _minter.performanceFee(profit) : 0; if (withdrawalFee.add(performanceFee) > DUST) { _minter.mintForV2(address(_stakingToken), withdrawalFee, performanceFee, msg.sender, depositTimestamp); if (performanceFee > 0) { emit ProfitPaid(msg.sender, profit, performanceFee); } amount = amount.sub(withdrawalFee).sub(performanceFee); } _stakingToken.safeTransfer(msg.sender, amount); emit Withdrawn(msg.sender, amount, withdrawalFee); } function harvest() external override onlyKeeper { _harvest(); uint before = _stakingToken.balanceOf(address(this)); zap.zapInToken(address(SUSHI), sushiHarvested, address(_stakingToken)); zap.zapInToken(address(WMATIC), wmaticHarvested, address(_stakingToken)); uint harvested = _stakingToken.balanceOf(address(this)).sub(before); SUSHI_MINI_CHEF.deposit(pid, harvested, address(this)); emit Harvested(harvested); sushiHarvested = 0; wmaticHarvested = 0; } function _harvest() private updateSushiHarvested { SUSHI_MINI_CHEF.harvest(pid, address(this)); } function withdraw(uint shares) external override onlyWhitelisted { uint amount = balance().mul(shares).div(totalShares); totalShares = totalShares.sub(shares); _shares[msg.sender] = _shares[msg.sender].sub(shares); amount = _withdrawTokenWithCorrection(amount); _stakingToken.safeTransfer(msg.sender, amount); emit Withdrawn(msg.sender, amount, 0); } // @dev underlying only + withdrawal fee + no perf fee function withdrawUnderlying(uint _amount) external { uint amount = Math.min(_amount, _principal[msg.sender]); uint shares = Math.min(amount.mul(totalShares).div(balance()), _shares[msg.sender]); totalShares = totalShares.sub(shares); _shares[msg.sender] = _shares[msg.sender].sub(shares); _principal[msg.sender] = _principal[msg.sender].sub(amount); amount = _withdrawTokenWithCorrection(amount); uint depositTimestamp = _depositedAt[msg.sender]; uint withdrawalFee = canMint() ? _minter.withdrawalFee(amount, depositTimestamp) : 0; if (withdrawalFee > DUST) { _minter.mintForV2(address(_stakingToken), withdrawalFee, 0, msg.sender, depositTimestamp); amount = amount.sub(withdrawalFee); } _stakingToken.safeTransfer(msg.sender, amount); emit Withdrawn(msg.sender, amount, withdrawalFee); } // @dev profits only (underlying + bunny) + no withdraw fee + perf fee function getReward() external override { uint amount = earned(msg.sender); uint shares = Math.min(amount.mul(totalShares).div(balance()), _shares[msg.sender]); totalShares = totalShares.sub(shares); _shares[msg.sender] = _shares[msg.sender].sub(shares); _cleanupIfDustShares(); amount = _withdrawTokenWithCorrection(amount); uint depositTimestamp = _depositedAt[msg.sender]; uint performanceFee = canMint() ? _minter.performanceFee(amount) : 0; if (performanceFee > DUST) { _minter.mintForV2(address(_stakingToken), 0, performanceFee, msg.sender, depositTimestamp); amount = amount.sub(performanceFee); } _stakingToken.safeTransfer(msg.sender, amount); emit ProfitPaid(msg.sender, amount, performanceFee); } /* ========== PRIVATE FUNCTIONS ========== */ function _depositTo(uint _amount, address _to) private notPaused updateSushiHarvested { uint _pool = balance(); uint _before = _stakingToken.balanceOf(address(this)); _stakingToken.safeTransferFrom(msg.sender, address(this), _amount); uint _after = _stakingToken.balanceOf(address(this)); _amount = _after.sub(_before); // Additional check for deflationary tokens uint shares = 0; if (totalShares == 0) { shares = _amount; } else { shares = (_amount.mul(totalShares)).div(_pool); } totalShares = totalShares.add(shares); _shares[_to] = _shares[_to].add(shares); _principal[_to] = _principal[_to].add(_amount); _depositedAt[_to] = block.timestamp; SUSHI_MINI_CHEF.deposit(pid, _amount, address(this)); emit Deposited(_to, _amount); } function _withdrawTokenWithCorrection(uint amount) private updateSushiHarvested returns (uint) { uint before = _stakingToken.balanceOf(address(this)); SUSHI_MINI_CHEF.withdraw(pid, amount, address(this)); return _stakingToken.balanceOf(address(this)).sub(before); } function _cleanupIfDustShares() private { uint shares = _shares[msg.sender]; if (shares > 0 && shares < DUST) { totalShares = totalShares.sub(shares); delete _shares[msg.sender]; } } /* ========== SALVAGE PURPOSE ONLY ========== */ // @dev stakingToken must not remain balance in this contract. So dev should salvage staking token transferred by mistake. function recoverToken(address token, uint amount) external override onlyOwner { if (token == address(SUSHI)) { uint sushiBalance = SUSHI.balanceOf(address(this)); require(amount <= sushiBalance.sub(sushiHarvested), "VaultFlipToFlip: cannot recover lp's harvested sushi"); } if (token == address(WMATIC)){ uint wmaticBalance = WMATIC.balanceOf(address(this)); require(amount <= wmaticBalance.sub(wmaticHarvested)); } IBEP20(token).safeTransfer(owner(), amount); emit Recovered(token, amount); } }
更改後文本
開啟檔案
// 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/SafeBEP20.sol"; import "@openzeppelin/contracts/math/Math.sol"; import {PoolConstant} from "../library/PoolConstant.sol"; import "../interfaces/IUniswapV2Pair.sol"; import "../interfaces/IUniswapV2Factory.sol"; import "../interfaces/IStrategy.sol"; import "../interfaces/ISushiMiniChefV2.sol"; import "../interfaces/IZap.sol"; import "./VaultController.sol"; contract VaultSushiFlipToFlip is VaultController, IStrategy { using SafeBEP20 for IBEP20; using SafeMath for uint256; /* ========== CONSTANTS ============= */ IBEP20 private constant SUSHI = IBEP20(0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a); IBEP20 private constant WMATIC = IBEP20(0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270); PoolConstant.PoolTypes public constant override poolType = PoolConstant.PoolTypes.FlipToFlip; ISushiMiniChefV2 private constant SUSHI_MINI_CHEF = ISushiMiniChefV2(0x0769fd68dFb93167989C6f7254cd0D766Fb2841F); IZap private constant zap = IZap(0x93bCE7E49E26AF0f87b74583Ba6551DF5E4867B7); uint private constant DUST = 1000; /* ========== STATE VARIABLES ========== */ uint public override pid; address private _token0; address private _token1; uint public totalShares; mapping (address => uint) private _shares; mapping (address => uint) private _principal; mapping (address => uint) private _depositedAt; uint public sushiHarvested; uint public wmaticHarvested; uint public totalBalance; /* ========== MODIFIER ========== */ modifier updateSushiHarvested { uint _before = SUSHI.balanceOf(address(this)); uint _beforeWmatic = WMATIC.balanceOf(address(this)); _; uint _after = SUSHI.balanceOf(address(this)); uint _afterWmatic = WMATIC.balanceOf(address(this)); sushiHarvested = sushiHarvested.add(_after).sub(_before); wmaticHarvested = wmaticHarvested.add(_afterWmatic).sub(_beforeWmatic); } /* ========== INITIALIZER ========== */ function initialize(uint _pid, address _token) external initializer { __VaultController_init(IBEP20(_token)); _stakingToken.safeApprove(address(SUSHI_MINI_CHEF), uint(- 1)); pid = _pid; SUSHI.safeApprove(address(zap), uint(- 1)); WMATIC.safeApprove(address(zap), uint(- 1)); } /* ========== VIEW FUNCTIONS ========== */ function totalSupply() external view override returns (uint) { return totalShares; } function balance() public view override returns (uint amount) { (amount,) = SUSHI_MINI_CHEF.userInfo(pid, address(this)); amount = Math.min(amount, totalBalance); } function balanceOf(address account) public view override returns(uint) { if (totalShares == 0) return 0; return balance().mul(sharesOf(account)).div(totalShares); } function withdrawableBalanceOf(address account) public view override returns (uint) { return balanceOf(account); } function sharesOf(address account) public view override returns (uint) { return _shares[account]; } function principalOf(address account) public view override returns (uint) { return _principal[account]; } function earned(address account) public view override returns (uint) { if (balanceOf(account) >= principalOf(account) + DUST) { return balanceOf(account).sub(principalOf(account)); } else { return 0; } } function depositedAt(address account) external view override returns (uint) { return _depositedAt[account]; } function rewardsToken() external view override returns (address) { return address(_stakingToken); } function priceShare() external view override returns(uint) { if (totalShares == 0) return 1e18; return balance().mul(1e18).div(totalShares); } /* ========== MUTATIVE FUNCTIONS ========== */ function deposit(uint _amount) public override { _depositTo(_amount, msg.sender); } function depositAll() external override { deposit(_stakingToken.balanceOf(msg.sender)); } function withdrawAll() external override { uint amount = balanceOf(msg.sender); uint principal = principalOf(msg.sender); uint depositTimestamp = _depositedAt[msg.sender]; totalBalance = totalBalance.sub(amount); totalShares = totalShares.sub(_shares[msg.sender]); delete _shares[msg.sender]; delete _principal[msg.sender]; delete _depositedAt[msg.sender]; amount = _withdrawTokenWithCorrection(amount); uint profit = amount > principal ? amount.sub(principal) : 0; uint withdrawalFee = canMint() ? _minter.withdrawalFee(principal, depositTimestamp) : 0; uint performanceFee = canMint() ? _minter.performanceFee(profit) : 0; if (withdrawalFee.add(performanceFee) > DUST) { _minter.mintForV2(address(_stakingToken), withdrawalFee, performanceFee, msg.sender, depositTimestamp); if (performanceFee > 0) { emit ProfitPaid(msg.sender, profit, performanceFee); } amount = amount.sub(withdrawalFee).sub(performanceFee); } _stakingToken.safeTransfer(msg.sender, amount); emit Withdrawn(msg.sender, amount, withdrawalFee); } function harvest() external override onlyKeeper { _harvest(); uint before = _stakingToken.balanceOf(address(this)); zap.zapInToken(address(SUSHI), sushiHarvested, address(_stakingToken)); zap.zapInToken(address(WMATIC), wmaticHarvested, address(_stakingToken)); uint harvested = _stakingToken.balanceOf(address(this)).sub(before); totalBalance = totalBalance.add(harvested); SUSHI_MINI_CHEF.deposit(pid, harvested, address(this)); emit Harvested(harvested); sushiHarvested = 0; wmaticHarvested = 0; } function _harvest() private updateSushiHarvested { SUSHI_MINI_CHEF.harvest(pid, address(this)); } function withdraw(uint shares) external override onlyWhitelisted { uint amount = balance().mul(shares).div(totalShares); totalBalance = totalBalance.sub(amount); totalShares = totalShares.sub(shares); _shares[msg.sender] = _shares[msg.sender].sub(shares); amount = _withdrawTokenWithCorrection(amount); _stakingToken.safeTransfer(msg.sender, amount); emit Withdrawn(msg.sender, amount, 0); } // @dev underlying only + withdrawal fee + no perf fee function withdrawUnderlying(uint _amount) external { uint amount = Math.min(_amount, _principal[msg.sender]); uint shares = Math.min(amount.mul(totalShares).div(balance()), _shares[msg.sender]); totalBalance = totalBalance.sub(amount); totalShares = totalShares.sub(shares); _shares[msg.sender] = _shares[msg.sender].sub(shares); _principal[msg.sender] = _principal[msg.sender].sub(amount); amount = _withdrawTokenWithCorrection(amount); uint depositTimestamp = _depositedAt[msg.sender]; uint withdrawalFee = canMint() ? _minter.withdrawalFee(amount, depositTimestamp) : 0; if (withdrawalFee > DUST) { _minter.mintForV2(address(_stakingToken), withdrawalFee, 0, msg.sender, depositTimestamp); amount = amount.sub(withdrawalFee); } _stakingToken.safeTransfer(msg.sender, amount); emit Withdrawn(msg.sender, amount, withdrawalFee); } // @dev profits only (underlying + bunny) + no withdraw fee + perf fee function getReward() external override { uint amount = earned(msg.sender); uint shares = Math.min(amount.mul(totalShares).div(balance()), _shares[msg.sender]); totalBalance = totalBalance.sub(amount); totalShares = totalShares.sub(shares); _shares[msg.sender] = _shares[msg.sender].sub(shares); _cleanupIfDustShares(); amount = _withdrawTokenWithCorrection(amount); uint depositTimestamp = _depositedAt[msg.sender]; uint performanceFee = canMint() ? _minter.performanceFee(amount) : 0; if (performanceFee > DUST) { _minter.mintForV2(address(_stakingToken), 0, performanceFee, msg.sender, depositTimestamp); amount = amount.sub(performanceFee); } _stakingToken.safeTransfer(msg.sender, amount); emit ProfitPaid(msg.sender, amount, performanceFee); } /* ========== PRIVATE FUNCTIONS ========== */ function _depositTo(uint _amount, address _to) private notPaused updateSushiHarvested { uint _pool = balance(); uint _before = _stakingToken.balanceOf(address(this)); _stakingToken.safeTransferFrom(msg.sender, address(this), _amount); uint _after = _stakingToken.balanceOf(address(this)); _amount = _after.sub(_before); // Additional check for deflationary tokens uint shares = 0; if (totalShares == 0) { shares = _amount; } else { shares = (_amount.mul(totalShares)).div(_pool); } totalBalance = totalBalance.add(_amount); totalShares = totalShares.add(shares); _shares[_to] = _shares[_to].add(shares); _principal[_to] = _principal[_to].add(_amount); _depositedAt[_to] = block.timestamp; SUSHI_MINI_CHEF.deposit(pid, _amount, address(this)); emit Deposited(_to, _amount); } function _withdrawTokenWithCorrection(uint amount) private updateSushiHarvested returns (uint) { uint before = _stakingToken.balanceOf(address(this)); SUSHI_MINI_CHEF.withdraw(pid, amount, address(this)); return _stakingToken.balanceOf(address(this)).sub(before); } function _cleanupIfDustShares() private { uint shares = _shares[msg.sender]; if (shares > 0 && shares < DUST) { totalShares = totalShares.sub(shares); delete _shares[msg.sender]; } } /* ========== SALVAGE PURPOSE ONLY ========== */ // @dev stakingToken must not remain balance in this contract. So dev should salvage staking token transferred by mistake. function recoverToken(address token, uint amount) external override onlyOwner { if (token == address(SUSHI)) { uint sushiBalance = SUSHI.balanceOf(address(this)); require(amount <= sushiBalance.sub(sushiHarvested), "VaultFlipToFlip: cannot recover lp's harvested sushi"); } if (token == address(WMATIC)){ uint wmaticBalance = WMATIC.balanceOf(address(this)); require(amount <= wmaticBalance.sub(wmaticHarvested)); } IBEP20(token).safeTransfer(owner(), amount); emit Recovered(token, amount); } function setTotalBalance() external onlyOwner { require(totalBalance == 0, "VaultSushiFlipToFlip: can't update totalBalance"); (uint amount,) = SUSHI_MINI_CHEF.userInfo(pid, address(this)); totalBalance = amount; } }
尋找差異