文件 1 的 1:TokenManager.sol
pragma solidity 0.6.12;
interface ILiquidationManager {
function setCircuitBreaker(bool _emergency) external returns (bool);
function partialLiquidation(address payable delinquentBorrower, uint256 targetHandler, uint256 liquidateAmount, uint256 receiveHandler) external returns (uint256);
function checkLiquidation(address payable userAddr) external view returns (bool);
}
pragma solidity 0.6.12;
interface IManagerSlotSetter {
function ownershipTransfer(address payable _owner) external returns (bool);
function setOperator(address payable adminAddr, bool flag) external returns (bool);
function setOracleProxy(address oracleProxyAddr) external returns (bool);
function setRewardErc20(address erc20Addr) external returns (bool);
function setBreakerTable(address _target, bool _status) external returns (bool);
function setCircuitBreaker(bool _emergency) external returns (bool);
function handlerRegister(uint256 handlerID, address tokenHandlerAddr, uint256 flashFeeRate, uint256 discountBase) external returns (bool);
function setLiquidationManager(address liquidationManagerAddr) external returns (bool);
function setHandlerSupport(uint256 handlerID, bool support) external returns (bool);
function setPositionStorageAddr(address _positionStorageAddr) external returns (bool);
function setNFTAddr(address _nftAddr) external returns (bool);
function setDiscountBase(uint256 handlerID, uint256 feeBase) external returns (bool);
function setFlashloanAddr(address _flashloanAddr) external returns (bool);
function sethandlerManagerAddr(address _handlerManagerAddr) external returns (bool);
function setSlotSetterAddr(address _slotSetterAddr) external returns (bool);
function setFlashloanFee(uint256 handlerID, uint256 flashFeeRate) external returns (bool);
}
pragma solidity 0.6.12;
interface IHandlerManager {
function applyInterestHandlers(address payable userAddr, uint256 callerID, bool allFlag) external returns (uint256, uint256, uint256, uint256, uint256, uint256);
function interestUpdateReward() external returns (bool);
function updateRewardParams(address payable userAddr) external returns (bool);
function rewardClaimAll(address payable userAddr) external returns (uint256);
function claimHandlerReward(uint256 handlerID, address payable userAddr) external returns (uint256);
function ownerRewardTransfer(uint256 _amount) external returns (bool);
}
pragma solidity 0.6.12;
interface IManagerFlashloan {
function withdrawFlashloanFee(uint256 handlerID) external returns (bool);
function flashloan(
uint256 handlerID,
address receiverAddress,
uint256 amount,
bytes calldata params
) external returns (bool);
function getFee(uint256 handlerID, uint256 amount) external view returns (uint256);
function getFeeTotal(uint256 handlerID) external view returns (uint256);
function getFeeFromArguments(uint256 handlerID, uint256 amount, uint256 bifiAmo) external view returns (uint256);
}
pragma solidity ^0.6.12;
library SafeMath {
uint256 internal constant unifiedPoint = 10 ** 18;
function add(uint256 a, uint256 b) internal pure returns (uint256)
{
uint256 c = a + b;
require(c >= a, "a");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256)
{
return _sub(a, b, "s");
}
function mul(uint256 a, uint256 b) internal pure returns (uint256)
{
return _mul(a, b);
}
function div(uint256 a, uint256 b) internal pure returns (uint256)
{
return _div(a, b, "d");
}
function _sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256)
{
require(b <= a, errorMessage);
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, "m");
return c;
}
function _div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256)
{
require(b > 0, errorMessage);
return a / b;
}
function unifiedDiv(uint256 a, uint256 b) internal pure returns (uint256)
{
return _div(_mul(a, unifiedPoint), b, "d");
}
function unifiedMul(uint256 a, uint256 b) internal pure returns (uint256)
{
return _div(_mul(a, b), unifiedPoint, "m");
}
}
pragma solidity 0.6.12;
interface IManagerDataStorage {
function getGlobalRewardPerBlock() external view returns (uint256);
function setGlobalRewardPerBlock(uint256 _globalRewardPerBlock) external returns (bool);
function getGlobalRewardDecrement() external view returns (uint256);
function setGlobalRewardDecrement(uint256 _globalRewardDecrement) external returns (bool);
function getGlobalRewardTotalAmount() external view returns (uint256);
function setGlobalRewardTotalAmount(uint256 _globalRewardTotalAmount) external returns (bool);
function getAlphaRate() external view returns (uint256);
function setAlphaRate(uint256 _alphaRate) external returns (bool);
function getAlphaLastUpdated() external view returns (uint256);
function setAlphaLastUpdated(uint256 _alphaLastUpdated) external returns (bool);
function getRewardParamUpdateRewardPerBlock() external view returns (uint256);
function setRewardParamUpdateRewardPerBlock(uint256 _rewardParamUpdateRewardPerBlock) external returns (bool);
function getRewardParamUpdated() external view returns (uint256);
function setRewardParamUpdated(uint256 _rewardParamUpdated) external returns (bool);
function getInterestUpdateRewardPerblock() external view returns (uint256);
function setInterestUpdateRewardPerblock(uint256 _interestUpdateRewardPerblock) external returns (bool);
function getInterestRewardUpdated() external view returns (uint256);
function setInterestRewardUpdated(uint256 _interestRewardLastUpdated) external returns (bool);
function setTokenHandler(uint256 handlerID, address handlerAddr) external returns (bool);
function getTokenHandlerInfo(uint256 handlerID) external view returns (bool, address);
function getTokenHandlerID(uint256 index) external view returns (uint256);
function getTokenHandlerAddr(uint256 handlerID) external view returns (address);
function setTokenHandlerAddr(uint256 handlerID, address handlerAddr) external returns (bool);
function getTokenHandlerExist(uint256 handlerID) external view returns (bool);
function setTokenHandlerExist(uint256 handlerID, bool exist) external returns (bool);
function getTokenHandlerSupport(uint256 handlerID) external view returns (bool);
function setTokenHandlerSupport(uint256 handlerID, bool support) external returns (bool);
function setLiquidationManagerAddr(address _liquidationManagerAddr) external returns (bool);
function getLiquidationManagerAddr() external view returns (address);
function setManagerAddr(address _managerAddr) external returns (bool);
}
pragma solidity 0.6.12;
interface IOracleProxy {
function getTokenPrice(uint256 tokenID) external view returns (uint256);
function getOracleFeed(uint256 tokenID) external view returns (address, uint256);
function setOracleFeed(uint256 tokenID, address feedAddr, uint256 decimals, bool needPriceConvert, uint256 priceConvertID) external returns (bool);
}
pragma solidity 0.6.12;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external ;
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 ;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
pragma solidity 0.6.12;
interface IObserver {
function getAlphaBaseAsset() external view returns (uint256[] memory);
function setChainGlobalRewardPerblock(uint256 _idx, uint256 globalRewardPerBlocks) external returns (bool);
function updateChainMarketInfo(uint256 _idx, uint256 chainDeposit, uint256 chainBorrow) external returns (bool);
}
pragma solidity 0.6.12;
interface IProxy {
function handlerProxy(bytes memory data) external returns (bool, bytes memory);
function handlerViewProxy(bytes memory data) external view returns (bool, bytes memory);
function siProxy(bytes memory data) external returns (bool, bytes memory);
function siViewProxy(bytes memory data) external view returns (bool, bytes memory);
}
pragma solidity 0.6.12;
interface IMarketHandler {
function setCircuitBreaker(bool _emergency) external returns (bool);
function setCircuitBreakWithOwner(bool _emergency) external returns (bool);
function getTokenName() external view returns (string memory);
function ownershipTransfer(address payable newOwner) external returns (bool);
function deposit(uint256 unifiedTokenAmount, bool allFlag) external payable returns (bool);
function withdraw(uint256 unifiedTokenAmount, bool allFlag) external returns (bool);
function borrow(uint256 unifiedTokenAmount, bool allFlag) external returns (bool);
function repay(uint256 unifiedTokenAmount, bool allFlag) external payable returns (bool);
function executeFlashloan(
address receiverAddress,
uint256 amount
) external returns (bool);
function depositFlashloanFee(
uint256 amount
) external returns (bool);
function convertUnifiedToUnderlying(uint256 unifiedTokenAmount) external view returns (uint256);
function partialLiquidationUser(address payable delinquentBorrower, uint256 liquidateAmount, address payable liquidator, uint256 rewardHandlerID) external returns (uint256, uint256, uint256);
function partialLiquidationUserReward(address payable delinquentBorrower, uint256 liquidationAmountWithReward, address payable liquidator) external returns (uint256);
function getTokenHandlerLimit() external view returns (uint256, uint256);
function getTokenHandlerBorrowLimit() external view returns (uint256);
function getTokenHandlerMarginCallLimit() external view returns (uint256);
function setTokenHandlerBorrowLimit(uint256 borrowLimit) external returns (bool);
function setTokenHandlerMarginCallLimit(uint256 marginCallLimit) external returns (bool);
function getTokenLiquidityAmountWithInterest(address payable userAddr) external view returns (uint256);
function getUserAmountWithInterest(address payable userAddr) external view returns (uint256, uint256);
function getUserAmount(address payable userAddr) external view returns (uint256, uint256);
function getUserMaxBorrowAmount(address payable userAddr) external view returns (uint256);
function getUserMaxWithdrawAmount(address payable userAddr) external view returns (uint256);
function getUserMaxRepayAmount(address payable userAddr) external view returns (uint256);
function checkFirstAction() external returns (bool);
function applyInterest(address payable userAddr) external returns (uint256, uint256);
function reserveDeposit(uint256 unifiedTokenAmount) external payable returns (bool);
function reserveWithdraw(uint256 unifiedTokenAmount) external returns (bool);
function withdrawFlashloanFee(uint256 unifiedTokenAmount) external returns (bool);
function getDepositTotalAmount() external view returns (uint256);
function getBorrowTotalAmount() external view returns (uint256);
function getSIRandBIR() external view returns (uint256, uint256);
function getERC20Addr() external view returns (address);
}
pragma solidity 0.6.12;
interface IServiceIncentive {
function setCircuitBreakWithOwner(bool emergency) external returns (bool);
function setCircuitBreaker(bool emergency) external returns (bool);
function updateRewardPerBlockLogic(uint256 _rewardPerBlock) external returns (bool);
function updateRewardLane(address payable userAddr) external returns (bool);
function getBetaRateBaseTotalAmount() external view returns (uint256);
function getBetaRateBaseUserAmount(address payable userAddr) external view returns (uint256);
function getMarketRewardInfo() external view returns (uint256, uint256, uint256);
function getUserRewardInfo(address payable userAddr) external view returns (uint256, uint256, uint256);
function claimRewardAmountUser(address payable userAddr) external returns (uint256);
}
pragma solidity 0.6.12;
contract Modifier {
string internal constant ONLY_OWNER = "O";
string internal constant ONLY_MANAGER = "M";
string internal constant CIRCUIT_BREAKER = "emergency";
}
contract ManagerModifier is Modifier {
string internal constant ONLY_HANDLER = "H";
string internal constant ONLY_LIQUIDATION_MANAGER = "LM";
string internal constant ONLY_BREAKER = "B";
}
contract HandlerDataStorageModifier is Modifier {
string internal constant ONLY_BIFI_CONTRACT = "BF";
}
contract SIDataStorageModifier is Modifier {
string internal constant ONLY_SI_HANDLER = "SI";
}
contract HandlerErrors is Modifier {
string internal constant USE_VAULE = "use value";
string internal constant USE_ARG = "use arg";
string internal constant EXCEED_LIMIT = "exceed limit";
string internal constant NO_LIQUIDATION = "no liquidation";
string internal constant NO_LIQUIDATION_REWARD = "no enough reward";
string internal constant NO_EFFECTIVE_BALANCE = "not enough balance";
string internal constant TRANSFER = "err transfer";
}
contract SIErrors is Modifier { }
contract InterestErrors is Modifier { }
contract LiquidationManagerErrors is Modifier {
string internal constant NO_DELINQUENT = "not delinquent";
}
contract ManagerErrors is ManagerModifier {
string internal constant REWARD_TRANSFER = "RT";
string internal constant UNSUPPORTED_TOKEN = "UT";
}
contract OracleProxyErrors is Modifier {
string internal constant ZERO_PRICE = "price zero";
}
contract RequestProxyErrors is Modifier { }
contract ManagerDataStorageErrors is ManagerModifier {
string internal constant NULL_ADDRESS = "err addr null";
}
pragma solidity 0.6.12;
contract ManagerSlot is ManagerErrors {
using SafeMath for uint256;
address public owner;
mapping(address => bool) operators;
mapping(address => Breaker) internal breakerTable;
bool public emergency = false;
IManagerDataStorage internal dataStorageInstance;
IOracleProxy internal oracleProxy;
IERC20 internal rewardErc20Instance;
IObserver public Observer;
address public slotSetterAddr;
address public handlerManagerAddr;
address public flashloanAddr;
address public positionStorageAddr;
address public nftAddr;
uint256 public tokenHandlerLength;
struct FeeRateParams {
uint256 unifiedPoint;
uint256 minimum;
uint256 slope;
uint256 discountRate;
}
struct HandlerFlashloan {
uint256 flashFeeRate;
uint256 discountBase;
uint256 feeTotal;
}
mapping(uint256 => HandlerFlashloan) public handlerFlashloan;
struct UserAssetsInfo {
uint256 depositAssetSum;
uint256 borrowAssetSum;
uint256 marginCallLimitSum;
uint256 depositAssetBorrowLimitSum;
uint256 depositAsset;
uint256 borrowAsset;
uint256 price;
uint256 callerPrice;
uint256 depositAmount;
uint256 borrowAmount;
uint256 borrowLimit;
uint256 marginCallLimit;
uint256 callerBorrowLimit;
uint256 userBorrowableAsset;
uint256 withdrawableAsset;
}
struct Breaker {
bool auth;
bool tried;
}
struct ContractInfo {
bool support;
address addr;
address tokenAddr;
uint256 expectedBalance;
uint256 afterBalance;
IProxy tokenHandler;
bytes data;
IMarketHandler handlerFunction;
IServiceIncentive siFunction;
IOracleProxy oracleProxy;
IManagerDataStorage managerDataStorage;
}
modifier onlyOwner {
require(msg.sender == owner, ONLY_OWNER);
_;
}
modifier onlyHandler(uint256 handlerID) {
_isHandler(handlerID);
_;
}
modifier onlyOperators {
address payable sender = msg.sender;
require(operators[sender] || sender == owner);
_;
}
function _isHandler(uint256 handlerID) internal view {
address msgSender = msg.sender;
require((msgSender == dataStorageInstance.getTokenHandlerAddr(handlerID)) || (msgSender == owner), ONLY_HANDLER);
}
modifier onlyLiquidationManager {
_isLiquidationManager();
_;
}
function _isLiquidationManager() internal view {
address msgSender = msg.sender;
require((msgSender == dataStorageInstance.getLiquidationManagerAddr()) || (msgSender == owner), ONLY_LIQUIDATION_MANAGER);
}
modifier circuitBreaker {
_isCircuitBreak();
_;
}
function _isCircuitBreak() internal view {
require((!emergency) || (msg.sender == owner), CIRCUIT_BREAKER);
}
modifier onlyBreaker {
_isBreaker();
_;
}
function _isBreaker() internal view {
require(breakerTable[msg.sender].auth, ONLY_BREAKER);
}
}
pragma solidity 0.6.12;
contract TokenManager is ManagerSlot {
constructor (address managerDataStorageAddr, address oracleProxyAddr, address _slotSetterAddr, address _handlerManagerAddr, address _flashloanAddr, address breaker, address erc20Addr) public
{
owner = msg.sender;
dataStorageInstance = IManagerDataStorage(managerDataStorageAddr);
oracleProxy = IOracleProxy(oracleProxyAddr);
rewardErc20Instance = IERC20(erc20Addr);
slotSetterAddr = _slotSetterAddr;
handlerManagerAddr = _handlerManagerAddr;
flashloanAddr = _flashloanAddr;
breakerTable[owner].auth = true;
breakerTable[breaker].auth = true;
}
function ownershipTransfer(address payable _owner) onlyOwner public returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.ownershipTransfer.selector,
_owner
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setOperator(address payable adminAddr, bool flag) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setOperator.selector,
adminAddr, flag
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setOracleProxy(address oracleProxyAddr) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setOracleProxy.selector,
oracleProxyAddr
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setRewardErc20(address erc20Addr) onlyOwner public returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setRewardErc20.selector,
erc20Addr
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setBreakerTable(address _target, bool _status) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setBreakerTable.selector,
_target, _status
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setCircuitBreaker(bool _emergency) onlyBreaker external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setCircuitBreaker.selector,
_emergency
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setSlotSetterAddr(address _slotSetterAddr) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter.setSlotSetterAddr.selector,
_slotSetterAddr
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function sethandlerManagerAddr(address _handlerManagerAddr) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter.sethandlerManagerAddr.selector,
_handlerManagerAddr
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setFlashloanAddr(address _flashloanAddr) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter.setFlashloanAddr.selector,
_flashloanAddr
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setPositionStorageAddr(address _positionStorageAddr) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter.setPositionStorageAddr.selector,
_positionStorageAddr
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setNFTAddr(address _nftAddr) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter.setNFTAddr.selector,
_nftAddr
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setFlashloanFee(uint256 handlerID, uint256 flashFeeRate) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setFlashloanFee.selector,
handlerID,
flashFeeRate
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setDiscountBase(uint256 handlerID, uint256 feeBase) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setDiscountBase.selector,
handlerID,
feeBase
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function getCircuitBreaker() external view returns (bool)
{
return emergency;
}
function getTokenHandlerInfo(uint256 handlerID) external view returns (bool, address, string memory)
{
bool support;
address tokenHandlerAddr;
string memory tokenName;
if (dataStorageInstance.getTokenHandlerSupport(handlerID))
{
tokenHandlerAddr = dataStorageInstance.getTokenHandlerAddr(handlerID);
IProxy TokenHandler = IProxy(tokenHandlerAddr);
bytes memory data;
(, data) = TokenHandler.handlerViewProxy(
abi.encodeWithSelector(
IMarketHandler
.getTokenName.selector
)
);
tokenName = abi.decode(data, (string));
support = true;
}
return (support, tokenHandlerAddr, tokenName);
}
function handlerRegister(uint256 handlerID, address tokenHandlerAddr, uint256 flashFeeRate, uint256 discountBase) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.handlerRegister.selector,
handlerID, tokenHandlerAddr, flashFeeRate, discountBase
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function setLiquidationManager(address liquidationManagerAddr) onlyOwner external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setLiquidationManager.selector,
liquidationManagerAddr
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function rewardUpdateOfInAction(address payable userAddr, uint256 callerID) external returns (bool)
{
ContractInfo memory handlerInfo;
(handlerInfo.support, handlerInfo.addr) = dataStorageInstance.getTokenHandlerInfo(callerID);
if (handlerInfo.support)
{
IProxy TokenHandler;
TokenHandler = IProxy(handlerInfo.addr);
TokenHandler.siProxy(
abi.encodeWithSelector(
IServiceIncentive
.updateRewardLane.selector,
userAddr
)
);
}
return true;
}
function applyInterestHandlers(address payable userAddr, uint256 callerID, bool allFlag) external returns (uint256, uint256, uint256, uint256, uint256, uint256) {
bytes memory callData = abi.encodeWithSelector(
IHandlerManager
.applyInterestHandlers.selector,
userAddr, callerID, allFlag
);
(bool result, bytes memory returnData) = handlerManagerAddr.delegatecall(callData);
assert(result);
return abi.decode(returnData, (uint256, uint256, uint256, uint256, uint256, uint256));
}
function interestUpdateReward() external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IHandlerManager
.interestUpdateReward.selector
);
(result, ) = handlerManagerAddr.delegatecall(callData);
assert(result);
}
function updateRewardParams(address payable userAddr) onlyOperators external returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IHandlerManager
.updateRewardParams.selector,
userAddr
);
(result, ) = handlerManagerAddr.delegatecall(callData);
assert(result);
}
function rewardClaimAll(address payable userAddr) external returns (uint256)
{
bytes memory callData = abi.encodeWithSelector(
IHandlerManager
.rewardClaimAll.selector,
userAddr
);
(bool result, bytes memory returnData) = handlerManagerAddr.delegatecall(callData);
assert(result);
return abi.decode(returnData, (uint256));
}
function claimHandlerReward(uint256 handlerID, address payable userAddr) external returns (uint256) {
bytes memory callData = abi.encodeWithSelector(
IHandlerManager
.claimHandlerReward.selector,
handlerID, userAddr
);
(bool result, bytes memory returnData) = handlerManagerAddr.delegatecall(callData);
assert(result);
return abi.decode(returnData, (uint256));
}
function ownerRewardTransfer(uint256 _amount) onlyOwner external returns (bool result)
{
bytes memory callData = abi.encodeWithSelector(
IHandlerManager
.ownerRewardTransfer.selector,
_amount
);
(result, ) = handlerManagerAddr.delegatecall(callData);
assert(result);
}
function getTokenHandlerPrice(uint256 handlerID) external view returns (uint256)
{
return _getTokenHandlerPrice(handlerID);
}
function getTokenHandlerMarginCallLimit(uint256 handlerID) external view returns (uint256)
{
return _getTokenHandlerMarginCallLimit(handlerID);
}
function _getTokenHandlerMarginCallLimit(uint256 handlerID) internal view returns (uint256)
{
IProxy TokenHandler = IProxy(dataStorageInstance.getTokenHandlerAddr(handlerID));
bytes memory data;
(, data) = TokenHandler.handlerViewProxy(
abi.encodeWithSelector(
IMarketHandler
.getTokenHandlerMarginCallLimit.selector
)
);
return abi.decode(data, (uint256));
}
function getTokenHandlerBorrowLimit(uint256 handlerID) external view returns (uint256)
{
return _getTokenHandlerBorrowLimit(handlerID);
}
function _getTokenHandlerBorrowLimit(uint256 handlerID) internal view returns (uint256)
{
IProxy TokenHandler = IProxy(dataStorageInstance.getTokenHandlerAddr(handlerID));
bytes memory data;
(, data) = TokenHandler.handlerViewProxy(
abi.encodeWithSelector(
IMarketHandler
.getTokenHandlerBorrowLimit.selector
)
);
return abi.decode(data, (uint256));
}
function getTokenHandlerSupport(uint256 handlerID) external view returns (bool)
{
return dataStorageInstance.getTokenHandlerSupport(handlerID);
}
function setTokenHandlersLength(uint256 _tokenHandlerLength) onlyOwner external returns (bool)
{
tokenHandlerLength = _tokenHandlerLength;
return true;
}
function getTokenHandlersLength() external view returns (uint256)
{
return tokenHandlerLength;
}
function getTokenHandlerID(uint256 index) external view returns (uint256)
{
return dataStorageInstance.getTokenHandlerID(index);
}
function getUserExtraLiquidityAmount(address payable userAddr, uint256 handlerID) external view returns (uint256)
{
return _getUserExtraLiquidityAmount(userAddr, handlerID);
}
function getUserIntraHandlerAssetWithInterest(address payable userAddr, uint256 handlerID) external view returns (uint256, uint256)
{
return _getUserIntraHandlerAssetWithInterest(userAddr, handlerID);
}
function getUserTotalIntraCreditAsset(address payable userAddr) external view returns (uint256, uint256)
{
return _getUserTotalIntraCreditAsset(userAddr);
}
function getUserLimitIntraAsset(address payable userAddr) external view returns (uint256, uint256)
{
uint256 userTotalBorrowLimitAsset;
uint256 userTotalMarginCallLimitAsset;
for (uint256 handlerID; handlerID < tokenHandlerLength; handlerID++)
{
if (dataStorageInstance.getTokenHandlerSupport(handlerID))
{
uint256 depositHandlerAsset;
uint256 borrowHandlerAsset;
(depositHandlerAsset, borrowHandlerAsset) = _getUserIntraHandlerAssetWithInterest(userAddr, handlerID);
uint256 borrowLimit = _getTokenHandlerBorrowLimit(handlerID);
uint256 marginCallLimit = _getTokenHandlerMarginCallLimit(handlerID);
uint256 userBorrowLimitAsset = depositHandlerAsset.unifiedMul(borrowLimit);
uint256 userMarginCallLimitAsset = depositHandlerAsset.unifiedMul(marginCallLimit);
userTotalBorrowLimitAsset = userTotalBorrowLimitAsset.add(userBorrowLimitAsset);
userTotalMarginCallLimitAsset = userTotalMarginCallLimitAsset.add(userMarginCallLimitAsset);
}
else
{
continue;
}
}
return (userTotalBorrowLimitAsset, userTotalMarginCallLimitAsset);
}
function getUserCollateralizableAmount(address payable userAddr, uint256 callerID) external view returns (uint256)
{
uint256 userTotalBorrowAsset;
uint256 depositAssetBorrowLimitSum;
uint256 depositHandlerAsset;
uint256 borrowHandlerAsset;
for (uint256 handlerID; handlerID < tokenHandlerLength; handlerID++)
{
if (dataStorageInstance.getTokenHandlerSupport(handlerID))
{
(depositHandlerAsset, borrowHandlerAsset) = _getUserIntraHandlerAssetWithInterest(userAddr, handlerID);
userTotalBorrowAsset = userTotalBorrowAsset.add(borrowHandlerAsset);
depositAssetBorrowLimitSum = depositAssetBorrowLimitSum
.add(
depositHandlerAsset
.unifiedMul( _getTokenHandlerBorrowLimit(handlerID) )
);
}
}
if (depositAssetBorrowLimitSum > userTotalBorrowAsset)
{
return depositAssetBorrowLimitSum
.sub(userTotalBorrowAsset)
.unifiedDiv( _getTokenHandlerBorrowLimit(callerID) )
.unifiedDiv( _getTokenHandlerPrice(callerID) );
}
return 0;
}
function partialLiquidationUser(address payable delinquentBorrower, uint256 liquidateAmount, address payable liquidator, uint256 liquidateHandlerID, uint256 rewardHandlerID) onlyLiquidationManager external returns (uint256, uint256, uint256)
{
address tokenHandlerAddr = dataStorageInstance.getTokenHandlerAddr(liquidateHandlerID);
IProxy TokenHandler = IProxy(tokenHandlerAddr);
bytes memory data;
data = abi.encodeWithSelector(
IMarketHandler
.partialLiquidationUser.selector,
delinquentBorrower,
liquidateAmount,
liquidator,
rewardHandlerID
);
(, data) = TokenHandler.handlerProxy(data);
return abi.decode(data, (uint256, uint256, uint256));
}
function getMaxLiquidationReward(address payable delinquentBorrower, uint256 liquidateHandlerID, uint256 liquidateAmount, uint256 rewardHandlerID, uint256 rewardRatio) external view returns (uint256)
{
uint256 liquidatePrice = _getTokenHandlerPrice(liquidateHandlerID);
uint256 rewardPrice = _getTokenHandlerPrice(rewardHandlerID);
uint256 delinquentBorrowerRewardDeposit;
(delinquentBorrowerRewardDeposit, ) = _getHandlerAmount(delinquentBorrower, rewardHandlerID);
uint256 rewardAsset = delinquentBorrowerRewardDeposit.unifiedMul(rewardPrice).unifiedMul(rewardRatio);
if (liquidateAmount.unifiedMul(liquidatePrice) > rewardAsset)
{
return rewardAsset.unifiedDiv(liquidatePrice);
}
else
{
return liquidateAmount;
}
}
function partialLiquidationUserReward(address payable delinquentBorrower, uint256 rewardAmount, address payable liquidator, uint256 handlerID) onlyLiquidationManager external returns (uint256)
{
address tokenHandlerAddr = dataStorageInstance.getTokenHandlerAddr(handlerID);
IProxy TokenHandler = IProxy(tokenHandlerAddr);
bytes memory data;
data = abi.encodeWithSelector(
IMarketHandler
.partialLiquidationUserReward.selector,
delinquentBorrower,
rewardAmount,
liquidator
);
(, data) = TokenHandler.handlerProxy(data);
return abi.decode(data, (uint256));
}
function flashloan(
uint256 handlerID,
address receiverAddress,
uint256 amount,
bytes calldata params
) external returns (bool) {
bytes memory callData = abi.encodeWithSelector(
IManagerFlashloan
.flashloan.selector,
handlerID, receiverAddress, amount, params
);
(bool result, bytes memory returnData) = flashloanAddr.delegatecall(callData);
assert(result);
return abi.decode(returnData, (bool));
}
function getFeeTotal(uint256 handlerID) external returns (uint256)
{
bytes memory callData = abi.encodeWithSelector(
IManagerFlashloan
.getFeeTotal.selector,
handlerID
);
(bool result, bytes memory returnData) = flashloanAddr.delegatecall(callData);
assert(result);
return abi.decode(returnData, (uint256));
}
function withdrawFlashloanFee(
uint256 handlerID
) external onlyOwner returns (bool) {
bytes memory callData = abi.encodeWithSelector(
IManagerFlashloan
.withdrawFlashloanFee.selector,
handlerID
);
(bool result, bytes memory returnData) = flashloanAddr.delegatecall(callData);
assert(result);
return abi.decode(returnData, (bool));
}
function getFeeFromArguments(
uint256 handlerID,
uint256 amount,
uint256 bifiAmount
) external returns (uint256) {
bytes memory callData = abi.encodeWithSelector(
IManagerFlashloan
.getFeeFromArguments.selector,
handlerID, amount, bifiAmount
);
(bool result, bytes memory returnData) = flashloanAddr.delegatecall(callData);
assert(result);
return abi.decode(returnData, (uint256));
}
function _getHandlerAmount(address payable userAddr, uint256 handlerID) internal view returns (uint256, uint256)
{
IProxy TokenHandler = IProxy(dataStorageInstance.getTokenHandlerAddr(handlerID));
bytes memory data;
(, data) = TokenHandler.handlerViewProxy(
abi.encodeWithSelector(
IMarketHandler
.getUserAmount.selector,
userAddr
)
);
return abi.decode(data, (uint256, uint256));
}
function _getHandlerAmountWithAmount(address payable userAddr, uint256 handlerID) internal view returns (uint256, uint256)
{
IProxy TokenHandler = IProxy(dataStorageInstance.getTokenHandlerAddr(handlerID));
bytes memory data;
(, data) = TokenHandler.handlerViewProxy(
abi.encodeWithSelector(
IMarketHandler
.getUserAmountWithInterest.selector,
userAddr
)
);
return abi.decode(data, (uint256, uint256));
}
function setHandlerSupport(uint256 handlerID, bool support) onlyOwner public returns (bool result) {
bytes memory callData = abi.encodeWithSelector(
IManagerSlotSetter
.setHandlerSupport.selector,
handlerID, support
);
(result, ) = slotSetterAddr.delegatecall(callData);
assert(result);
}
function getOwner() public view returns (address)
{
return owner;
}
function _getUserIntraHandlerAssetWithInterest(address payable userAddr, uint256 handlerID) internal view returns (uint256, uint256)
{
uint256 price = _getTokenHandlerPrice(handlerID);
IProxy TokenHandler = IProxy(dataStorageInstance.getTokenHandlerAddr(handlerID));
uint256 depositAmount;
uint256 borrowAmount;
bytes memory data;
(, data) = TokenHandler.handlerViewProxy(
abi.encodeWithSelector(
IMarketHandler.getUserAmountWithInterest.selector,
userAddr
)
);
(depositAmount, borrowAmount) = abi.decode(data, (uint256, uint256));
uint256 depositAsset = depositAmount.unifiedMul(price);
uint256 borrowAsset = borrowAmount.unifiedMul(price);
return (depositAsset, borrowAsset);
}
function _getUserTotalIntraCreditAsset(address payable userAddr) internal view returns (uint256, uint256)
{
uint256 depositTotalCredit;
uint256 borrowTotalCredit;
for (uint256 handlerID; handlerID < tokenHandlerLength; handlerID++)
{
if (dataStorageInstance.getTokenHandlerSupport(handlerID))
{
uint256 depositHandlerAsset;
uint256 borrowHandlerAsset;
(depositHandlerAsset, borrowHandlerAsset) = _getUserIntraHandlerAssetWithInterest(userAddr, handlerID);
uint256 borrowLimit = _getTokenHandlerBorrowLimit(handlerID);
uint256 depositHandlerCredit = depositHandlerAsset.unifiedMul(borrowLimit);
depositTotalCredit = depositTotalCredit.add(depositHandlerCredit);
borrowTotalCredit = borrowTotalCredit.add(borrowHandlerAsset);
}
else
{
continue;
}
}
return (depositTotalCredit, borrowTotalCredit);
}
function _getUserExtraLiquidityAmount(address payable userAddr, uint256 handlerID) internal view returns (uint256) {
uint256 depositCredit;
uint256 borrowCredit;
(depositCredit, borrowCredit) = _getUserTotalIntraCreditAsset(userAddr);
if (depositCredit == 0)
{
return 0;
}
if (depositCredit > borrowCredit)
{
return depositCredit.sub(borrowCredit).unifiedDiv(_getTokenHandlerPrice(handlerID));
}
else
{
return 0;
}
}
function getFeePercent(uint256 handlerID) external view returns (uint256)
{
return handlerFlashloan[handlerID].flashFeeRate;
}
function _getTokenHandlerPrice(uint256 handlerID) internal view returns (uint256)
{
return (oracleProxy.getTokenPrice(handlerID));
}
function getRewardErc20() public view returns (address)
{
return address(rewardErc20Instance);
}
function getGlobalRewardInfo() external view returns (uint256, uint256, uint256)
{
IManagerDataStorage _dataStorage = dataStorageInstance;
return (_dataStorage.getGlobalRewardPerBlock(), _dataStorage.getGlobalRewardDecrement(), _dataStorage.getGlobalRewardTotalAmount());
}
function setObserverAddr(address observerAddr) onlyOwner external returns (bool) {
Observer = IObserver( observerAddr );
}
fallback () external payable
{
}
}