Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
BorrowerOperations
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 1 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/core/IPositionManager.sol";
import "../interfaces/core/IDebtToken.sol";
import "../dependencies/PropBase.sol";
import "../dependencies/PropMath.sol";
import "../dependencies/PropOwnable.sol";
import "../dependencies/DelegatedOps.sol";
/**
@title Borrower Operations
@notice Based on Liquity's `BorrowerOperations`
https://github.com/liquity/dev/blob/main/packages/contracts/contracts/BorrowerOperations.sol
This custom implementation is modified to support multiple collaterals. There is a 1:n
relationship between `BorrowerOperations` and each `PositionManager` / `SortedPositions` pair.
*/
contract BorrowerOperations is PropBase, PropOwnable, DelegatedOps {
using SafeERC20 for IERC20;
IDebtToken public immutable debtToken;
address public immutable factory;
uint256 public minNetDebt;
mapping(IPositionManager => PositionManagerData) public positionManagersData;
IPositionManager[] public positionManagers;
struct PositionManagerData {
IERC20 collateralToken;
uint16 index;
}
struct SystemBalances {
uint256[] collaterals;
uint256[] debts;
uint256[] prices;
}
struct LocalVariables_adjustPosition {
uint256 price;
uint256 totalPricedCollateral;
uint256 totalDebt;
uint256 collChange;
uint256 netDebtChange;
bool isCollIncrease;
uint256 debt;
uint256 coll;
uint256 newDebt;
uint256 newColl;
uint256 stake;
uint256 debtChange;
address account;
uint256 MCR;
}
struct LocalVariables_openPosition {
uint256 price;
uint256 totalPricedCollateral;
uint256 totalDebt;
uint256 netDebt;
uint256 compositeDebt;
uint256 ICR;
uint256 NICR;
uint256 stake;
uint256 arrayIndex;
}
enum BorrowerOperation {
openPosition,
closePosition,
adjustPosition
}
event PositionUpdated(
IPositionManager indexed _positionManager,
address indexed _borrower,
uint256 _debt,
uint256 _coll,
uint256 stake,
BorrowerOperation operation
);
event PositionCreated(IPositionManager indexed positionManager, address indexed _borrower, uint256 arrayIndex);
event BorrowingFeePaid(IPositionManager indexed positionManager, address indexed borrower, uint256 amount);
event CollateralConfigured(IPositionManager positionManager, IERC20 collateralToken);
event PositionManagerRemoved(IPositionManager positionManager);
constructor(
address _core,
address _debtTokenAddress,
address _factory,
uint256 _minNetDebt,
uint256 _gasCompensation
) PropOwnable(_core) PropBase(_gasCompensation) DelegatedOps(_core) {
if (_core == address(0) || _debtTokenAddress == address(0) || _factory == address(0)) {
revert("BorrowerOperations: 0 address");
}
debtToken = IDebtToken(_debtTokenAddress);
factory = _factory;
_setMinNetDebt(_minNetDebt);
}
function setMinNetDebt(uint256 _minNetDebt) public onlyOwner {
_setMinNetDebt(_minNetDebt);
}
function _setMinNetDebt(uint256 _minNetDebt) internal {
require(_minNetDebt > 0);
minNetDebt = _minNetDebt;
}
function configureCollateral(IPositionManager positionManager, IERC20 collateralToken) external {
require(msg.sender == factory, "!factory");
positionManagersData[positionManager] = PositionManagerData(collateralToken, uint16(positionManagers.length));
positionManagers.push(positionManager);
emit CollateralConfigured(positionManager, collateralToken);
}
function removePositionManager(IPositionManager positionManager) external {
PositionManagerData memory dmData = positionManagersData[positionManager];
require(
address(dmData.collateralToken) != address(0) &&
positionManager.sunsetting() &&
positionManager.getEntireSystemDebt() == 0,
"Position Manager cannot be removed"
);
delete positionManagersData[positionManager];
uint256 lastIndex = positionManagers.length - 1;
if (dmData.index < lastIndex) {
IPositionManager lastDm = positionManagers[lastIndex];
positionManagers[dmData.index] = lastDm;
positionManagersData[lastDm].index = dmData.index;
}
positionManagers.pop();
emit PositionManagerRemoved(positionManager);
}
/**
@notice Get the global total collateral ratio
*/
function getTCR() external view returns (uint256 globalTotalCollateralRatio) {
SystemBalances memory balances = fetchBalances();
(globalTotalCollateralRatio, , ) = _getTCRData(balances);
return globalTotalCollateralRatio;
}
/**
@notice Get total collateral and debt balances for all active collaterals, as well as
the current collateral prices
*/
function fetchBalances() public view returns (SystemBalances memory balances) {
uint256 loopEnd = positionManagers.length;
balances = SystemBalances({
collaterals: new uint256[](loopEnd),
debts: new uint256[](loopEnd),
prices: new uint256[](loopEnd)
});
for (uint256 i; i < loopEnd; ) {
IPositionManager positionManager = positionManagers[i];
(uint256 collateral, uint256 debt, uint256 price) = positionManager.getEntireSystemBalances();
balances.collaterals[i] = collateral;
balances.debts[i] = debt;
balances.prices[i] = price;
unchecked {
++i;
}
}
}
function checkRecoveryMode(uint256 TCR) public view returns (bool) {
return TCR < CORE.CCR();
}
function getCompositeDebt(uint256 _debt) external view returns (uint256) {
return _getCompositeDebt(_debt);
}
// --- Borrower Position Operations ---
function openPosition(
IPositionManager positionManager,
address account,
uint256 _maxFeePercentage,
uint256 _collateralAmount,
uint256 _debtAmount,
address _upperHint,
address _lowerHint
) external callerOrDelegated(account) {
require(!CORE.paused(), "Deposits are paused");
IERC20 collateralToken;
LocalVariables_openPosition memory vars;
bool isRecoveryMode;
(
collateralToken,
vars.price,
vars.totalPricedCollateral,
vars.totalDebt,
isRecoveryMode
) = _getCollateralAndTCRData(positionManager);
_requireValidMaxFeePercentage(_maxFeePercentage);
vars.netDebt = _debtAmount;
if (!isRecoveryMode) {
vars.netDebt = vars.netDebt + _triggerBorrowingFee(positionManager, account, _maxFeePercentage, _debtAmount);
}
_requireAtLeastMinNetDebt(vars.netDebt);
// ICR is based on the composite debt, i.e. the requested Debt amount + Debt borrowing fee + Debt gas comp.
vars.compositeDebt = _getCompositeDebt(vars.netDebt);
vars.ICR = PropMath._computeCR(_collateralAmount, vars.compositeDebt, vars.price);
vars.NICR = PropMath._computeNominalCR(_collateralAmount, vars.compositeDebt);
if (isRecoveryMode) {
_requireICRisAboveCCR(vars.ICR);
} else {
_requireICRisAboveMCR(vars.ICR, positionManager.MCR());
uint256 newTCR = _getNewTCRFromPositionChange(
vars.totalPricedCollateral,
vars.totalDebt,
_collateralAmount * vars.price,
true,
vars.compositeDebt,
true
); // bools: coll increase, debt increase
_requireNewTCRisAboveCCR(newTCR);
}
// Create the position
(vars.stake, vars.arrayIndex) = positionManager.openPosition(
account,
_collateralAmount,
vars.compositeDebt,
vars.NICR,
_upperHint,
_lowerHint
);
emit PositionCreated(positionManager, account, vars.arrayIndex);
// Move the collateral to the Position Manager
collateralToken.safeTransferFrom(msg.sender, address(positionManager), _collateralAmount);
// and mint the DebtAmount to the caller and gas compensation for Gas Pool
debtToken.mintWithGasCompensation(msg.sender, _debtAmount);
emit PositionUpdated(positionManager, account, vars.compositeDebt, _collateralAmount, vars.stake, BorrowerOperation.openPosition);
}
// Send collateral to a position
function addColl(
IPositionManager positionManager,
address account,
uint256 _collateralAmount,
address _upperHint,
address _lowerHint
) external callerOrDelegated(account) {
require(!CORE.paused(), "Position adjustments are paused");
_adjustPosition(positionManager, account, 0, _collateralAmount, 0, 0, false, _upperHint, _lowerHint);
}
// Withdraw collateral from a position
function withdrawColl(
IPositionManager positionManager,
address account,
uint256 _collWithdrawal,
address _upperHint,
address _lowerHint
) external callerOrDelegated(account) {
_adjustPosition(positionManager, account, 0, 0, _collWithdrawal, 0, false, _upperHint, _lowerHint);
}
// Withdraw Debt tokens from a position: mint new Debt tokens to the owner, and increase the positions debt accordingly
function withdrawDebt(
IPositionManager positionManager,
address account,
uint256 _maxFeePercentage,
uint256 _debtAmount,
address _upperHint,
address _lowerHint
) external callerOrDelegated(account) {
require(!CORE.paused(), "Withdrawals are paused");
_adjustPosition(positionManager, account, _maxFeePercentage, 0, 0, _debtAmount, true, _upperHint, _lowerHint);
}
// Repay Debt tokens to a Position: Burn the repaid Debt tokens, and reduce the positions debt accordingly
function repayDebt(
IPositionManager positionManager,
address account,
uint256 _debtAmount,
address _upperHint,
address _lowerHint
) external callerOrDelegated(account) {
_adjustPosition(positionManager, account, 0, 0, 0, _debtAmount, false, _upperHint, _lowerHint);
}
function adjustPosition(
IPositionManager positionManager,
address account,
uint256 _maxFeePercentage,
uint256 _collDeposit,
uint256 _collWithdrawal,
uint256 _debtChange,
bool _isDebtIncrease,
address _upperHint,
address _lowerHint
) external callerOrDelegated(account) {
require((_collDeposit == 0 && !_isDebtIncrease) || !CORE.paused(), "Position adjustments are paused");
require(_collDeposit == 0 || _collWithdrawal == 0, "BorrowerOperations: Cannot withdraw and add coll");
_adjustPosition(
positionManager,
account,
_maxFeePercentage,
_collDeposit,
_collWithdrawal,
_debtChange,
_isDebtIncrease,
_upperHint,
_lowerHint
);
}
function _adjustPosition(
IPositionManager positionManager,
address account,
uint256 _maxFeePercentage,
uint256 _collDeposit,
uint256 _collWithdrawal,
uint256 _debtChange,
bool _isDebtIncrease,
address _upperHint,
address _lowerHint
) internal {
require(
_collDeposit != 0 || _collWithdrawal != 0 || _debtChange != 0,
"BorrowerOps: There must be either a collateral change or a debt change"
);
IERC20 collateralToken;
LocalVariables_adjustPosition memory vars;
bool isRecoveryMode;
(
collateralToken,
vars.price,
vars.totalPricedCollateral,
vars.totalDebt,
isRecoveryMode
) = _getCollateralAndTCRData(positionManager);
(vars.coll, vars.debt) = positionManager.applyPendingRewards(account);
// Get the collChange based on whether or not collateral was sent in the transaction
(vars.collChange, vars.isCollIncrease) = _getCollChange(_collDeposit, _collWithdrawal);
vars.netDebtChange = _debtChange;
vars.debtChange = _debtChange;
vars.account = account;
vars.MCR = positionManager.MCR();
if (_isDebtIncrease) {
require(_debtChange > 0, "BorrowerOps: Debt increase requires non-zero debtChange");
_requireValidMaxFeePercentage(_maxFeePercentage);
if (!isRecoveryMode) {
// If the adjustment incorporates a debt increase and system is in Normal Mode, trigger a borrowing fee
vars.netDebtChange += _triggerBorrowingFee(positionManager, account, _maxFeePercentage, _debtChange);
}
}
// Calculate old and new ICRs and check if adjustment satisfies all conditions for the current system mode
_requireValidAdjustmentInCurrentMode(
vars.totalPricedCollateral,
vars.totalDebt,
isRecoveryMode,
_collWithdrawal,
_isDebtIncrease,
vars
);
// When the adjustment is a debt repayment, check it's a valid amount and that the caller has enough Debt
if (!_isDebtIncrease && _debtChange > 0) {
_requireAtLeastMinNetDebt(_getNetDebt(vars.debt) - vars.netDebtChange);
}
// If we are increasing collateral, send tokens to the position manager prior to adjusting the position
if (vars.isCollIncrease) collateralToken.safeTransferFrom(msg.sender, address(positionManager), vars.collChange);
(vars.newColl, vars.newDebt, vars.stake) = positionManager.updatePositionFromAdjustment(
_isDebtIncrease,
vars.debtChange,
vars.netDebtChange,
vars.isCollIncrease,
vars.collChange,
_upperHint,
_lowerHint,
vars.account,
msg.sender
);
emit PositionUpdated(positionManager, vars.account, vars.newDebt, vars.newColl, vars.stake, BorrowerOperation.adjustPosition);
}
function closePosition(IPositionManager positionManager, address account) external callerOrDelegated(account) {
IERC20 collateralToken;
uint256 price;
bool isRecoveryMode;
uint256 totalPricedCollateral;
uint256 totalDebt;
(collateralToken, price, totalPricedCollateral, totalDebt, isRecoveryMode) = _getCollateralAndTCRData(
positionManager
);
require(!isRecoveryMode, "BorrowerOps: Operation not permitted during Recovery Mode");
(uint256 coll, uint256 debt) = positionManager.applyPendingRewards(account);
uint256 newTCR = _getNewTCRFromPositionChange(totalPricedCollateral, totalDebt, coll * price, false, debt, false);
_requireNewTCRisAboveCCR(newTCR);
positionManager.closePosition(account, msg.sender, coll, debt);
emit PositionUpdated(positionManager, account, 0, 0, 0, BorrowerOperation.closePosition);
// Burn the repaid Debt from the user's balance and the gas compensation from the Gas Pool
debtToken.burnWithGasCompensation(msg.sender, debt - DEBT_GAS_COMPENSATION);
}
// --- Helper functions ---
function _triggerBorrowingFee(
IPositionManager _positionManager,
address _caller,
uint256 _maxFeePercentage,
uint256 _debtAmount
) internal returns (uint256) {
/// @dev Doesn't update the base rate
uint256 debtFee = _positionManager.decayBaseRateAndGetBorrowingFee(_debtAmount);
_requireUserAcceptsFee(debtFee, _debtAmount, _maxFeePercentage);
debtToken.mint(CORE.feeReceiver(), debtFee);
emit BorrowingFeePaid(_positionManager, _caller, debtFee);
return debtFee;
}
function _getCollChange(
uint256 _collReceived,
uint256 _requestedCollWithdrawal
) internal pure returns (uint256 collChange, bool isCollIncrease) {
if (_collReceived != 0) {
collChange = _collReceived;
isCollIncrease = true;
} else {
collChange = _requestedCollWithdrawal;
}
}
function _requireValidAdjustmentInCurrentMode(
uint256 totalPricedCollateral,
uint256 totalDebt,
bool _isRecoveryMode,
uint256 _collWithdrawal,
bool _isDebtIncrease,
LocalVariables_adjustPosition memory _vars
) internal view {
/*
*In Recovery Mode, only allow:
*
* - Pure collateral top-up
* - Pure debt repayment
* - Collateral top-up with debt repayment
* - A debt increase combined with a collateral top-up which makes the ICR >= 150% and improves the ICR (and by extension improves the TCR).
*
* In Normal Mode, ensure:
*
* - The new ICR is above MCR
* - The adjustment won't pull the TCR below CCR
*/
// Get the positions old ICR before the adjustment
uint256 oldICR = PropMath._computeCR(_vars.coll, _vars.debt, _vars.price);
// Get the positions new ICR after the adjustment
uint256 newICR = _getNewICRFromPositionChange(
_vars.coll,
_vars.debt,
_vars.collChange,
_vars.isCollIncrease,
_vars.netDebtChange,
_isDebtIncrease,
_vars.price
);
if (_isRecoveryMode) {
require(_collWithdrawal == 0, "BorrowerOps: Collateral withdrawal not permitted Recovery Mode");
if (_isDebtIncrease) {
_requireICRisAboveCCR(newICR);
_requireNewICRisAboveOldICR(newICR, oldICR);
}
} else {
// if Normal Mode
_requireICRisAboveMCR(newICR, _vars.MCR);
uint256 newTCR = _getNewTCRFromPositionChange(
totalPricedCollateral,
totalDebt,
_vars.collChange * _vars.price,
_vars.isCollIncrease,
_vars.netDebtChange,
_isDebtIncrease
);
_requireNewTCRisAboveCCR(newTCR);
}
}
function _requireICRisAboveMCR(uint256 _newICR, uint256 MCR) internal view {
require(
_newICR >= MCR,
"BorrowerOps: An operation that would result in ICR < MCR is not permitted"
);
}
function _requireICRisAboveCCR(uint256 _newICR) internal view {
require(_newICR >= CORE.CCR(), "BorrowerOps: Operation must leave position with ICR >= CCR");
}
function _requireNewICRisAboveOldICR(uint256 _newICR, uint256 _oldICR) internal pure {
require(_newICR >= _oldICR, "BorrowerOps: Cannot decrease your Position's ICR in Recovery Mode");
}
function _requireNewTCRisAboveCCR(uint256 _newTCR) internal view {
require(_newTCR >= CORE.CCR(), "BorrowerOps: An operation that would result in TCR < CCR is not permitted");
}
function _requireAtLeastMinNetDebt(uint256 _netDebt) internal view {
require(_netDebt >= minNetDebt, "BorrowerOps: Position's net debt must be greater than minimum");
}
function _requireValidMaxFeePercentage(uint256 _maxFeePercentage) internal pure {
require(_maxFeePercentage <= DECIMAL_PRECISION, "Max fee percentage must less than or equal to 100%");
}
// Compute the new collateral ratio, considering the change in coll and debt. Assumes 0 pending rewards.
function _getNewICRFromPositionChange(
uint256 _coll,
uint256 _debt,
uint256 _collChange,
bool _isCollIncrease,
uint256 _debtChange,
bool _isDebtIncrease,
uint256 _price
) internal pure returns (uint256) {
(uint256 newColl, uint256 newDebt) = _getNewPositionAmounts(
_coll,
_debt,
_collChange,
_isCollIncrease,
_debtChange,
_isDebtIncrease
);
uint256 newICR = PropMath._computeCR(newColl, newDebt, _price);
return newICR;
}
function _getNewPositionAmounts(
uint256 _coll,
uint256 _debt,
uint256 _collChange,
bool _isCollIncrease,
uint256 _debtChange,
bool _isDebtIncrease
) internal pure returns (uint256, uint256) {
uint256 newColl = _coll;
uint256 newDebt = _debt;
newColl = _isCollIncrease ? _coll + _collChange : _coll - _collChange;
newDebt = _isDebtIncrease ? _debt + _debtChange : _debt - _debtChange;
return (newColl, newDebt);
}
function _getNewTCRFromPositionChange(
uint256 totalColl,
uint256 totalDebt,
uint256 _collChange,
bool _isCollIncrease,
uint256 _debtChange,
bool _isDebtIncrease
) internal pure returns (uint256) {
totalDebt = _isDebtIncrease ? totalDebt + _debtChange : totalDebt - _debtChange;
totalColl = _isCollIncrease ? totalColl + _collChange : totalColl - _collChange;
uint256 newTCR = PropMath._computeCR(totalColl, totalDebt);
return newTCR;
}
function _getTCRData(
SystemBalances memory balances
) internal pure returns (uint256 amount, uint256 totalPricedCollateral, uint256 totalDebt) {
uint256 loopEnd = balances.collaterals.length;
for (uint256 i; i < loopEnd; ) {
totalPricedCollateral += (balances.collaterals[i] * balances.prices[i]);
totalDebt += balances.debts[i];
unchecked {
++i;
}
}
amount = PropMath._computeCR(totalPricedCollateral, totalDebt);
return (amount, totalPricedCollateral, totalDebt);
}
function _getCollateralAndTCRData(
IPositionManager positionManager
)
internal view
returns (
IERC20 collateralToken,
uint256 price,
uint256 totalPricedCollateral,
uint256 totalDebt,
bool isRecoveryMode
)
{
PositionManagerData storage t = positionManagersData[positionManager];
uint256 index;
(collateralToken, index) = (t.collateralToken, t.index);
require(address(collateralToken) != address(0), "Collateral not enabled");
uint256 amount;
SystemBalances memory balances = fetchBalances();
(amount, totalPricedCollateral, totalDebt) = _getTCRData(balances);
isRecoveryMode = checkRecoveryMode(amount);
return (collateralToken, balances.prices[index], totalPricedCollateral, totalDebt, isRecoveryMode);
}
function getGlobalSystemBalances() external view returns (uint256 totalPricedCollateral, uint256 totalDebt) {
SystemBalances memory balances = fetchBalances();
(, totalPricedCollateral, totalDebt) = _getTCRData(balances);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
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));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
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) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC3156FlashBorrower} from "@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IFactory} from "./IFactory.sol";
interface IPositionManager {
event BaseRateUpdated(uint256 _baseRate);
event CollateralSent(address _to, uint256 _amount);
event LTermsUpdated(uint256 _L_collateral, uint256 _L_debt);
event LastFeeOpTimeUpdated(uint256 _lastFeeOpTime);
event Redemption(
address indexed _redeemer,
uint256 _attemptedDebtAmount,
uint256 _actualDebtAmount,
uint256 _collateralSent,
uint256 _collateralFee
);
event SystemSnapshotsUpdated(uint256 _totalStakesSnapshot, uint256 _totalCollateralSnapshot);
event TotalStakesUpdated(uint256 _newTotalStakes);
event PositionIndexUpdated(address _borrower, uint256 _newIndex);
event PositionSnapshotsUpdated(uint256 _L_collateral, uint256 _L_debt);
event PositionUpdated(address indexed _borrower, uint256 _debt, uint256 _coll, uint256 _stake, uint8 _operation);
function addCollateralSurplus(address borrower, uint256 collSurplus) external;
function applyPendingRewards(address _borrower) external returns (uint256 coll, uint256 debt);
function claimCollateral(address borrower, address _receiver) external;
function closePosition(address _borrower, address _receiver, uint256 collAmount, uint256 debtAmount) external;
function closePositionByLiquidation(address _borrower) external;
function setCollVaultRouter(address _collVaultRouter) external;
function collectInterests() external;
function decayBaseRateAndGetBorrowingFee(uint256 _debt) external returns (uint256);
function decreaseDebtAndSendCollateral(address account, uint256 debt, uint256 coll) external;
function fetchPrice() external view returns (uint256);
function finalizeLiquidation(
address _liquidator,
uint256 _debt,
uint256 _coll,
uint256 _collSurplus,
uint256 _debtGasComp,
uint256 _collGasComp
) external;
function getEntireSystemBalances() external view returns (uint256, uint256, uint256);
function movePendingPositionRewardsToActiveBalances(uint256 _debt, uint256 _collateral) external;
function openPosition(
address _borrower,
uint256 _collateralAmount,
uint256 _compositeDebt,
uint256 NICR,
address _upperHint,
address _lowerHint
) external returns (uint256 stake, uint256 arrayIndex);
function redeemCollateral(
uint256 _debtAmount,
address _firstRedemptionHint,
address _upperPartialRedemptionHint,
address _lowerPartialRedemptionHint,
uint256 _partialRedemptionHintNICR,
uint256 _maxIterations,
uint256 _maxFeePercentage
) external;
function setAddresses(address _priceFeedAddress, address _sortedPositionsAddress, address _collateralToken) external;
function setParameters(
IFactory.DeploymentParams calldata _params
) external;
function setPaused(bool _paused) external;
function setPriceFeed(address _priceFeedAddress) external;
function startSunset() external;
function updateBalances() external;
function updatePositionFromAdjustment(
bool _isDebtIncrease,
uint256 _debtChange,
uint256 _netDebtChange,
bool _isCollIncrease,
uint256 _collChange,
address _upperHint,
address _lowerHint,
address _borrower,
address _receiver
) external returns (uint256, uint256, uint256);
function DEBT_GAS_COMPENSATION() external view returns (uint256);
function DECIMAL_PRECISION() external view returns (uint256);
function L_collateral() external view returns (uint256);
function L_debt() external view returns (uint256);
function MCR() external view returns (uint256);
function PERCENT_DIVISOR() external view returns (uint256);
function CORE() external view returns (address);
function SUNSETTING_INTEREST_RATE() external view returns (uint256);
function Positions(
address
)
external
view
returns (
uint256 debt,
uint256 coll,
uint256 stake,
uint8 status,
uint128 arrayIndex,
uint256 activeInterestIndex
);
function activeInterestIndex() external view returns (uint256);
function baseRate() external view returns (uint256);
function borrowerOperations() external view returns (address);
function borrowingFeeFloor() external view returns (uint256);
function collateralToken() external view returns (address);
function debtToken() external view returns (address);
function collVaultRouter() external view returns (address);
function defaultedCollateral() external view returns (uint256);
function defaultedDebt() external view returns (uint256);
function getBorrowingFee(uint256 _debt) external view returns (uint256);
function getBorrowingFeeWithDecay(uint256 _debt) external view returns (uint256);
function getBorrowingRate() external view returns (uint256);
function getBorrowingRateWithDecay() external view returns (uint256);
function getCurrentICR(address _borrower, uint256 _price) external view returns (uint256);
function getEntireDebtAndColl(
address _borrower
) external view returns (uint256 debt, uint256 coll, uint256 pendingDebtReward, uint256 pendingCollateralReward);
function getEntireSystemColl() external view returns (uint256);
function getEntireSystemDebt() external view returns (uint256);
function getNominalICR(address _borrower) external view returns (uint256);
function getPendingCollAndDebtRewards(address _borrower) external view returns (uint256, uint256);
function getRedemptionFeeWithDecay(uint256 _collateralDrawn) external view returns (uint256);
function getRedemptionRate() external view returns (uint256);
function getRedemptionRateWithDecay() external view returns (uint256);
function getTotalActiveCollateral() external view returns (uint256);
function getTotalActiveDebt() external view returns (uint256);
function getPositionCollAndDebt(address _borrower) external view returns (uint256 coll, uint256 debt);
function getPositionFromPositionOwnersArray(uint256 _index) external view returns (address);
function getPositionOwnersCount() external view returns (uint256);
function getPositionStake(address _borrower) external view returns (uint256);
function getPositionStatus(address _borrower) external view returns (uint256);
function guardian() external view returns (address);
function hasPendingRewards(address _borrower) external view returns (bool);
function interestPayable() external view returns (uint256);
function interestRate() external view returns (uint256);
function lastActiveIndexUpdate() external view returns (uint256);
function lastCollateralError_Redistribution() external view returns (uint256);
function lastDebtError_Redistribution() external view returns (uint256);
function lastFeeOperationTime() external view returns (uint256);
function liquidationManager() external view returns (address);
function maxBorrowingFee() external view returns (uint256);
function maxRedemptionFee() external view returns (uint256);
function maxSystemDebt() external view returns (uint256);
function minuteDecayFactor() external view returns (uint256);
function owner() external view returns (address);
function paused() external view returns (bool);
function priceFeed() external view returns (address);
function redemptionFeeFloor() external view returns (uint256);
function rewardSnapshots(address) external view returns (uint256 collateral, uint256 debt);
function sortedPositions() external view returns (address);
function sunsetting() external view returns (bool);
function surplusBalances(address) external view returns (uint256);
function systemDeploymentTime() external view returns (uint256);
function totalCollateralSnapshot() external view returns (uint256);
function totalStakes() external view returns (uint256);
function totalStakesSnapshot() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC3156FlashBorrower } from "@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol";
import "./ICore.sol";
interface IDebtToken is IERC20 {
// --- Events ---
event FlashLoanFeeUpdated(uint256 newFee);
// --- Public constants ---
function version() external view returns (string memory);
function permitTypeHash() external view returns (bytes32);
// --- Public immutables ---
function gasPool() external view returns (address);
function DEBT_GAS_COMPENSATION() external view returns (uint256);
// --- Public mappings ---
function liquidStabilityPools(address) external view returns (bool);
function borrowerOperations(address) external view returns (bool);
function factories(address) external view returns (bool);
function peripheries(address) external view returns (bool);
function positionManagers(address) external view returns (bool);
// --- External functions ---
function enablePositionManager(address _positionManager) external;
function mintWithGasCompensation(address _account, uint256 _amount) external returns (bool);
function burnWithGasCompensation(address _account, uint256 _amount) external returns (bool);
function mint(address _account, uint256 _amount) external;
function burn(address _account, uint256 _amount) external;
function decimals() external view returns (uint8);
function sendToPeriphery(address _sender, uint256 _amount) external;
function sendToSP(address _sender, uint256 _amount) external;
function returnFromPool(address _poolAddress, address _receiver, uint256 _amount) external;
function transfer(address recipient, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function maxFlashLoan(address token) external view returns (uint256);
function flashFee(address token, uint256 amount) external view returns (uint256);
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
function whitelistLiquidStabilityPoolAddress(address _liquidStabilityPool, bool active) external;
function whitelistBorrowerOperationsAddress(address _borrowerOperations, bool active) external;
function whitelistFactoryAddress(address _factory, bool active) external;
function whitelistPeripheryAddress(address _periphery, bool active) external;
function whitelistPSM(address, bool) external;
function setDebtGasCompensation(uint256 _gasCompensation, bool _isFinalValue) external;
function setFlashLoanFee(uint256 _fee) external;
function DOMAIN_SEPARATOR() external view returns (bytes32);
function permit(
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
/*
* Base contract for PositionManager, BorrowerOperations and StabilityPool. Contains global system constants and
* common functions.
*/
contract PropBase {
uint256 public constant DECIMAL_PRECISION = 1e18;
// Amount of debt to be locked in gas pool on opening positions
uint256 public immutable DEBT_GAS_COMPENSATION;
uint256 public constant PERCENT_DIVISOR = 1000; // dividing by 1000 yields 0.1%
constructor(uint256 _gasCompensation) {
DEBT_GAS_COMPENSATION = _gasCompensation;
}
// --- Gas compensation functions ---
// Returns the composite debt (drawn debt + gas compensation) of a position, for the purpose of ICR calculation
function _getCompositeDebt(uint256 _debt) internal view returns (uint256) {
return _debt + DEBT_GAS_COMPENSATION;
}
function _getNetDebt(uint256 _debt) internal view returns (uint256) {
return _debt - DEBT_GAS_COMPENSATION;
}
// Return the amount of collateral to be drawn from a position's collateral and sent as gas compensation.
function _getCollGasCompensation(uint256 _entireColl) internal pure returns (uint256) {
return _entireColl / PERCENT_DIVISOR;
}
function _requireUserAcceptsFee(uint256 _fee, uint256 _amount, uint256 _maxFeePercentage) internal pure {
uint256 feePercentage = _amount != 0 ? (_fee * DECIMAL_PRECISION) / _amount : 0;
require(feePercentage <= _maxFeePercentage, "Fee exceeded provided maximum");
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
library PropMath {
uint256 internal constant DECIMAL_PRECISION = 1e18;
/* Precision for Nominal ICR (independent of price). Rationale for the value:
*
* - Making it “too high” could lead to overflows.
* - Making it “too low” could lead to an ICR equal to zero, due to truncation from Solidity floor division.
*
* This value of 1e20 is chosen for safety: the NICR will only overflow for numerator > ~1e39,
* and will only truncate to 0 if the denominator is at least 1e20 times greater than the numerator.
*
*/
uint256 internal constant NICR_PRECISION = 1e20;
function _min(uint256 _a, uint256 _b) internal pure returns (uint256) {
return (_a < _b) ? _a : _b;
}
function _max(uint256 _a, uint256 _b) internal pure returns (uint256) {
return (_a >= _b) ? _a : _b;
}
/*
* Multiply two decimal numbers and use normal rounding rules:
* -round product up if 19'th mantissa digit >= 5
* -round product down if 19'th mantissa digit < 5
*
* Used only inside the exponentiation, _decPow().
*/
function decMul(uint256 x, uint256 y) internal pure returns (uint256 decProd) {
uint256 prod_xy = x * y;
decProd = (prod_xy + (DECIMAL_PRECISION / 2)) / DECIMAL_PRECISION;
}
/*
* _decPow: Exponentiation function for 18-digit decimal base, and integer exponent n.
*
* Uses the efficient "exponentiation by squaring" algorithm. O(log(n)) complexity.
*
* Called by two functions that represent time in units of minutes:
* 1) PositionManager._calcDecayedBaseRate
* 2) CommunityIssuance._getCumulativeIssuanceFraction
*
* The exponent is capped to avoid reverting due to overflow. The cap 525600000 equals
* "minutes in 1000 years": 60 * 24 * 365 * 1000
*
* If a period of > 1000 years is ever used as an exponent in either of the above functions, the result will be
* negligibly different from just passing the cap, since:
*
* In function 1), the decayed base rate will be 0 for 1000 years or > 1000 years
* In function 2), the difference in tokens issued at 1000 years and any time > 1000 years, will be negligible
*/
function _decPow(uint256 _base, uint256 _minutes) internal pure returns (uint256) {
if (_minutes > 525600000) {
_minutes = 525600000;
} // cap to avoid overflow
if (_minutes == 0) {
return DECIMAL_PRECISION;
}
uint256 y = DECIMAL_PRECISION;
uint256 x = _base;
uint256 n = _minutes;
// Exponentiation-by-squaring
while (n > 1) {
if (n % 2 == 0) {
x = decMul(x, x);
n = n / 2;
} else {
// if (n % 2 != 0)
y = decMul(x, y);
x = decMul(x, x);
n = (n - 1) / 2;
}
}
return decMul(x, y);
}
function _getAbsoluteDifference(uint256 _a, uint256 _b) internal pure returns (uint256) {
return (_a >= _b) ? _a - _b : _b - _a;
}
function _computeNominalCR(uint256 _coll, uint256 _debt) internal pure returns (uint256) {
if (_debt > 0) {
return (_coll * NICR_PRECISION) / _debt;
}
// Return the maximal value for uint256 if the Position has a debt of 0. Represents "infinite" CR.
else {
// if (_debt == 0)
return 2 ** 256 - 1;
}
}
function _computeCR(uint256 _coll, uint256 _debt, uint256 _price) internal pure returns (uint256) {
if (_debt > 0) {
uint256 newCollRatio = (_coll * _price) / _debt;
return newCollRatio;
}
// Return the maximal value for uint256 if the Position has a debt of 0. Represents "infinite" CR.
else {
// if (_debt == 0)
return 2 ** 256 - 1;
}
}
function _computeCR(uint256 _coll, uint256 _debt) internal pure returns (uint256) {
if (_debt > 0) {
uint256 newCollRatio = (_coll) / _debt;
return newCollRatio;
}
// Return the maximal value for uint256 if the Position has a debt of 0. Represents "infinite" CR.
else {
// if (_debt == 0)
return 2 ** 256 - 1;
}
}
function _isApproxEqAbs(uint256 a, uint256 b, uint256 tolerance) internal pure returns (bool) {
return a > b ? (a - b) <= tolerance : (b - a) <= tolerance;
}
function _isWithinToleranceAbove(
uint256 a,
uint256 b,
uint256 tolerance
) internal pure returns (bool) {
if (a < b) return false;
return (a - b) <= tolerance;
}
function _isWithinToleranceBelow(
uint256 a,
uint256 b,
uint256 tolerance
) internal pure returns (bool) {
if (a > b) return false;
return (b - a) <= tolerance;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import "../interfaces/core/ICore.sol";
/**
@title Prop Ownable
@notice Contracts inheriting `PropOwnable` have the same owner as `PropCore`.
The ownership cannot be independently modified or renounced.
@dev In the contracts that use CORE to interact with protocol instance specific parameters,
the immutable will be instanced with PropCore.sol, eitherway, it will be MetaCore.sol
*/
contract PropOwnable {
ICore public immutable CORE;
constructor(address _core) {
CORE = ICore(_core);
}
modifier onlyOwner() {
require(msg.sender == CORE.owner(), "Only owner");
_;
}
function owner() public view returns (address) {
return CORE.owner();
}
function guardian() public view returns (address) {
return CORE.guardian();
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {ICore} from "../interfaces/core/ICore.sol";
/**
@title Delegated Operations
@notice Allows delegation to specific contract functionality. Useful for creating
wrapper contracts to bundle multiple interactions into a single call.
Functions that supports delegation should include an `account` input allowing
the delegated caller to indicate who they are calling on behalf of. In executing
the call, all internal state updates should be applied for `account` and all
value transfers should occur to or from the caller.
For example: a delegated call to `openPosition` should transfer collateral
from the caller, create the debt position for `account`, and send newly
minted tokens to the caller.
*/
contract DelegatedOps {
ICore immutable core;
mapping(address owner => mapping(address caller => bool isApproved)) public isApprovedDelegate;
event DelegateApprovalSet(address indexed owner, address indexed delegate, bool isApproved);
constructor(address _core) {
if (_core == address(0)) {
revert("DelegatedOps: 0 address");
}
core = ICore(_core);
}
modifier callerOrDelegated(address _account) {
require(msg.sender == _account || core.isPeriphery(msg.sender) || isApprovedDelegate[_account][msg.sender], "Delegate not approved");
_;
}
function setDelegateApproval(address _delegate, bool _isApproved) external {
isApprovedDelegate[msg.sender][_delegate] = _isApproved;
emit DelegateApprovalSet(msg.sender, _delegate, _isApproved);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
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");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
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");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (interfaces/IERC3156FlashBorrower.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC3156 FlashBorrower, as defined in
* https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
*
* _Available since v4.1._
*/
interface IERC3156FlashBorrower {
/**
* @dev Receive a flash loan.
* @param initiator The initiator of the loan.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @param fee The additional amount of tokens to repay.
* @param data Arbitrary data structure, intended to contain user-defined parameters.
* @return The keccak256 hash of "IERC3156FlashBorrower.onFlashLoan"
*/
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
interface IFactory {
// commented values are suggested default parameters
struct DeploymentParams {
uint256 minuteDecayFactor; // 999037758833783000 (half life of 12 hours)
uint256 redemptionFeeFloor; // 1e18 / 1000 * 5 (0.5%)
uint256 maxRedemptionFee; // 1e18 (100%)
uint256 borrowingFeeFloor; // 1e18 / 1000 * 5 (0.5%)
uint256 maxBorrowingFee; // 1e18 / 100 * 5 (5%)
uint256 interestRateInBps; // 100 (1%)
uint256 maxDebt;
uint256 MCR; // 12 * 1e17 (120%)
address collVaultRouter; // set to address(0) if PositionManager coll is not CollateralVault
}
event NewDeployment(address collateral, address priceFeed, address positionManager, address sortedPositions);
function deployNewInstance(
address collateral,
address priceFeed,
address customPositionManagerImpl,
address customSortedPositionsImpl,
DeploymentParams calldata params,
uint64 unlockRatePerSecond,
bool forceThroughLspBalanceCheck
) external;
function setImplementations(address _positionManagerImpl, address _sortedPositionsImpl) external;
function CORE() external view returns (address);
function borrowerOperations() external view returns (address);
function debtToken() external view returns (address);
function guardian() external view returns (address);
function liquidationManager() external view returns (address);
function owner() external view returns (address);
function sortedPositionsImpl() external view returns (address);
function liquidStabilityPool() external view returns (address);
function positionManagerCount() external view returns (uint256);
function positionManagerImpl() external view returns (address);
function positionManagers(uint256) external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {IMetaCore} from "src/interfaces/core/IMetaCore.sol";
interface ICore {
// --- Public variables ---
function metaCore() external view returns (IMetaCore);
function startTime() external view returns (uint256);
function CCR() external view returns (uint256);
function dmBootstrapPeriod() external view returns (uint64);
function isPeriphery(address peripheryContract) external view returns (bool);
// --- External functions ---
function setPeripheryEnabled(address _periphery, bool _enabled) external;
function setPMBootstrapPeriod(address dm, uint64 _bootstrapPeriod) external;
function setNewCCR(uint256 _CCR) external;
function priceFeed() external view returns (address);
function owner() external view returns (address);
function pendingOwner() external view returns (address);
function guardian() external view returns (address);
function feeReceiver() external view returns (address);
function paused() external view returns (bool);
function lspBootstrapPeriod() external view returns (uint64);
function getLspEntryFee(address rebalancer) external view returns (uint16);
function getLspExitFee(address rebalancer) external view returns (uint16);
function interestProtocolShare() external view returns (uint16);
function defaultInterestReceiver() external view returns (address);
// --- Events ---
event CCRSet(uint256 initialCCR);
event PMBootstrapPeriodSet(address dm, uint64 bootstrapPeriod);
event PeripheryEnabled(address indexed periphery, bool enabled);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
interface IMetaCore {
// ---------------------------------
// Structures
// ---------------------------------
struct FeeInfo {
bool existsForDebtToken;
uint16 debtTokenFee;
}
struct RebalancerFeeInfo {
bool exists;
uint16 entryFee;
uint16 exitFee;
}
// ---------------------------------
// Public constants
// ---------------------------------
function OWNERSHIP_TRANSFER_DELAY() external view returns (uint256);
function DEFAULT_FLASH_LOAN_FEE() external view returns (uint16);
// ---------------------------------
// Public state variables
// ---------------------------------
function debtToken() external view returns (address);
function lspEntryFee() external view returns (uint16);
function lspExitFee() external view returns (uint16);
function interestProtocolShare() external view returns (uint16);
/// @dev Default interest receiver for all PositionManagers, unless overriden in the respective PM
function defaultInterestReceiver() external view returns (address);
function feeReceiver() external view returns (address);
function priceFeed() external view returns (address);
function owner() external view returns (address);
function pendingOwner() external view returns (address);
function ownershipTransferDeadline() external view returns (uint256);
function guardian() external view returns (address);
function paused() external view returns (bool);
function lspBootstrapPeriod() external view returns (uint64);
// ---------------------------------
// External functions
// ---------------------------------
function setFeeReceiver(address _feeReceiver) external;
function setPriceFeed(address _priceFeed) external;
function setGuardian(address _guardian) external;
/**
* @notice Global pause/unpause
* Pausing halts new deposits/borrowing across the protocol
*/
function setPaused(bool _paused) external;
/**
* @notice Extend or change the LSP bootstrap period,
* after which certain protocol mechanics change
*/
function setLspBootstrapPeriod(uint64 _bootstrapPeriod) external;
/**
* @notice Set a custom flash-loan fee for a given periphery contract
* @param _periphery Target contract that will get this custom fee
* @param _debtTokenFee Fee in basis points (bp)
* @param _existsForDebtToken Whether this custom fee is used when the caller = `debtToken`
*/
function setPeripheryFlashLoanFee(address _periphery, uint16 _debtTokenFee, bool _existsForDebtToken) external;
/**
* @notice Begin the ownership transfer process
* @param newOwner The address proposed to be the new owner
*/
function commitTransferOwnership(address newOwner) external;
/**
* @notice Finish the ownership transfer, after the mandatory delay
*/
function acceptTransferOwnership() external;
/**
* @notice Revoke a pending ownership transfer
*/
function revokeTransferOwnership() external;
/**
* @notice Look up a custom flash-loan fee for a specific periphery contract
* @param peripheryContract The contract that might have a custom fee
* @return The flash-loan fee in basis points
*/
function getPeripheryFlashLoanFee(address peripheryContract) external view returns (uint16);
/**
* @notice Set / override entry & exit fees for a special rebalancer contract
*/
function setRebalancerFee(address _rebalancer, uint16 _entryFee, uint16 _exitFee) external;
/**
* @notice Set the LSP entry fee globally
* @param _fee Fee in basis points
*/
function setEntryFee(uint16 _fee) external;
/**
* @notice Set the LSP exit fee globally
* @param _fee Fee in basis points
*/
function setExitFee(uint16 _fee) external;
/**
* @notice Set the interest protocol share globally to all PositionManagers
* @param _interestProtocolShare Share in basis points
*/
function setInterestProtocolShare(uint16 _interestProtocolShare) external;
/**
* @notice Look up the LSP entry fee for a rebalancer
* @param rebalancer Possibly has a special fee
* @return The entry fee in basis points
*/
function getLspEntryFee(address rebalancer) external view returns (uint16);
/**
* @notice Look up the LSP exit fee for a rebalancer
* @param rebalancer Possibly has a special fee
* @return The exit fee in basis points
*/
function getLspExitFee(address rebalancer) external view returns (uint16);
// ---------------------------------
// Events
// ---------------------------------
event NewOwnerCommitted(address indexed owner, address indexed pendingOwner, uint256 deadline);
event NewOwnerAccepted(address indexed oldOwner, address indexed newOwner);
event NewOwnerRevoked(address indexed owner, address indexed revokedOwner);
event FeeReceiverSet(address indexed feeReceiver);
event PriceFeedSet(address indexed priceFeed);
event GuardianSet(address indexed guardian);
event PeripheryFlashLoanFee(address indexed periphery, uint16 debtTokenFee);
event LSPBootstrapPeriodSet(uint64 bootstrapPeriod);
event RebalancerFees(address indexed rebalancer, uint16 entryFee, uint16 exitFee);
event EntryFeeSet(uint16 fee);
event ExitFeeSet(uint16 fee);
event InterestProtocolShareSet(uint16 interestProtocolShare);
event DefaultInterestReceiverSet(address indexed defaultInterestReceiver);
event Paused();
event Unpaused();
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin-upgradeable/contracts/=lib/openzeppelin-contracts-upgradeable/contracts/",
"solady/=lib/solady/src/",
"@solmate/=lib/solmate/src/",
"@chimera/=lib/chimera/src/",
"forge-std/=lib/forge-std/src/",
"@uniswap/v3-core/=lib/v3-core/",
"@uniswap/v3-periphery/=lib/v3-periphery/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"chimera/=lib/chimera/src/",
"ds-test/=lib/solmate/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"rewards/=lib/rewards/",
"solmate/=lib/solmate/src/",
"uniswap/=lib/uniswap/",
"v3-core/=lib/v3-core/contracts/",
"v3-periphery/=lib/v3-periphery/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 1
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_core","type":"address"},{"internalType":"address","name":"_debtTokenAddress","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"uint256","name":"_minNetDebt","type":"uint256"},{"internalType":"uint256","name":"_gasCompensation","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BorrowingFeePaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"indexed":false,"internalType":"contract IERC20","name":"collateralToken","type":"address"}],"name":"CollateralConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"bool","name":"isApproved","type":"bool"}],"name":"DelegateApprovalSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"indexed":true,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"arrayIndex","type":"uint256"}],"name":"PositionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IPositionManager","name":"positionManager","type":"address"}],"name":"PositionManagerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IPositionManager","name":"_positionManager","type":"address"},{"indexed":true,"internalType":"address","name":"_borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"_debt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_coll","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stake","type":"uint256"},{"indexed":false,"internalType":"enum BorrowerOperations.BorrowerOperation","name":"operation","type":"uint8"}],"name":"PositionUpdated","type":"event"},{"inputs":[],"name":"CORE","outputs":[{"internalType":"contract ICore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEBT_GAS_COMPENSATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_collateralAmount","type":"uint256"},{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"}],"name":"addColl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_maxFeePercentage","type":"uint256"},{"internalType":"uint256","name":"_collDeposit","type":"uint256"},{"internalType":"uint256","name":"_collWithdrawal","type":"uint256"},{"internalType":"uint256","name":"_debtChange","type":"uint256"},{"internalType":"bool","name":"_isDebtIncrease","type":"bool"},{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"}],"name":"adjustPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"TCR","type":"uint256"}],"name":"checkRecoveryMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"internalType":"contract IERC20","name":"collateralToken","type":"address"}],"name":"configureCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"debtToken","outputs":[{"internalType":"contract IDebtToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fetchBalances","outputs":[{"components":[{"internalType":"uint256[]","name":"collaterals","type":"uint256[]"},{"internalType":"uint256[]","name":"debts","type":"uint256[]"},{"internalType":"uint256[]","name":"prices","type":"uint256[]"}],"internalType":"struct BorrowerOperations.SystemBalances","name":"balances","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debt","type":"uint256"}],"name":"getCompositeDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalSystemBalances","outputs":[{"internalType":"uint256","name":"totalPricedCollateral","type":"uint256"},{"internalType":"uint256","name":"totalDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTCR","outputs":[{"internalType":"uint256","name":"globalTotalCollateralRatio","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"caller","type":"address"}],"name":"isApprovedDelegate","outputs":[{"internalType":"bool","name":"isApproved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minNetDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_maxFeePercentage","type":"uint256"},{"internalType":"uint256","name":"_collateralAmount","type":"uint256"},{"internalType":"uint256","name":"_debtAmount","type":"uint256"},{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"}],"name":"openPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"positionManagers","outputs":[{"internalType":"contract IPositionManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"","type":"address"}],"name":"positionManagersData","outputs":[{"internalType":"contract IERC20","name":"collateralToken","type":"address"},{"internalType":"uint16","name":"index","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"}],"name":"removePositionManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_debtAmount","type":"uint256"},{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"}],"name":"repayDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"},{"internalType":"bool","name":"_isApproved","type":"bool"}],"name":"setDelegateApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minNetDebt","type":"uint256"}],"name":"setMinNetDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_collWithdrawal","type":"uint256"},{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"}],"name":"withdrawColl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_maxFeePercentage","type":"uint256"},{"internalType":"uint256","name":"_debtAmount","type":"uint256"},{"internalType":"address","name":"_upperHint","type":"address"},{"internalType":"address","name":"_lowerHint","type":"address"}],"name":"withdrawDebt","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
610120604052348015610010575f80fd5b5060405161380238038061380283398101604081905261002f9161016a565b60808190526001600160a01b03851660a081905285906100965760405162461bcd60e51b815260206004820152601760248201527f44656c6567617465644f70733a2030206164647265737300000000000000000060448201526064015b60405180910390fd5b6001600160a01b0390811660c052851615806100b957506001600160a01b038416155b806100cb57506001600160a01b038316155b156101185760405162461bcd60e51b815260206004820152601d60248201527f426f72726f7765724f7065726174696f6e733a20302061646472657373000000604482015260640161008d565b6001600160a01b0380851660e0528316610100526101358261013f565b50505050506101bc565b5f811161014a575f80fd5b600155565b80516001600160a01b0381168114610165575f80fd5b919050565b5f805f805f60a0868803121561017e575f80fd5b6101878661014f565b94506101956020870161014f565b93506101a36040870161014f565b6060870151608090970151959894975095949392505050565b60805160a05160c05160e051610100516135616102a15f395f81816103be0152610b9f01525f81816103e5015281816108b0015281816119020152611f3a01525f818161046c015281816110180152818161123a0152818161133801528181611673015281816119e70152611c1601525f81816102a5015281816105320152818161097d01528181610a5701528181610add01528181610f94015281816110e701528181611aa401528181611cd301528181611f6901528181612195015261235801525f81816102010152818161192d015281816121080152612cb401526135615ff3fe608060405234801561000f575f80fd5b5060043610610152575f3560e01c80631930e8251461015657806320e467f61461019557806326caa39d146101b5578063438d641a146101ca578063452a9320146101dd5780634870dd9a146101e55780634ba4a28b146101fc5780634e443d9e146102235780634ff81443146102365780635f9a6a77146102495780636b6c0774146102a0578063716c53c2146102c7578063778c5c64146102e45780638a05a2e6146102f75780638da5cb5b1461030a578063969c2452146103125780639efeaeb21461031b578063a20baee61461032e578063a2e8dc0a1461033d578063a6b6c8ee14610350578063b51237a914610363578063b620115d14610378578063bf42841c14610380578063c2af1eca14610393578063c3c854b6146103a6578063c45a0155146103b9578063f8d89898146103e0578063fded3d3514610407575b5f80fd5b610180610164366004612f72565b5f60208181529281526040808220909352908152205460ff1681565b60405190151581526020015b60405180910390f35b6101a86101a3366004612fa9565b61041a565b60405161018c9190612fc0565b6101c86101c3366004612fd4565b610442565b005b6101c86101d8366004612fa9565b61097b565b6101a8610a54565b6101ee6103e881565b60405190815260200161018c565b6101ee7f000000000000000000000000000000000000000000000000000000000000000081565b610180610231366004612fa9565b610ada565b6101ee610244366004612fa9565b610b63565b61027e61025736600461304a565b60026020525f90815260409020546001600160a01b03811690600160a01b900461ffff1682565b604080516001600160a01b03909316835261ffff90911660208301520161018c565b6101a87f000000000000000000000000000000000000000000000000000000000000000081565b6102cf610b73565b6040805192835260208301919091520161018c565b6101c86102f2366004612f72565b610b94565b6101c861030536600461304a565b610cd1565b6101a8610f91565b6101ee60015481565b6101c8610329366004613072565b610fee565b6101ee670de0b6b3a764000081565b6101c861034b366004613104565b611210565b6101c861035e366004613104565b61130e565b61036b611404565b60405161018c91906131a2565b6101ee61162b565b6101c861038e366004612f72565b611649565b6101c86103a1366004613201565b6119bd565b6101c86103b436600461326d565b611b83565b6101a87f000000000000000000000000000000000000000000000000000000000000000081565b6101a87f000000000000000000000000000000000000000000000000000000000000000081565b6101c8610415366004613104565b611bec565b60038181548110610429575f80fd5b5f918252602090912001546001600160a01b0316905081565b85336001600160a01b03821614806104e05750604051638fcfa77560e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638fcfa775906104a1903390600401612fc0565b602060405180830381865afa1580156104bc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e09190613299565b8061050b57506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b6105305760405162461bcd60e51b8152600401610527906132b4565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561058c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105b09190613299565b156105f35760405162461bcd60e51b815260206004820152601360248201527211195c1bdcda5d1cc8185c99481c185d5cd959606a1b6044820152606401610527565b5f61063a6040518061012001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f6106448b611d7f565b60408701919091526020860191909152908452909350905061066589611e4c565b60608201879052806106925761067d8b8b8b8a611ebf565b826060015161068c91906132f7565b60608301525b61069f826060015161208a565b6106ac8260600151612102565b6080830181905282516106c0918a9161212d565b60a083015260808201516106d590899061215e565b60c083015280156106f2576106ed8260a00151612193565b610797565b61075f8260a001518c6001600160a01b031663794e57246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610736573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061075a919061330a565b612285565b5f61078a83602001518460400151855f01518c61077c9190613321565b6001876080015160016122fe565b905061079581612356565b505b608082015160c083015160405163513de6d560e11b81526001600160a01b038d81166004830152602482018c905260448201939093526064810191909152878216608482015286821660a4820152908c169063a27bcdaa9060c40160408051808303815f875af115801561080d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108319190613338565b610100840181905260e08401919091526040519081526001600160a01b038b811691908d16907f756999f76d314557edacbe03e4a4cd729c1f2e73b0406791914643afa7aa312e9060200160405180910390a36108996001600160a01b038416338d8b61244a565b60405163467fafdf60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638cff5fbe906108e79033908b9060040161335a565b6020604051808303815f875af1158015610903573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109279190613299565b50896001600160a01b03168b6001600160a01b03165f805160206134ec83398151915284608001518b8660e001515f6040516109669493929190613393565b60405180910390a35050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109fb91906133b5565b6001600160a01b0316336001600160a01b031614610a485760405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b6044820152606401610527565b610a51816124aa565b50565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ab1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad591906133b5565b905090565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635733d58f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b37573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5b919061330a565b909110919050565b5f610b6d82612102565b92915050565b5f805f610b7e611404565b9050610b89816124ba565b909590945092505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610bf75760405162461bcd60e51b815260206004820152600860248201526721666163746f727960c01b6044820152606401610527565b6040805180820182526001600160a01b038381168083526003805461ffff90811660208087019182528986165f81815260028352898120985189549451909516600160a01b026001600160b01b03199094169490971693909317919091179095558154600181018355919093527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b031916831790558351918252918101919091527ff6e0528dc0c0ef50525339faff44940d57e7897bee18b67dd0aa23bba1749ad2910160405180910390a15050565b6001600160a01b038181165f90815260026020908152604091829020825180840190935254928316808352600160a01b90930461ffff16908201529015801590610d765750816001600160a01b0316639484fb8e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d769190613299565b8015610ddf5750816001600160a01b031663795d26c36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610db9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddd919061330a565b155b610e365760405162461bcd60e51b815260206004820152602260248201527f506f736974696f6e204d616e616765722063616e6e6f742062652072656d6f76604482015261195960f21b6064820152608401610527565b6001600160a01b0382165f90815260026020526040812080546001600160b01b0319169055600354610e6a906001906133d0565b905080826020015161ffff161015610f23575f60038281548110610e9057610e906133e3565b905f5260205f20015f9054906101000a90046001600160a01b03169050806003846020015161ffff1681548110610ec957610ec96133e3565b5f918252602080832090910180546001600160a01b039485166001600160a01b031990911617905585810151939092168152600290915260409020805461ffff909216600160a01b0261ffff60a01b199092169190911790555b6003805480610f3457610f346133f7565b5f8281526020902081015f1990810180546001600160a01b03191690550190556040517fbc0a65aee62a88547316ae28fe2969b4e94a57ccfd27cb2e0bd21109ec4b1c8e90610f84908590612fc0565b60405180910390a1505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ab1573d5f803e3d5ffd5b87336001600160a01b038216148061108c5750604051638fcfa77560e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638fcfa7759061104d903390600401612fc0565b602060405180830381865afa158015611068573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061108c9190613299565b806110b757506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b6110d35760405162461bcd60e51b8152600401610527906132b4565b861580156110df575083155b8061116757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611141573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111659190613299565b155b6111835760405162461bcd60e51b81526004016105279061340b565b86158061118e575085155b6111f35760405162461bcd60e51b815260206004820152603060248201527f426f72726f7765724f7065726174696f6e733a2043616e6e6f7420776974686460448201526f1c985dc8185b99081859190818dbdb1b60821b6064820152608401610527565b6112048a8a8a8a8a8a8a8a8a612566565b50505050505050505050565b83336001600160a01b03821614806112ae5750604051638fcfa77560e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638fcfa7759061126f903390600401612fc0565b602060405180830381865afa15801561128a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112ae9190613299565b806112d957506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b6112f55760405162461bcd60e51b8152600401610527906132b4565b61130686865f805f895f8a8a612566565b505050505050565b83336001600160a01b03821614806113ac5750604051638fcfa77560e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638fcfa7759061136d903390600401612fc0565b602060405180830381865afa158015611388573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113ac9190613299565b806113d757506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b6113f35760405162461bcd60e51b8152600401610527906132b4565b61130686865f80885f808a8a612566565b61142860405180606001604052806060815260200160608152602001606081525090565b600354604080516060810190915280826001600160401b0381111561144f5761144f613442565b604051908082528060200260200182016040528015611478578160200160208202803683370190505b508152602001826001600160401b0381111561149657611496613442565b6040519080825280602002602001820160405280156114bf578160200160208202803683370190505b508152602001826001600160401b038111156114dd576114dd613442565b604051908082528060200260200182016040528015611506578160200160208202803683370190505b50905291505f5b81811015611626575f60038281548110611529576115296133e3565b905f5260205f20015f9054906101000a90046001600160a01b031690505f805f836001600160a01b03166301c799fc6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611585573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115a99190613456565b92509250925082875f015186815181106115c5576115c56133e3565b60200260200101818152505081876020015186815181106115e8576115e86133e3565b602002602001018181525050808760400151868151811061160b5761160b6133e3565b6020026020010181815250508460010194505050505061150d565b505090565b5f80611635611404565b9050611640816124ba565b50909392505050565b80336001600160a01b03821614806116e75750604051638fcfa77560e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638fcfa775906116a8903390600401612fc0565b602060405180830381865afa1580156116c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116e79190613299565b8061171257506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b61172e5760405162461bcd60e51b8152600401610527906132b4565b5f805f805f61173c88611d7f565b939850919650919450909250905082156117ba5760405162461bcd60e51b815260206004820152603960248201527f426f72726f7765724f70733a204f7065726174696f6e206e6f74207065726d696044820152787474656420647572696e67205265636f76657279204d6f646560381b6064820152608401610527565b5f80896001600160a01b0316630b0765578a6040518263ffffffff1660e01b81526004016117e89190612fc0565b60408051808303815f875af1158015611803573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118279190613338565b90925090505f611844858561183c8a87613321565b5f865f6122fe565b905061184f81612356565b6040516310cf7e2360e11b81526001600160a01b038b8116600483015233602483015260448201859052606482018490528c169063219efc46906084015f604051808303815f87803b1580156118a3575f80fd5b505af11580156118b5573d5f803e3d5ffd5b50505050896001600160a01b03168b6001600160a01b03165f805160206134ec8339815191525f805f60016040516118f09493929190613393565b60405180910390a36001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166385177509336119527f0000000000000000000000000000000000000000000000000000000000000000866133d0565b6040518363ffffffff1660e01b815260040161196f92919061335a565b6020604051808303815f875af115801561198b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119af9190613299565b505050505050505050505050565b84336001600160a01b0382161480611a5b5750604051638fcfa77560e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638fcfa77590611a1c903390600401612fc0565b602060405180830381865afa158015611a37573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a5b9190613299565b80611a8657506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b611aa25760405162461bcd60e51b8152600401610527906132b4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611afe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b229190613299565b15611b685760405162461bcd60e51b815260206004820152601660248201527515da5d1a191c985dd85b1cc8185c99481c185d5cd95960521b6044820152606401610527565b611b7a8787875f808960018a8a612566565b50505050505050565b335f818152602081815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f92d241afb0a1a9b3441bf1bd6bea0f9164cf5a2562cbe4bcc34ab943b2465608910160405180910390a35050565b83336001600160a01b0382161480611c8a5750604051638fcfa77560e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638fcfa77590611c4b903390600401612fc0565b602060405180830381865afa158015611c66573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c8a9190613299565b80611cb557506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b611cd15760405162461bcd60e51b8152600401610527906132b4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d519190613299565b15611d6e5760405162461bcd60e51b81526004016105279061340b565b61130686865f875f805f8a8a612566565b6001600160a01b038181165f90815260026020526040812080549283169282918291829190600160a01b900461ffff1686611df55760405162461bcd60e51b815260206004820152601660248201527510dbdb1b185d195c985b081b9bdd08195b98589b195960521b6044820152606401610527565b5f80611dff611404565b9050611e0a816124ba565b90985096509150611e1a82610ada565b94508881604001518481518110611e3357611e336133e3565b6020026020010151985098505050505091939590929450565b670de0b6b3a7640000811115610a515760405162461bcd60e51b815260206004820152603260248201527f4d6178206665652070657263656e74616765206d757374206c657373207468616044820152716e206f7220657175616c20746f203130302560701b6064820152608401610527565b60405163b2f29d7b60e01b8152600481018290525f9081906001600160a01b0387169063b2f29d7b906024016020604051808303815f875af1158015611f07573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f2b919061330a565b9050611f388184866129f9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166340c10f197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3f006746040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fc3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe791906133b5565b836040518363ffffffff1660e01b815260040161200592919061335a565b5f604051808303815f87803b15801561201c575f80fd5b505af115801561202e573d5f803e3d5ffd5b50505050846001600160a01b0316866001600160a01b03167fd89359f0d8e7f936d0682c5565cc5a16989a91560a80c7b06c46c28e52a5d43a8360405161207791815260200190565b60405180910390a390505b949350505050565b600154811015610a515760405162461bcd60e51b815260206004820152603d60248201527f426f72726f7765724f70733a20506f736974696f6e2773206e6574206465627460448201527f206d7573742062652067726561746572207468616e206d696e696d756d0000006064820152608401610527565b5f610b6d7f0000000000000000000000000000000000000000000000000000000000000000836132f7565b5f8215612153575f836121408487613321565b61214a9190613481565b91506121579050565b505f195b9392505050565b5f811561218a578161217968056bc75e2d6310000085613321565b6121839190613481565b9050610b6d565b505f1992915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635733d58f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ef573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612213919061330a565b811015610a515760405162461bcd60e51b815260206004820152603a60248201527f426f72726f7765724f70733a204f7065726174696f6e206d757374206c65617660448201527932903837b9b4ba34b7b7103bb4ba341024a1a9101f1e9021a1a960311b6064820152608401610527565b808210156122fa5760405162461bcd60e51b815260206004820152604960248201525f8051602061350c83398151915260448201527f6f756c6420726573756c7420696e20494352203c204d4352206973206e6f74206064820152681c195c9b5a5d1d195960ba1b608482015260a401610527565b5050565b5f816123135761230e83876133d0565b61231d565b61231d83876132f7565b9550836123335761232e85886133d0565b61233d565b61233d85886132f7565b96505f61234a8888612a76565b98975050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635733d58f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123d6919061330a565b811015610a515760405162461bcd60e51b815260206004820152604960248201525f8051602061350c83398151915260448201527f6f756c6420726573756c7420696e20544352203c20434352206973206e6f74206064820152681c195c9b5a5d1d195960ba1b608482015260a401610527565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526124a4908590612a91565b50505050565b5f81116124b5575f80fd5b600155565b8051515f9081908190815b8181101561255157856040015181815181106124e3576124e36133e3565b6020026020010151865f01518281518110612500576125006133e3565b60200260200101516125129190613321565b61251c90856132f7565b935085602001518181518110612534576125346133e3565b60200260200101518361254791906132f7565b92506001016124c5565b5061255c8383612a76565b9350509193909250565b8515158061257357508415155b8061257d57508315155b6125fe5760405162461bcd60e51b815260206004820152604660248201527f426f72726f7765724f70733a205468657265206d75737420626520656974686560448201527f72206120636f6c6c61746572616c206368616e6765206f7220612064656274206064820152656368616e676560d01b608482015260a401610527565b5f61266e604051806101c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f151581526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81525090565b5f6126788c611d7f565b60408088019290925260208701929092529185529051630b07655760e01b815291945091506001600160a01b038d1690630b076557906126bc908e90600401612fc0565b60408051808303815f875af11580156126d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fb9190613338565b60c084015260e083015261270f8989612b67565b151560a084015260608301526080820187905261016082018790526001600160a01b03808c1661018084015260408051631e5395c960e21b81529051918e169163794e5724916004808201926020929091908290030181865afa158015612778573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061279c919061330a565b6101a08301528515612846575f87116128175760405162461bcd60e51b815260206004820152603760248201527f426f72726f7765724f70733a204465627420696e637265617365207265717569604482015276726573206e6f6e2d7a65726f20646562744368616e676560481b6064820152608401610527565b6128208a611e4c565b80612846576128318c8c8c8a611ebf565b8260800181815161284291906132f7565b9052505b61285c82602001518360400151838b8a87612b85565b8515801561286957505f87115b156128925761289282608001516128838460c00151612cae565b61288d91906133d0565b61208a565b8160a00151156128b95760608201516128b9906001600160a01b0385169033908f9061244a565b610160820151608083015160a0840151606085015161018086015160405163d23ab46160e01b81528b1515600482015260248101959095526044850193909352901515606484015260848301526001600160a01b0387811660a484015286811660c484015290811660e4830152336101048301528d169063d23ab46190610124016060604051808303815f875af1158015612956573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061297a9190613456565b8461012001856101000186610140018381525083815250838152505050508161018001516001600160a01b03168c6001600160a01b03165f805160206134ec83398151915284610100015185610120015186610140015160026040516129e39493929190613393565b60405180910390a3505050505050505050505050565b5f825f03612a07575f612a24565b82612a1a670de0b6b3a764000086613321565b612a249190613481565b9050818111156124a45760405162461bcd60e51b815260206004820152601d60248201527f4665652065786365656465642070726f7669646564206d6178696d756d0000006044820152606401610527565b5f811561218a575f612a888385613481565b9150610b6d9050565b5f612ae5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612cd99092919063ffffffff16565b805190915015612b625780806020019051810190612b039190613299565b612b625760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610527565b505050565b5f808315612b7a57508290506001612b7e565b8291505b9250929050565b5f612b9c8260e001518360c00151845f015161212d565b90505f612bc58360e001518460c0015185606001518660a00151876080015189895f0151612ce7565b90508515612c5f578415612c415760405162461bcd60e51b815260206004820152603e60248201527f426f72726f7765724f70733a20436f6c6c61746572616c20776974686472617760448201527f616c206e6f74207065726d6974746564205265636f76657279204d6f646500006064820152608401610527565b8315612c5a57612c5081612193565b612c5a8183612d17565b612ca4565b612c6e81846101a00151612285565b5f612c978989865f01518760600151612c879190613321565b8760a0015188608001518a6122fe565b9050612ca281612356565b505b5050505050505050565b5f610b6d7f0000000000000000000000000000000000000000000000000000000000000000836133d0565b606061208284845f85612d97565b5f805f612cf88a8a8a8a8a8a612e6e565b915091505f612d0883838761212d565b9b9a5050505050505050505050565b808210156122fa5760405162461bcd60e51b815260206004820152604160248201527f426f72726f7765724f70733a2043616e6e6f7420646563726561736520796f7560448201527f7220506f736974696f6e27732049435220696e205265636f76657279204d6f646064820152606560f81b608482015260a401610527565b606082471015612df85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610527565b5f80866001600160a01b03168587604051612e1391906134a0565b5f6040518083038185875af1925050503d805f8114612e4d576040519150601f19603f3d011682016040523d82523d5f602084013e612e52565b606091505b5091509150612e6387838387612ec1565b979650505050505050565b5f80878786612e8657612e81888b6133d0565b612e90565b612e90888b6132f7565b915084612ea657612ea1868a6133d0565b612eb0565b612eb0868a6132f7565b919a91995090975050505050505050565b60608315612f2f5782515f03612f28576001600160a01b0385163b612f285760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610527565b5081612082565b6120828383815115612f445781518083602001fd5b8060405162461bcd60e51b815260040161052791906134b6565b6001600160a01b0381168114610a51575f80fd5b5f8060408385031215612f83575f80fd5b8235612f8e81612f5e565b91506020830135612f9e81612f5e565b809150509250929050565b5f60208284031215612fb9575f80fd5b5035919050565b6001600160a01b0391909116815260200190565b5f805f805f805f60e0888a031215612fea575f80fd5b8735612ff581612f5e565b9650602088013561300581612f5e565b955060408801359450606088013593506080880135925060a088013561302a81612f5e565b915060c088013561303a81612f5e565b8091505092959891949750929550565b5f6020828403121561305a575f80fd5b813561215781612f5e565b8015158114610a51575f80fd5b5f805f805f805f805f6101208a8c03121561308b575f80fd5b893561309681612f5e565b985060208a01356130a681612f5e565b975060408a0135965060608a0135955060808a0135945060a08a0135935060c08a01356130d281613065565b925060e08a01356130e281612f5e565b91506101008a01356130f381612f5e565b809150509295985092959850929598565b5f805f805f60a08688031215613118575f80fd5b853561312381612f5e565b9450602086013561313381612f5e565b935060408601359250606086013561314a81612f5e565b9150608086013561315a81612f5e565b809150509295509295909350565b5f8151808452602084019350602083015f5b8281101561319857815186526020958601959091019060010161317a565b5093949350505050565b602081525f8251606060208401526131bd6080840182613168565b90506020840151601f198483030160408501526131da8282613168565b9150506040840151601f198483030160608501526131f88282613168565b95945050505050565b5f805f805f8060c08789031215613216575f80fd5b863561322181612f5e565b9550602087013561323181612f5e565b94506040870135935060608701359250608087013561324f81612f5e565b915060a087013561325f81612f5e565b809150509295509295509295565b5f806040838503121561327e575f80fd5b823561328981612f5e565b91506020830135612f9e81613065565b5f602082840312156132a9575f80fd5b815161215781613065565b60208082526015908201527411195b1959d85d19481b9bdd08185c1c1c9bdd9959605a1b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610b6d57610b6d6132e3565b5f6020828403121561331a575f80fd5b5051919050565b8082028115828204841417610b6d57610b6d6132e3565b5f8060408385031215613349575f80fd5b505080516020909101519092909150565b6001600160a01b03929092168252602082015260400190565b6003811061338f57634e487b7160e01b5f52602160045260245ffd5b9052565b8481526020810184905260408101839052608081016131f86060830184613373565b5f602082840312156133c5575f80fd5b815161215781612f5e565b81810381811115610b6d57610b6d6132e3565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b6020808252601f908201527f506f736974696f6e2061646a7573746d656e7473206172652070617573656400604082015260600190565b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215613468575f80fd5b5050815160208301516040909301519094929350919050565b5f8261349b57634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fea324e5da70af90221ccc670b176f09261ae0fcc1cb5b7c9c2f1e890bad70bb88426f72726f7765724f70733a20416e206f7065726174696f6e20746861742077a2646970667358221220308e5167aeb6be2e1a7a135502ef54fcb91d9914b7d43828813c007187fae5e064736f6c634300081a0033000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d570000000000000000000000000f26bbb8962d73bc891327f14db5162d5279899f0000000000000000000000004e8781e422a5e6fa1a422d6f6c6938111446f9060000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000000000de0b6b3a7640000
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610152575f3560e01c80631930e8251461015657806320e467f61461019557806326caa39d146101b5578063438d641a146101ca578063452a9320146101dd5780634870dd9a146101e55780634ba4a28b146101fc5780634e443d9e146102235780634ff81443146102365780635f9a6a77146102495780636b6c0774146102a0578063716c53c2146102c7578063778c5c64146102e45780638a05a2e6146102f75780638da5cb5b1461030a578063969c2452146103125780639efeaeb21461031b578063a20baee61461032e578063a2e8dc0a1461033d578063a6b6c8ee14610350578063b51237a914610363578063b620115d14610378578063bf42841c14610380578063c2af1eca14610393578063c3c854b6146103a6578063c45a0155146103b9578063f8d89898146103e0578063fded3d3514610407575b5f80fd5b610180610164366004612f72565b5f60208181529281526040808220909352908152205460ff1681565b60405190151581526020015b60405180910390f35b6101a86101a3366004612fa9565b61041a565b60405161018c9190612fc0565b6101c86101c3366004612fd4565b610442565b005b6101c86101d8366004612fa9565b61097b565b6101a8610a54565b6101ee6103e881565b60405190815260200161018c565b6101ee7f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b610180610231366004612fa9565b610ada565b6101ee610244366004612fa9565b610b63565b61027e61025736600461304a565b60026020525f90815260409020546001600160a01b03811690600160a01b900461ffff1682565b604080516001600160a01b03909316835261ffff90911660208301520161018c565b6101a87f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d5781565b6102cf610b73565b6040805192835260208301919091520161018c565b6101c86102f2366004612f72565b610b94565b6101c861030536600461304a565b610cd1565b6101a8610f91565b6101ee60015481565b6101c8610329366004613072565b610fee565b6101ee670de0b6b3a764000081565b6101c861034b366004613104565b611210565b6101c861035e366004613104565b61130e565b61036b611404565b60405161018c91906131a2565b6101ee61162b565b6101c861038e366004612f72565b611649565b6101c86103a1366004613201565b6119bd565b6101c86103b436600461326d565b611b83565b6101a87f0000000000000000000000004e8781e422a5e6fa1a422d6f6c6938111446f90681565b6101a87f0000000000000000000000000f26bbb8962d73bc891327f14db5162d5279899f81565b6101c8610415366004613104565b611bec565b60038181548110610429575f80fd5b5f918252602090912001546001600160a01b0316905081565b85336001600160a01b03821614806104e05750604051638fcfa77560e01b81526001600160a01b037f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d571690638fcfa775906104a1903390600401612fc0565b602060405180830381865afa1580156104bc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e09190613299565b8061050b57506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b6105305760405162461bcd60e51b8152600401610527906132b4565b60405180910390fd5b7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561058c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105b09190613299565b156105f35760405162461bcd60e51b815260206004820152601360248201527211195c1bdcda5d1cc8185c99481c185d5cd959606a1b6044820152606401610527565b5f61063a6040518061012001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f6106448b611d7f565b60408701919091526020860191909152908452909350905061066589611e4c565b60608201879052806106925761067d8b8b8b8a611ebf565b826060015161068c91906132f7565b60608301525b61069f826060015161208a565b6106ac8260600151612102565b6080830181905282516106c0918a9161212d565b60a083015260808201516106d590899061215e565b60c083015280156106f2576106ed8260a00151612193565b610797565b61075f8260a001518c6001600160a01b031663794e57246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610736573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061075a919061330a565b612285565b5f61078a83602001518460400151855f01518c61077c9190613321565b6001876080015160016122fe565b905061079581612356565b505b608082015160c083015160405163513de6d560e11b81526001600160a01b038d81166004830152602482018c905260448201939093526064810191909152878216608482015286821660a4820152908c169063a27bcdaa9060c40160408051808303815f875af115801561080d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108319190613338565b610100840181905260e08401919091526040519081526001600160a01b038b811691908d16907f756999f76d314557edacbe03e4a4cd729c1f2e73b0406791914643afa7aa312e9060200160405180910390a36108996001600160a01b038416338d8b61244a565b60405163467fafdf60e11b81526001600160a01b037f0000000000000000000000000f26bbb8962d73bc891327f14db5162d5279899f1690638cff5fbe906108e79033908b9060040161335a565b6020604051808303815f875af1158015610903573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109279190613299565b50896001600160a01b03168b6001600160a01b03165f805160206134ec83398151915284608001518b8660e001515f6040516109669493929190613393565b60405180910390a35050505050505050505050565b7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109fb91906133b5565b6001600160a01b0316336001600160a01b031614610a485760405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b6044820152606401610527565b610a51816124aa565b50565b5f7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b031663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ab1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad591906133b5565b905090565b5f7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316635733d58f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b37573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5b919061330a565b909110919050565b5f610b6d82612102565b92915050565b5f805f610b7e611404565b9050610b89816124ba565b909590945092505050565b336001600160a01b037f0000000000000000000000004e8781e422a5e6fa1a422d6f6c6938111446f9061614610bf75760405162461bcd60e51b815260206004820152600860248201526721666163746f727960c01b6044820152606401610527565b6040805180820182526001600160a01b038381168083526003805461ffff90811660208087019182528986165f81815260028352898120985189549451909516600160a01b026001600160b01b03199094169490971693909317919091179095558154600181018355919093527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b031916831790558351918252918101919091527ff6e0528dc0c0ef50525339faff44940d57e7897bee18b67dd0aa23bba1749ad2910160405180910390a15050565b6001600160a01b038181165f90815260026020908152604091829020825180840190935254928316808352600160a01b90930461ffff16908201529015801590610d765750816001600160a01b0316639484fb8e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d769190613299565b8015610ddf5750816001600160a01b031663795d26c36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610db9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddd919061330a565b155b610e365760405162461bcd60e51b815260206004820152602260248201527f506f736974696f6e204d616e616765722063616e6e6f742062652072656d6f76604482015261195960f21b6064820152608401610527565b6001600160a01b0382165f90815260026020526040812080546001600160b01b0319169055600354610e6a906001906133d0565b905080826020015161ffff161015610f23575f60038281548110610e9057610e906133e3565b905f5260205f20015f9054906101000a90046001600160a01b03169050806003846020015161ffff1681548110610ec957610ec96133e3565b5f918252602080832090910180546001600160a01b039485166001600160a01b031990911617905585810151939092168152600290915260409020805461ffff909216600160a01b0261ffff60a01b199092169190911790555b6003805480610f3457610f346133f7565b5f8281526020902081015f1990810180546001600160a01b03191690550190556040517fbc0a65aee62a88547316ae28fe2969b4e94a57ccfd27cb2e0bd21109ec4b1c8e90610f84908590612fc0565b60405180910390a1505050565b5f7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ab1573d5f803e3d5ffd5b87336001600160a01b038216148061108c5750604051638fcfa77560e01b81526001600160a01b037f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d571690638fcfa7759061104d903390600401612fc0565b602060405180830381865afa158015611068573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061108c9190613299565b806110b757506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b6110d35760405162461bcd60e51b8152600401610527906132b4565b861580156110df575083155b8061116757507f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611141573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111659190613299565b155b6111835760405162461bcd60e51b81526004016105279061340b565b86158061118e575085155b6111f35760405162461bcd60e51b815260206004820152603060248201527f426f72726f7765724f7065726174696f6e733a2043616e6e6f7420776974686460448201526f1c985dc8185b99081859190818dbdb1b60821b6064820152608401610527565b6112048a8a8a8a8a8a8a8a8a612566565b50505050505050505050565b83336001600160a01b03821614806112ae5750604051638fcfa77560e01b81526001600160a01b037f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d571690638fcfa7759061126f903390600401612fc0565b602060405180830381865afa15801561128a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112ae9190613299565b806112d957506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b6112f55760405162461bcd60e51b8152600401610527906132b4565b61130686865f805f895f8a8a612566565b505050505050565b83336001600160a01b03821614806113ac5750604051638fcfa77560e01b81526001600160a01b037f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d571690638fcfa7759061136d903390600401612fc0565b602060405180830381865afa158015611388573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113ac9190613299565b806113d757506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b6113f35760405162461bcd60e51b8152600401610527906132b4565b61130686865f80885f808a8a612566565b61142860405180606001604052806060815260200160608152602001606081525090565b600354604080516060810190915280826001600160401b0381111561144f5761144f613442565b604051908082528060200260200182016040528015611478578160200160208202803683370190505b508152602001826001600160401b0381111561149657611496613442565b6040519080825280602002602001820160405280156114bf578160200160208202803683370190505b508152602001826001600160401b038111156114dd576114dd613442565b604051908082528060200260200182016040528015611506578160200160208202803683370190505b50905291505f5b81811015611626575f60038281548110611529576115296133e3565b905f5260205f20015f9054906101000a90046001600160a01b031690505f805f836001600160a01b03166301c799fc6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611585573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115a99190613456565b92509250925082875f015186815181106115c5576115c56133e3565b60200260200101818152505081876020015186815181106115e8576115e86133e3565b602002602001018181525050808760400151868151811061160b5761160b6133e3565b6020026020010181815250508460010194505050505061150d565b505090565b5f80611635611404565b9050611640816124ba565b50909392505050565b80336001600160a01b03821614806116e75750604051638fcfa77560e01b81526001600160a01b037f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d571690638fcfa775906116a8903390600401612fc0565b602060405180830381865afa1580156116c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116e79190613299565b8061171257506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b61172e5760405162461bcd60e51b8152600401610527906132b4565b5f805f805f61173c88611d7f565b939850919650919450909250905082156117ba5760405162461bcd60e51b815260206004820152603960248201527f426f72726f7765724f70733a204f7065726174696f6e206e6f74207065726d696044820152787474656420647572696e67205265636f76657279204d6f646560381b6064820152608401610527565b5f80896001600160a01b0316630b0765578a6040518263ffffffff1660e01b81526004016117e89190612fc0565b60408051808303815f875af1158015611803573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118279190613338565b90925090505f611844858561183c8a87613321565b5f865f6122fe565b905061184f81612356565b6040516310cf7e2360e11b81526001600160a01b038b8116600483015233602483015260448201859052606482018490528c169063219efc46906084015f604051808303815f87803b1580156118a3575f80fd5b505af11580156118b5573d5f803e3d5ffd5b50505050896001600160a01b03168b6001600160a01b03165f805160206134ec8339815191525f805f60016040516118f09493929190613393565b60405180910390a36001600160a01b037f0000000000000000000000000f26bbb8962d73bc891327f14db5162d5279899f166385177509336119527f0000000000000000000000000000000000000000000000000de0b6b3a7640000866133d0565b6040518363ffffffff1660e01b815260040161196f92919061335a565b6020604051808303815f875af115801561198b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119af9190613299565b505050505050505050505050565b84336001600160a01b0382161480611a5b5750604051638fcfa77560e01b81526001600160a01b037f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d571690638fcfa77590611a1c903390600401612fc0565b602060405180830381865afa158015611a37573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a5b9190613299565b80611a8657506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b611aa25760405162461bcd60e51b8152600401610527906132b4565b7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611afe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b229190613299565b15611b685760405162461bcd60e51b815260206004820152601660248201527515da5d1a191c985dd85b1cc8185c99481c185d5cd95960521b6044820152606401610527565b611b7a8787875f808960018a8a612566565b50505050505050565b335f818152602081815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f92d241afb0a1a9b3441bf1bd6bea0f9164cf5a2562cbe4bcc34ab943b2465608910160405180910390a35050565b83336001600160a01b0382161480611c8a5750604051638fcfa77560e01b81526001600160a01b037f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d571690638fcfa77590611c4b903390600401612fc0565b602060405180830381865afa158015611c66573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c8a9190613299565b80611cb557506001600160a01b0381165f9081526020818152604080832033845290915290205460ff165b611cd15760405162461bcd60e51b8152600401610527906132b4565b7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d519190613299565b15611d6e5760405162461bcd60e51b81526004016105279061340b565b61130686865f875f805f8a8a612566565b6001600160a01b038181165f90815260026020526040812080549283169282918291829190600160a01b900461ffff1686611df55760405162461bcd60e51b815260206004820152601660248201527510dbdb1b185d195c985b081b9bdd08195b98589b195960521b6044820152606401610527565b5f80611dff611404565b9050611e0a816124ba565b90985096509150611e1a82610ada565b94508881604001518481518110611e3357611e336133e3565b6020026020010151985098505050505091939590929450565b670de0b6b3a7640000811115610a515760405162461bcd60e51b815260206004820152603260248201527f4d6178206665652070657263656e74616765206d757374206c657373207468616044820152716e206f7220657175616c20746f203130302560701b6064820152608401610527565b60405163b2f29d7b60e01b8152600481018290525f9081906001600160a01b0387169063b2f29d7b906024016020604051808303815f875af1158015611f07573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f2b919061330a565b9050611f388184866129f9565b7f0000000000000000000000000f26bbb8962d73bc891327f14db5162d5279899f6001600160a01b03166340c10f197f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b031663b3f006746040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fc3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe791906133b5565b836040518363ffffffff1660e01b815260040161200592919061335a565b5f604051808303815f87803b15801561201c575f80fd5b505af115801561202e573d5f803e3d5ffd5b50505050846001600160a01b0316866001600160a01b03167fd89359f0d8e7f936d0682c5565cc5a16989a91560a80c7b06c46c28e52a5d43a8360405161207791815260200190565b60405180910390a390505b949350505050565b600154811015610a515760405162461bcd60e51b815260206004820152603d60248201527f426f72726f7765724f70733a20506f736974696f6e2773206e6574206465627460448201527f206d7573742062652067726561746572207468616e206d696e696d756d0000006064820152608401610527565b5f610b6d7f0000000000000000000000000000000000000000000000000de0b6b3a7640000836132f7565b5f8215612153575f836121408487613321565b61214a9190613481565b91506121579050565b505f195b9392505050565b5f811561218a578161217968056bc75e2d6310000085613321565b6121839190613481565b9050610b6d565b505f1992915050565b7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316635733d58f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ef573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612213919061330a565b811015610a515760405162461bcd60e51b815260206004820152603a60248201527f426f72726f7765724f70733a204f7065726174696f6e206d757374206c65617660448201527932903837b9b4ba34b7b7103bb4ba341024a1a9101f1e9021a1a960311b6064820152608401610527565b808210156122fa5760405162461bcd60e51b815260206004820152604960248201525f8051602061350c83398151915260448201527f6f756c6420726573756c7420696e20494352203c204d4352206973206e6f74206064820152681c195c9b5a5d1d195960ba1b608482015260a401610527565b5050565b5f816123135761230e83876133d0565b61231d565b61231d83876132f7565b9550836123335761232e85886133d0565b61233d565b61233d85886132f7565b96505f61234a8888612a76565b98975050505050505050565b7f000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d576001600160a01b0316635733d58f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123d6919061330a565b811015610a515760405162461bcd60e51b815260206004820152604960248201525f8051602061350c83398151915260448201527f6f756c6420726573756c7420696e20544352203c20434352206973206e6f74206064820152681c195c9b5a5d1d195960ba1b608482015260a401610527565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526124a4908590612a91565b50505050565b5f81116124b5575f80fd5b600155565b8051515f9081908190815b8181101561255157856040015181815181106124e3576124e36133e3565b6020026020010151865f01518281518110612500576125006133e3565b60200260200101516125129190613321565b61251c90856132f7565b935085602001518181518110612534576125346133e3565b60200260200101518361254791906132f7565b92506001016124c5565b5061255c8383612a76565b9350509193909250565b8515158061257357508415155b8061257d57508315155b6125fe5760405162461bcd60e51b815260206004820152604660248201527f426f72726f7765724f70733a205468657265206d75737420626520656974686560448201527f72206120636f6c6c61746572616c206368616e6765206f7220612064656274206064820152656368616e676560d01b608482015260a401610527565b5f61266e604051806101c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f151581526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81525090565b5f6126788c611d7f565b60408088019290925260208701929092529185529051630b07655760e01b815291945091506001600160a01b038d1690630b076557906126bc908e90600401612fc0565b60408051808303815f875af11580156126d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fb9190613338565b60c084015260e083015261270f8989612b67565b151560a084015260608301526080820187905261016082018790526001600160a01b03808c1661018084015260408051631e5395c960e21b81529051918e169163794e5724916004808201926020929091908290030181865afa158015612778573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061279c919061330a565b6101a08301528515612846575f87116128175760405162461bcd60e51b815260206004820152603760248201527f426f72726f7765724f70733a204465627420696e637265617365207265717569604482015276726573206e6f6e2d7a65726f20646562744368616e676560481b6064820152608401610527565b6128208a611e4c565b80612846576128318c8c8c8a611ebf565b8260800181815161284291906132f7565b9052505b61285c82602001518360400151838b8a87612b85565b8515801561286957505f87115b156128925761289282608001516128838460c00151612cae565b61288d91906133d0565b61208a565b8160a00151156128b95760608201516128b9906001600160a01b0385169033908f9061244a565b610160820151608083015160a0840151606085015161018086015160405163d23ab46160e01b81528b1515600482015260248101959095526044850193909352901515606484015260848301526001600160a01b0387811660a484015286811660c484015290811660e4830152336101048301528d169063d23ab46190610124016060604051808303815f875af1158015612956573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061297a9190613456565b8461012001856101000186610140018381525083815250838152505050508161018001516001600160a01b03168c6001600160a01b03165f805160206134ec83398151915284610100015185610120015186610140015160026040516129e39493929190613393565b60405180910390a3505050505050505050505050565b5f825f03612a07575f612a24565b82612a1a670de0b6b3a764000086613321565b612a249190613481565b9050818111156124a45760405162461bcd60e51b815260206004820152601d60248201527f4665652065786365656465642070726f7669646564206d6178696d756d0000006044820152606401610527565b5f811561218a575f612a888385613481565b9150610b6d9050565b5f612ae5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612cd99092919063ffffffff16565b805190915015612b625780806020019051810190612b039190613299565b612b625760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610527565b505050565b5f808315612b7a57508290506001612b7e565b8291505b9250929050565b5f612b9c8260e001518360c00151845f015161212d565b90505f612bc58360e001518460c0015185606001518660a00151876080015189895f0151612ce7565b90508515612c5f578415612c415760405162461bcd60e51b815260206004820152603e60248201527f426f72726f7765724f70733a20436f6c6c61746572616c20776974686472617760448201527f616c206e6f74207065726d6974746564205265636f76657279204d6f646500006064820152608401610527565b8315612c5a57612c5081612193565b612c5a8183612d17565b612ca4565b612c6e81846101a00151612285565b5f612c978989865f01518760600151612c879190613321565b8760a0015188608001518a6122fe565b9050612ca281612356565b505b5050505050505050565b5f610b6d7f0000000000000000000000000000000000000000000000000de0b6b3a7640000836133d0565b606061208284845f85612d97565b5f805f612cf88a8a8a8a8a8a612e6e565b915091505f612d0883838761212d565b9b9a5050505050505050505050565b808210156122fa5760405162461bcd60e51b815260206004820152604160248201527f426f72726f7765724f70733a2043616e6e6f7420646563726561736520796f7560448201527f7220506f736974696f6e27732049435220696e205265636f76657279204d6f646064820152606560f81b608482015260a401610527565b606082471015612df85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610527565b5f80866001600160a01b03168587604051612e1391906134a0565b5f6040518083038185875af1925050503d805f8114612e4d576040519150601f19603f3d011682016040523d82523d5f602084013e612e52565b606091505b5091509150612e6387838387612ec1565b979650505050505050565b5f80878786612e8657612e81888b6133d0565b612e90565b612e90888b6132f7565b915084612ea657612ea1868a6133d0565b612eb0565b612eb0868a6132f7565b919a91995090975050505050505050565b60608315612f2f5782515f03612f28576001600160a01b0385163b612f285760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610527565b5081612082565b6120828383815115612f445781518083602001fd5b8060405162461bcd60e51b815260040161052791906134b6565b6001600160a01b0381168114610a51575f80fd5b5f8060408385031215612f83575f80fd5b8235612f8e81612f5e565b91506020830135612f9e81612f5e565b809150509250929050565b5f60208284031215612fb9575f80fd5b5035919050565b6001600160a01b0391909116815260200190565b5f805f805f805f60e0888a031215612fea575f80fd5b8735612ff581612f5e565b9650602088013561300581612f5e565b955060408801359450606088013593506080880135925060a088013561302a81612f5e565b915060c088013561303a81612f5e565b8091505092959891949750929550565b5f6020828403121561305a575f80fd5b813561215781612f5e565b8015158114610a51575f80fd5b5f805f805f805f805f6101208a8c03121561308b575f80fd5b893561309681612f5e565b985060208a01356130a681612f5e565b975060408a0135965060608a0135955060808a0135945060a08a0135935060c08a01356130d281613065565b925060e08a01356130e281612f5e565b91506101008a01356130f381612f5e565b809150509295985092959850929598565b5f805f805f60a08688031215613118575f80fd5b853561312381612f5e565b9450602086013561313381612f5e565b935060408601359250606086013561314a81612f5e565b9150608086013561315a81612f5e565b809150509295509295909350565b5f8151808452602084019350602083015f5b8281101561319857815186526020958601959091019060010161317a565b5093949350505050565b602081525f8251606060208401526131bd6080840182613168565b90506020840151601f198483030160408501526131da8282613168565b9150506040840151601f198483030160608501526131f88282613168565b95945050505050565b5f805f805f8060c08789031215613216575f80fd5b863561322181612f5e565b9550602087013561323181612f5e565b94506040870135935060608701359250608087013561324f81612f5e565b915060a087013561325f81612f5e565b809150509295509295509295565b5f806040838503121561327e575f80fd5b823561328981612f5e565b91506020830135612f9e81613065565b5f602082840312156132a9575f80fd5b815161215781613065565b60208082526015908201527411195b1959d85d19481b9bdd08185c1c1c9bdd9959605a1b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610b6d57610b6d6132e3565b5f6020828403121561331a575f80fd5b5051919050565b8082028115828204841417610b6d57610b6d6132e3565b5f8060408385031215613349575f80fd5b505080516020909101519092909150565b6001600160a01b03929092168252602082015260400190565b6003811061338f57634e487b7160e01b5f52602160045260245ffd5b9052565b8481526020810184905260408101839052608081016131f86060830184613373565b5f602082840312156133c5575f80fd5b815161215781612f5e565b81810381811115610b6d57610b6d6132e3565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b6020808252601f908201527f506f736974696f6e2061646a7573746d656e7473206172652070617573656400604082015260600190565b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215613468575f80fd5b5050815160208301516040909301519094929350919050565b5f8261349b57634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fea324e5da70af90221ccc670b176f09261ae0fcc1cb5b7c9c2f1e890bad70bb88426f72726f7765724f70733a20416e206f7065726174696f6e20746861742077a2646970667358221220308e5167aeb6be2e1a7a135502ef54fcb91d9914b7d43828813c007187fae5e064736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d570000000000000000000000000f26bbb8962d73bc891327f14db5162d5279899f0000000000000000000000004e8781e422a5e6fa1a422d6f6c6938111446f9060000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000000000de0b6b3a7640000
-----Decoded View---------------
Arg [0] : _core (address): 0xF6ec524105548C37D3C2eB482BA197AE19740d57
Arg [1] : _debtTokenAddress (address): 0x0F26bBb8962d73bC891327F14dB5162D5279899F
Arg [2] : _factory (address): 0x4E8781E422a5E6fA1a422D6F6C6938111446F906
Arg [3] : _minNetDebt (uint256): 100000000000000000000
Arg [4] : _gasCompensation (uint256): 1000000000000000000
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000f6ec524105548c37d3c2eb482ba197ae19740d57
Arg [1] : 0000000000000000000000000f26bbb8962d73bc891327f14db5162d5279899f
Arg [2] : 0000000000000000000000004e8781e422a5e6fa1a422d6f6c6938111446f906
Arg [3] : 0000000000000000000000000000000000000000000000056bc75e2d63100000
Arg [4] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.