编译器
0.6.12+commit.27d51765
文件 1 的 18:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 18:AggregatorV3Interface.sol
pragma solidity >=0.6.0;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
文件 3 的 18:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 4 的 18:Errors.sol
pragma solidity <0.8.0;
library Errors {
string public constant VL_INDEX_OVERFLOW = "100";
string public constant VL_INVALID_MINT_AMOUNT = "101";
string public constant VL_INVALID_BURN_AMOUNT = "102";
string public constant VL_AMOUNT_ERROR = "103";
string public constant VL_INVALID_WITHDRAW_AMOUNT = "104";
string public constant VL_INVALID_BORROW_AMOUNT = "105";
string public constant VL_NO_DEBT_TO_PAYBACK = "106";
string public constant VL_MISSING_ERC20_ALLOWANCE = "107";
string public constant VL_USER_NOT_LIQUIDATABLE = "108";
string public constant VL_DEBT_LESS_THAN_AMOUNT = "109";
string public constant VL_PROVIDER_ALREADY_ADDED = "110";
string public constant VL_NOT_AUTHORIZED = "111";
string public constant VL_INVALID_COLLATERAL = "112";
string public constant VL_NO_ERC20_BALANCE = "113";
string public constant VL_INPUT_ERROR = "114";
string public constant VL_ASSET_EXISTS = "115";
string public constant VL_ZERO_ADDR_1155 = "116";
string public constant VL_NOT_A_CONTRACT = "117";
string public constant VL_INVALID_ASSETID_1155 = "118";
string public constant VL_NO_ERC1155_BALANCE = "119";
string public constant VL_MISSING_ERC1155_APPROVAL = "120";
string public constant VL_RECEIVER_REJECT_1155 = "121";
string public constant VL_RECEIVER_CONTRACT_NON_1155 = "122";
string public constant VL_OPTIMIZER_FEE_SMALL = "123";
string public constant VL_UNDERCOLLATERIZED_ERROR = "124";
string public constant VL_MINIMUM_PAYBACK_ERROR = "125";
string public constant VL_HARVESTING_FAILED = "126";
string public constant MATH_DIVISION_BY_ZERO = "201";
string public constant MATH_ADDITION_OVERFLOW = "202";
string public constant MATH_MULTIPLICATION_OVERFLOW = "203";
string public constant RF_NO_GREENLIGHT = "300";
string public constant RF_INVALID_RATIO_VALUES = "301";
string public constant RF_CHECK_RATES_FALSE = "302";
string public constant VLT_CALLER_MUST_BE_VAULT = "401";
string public constant SP_ALPHA_WHITELIST = "901";
}
文件 5 的 18:IAlphaWhiteList.sol
pragma solidity >=0.6.12 <0.8.0;
interface IAlphaWhiteList {
function whiteListRoutine(
address _usrAddrs,
uint64 _assetId,
uint256 _amount,
address _erc1155
) external returns(bool);
}
文件 6 的 18:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 7 的 18:IFujiAdmin.sol
pragma solidity >=0.6.12 <0.8.0;
interface IFujiAdmin {
function getFlasher() external view returns (address);
function getFliquidator() external view returns (address);
function getController() external view returns (address);
function getTreasury() external view returns (address payable);
function getaWhiteList() external view returns (address);
function getVaultHarvester() external view returns (address);
function getBonusFlashL() external view returns (uint64, uint64);
function getBonusLiq() external view returns (uint64, uint64);
}
文件 8 的 18:IFujiERC1155.sol
pragma solidity >=0.6.12;
pragma experimental ABIEncoderV2;
interface IFujiERC1155 {
enum AssetType {
collateralToken,
debtToken
}
function getAssetID(AssetType _type, address _assetAddr) external view returns (uint256);
function qtyOfManagedAssets() external view returns (uint64);
function balanceOf(address _account, uint256 _id) external view returns (uint256);
function mint(
address _account,
uint256 _id,
uint256 _amount,
bytes memory _data
) external;
function burn(
address _account,
uint256 _id,
uint256 _amount
) external;
function updateState(uint256 _assetID, uint256 _newBalance) external;
function addInitializeAsset(AssetType _type, address _addr) external returns (uint64);
}
文件 9 的 18:IProvider.sol
pragma solidity >=0.4.25 <0.7.0;
interface IProvider {
function deposit(address _collateralAsset, uint256 _collateralAmount) external payable;
function borrow(address _borrowAsset, uint256 _borrowAmount) external payable;
function withdraw(address _collateralAsset, uint256 _collateralAmount) external payable;
function payback(address _borrowAsset, uint256 _borrowAmount) external payable;
function getBorrowRateFor(address _asset) external view returns (uint256);
function getBorrowBalance(address _asset) external view returns (uint256);
function getDepositBalance(address _asset) external view returns (uint256);
function getBorrowBalanceOf(address _asset, address _who) external returns (uint256);
}
文件 10 的 18:IVault.sol
pragma solidity >=0.6.12;
pragma experimental ABIEncoderV2;
interface IVault {
event Deposit(address indexed userAddrs, address indexed asset, uint256 amount);
event Withdraw(address indexed userAddrs, address indexed asset, uint256 amount);
event Borrow(address indexed userAddrs, address indexed asset, uint256 amount);
event Payback(address indexed userAddrs, address indexed asset, uint256 amount);
event SetActiveProvider(address providerAddr);
event Switch(
address vault,
address fromProviderAddrs,
address toProviderAddr,
uint256 debtamount,
uint256 collattamount
);
function deposit(uint256 _collateralAmount) external payable;
function withdraw(int256 _withdrawAmount) external;
function borrow(uint256 _borrowAmount) external;
function payback(int256 _repayAmount) external payable;
function executeSwitch(
address _newProvider,
uint256 _flashLoanDebt,
uint256 _fee
) external;
function activeProvider() external view returns (address);
function borrowBalance(address _provider) external view returns (uint256);
function depositBalance(address _provider) external view returns (uint256);
function getNeededCollateralFor(uint256 _amount, bool _withFactors)
external
view
returns (uint256);
function getLiquidationBonusFor(uint256 _amount, bool _flash) external view returns (uint256);
function getProviders() external view returns (address[] memory);
function fujiERC1155() external view returns (address);
function setActiveProvider(address _provider) external;
function updateF1155Balances() external;
}
文件 11 的 18:LibUniERC20.sol
pragma solidity ^0.6.12;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
library UniERC20 {
using SafeERC20 for IERC20;
IERC20 private constant _ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
IERC20 private constant _ZERO_ADDRESS = IERC20(0);
function isETH(IERC20 token) internal pure returns (bool) {
return (token == _ZERO_ADDRESS || token == _ETH_ADDRESS);
}
function uniBalanceOf(IERC20 token, address account) internal view returns (uint256) {
if (isETH(token)) {
return account.balance;
} else {
return token.balanceOf(account);
}
}
function uniTransfer(
IERC20 token,
address payable to,
uint256 amount
) internal {
if (amount > 0) {
if (isETH(token)) {
to.transfer(amount);
} else {
token.safeTransfer(to, amount);
}
}
}
function uniApprove(
IERC20 token,
address to,
uint256 amount
) internal {
require(!isETH(token), "Approve called on ETH");
if (amount == 0) {
token.safeApprove(to, 0);
} else {
uint256 allowance = token.allowance(address(this), to);
if (allowance < amount) {
if (allowance > 0) {
token.safeApprove(to, 0);
}
token.safeApprove(to, amount);
}
}
}
}
文件 12 的 18:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 13 的 18:Pausable.sol
pragma solidity >=0.6.0 <0.8.0;
import "./Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor () internal {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 14 的 18:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 15 的 18:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 16 的 18:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 17 的 18:VaultBase.sol
pragma solidity >=0.6.12;
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { UniERC20 } from "../Libraries/LibUniERC20.sol";
contract VaultControl is Ownable, Pausable {
using SafeMath for uint256;
using UniERC20 for IERC20;
struct VaultAssets {
address collateralAsset;
address borrowAsset;
uint64 collateralID;
uint64 borrowID;
}
VaultAssets public vAssets;
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_pause();
}
}
contract VaultBase is VaultControl {
function _deposit(uint256 _amount, address _provider) internal {
bytes memory data =
abi.encodeWithSignature("deposit(address,uint256)", vAssets.collateralAsset, _amount);
_execute(_provider, data);
}
function _withdraw(uint256 _amount, address _provider) internal {
bytes memory data =
abi.encodeWithSignature("withdraw(address,uint256)", vAssets.collateralAsset, _amount);
_execute(_provider, data);
}
function _borrow(uint256 _amount, address _provider) internal {
bytes memory data =
abi.encodeWithSignature("borrow(address,uint256)", vAssets.borrowAsset, _amount);
_execute(_provider, data);
}
function _payback(uint256 _amount, address _provider) internal {
bytes memory data =
abi.encodeWithSignature("payback(address,uint256)", vAssets.borrowAsset, _amount);
_execute(_provider, data);
}
function _execute(address _target, bytes memory _data)
internal
whenNotPaused
returns (bytes memory response)
{
assembly {
let succeeded := delegatecall(sub(gas(), 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
let size := returndatasize()
response := mload(0x40)
mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))
mstore(response, size)
returndatacopy(add(response, 0x20), 0, size)
switch iszero(succeeded)
case 1 {
revert(add(response, 0x20), size)
}
}
}
}
文件 18 的 18:VaultETHUSDC.sol
pragma solidity >=0.4.25 <0.8.0;
pragma experimental ABIEncoderV2;
import { IVault } from "./IVault.sol";
import { VaultBase } from "./VaultBase.sol";
import { IFujiAdmin } from "../IFujiAdmin.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {
AggregatorV3Interface
} from "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IFujiERC1155 } from "../FujiERC1155/IFujiERC1155.sol";
import { IProvider } from "../Providers/IProvider.sol";
import { IAlphaWhiteList } from "../IAlphaWhiteList.sol";
import { Errors } from "../Libraries/Errors.sol";
interface IVaultHarvester {
function collectRewards(uint256 _farmProtocolNum) external returns (address claimedToken);
}
contract VaultETHUSDC is IVault, VaultBase, ReentrancyGuard {
uint256 internal constant _BASE = 1e18;
struct Factor {
uint64 a;
uint64 b;
}
Factor public safetyF;
Factor public collatF;
address[] public providers;
address public override activeProvider;
IFujiAdmin private _fujiAdmin;
address public override fujiERC1155;
AggregatorV3Interface public oracle;
modifier isAuthorized() {
require(
msg.sender == owner() || msg.sender == _fujiAdmin.getController(),
Errors.VL_NOT_AUTHORIZED
);
_;
}
modifier onlyFlash() {
require(msg.sender == _fujiAdmin.getFlasher(), Errors.VL_NOT_AUTHORIZED);
_;
}
constructor() public {
vAssets.collateralAsset = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
vAssets.borrowAsset = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
safetyF.a = 21;
safetyF.b = 20;
collatF.a = 80;
collatF.b = 63;
}
receive() external payable {}
function depositAndBorrow(uint256 _collateralAmount, uint256 _borrowAmount) external payable {
deposit(_collateralAmount);
borrow(_borrowAmount);
}
function paybackAndWithdraw(int256 _paybackAmount, int256 _collateralAmount) external payable {
payback(_paybackAmount);
withdraw(_collateralAmount);
}
function deposit(uint256 _collateralAmount) public payable override {
require(msg.value == _collateralAmount && _collateralAmount != 0, Errors.VL_AMOUNT_ERROR);
require(
IAlphaWhiteList(_fujiAdmin.getaWhiteList()).whiteListRoutine(
msg.sender,
vAssets.collateralID,
_collateralAmount,
fujiERC1155
),
Errors.SP_ALPHA_WHITELIST
);
_deposit(_collateralAmount, address(activeProvider));
IFujiERC1155(fujiERC1155).mint(msg.sender, vAssets.collateralID, _collateralAmount, "");
emit Deposit(msg.sender, vAssets.collateralAsset, _collateralAmount);
}
function withdraw(int256 _withdrawAmount) public override nonReentrant {
if (msg.sender != _fujiAdmin.getFliquidator()) {
updateF1155Balances();
uint256 providedCollateral =
IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.collateralID);
require(providedCollateral > 0, Errors.VL_INVALID_COLLATERAL);
uint256 neededCollateral =
getNeededCollateralFor(
IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID),
true
);
uint256 amountToWithdraw =
_withdrawAmount < 0 ? providedCollateral.sub(neededCollateral) : uint256(_withdrawAmount);
require(
amountToWithdraw != 0 && providedCollateral.sub(amountToWithdraw) >= neededCollateral,
Errors.VL_INVALID_WITHDRAW_AMOUNT
);
IFujiERC1155(fujiERC1155).burn(msg.sender, vAssets.collateralID, amountToWithdraw);
_withdraw(amountToWithdraw, address(activeProvider));
IERC20(vAssets.collateralAsset).uniTransfer(msg.sender, amountToWithdraw);
emit Withdraw(msg.sender, vAssets.collateralAsset, amountToWithdraw);
} else {
_withdraw(uint256(_withdrawAmount), address(activeProvider));
IERC20(vAssets.collateralAsset).uniTransfer(msg.sender, uint256(_withdrawAmount));
}
}
function borrow(uint256 _borrowAmount) public override nonReentrant {
updateF1155Balances();
uint256 providedCollateral =
IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.collateralID);
uint256 neededCollateral =
getNeededCollateralFor(
_borrowAmount.add(IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID)),
true
);
require(
_borrowAmount != 0 && providedCollateral > neededCollateral,
Errors.VL_INVALID_BORROW_AMOUNT
);
IFujiERC1155(fujiERC1155).mint(msg.sender, vAssets.borrowID, _borrowAmount, "");
_borrow(_borrowAmount, address(activeProvider));
IERC20(vAssets.borrowAsset).uniTransfer(msg.sender, _borrowAmount);
emit Borrow(msg.sender, vAssets.borrowAsset, _borrowAmount);
}
function payback(int256 _repayAmount) public payable override {
if (msg.sender != _fujiAdmin.getFliquidator()) {
updateF1155Balances();
uint256 userDebtBalance = IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID);
require(_repayAmount != 0 && userDebtBalance > 0, Errors.VL_NO_DEBT_TO_PAYBACK);
uint256 amountToPayback = _repayAmount < 0 ? userDebtBalance : uint256(_repayAmount);
require(
IERC20(vAssets.borrowAsset).allowance(msg.sender, address(this)) >= amountToPayback,
Errors.VL_MISSING_ERC20_ALLOWANCE
);
IERC20(vAssets.borrowAsset).transferFrom(msg.sender, address(this), amountToPayback);
_payback(amountToPayback, address(activeProvider));
IFujiERC1155(fujiERC1155).burn(msg.sender, vAssets.borrowID, amountToPayback);
emit Payback(msg.sender, vAssets.borrowAsset, userDebtBalance);
} else {
_payback(uint256(_repayAmount), address(activeProvider));
}
}
function executeSwitch(
address _newProvider,
uint256 _flashLoanAmount,
uint256 _fee
) external override onlyFlash whenNotPaused {
uint256 ratio =
(_flashLoanAmount).mul(1e18).div(
IProvider(activeProvider).getBorrowBalance(vAssets.borrowAsset)
);
_payback(_flashLoanAmount, activeProvider);
uint256 collateraltoMove =
IProvider(activeProvider).getDepositBalance(vAssets.collateralAsset).mul(ratio).div(1e18);
_withdraw(collateraltoMove, activeProvider);
_deposit(collateraltoMove, _newProvider);
_borrow(_flashLoanAmount.add(_fee), _newProvider);
IERC20(vAssets.borrowAsset).uniTransfer(msg.sender, _flashLoanAmount.add(_fee));
emit Switch(address(this), activeProvider, _newProvider, _flashLoanAmount, collateraltoMove);
}
function setFujiAdmin(address _newFujiAdmin) external onlyOwner {
_fujiAdmin = IFujiAdmin(_newFujiAdmin);
}
function setActiveProvider(address _provider) external override isAuthorized {
activeProvider = _provider;
emit SetActiveProvider(_provider);
}
function setFujiERC1155(address _fujiERC1155) external isAuthorized {
fujiERC1155 = _fujiERC1155;
vAssets.collateralID = IFujiERC1155(_fujiERC1155).addInitializeAsset(
IFujiERC1155.AssetType.collateralToken,
address(this)
);
vAssets.borrowID = IFujiERC1155(_fujiERC1155).addInitializeAsset(
IFujiERC1155.AssetType.debtToken,
address(this)
);
}
function setFactor(
uint64 _newFactorA,
uint64 _newFactorB,
bool _isSafety
) external isAuthorized {
if (_isSafety) {
safetyF.a = _newFactorA;
safetyF.b = _newFactorB;
} else {
collatF.a = _newFactorA;
collatF.b = _newFactorB;
}
}
function setOracle(address _oracle) external isAuthorized {
oracle = AggregatorV3Interface(_oracle);
}
function setProviders(address[] calldata _providers) external isAuthorized {
providers = _providers;
}
function updateF1155Balances() public override {
uint256 borrowBals;
uint256 depositBals;
uint256 length = providers.length;
for (uint256 i = 0; i < length; i++) {
borrowBals = borrowBals.add(IProvider(providers[i]).getBorrowBalance(vAssets.borrowAsset));
}
for (uint256 i = 0; i < length; i++) {
depositBals = depositBals.add(
IProvider(providers[i]).getDepositBalance(vAssets.collateralAsset)
);
}
IFujiERC1155(fujiERC1155).updateState(vAssets.borrowID, borrowBals);
IFujiERC1155(fujiERC1155).updateState(vAssets.collateralID, depositBals);
}
function getProviders() external view override returns (address[] memory) {
return providers;
}
function getLiquidationBonusFor(uint256 _amount, bool _flash)
external
view
override
returns (uint256)
{
if (_flash) {
(uint64 a, uint64 b) = _fujiAdmin.getBonusFlashL();
return _amount.mul(a).div(b);
} else {
(uint64 a, uint64 b) = _fujiAdmin.getBonusLiq();
return _amount.mul(a).div(b);
}
}
function getNeededCollateralFor(uint256 _amount, bool _withFactors)
public
view
override
returns (uint256)
{
(, int256 latestPrice, , , ) = oracle.latestRoundData();
uint256 minimumReq = (_amount.mul(1e12).mul(uint256(latestPrice))).div(_BASE);
if (_withFactors) {
return minimumReq.mul(collatF.a).mul(safetyF.a).div(collatF.b).div(safetyF.b);
} else {
return minimumReq;
}
}
function borrowBalance(address _provider) external view override returns (uint256) {
return IProvider(_provider).getBorrowBalance(vAssets.borrowAsset);
}
function depositBalance(address _provider) external view override returns (uint256) {
return IProvider(_provider).getDepositBalance(vAssets.collateralAsset);
}
function harvestRewards(uint256 _farmProtocolNum) external onlyOwner {
address tokenReturned =
IVaultHarvester(_fujiAdmin.getVaultHarvester()).collectRewards(_farmProtocolNum);
uint256 tokenBal = IERC20(tokenReturned).balanceOf(address(this));
require(tokenReturned != address(0) && tokenBal > 0, Errors.VL_HARVESTING_FAILED);
IERC20(tokenReturned).uniTransfer(payable(_fujiAdmin.getTreasury()), tokenBal);
}
}
{
"compilationTarget": {
"contracts/Vaults/VaultETHUSDC.sol": "VaultETHUSDC"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddrs","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddrs","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddrs","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Payback","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"providerAddr","type":"address"}],"name":"SetActiveProvider","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"fromProviderAddrs","type":"address"},{"indexed":false,"internalType":"address","name":"toProviderAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"debtamount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collattamount","type":"uint256"}],"name":"Switch","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddrs","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"activeProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_borrowAmount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_provider","type":"address"}],"name":"borrowBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatF","outputs":[{"internalType":"uint64","name":"a","type":"uint64"},{"internalType":"uint64","name":"b","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralAmount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralAmount","type":"uint256"},{"internalType":"uint256","name":"_borrowAmount","type":"uint256"}],"name":"depositAndBorrow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_provider","type":"address"}],"name":"depositBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newProvider","type":"address"},{"internalType":"uint256","name":"_flashLoanAmount","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"executeSwitch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fujiERC1155","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_flash","type":"bool"}],"name":"getLiquidationBonusFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_withFactors","type":"bool"}],"name":"getNeededCollateralFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProviders","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmProtocolNum","type":"uint256"}],"name":"harvestRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"_repayAmount","type":"int256"}],"name":"payback","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"_paybackAmount","type":"int256"},{"internalType":"int256","name":"_collateralAmount","type":"int256"}],"name":"paybackAndWithdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"providers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"safetyF","outputs":[{"internalType":"uint64","name":"a","type":"uint64"},{"internalType":"uint64","name":"b","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_provider","type":"address"}],"name":"setActiveProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_newFactorA","type":"uint64"},{"internalType":"uint64","name":"_newFactorB","type":"uint64"},{"internalType":"bool","name":"_isSafety","type":"bool"}],"name":"setFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newFujiAdmin","type":"address"}],"name":"setFujiAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fujiERC1155","type":"address"}],"name":"setFujiERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracle","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_providers","type":"address[]"}],"name":"setProviders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateF1155Balances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vAssets","outputs":[{"internalType":"address","name":"collateralAsset","type":"address"},{"internalType":"address","name":"borrowAsset","type":"address"},{"internalType":"uint64","name":"collateralID","type":"uint64"},{"internalType":"uint64","name":"borrowID","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"_withdrawAmount","type":"int256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]