Source Code
Latest 25 from a total of 465 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Execute | 16087703 | 108 days ago | IN | 0 HYPE | 0.00004197 | ||||
| Execute | 16073002 | 108 days ago | IN | 0 HYPE | 0.00004862 | ||||
| Execute | 16058301 | 108 days ago | IN | 0 HYPE | 0.00003921 | ||||
| Execute | 16043600 | 108 days ago | IN | 0 HYPE | 0.00004578 | ||||
| Execute | 16028899 | 108 days ago | IN | 0 HYPE | 0.00004639 | ||||
| Execute | 16014198 | 109 days ago | IN | 0 HYPE | 0.00008793 | ||||
| Execute | 15999497 | 109 days ago | IN | 0 HYPE | 0.00014445 | ||||
| Execute | 15984796 | 109 days ago | IN | 0 HYPE | 0.00008436 | ||||
| Execute | 15970095 | 109 days ago | IN | 0 HYPE | 0.00004578 | ||||
| Execute | 15955394 | 109 days ago | IN | 0 HYPE | 0.0000706 | ||||
| Execute | 15940693 | 109 days ago | IN | 0 HYPE | 0.00032122 | ||||
| Execute | 15925992 | 110 days ago | IN | 0 HYPE | 0.00004768 | ||||
| Execute | 15911291 | 110 days ago | IN | 0 HYPE | 0.00011593 | ||||
| Execute | 15896590 | 110 days ago | IN | 0 HYPE | 0.00006295 | ||||
| Execute | 15881889 | 110 days ago | IN | 0 HYPE | 0.00019078 | ||||
| Execute | 15867188 | 110 days ago | IN | 0 HYPE | 0.00008657 | ||||
| Execute | 15852487 | 110 days ago | IN | 0 HYPE | 0.00004578 | ||||
| Execute | 15837786 | 111 days ago | IN | 0 HYPE | 0.00008118 | ||||
| Execute | 15823085 | 111 days ago | IN | 0 HYPE | 0.00004578 | ||||
| Execute | 15808384 | 111 days ago | IN | 0 HYPE | 0.00005427 | ||||
| Execute | 15793683 | 111 days ago | IN | 0 HYPE | 0.00005587 | ||||
| Execute | 15778982 | 111 days ago | IN | 0 HYPE | 0.00007631 | ||||
| Execute | 15764281 | 111 days ago | IN | 0 HYPE | 0.00005645 | ||||
| Execute | 15749580 | 112 days ago | IN | 0 HYPE | 0.00006115 | ||||
| Execute | 15734879 | 112 days ago | IN | 0 HYPE | 0.00022266 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 9268733 | 185 days ago | 0.1 HYPE |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
UsdxlInterestRateController
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {ReentrancyGuard} from '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {IPool} from '@aave/core-v3/contracts/interfaces/IPool.sol';
import {IPoolConfigurator} from '@aave/core-v3/contracts/interfaces/IPoolConfigurator.sol';
import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol';
import {DataTypes} from '@aave/core-v3/contracts/protocol/libraries/types/DataTypes.sol';
import {IUsdxlToken} from '../../../usdxl/interfaces/IUsdxlToken.sol';
import {UsdxlMutableInterestRateStrategy} from './UsdxlMutableInterestRateStrategy.sol';
import {IWrappedHypeGateway} from '@hypurrfi/periphery/contracts/misc/interfaces/IWrappedHypeGateway.sol';
import {IAToken} from '@aave/core-v3/contracts/interfaces/IAToken.sol';
/**
* @title UsdxlInterestRateController
* @author Last Labs
* @notice Controller for USDXL interest rates based on price deviation from peg
* @dev Runs 3 times per day, maintains perpetual loan to ensure rate updates,
* adjusts rates based on USDXL price relative to $1 peg
*/
contract UsdxlInterestRateController is UsdxlMutableInterestRateStrategy, ReentrancyGuard {
using SafeERC20 for IERC20;
// Configurable parameters (can be updated by owner)
uint256 public minRate = 0.085e27; // 8.5% minimum rate (in ray)
uint256 public maxRate = 0.50e27; // 50% maximum rate (in ray)
uint256 public rateIncreaseAdjustment = 0.002e27; // 0.2% increase tick (in ray)
uint256 public rateDecreaseAdjustment = 0.001e27; // 0.1% decrease tick (in ray)
uint256 public priceThreshold = 0.995e8; // 0.995 threshold for rate adjustments
uint256 public targetPrice = 1e8; // $1 target price (8 decimals)
uint256 public perpetualLoanAmount; // Perpetual loan amount (in USDXL)
uint256 public executionInterval; // Execution interval in seconds
address public usdxlOracle; // USDXL oracle address
// State variables
IUsdxlToken public immutable USDXL_TOKEN;
address public immutable USDXL_RESERVE;
IWrappedHypeGateway public immutable WRAPPED_HYPE_GATEWAY;
uint256 public lastExecutionTime;
uint256 public currentRate;
bool public perpetualLoanActive;
uint256 public perpetualLoanDebt;
// Executor whitelist
mapping(address => bool) public executors;
// Events
event RateUpdated(uint256 oldRate, uint256 newRate, uint256 usdxlPrice, uint256 timestamp);
event PerpetualLoanCreated(uint256 amount, uint256 timestamp);
event PerpetualLoanRefreshed(uint256 amount, uint256 timestamp);
event ExecutionSkipped(uint256 reason, uint256 timestamp);
event PriceDataEmitted(uint256 offchainPrice, uint256 onchainPrice, uint256 timestamp);
event PerpetualLoanAmountUpdated(uint256 oldAmount, uint256 newAmount, uint256 timestamp);
event ExecutionIntervalUpdated(uint256 oldInterval, uint256 newInterval, uint256 timestamp);
event UsdxlOracleUpdated(address oldOracle, address newOracle, uint256 timestamp);
event MaxRateUpdated(uint256 oldMaxRate, uint256 newMaxRate, uint256 timestamp);
event ExecutorUpdated(address executor, bool enabled, uint256 timestamp);
event ParametersUpdated(
uint256 minRate,
uint256 maxRate,
uint256 rateIncreaseAdjustment,
uint256 rateDecreaseAdjustment,
uint256 priceThreshold,
uint256 targetPrice,
uint256 timestamp
);
event HYPEReceived(address sender, uint256 amount);
event HYPEWithdrawn(address recipient, uint256 amount);
event HYPESupplied(uint256 amount, uint256 timestamp);
event HYPEWithdrawnFromPool(uint256 amount, address recipient, uint256 timestamp);
event LoanClosed(uint256 timestamp);
// Errors
error ExecutionTooEarly();
error InvalidOraclePrice();
error PerpetualLoanFailed();
error RateUpdateFailed();
error InvalidParameter();
error UnauthorizedExecutor();
// Modifiers
modifier onlyOwnerOrExecutor() {
require(msg.sender == owner() || executors[msg.sender], "Unauthorized executor");
_;
}
/**
* @dev Constructor
* @param addressesProvider The Aave V3 Pool Addresses Provider
* @param usdxlToken The USDXL token address
* @param usdxlOracleAddress The USDXL oracle address
* @param usdxlReserve The USDXL reserve address in the pool
* @param initialRate The initial interest rate (in ray)
* @param owner The owner address
* @param initialPerpetualLoanAmount The initial perpetual loan amount (in USDXL)
* @param wrappedHypeGateway The WrappedHypeGateway address
*/
constructor(
address addressesProvider,
address usdxlToken,
address usdxlOracleAddress,
address usdxlReserve,
uint256 initialRate,
address owner,
uint256 initialPerpetualLoanAmount,
address wrappedHypeGateway
) UsdxlMutableInterestRateStrategy(addressesProvider, initialRate, owner) payable {
require(usdxlToken != address(0), "Invalid USDXL token");
require(usdxlOracleAddress != address(0), "Invalid USDXL oracle");
require(usdxlReserve != address(0), "Invalid USDXL reserve");
require(wrappedHypeGateway != address(0), "Invalid WrappedHypeGateway");
require(initialRate >= minRate, "Rate below minimum");
require(initialRate <= maxRate, "Rate above maximum");
require(initialPerpetualLoanAmount > 0, "Invalid perpetual loan amount");
USDXL_TOKEN = IUsdxlToken(usdxlToken);
USDXL_RESERVE = usdxlReserve;
WRAPPED_HYPE_GATEWAY = IWrappedHypeGateway(wrappedHypeGateway);
currentRate = initialRate;
lastExecutionTime = block.timestamp;
perpetualLoanAmount = initialPerpetualLoanAmount;
executionInterval = 4 hours; // Default execution interval
usdxlOracle = usdxlOracleAddress;
// If HYPE is sent on deployment, supply it to the WrappedHypeGateway
if (msg.value > 0) {
WRAPPED_HYPE_GATEWAY.depositHYPE{value: msg.value}(
address(0),
address(this),
0
);
emit HYPESupplied(msg.value, block.timestamp);
}
}
/**
* @notice Update maximum rate only
* @param newMaxRate The new maximum rate (in ray)
* @dev Only callable by owner
*/
function updateMaxRate(uint256 newMaxRate) external onlyOwner {
require(newMaxRate > 0, "Max rate must be positive");
require(newMaxRate > minRate, "Max rate must exceed min rate");
if (currentRate > newMaxRate) {
currentRate = newMaxRate;
}
uint256 oldMaxRate = maxRate;
maxRate = newMaxRate;
emit MaxRateUpdated(oldMaxRate, newMaxRate, block.timestamp);
}
/**
* @notice Update configurable parameters
* @param newMinRate The new minimum rate (in ray)
* @param newMaxRate The new maximum rate (in ray)
* @param newRateIncreaseAdjustment The new rate increase tick (in ray)
* @param newRateDecreaseAdjustment The new rate decrease tick (in ray)
* @param newPriceThreshold The new price threshold (8 decimals)
* @param newTargetPrice The new target price (8 decimals)
* @dev Only callable by owner
*/
function updateParameters(
uint256 newMinRate,
uint256 newMaxRate,
uint256 newRateIncreaseAdjustment,
uint256 newRateDecreaseAdjustment,
uint256 newPriceThreshold,
uint256 newTargetPrice
) external onlyOwner {
// Validate parameters
require(newMinRate > 0, "Min rate must be positive");
require(newMaxRate > 0, "Max rate must be positive");
require(newMaxRate > newMinRate, "Max rate must exceed min rate");
require(newRateIncreaseAdjustment > 0, "Increase adjustment must be positive");
require(newRateDecreaseAdjustment > 0, "Decrease adjustment must be positive");
require(newPriceThreshold > 0, "Price threshold must be positive");
require(newTargetPrice > 0, "Target price must be positive");
require(newPriceThreshold <= newTargetPrice, "Threshold cannot exceed target");
// Ensure current rate doesn't go outside new bounds
if (currentRate < newMinRate) {
revert("Current rate below new minimum");
}
if (currentRate > newMaxRate) {
currentRate = newMaxRate;
}
// Update parameters
minRate = newMinRate;
maxRate = newMaxRate;
rateIncreaseAdjustment = newRateIncreaseAdjustment;
rateDecreaseAdjustment = newRateDecreaseAdjustment;
priceThreshold = newPriceThreshold;
targetPrice = newTargetPrice;
emit ParametersUpdated(
newMinRate,
newMaxRate,
newRateIncreaseAdjustment,
newRateDecreaseAdjustment,
newPriceThreshold,
newTargetPrice,
block.timestamp
);
}
/**
* @notice Update minimum rate only
* @param newMinRate The new minimum rate (in ray)
* @dev Only callable by owner
*/
function updateMinRate(uint256 newMinRate) external onlyOwner {
require(newMinRate > 0, "Min rate must be positive");
if (currentRate < newMinRate) {
revert("Current rate below new minimum");
}
minRate = newMinRate;
emit ParametersUpdated(
newMinRate,
maxRate,
rateIncreaseAdjustment,
rateDecreaseAdjustment,
priceThreshold,
targetPrice,
block.timestamp
);
}
/**
* @notice Update rate increase adjustment only
* @param newRateIncreaseAdjustment The new rate increase tick (in ray)
* @dev Only callable by owner
*/
function updateRateIncreaseAdjustment(uint256 newRateIncreaseAdjustment) external onlyOwner {
require(newRateIncreaseAdjustment > 0, "Increase adjustment must be positive");
rateIncreaseAdjustment = newRateIncreaseAdjustment;
emit ParametersUpdated(
minRate,
maxRate,
newRateIncreaseAdjustment,
rateDecreaseAdjustment,
priceThreshold,
targetPrice,
block.timestamp
);
}
/**
* @notice Update rate decrease adjustment only
* @param newRateDecreaseAdjustment The new rate decrease tick (in ray)
* @dev Only callable by owner
*/
function updateRateDecreaseAdjustment(uint256 newRateDecreaseAdjustment) external onlyOwner {
require(newRateDecreaseAdjustment > 0, "Decrease adjustment must be positive");
rateDecreaseAdjustment = newRateDecreaseAdjustment;
emit ParametersUpdated(
minRate,
maxRate,
rateIncreaseAdjustment,
newRateDecreaseAdjustment,
priceThreshold,
targetPrice,
block.timestamp
);
}
/**
* @notice Update price threshold only
* @param newPriceThreshold The new price threshold (8 decimals)
* @dev Only callable by owner
*/
function updatePriceThreshold(uint256 newPriceThreshold) external onlyOwner {
require(newPriceThreshold > 0, "Price threshold must be positive");
require(newPriceThreshold <= targetPrice, "Threshold cannot exceed target");
priceThreshold = newPriceThreshold;
emit ParametersUpdated(
minRate,
maxRate,
rateIncreaseAdjustment,
rateDecreaseAdjustment,
newPriceThreshold,
targetPrice,
block.timestamp
);
}
/**
* @notice Update target price only
* @param newTargetPrice The new target price (8 decimals)
* @dev Only callable by owner
*/
function updateTargetPrice(uint256 newTargetPrice) external onlyOwner {
require(newTargetPrice > 0, "Target price must be positive");
require(priceThreshold <= newTargetPrice, "Threshold cannot exceed target");
targetPrice = newTargetPrice;
emit ParametersUpdated(
minRate,
maxRate,
rateIncreaseAdjustment,
rateDecreaseAdjustment,
priceThreshold,
newTargetPrice,
block.timestamp
);
}
/**
* @notice Update perpetual loan amount
* @param newAmount The new perpetual loan amount (in USDXL)
* @dev Only callable by owner
*/
function updatePerpetualLoanAmount(uint256 newAmount) external onlyOwner {
require(newAmount > 0, "Invalid perpetual loan amount");
uint256 oldAmount = perpetualLoanAmount;
perpetualLoanAmount = newAmount;
emit PerpetualLoanAmountUpdated(oldAmount, newAmount, block.timestamp);
}
/**
* @notice Update execution interval
* @param newInterval The new execution interval in seconds
* @dev Only callable by owner
*/
function updateExecutionInterval(uint256 newInterval) external onlyOwner {
require(newInterval > 0, "Execution interval must be positive");
uint256 oldInterval = executionInterval;
executionInterval = newInterval;
emit ExecutionIntervalUpdated(oldInterval, newInterval, block.timestamp);
}
/**
* @notice Update USDXL oracle
* @param newOracle The new USDXL oracle address
* @dev Only callable by owner
*/
function updateUsdxlOracle(address newOracle) external onlyOwner {
require(newOracle != address(0), "Invalid USDXL oracle");
address oldOracle = usdxlOracle;
usdxlOracle = newOracle;
emit UsdxlOracleUpdated(oldOracle, newOracle, block.timestamp);
}
/**
* @notice Execute rate control logic
* @dev Can be called by anyone, but only executes if enough time has passed
* @param offchainPrice Optional offchain-calculated USDXL price (8 decimals)
*/
function execute(int256 offchainPrice) external nonReentrant onlyOwnerOrExecutor {
// Check if enough time has passed since last execution
if (block.timestamp < lastExecutionTime + executionInterval) {
emit ExecutionSkipped(1, block.timestamp); // Reason 1: Too early
return;
}
// If offchainPrice is provided but zero, revert
if (offchainPrice <= 0) {
revert("Offchain price is zero");
}
// Get current USDXL price (onchain)
uint256 onchainPrice = _getUsdxlPrice();
// Use offchain price if provided and valid, otherwise use onchain price
uint256 usdxlPrice = uint256(offchainPrice);
if (usdxlPrice == 0) {
emit ExecutionSkipped(2, block.timestamp); // Reason 2: Invalid price
return;
}
// Emit price data for transparency
emit PriceDataEmitted(uint256(offchainPrice), onchainPrice, block.timestamp);
// Maintain perpetual loan to ensure rate updates
_maintainPerpetualLoan();
// Calculate new rate based on price
uint256 newRate = _calculateNewRate(usdxlPrice);
// Update rate if it has changed
if (newRate != currentRate) {
_updateInterestRate(newRate);
emit RateUpdated(currentRate, newRate, usdxlPrice, block.timestamp);
currentRate = newRate;
}
lastExecutionTime = block.timestamp;
}
/**
* @notice Emergency function to update rate manually
* @param newRate The new interest rate (in ray)
* @dev Only callable by owner
*/
function emergencyUpdateRate(uint256 newRate) external onlyOwner {
require(newRate >= minRate, "Rate below minimum");
require(newRate <= maxRate, "Rate above maximum");
_updateInterestRate(newRate);
currentRate = newRate;
emit RateUpdated(currentRate, newRate, 0, block.timestamp);
}
/**
* @notice Withdraw any accumulated USDXL from the controller
* @param amount The amount to withdraw
* @param to The recipient address
* @dev Only callable by owner
*/
function withdrawUsdxl(uint256 amount, address to) external onlyOwner {
require(to != address(0), "Invalid recipient");
require(amount > 0, "Invalid amount");
require(USDXL_TOKEN.balanceOf(address(this)) >= amount, "Insufficient balance");
USDXL_TOKEN.transfer(to, amount);
}
/**
* @notice Get current USDXL price from oracle
* @return The USDXL price in USD (8 decimals)
*/
function getUsdxlPrice() external view returns (uint256) {
return _getUsdxlPrice();
}
/**
* @notice Get the next execution time
* @return The timestamp when execute() can be called next
*/
function getNextExecutionTime() external view returns (uint256) {
return lastExecutionTime + executionInterval;
}
/**
* @notice Check if execution is due
* @return True if enough time has passed since last execution
*/
function isExecutionDue() external view returns (bool) {
return block.timestamp >= lastExecutionTime + executionInterval;
}
/**
* @notice Get all current parameters
* @return minRate_ The current minimum rate
* @return maxRate_ The current maximum rate
* @return rateIncreaseAdjustment_ The current rate increase tick
* @return rateDecreaseAdjustment_ The current rate decrease tick
* @return priceThreshold_ The current price threshold
* @return targetPrice_ The current target price
*/
function getParameters() external view returns (
uint256 minRate_,
uint256 maxRate_,
uint256 rateIncreaseAdjustment_,
uint256 rateDecreaseAdjustment_,
uint256 priceThreshold_,
uint256 targetPrice_
) {
return (minRate, maxRate, rateIncreaseAdjustment, rateDecreaseAdjustment, priceThreshold, targetPrice);
}
/**
* @dev Get USDXL price from oracle
* @return The USDXL price in USD (8 decimals)
*/
function _getUsdxlPrice() internal view returns (uint256) {
try this._callOracle() returns (int256 price) {
if (price <= 0) return 0;
return uint256(price);
} catch {
return 0;
}
}
/**
* @dev External function to call oracle (needed for try/catch)
* @return The USDXL price from oracle
*/
function _callOracle() external view returns (int256) {
// Call the oracle's latestAnswer function
(bool success, bytes memory data) = usdxlOracle.staticcall(
abi.encodeWithSignature("latestAnswer()")
);
if (!success || data.length == 0) {
return 0;
}
return abi.decode(data, (int256));
}
/**
* @dev Calculate new interest rate based on USDXL price
* @param usdxlPrice The current USDXL price
* @return The new interest rate (in ray)
*/
function _calculateNewRate(uint256 usdxlPrice) internal view returns (uint256) {
uint256 newRate = currentRate;
if (usdxlPrice < priceThreshold) {
// USDXL price below threshold, increase rate
newRate = currentRate + rateIncreaseAdjustment;
if (newRate > maxRate) {
newRate = maxRate;
}
} else if (usdxlPrice >= priceThreshold && currentRate > minRate) {
// USDXL price at or above threshold and current rate above minimum, decrease rate
newRate = currentRate > rateDecreaseAdjustment ? currentRate - rateDecreaseAdjustment : minRate;
if (newRate < minRate) {
newRate = minRate;
}
}
return newRate;
}
/**
* @dev Update the interest rate strategy with new rate
* @param newRate The new interest rate (in ray)
*/
function _updateInterestRate(uint256 newRate) internal {
// Update the rate directly in the inherited interest rate strategy
_baseVariableBorrowRate = newRate;
}
/**
* @dev Maintain perpetual loan to ensure rate updates
* Creates or refreshes a perpetual loan to keep the rate mechanism active
*/
function _maintainPerpetualLoan() internal {
IPool pool = IPool(ADDRESSES_PROVIDER.getPool());
if (!perpetualLoanActive) {
// Create initial perpetual loan
try pool.borrow(
USDXL_RESERVE,
perpetualLoanAmount,
2, // Variable rate mode
0, // Referral code
address(this)
) {
perpetualLoanActive = true;
perpetualLoanDebt = perpetualLoanAmount;
emit PerpetualLoanCreated(perpetualLoanAmount, block.timestamp);
} catch {
// If borrow fails, try with smaller amount
uint256 smallerAmount = perpetualLoanAmount / 10;
try pool.borrow(
USDXL_RESERVE,
smallerAmount,
2, // Variable rate mode
0, // Referral code
address(this)
) {
perpetualLoanActive = true;
perpetualLoanDebt = smallerAmount;
emit PerpetualLoanCreated(smallerAmount, block.timestamp);
} catch {
// If still fails, skip this execution
emit ExecutionSkipped(3, block.timestamp); // Reason 3: Borrow failed
return;
}
}
} else {
// Refresh perpetual loan by repaying and reborrowing
uint256 currentDebt = _getCurrentDebt();
if (currentDebt > 0) {
// Repay current debt
USDXL_TOKEN.approve(address(pool), currentDebt);
try pool.repay(
USDXL_RESERVE,
currentDebt,
2, // Variable rate mode
address(this)
) {
// Reborrow the same amount
try pool.borrow(
USDXL_RESERVE,
currentDebt,
2, // Variable rate mode
0, // Referral code
address(this)
) {
emit PerpetualLoanRefreshed(currentDebt, block.timestamp);
} catch {
// If reborrow fails, try with smaller amount
uint256 smallerAmount = currentDebt / 2;
try pool.borrow(
USDXL_RESERVE,
smallerAmount,
2, // Variable rate mode
0, // Referral code
address(this)
) {
perpetualLoanDebt = smallerAmount;
emit PerpetualLoanRefreshed(smallerAmount, block.timestamp);
} catch {
emit ExecutionSkipped(4, block.timestamp); // Reason 4: Reborrow failed
}
}
} catch {
emit ExecutionSkipped(5, block.timestamp); // Reason 5: Repay failed
}
}
}
}
/**
* @dev Get current debt amount for this contract
* @return The current debt amount
*/
function _getCurrentDebt() internal view returns (uint256) {
IPool pool = IPool(ADDRESSES_PROVIDER.getPool());
DataTypes.ReserveData memory reserveData = pool.getReserveData(USDXL_RESERVE);
// Get variable debt token
address variableDebtToken = reserveData.variableDebtTokenAddress;
if (variableDebtToken == address(0)) return 0;
return IERC20(variableDebtToken).balanceOf(address(this));
}
/**
* @notice Get current perpetual loan status
* @return active Whether the perpetual loan is active
* @return debt The current debt amount
*/
function getPerpetualLoanStatus() external view returns (bool active, uint256 debt) {
return (perpetualLoanActive, _getCurrentDebt());
}
/**
* @notice Emergency function to repay all debt and deactivate perpetual loan
* @dev Only callable by owner
*/
function emergencyRepayAll() external onlyOwner {
uint256 currentDebt = _getCurrentDebt();
if (currentDebt > 0) {
IPool pool = IPool(ADDRESSES_PROVIDER.getPool());
USDXL_TOKEN.approve(address(pool), currentDebt);
try pool.repay(
USDXL_RESERVE,
currentDebt,
2, // Variable rate mode
address(this)
) {
perpetualLoanActive = false;
perpetualLoanDebt = 0;
} catch {
revert("Repay failed");
}
} else {
}
}
/**
* @notice Get the current interest rate from the strategy
* @return The current interest rate (in ray)
*/
function getCurrentInterestRate() external view returns (uint256) {
return _baseVariableBorrowRate;
}
/**
* @notice Withdraw supplied HYPE from the lending pool
* @param amount The amount of aWHYPE to withdraw (use type(uint256).max for all)
* @param to The recipient address for the HYPE
* @dev Only callable by owner
*/
function withdrawSuppliedHYPE(uint256 amount, address payable to) external onlyOwner nonReentrant {
_withdrawSuppliedHYPE(amount, to);
}
function _withdrawSuppliedHYPE(uint256 amount, address payable to) internal {
require(to != address(0), "Invalid recipient");
require(amount > 0, "Invalid amount");
// Get the aWHYPE token address
IPool pool = IPool(ADDRESSES_PROVIDER.getPool());
address whypeAddress = WRAPPED_HYPE_GATEWAY.getWHYPEAddress();
DataTypes.ReserveData memory reserveData = pool.getReserveData(whypeAddress);
address aWhypeAddress = reserveData.aTokenAddress;
require(aWhypeAddress != address(0), "aWHYPE token not found");
IAToken aWhype = IAToken(aWhypeAddress);
uint256 balance = aWhype.balanceOf(address(this));
require(balance > 0, "No supplied HYPE to withdraw");
uint256 amountToWithdraw = amount;
if (amount == type(uint256).max) {
amountToWithdraw = balance;
} else {
require(amount <= balance, "Insufficient aWHYPE balance");
}
aWhype.approve(address(WRAPPED_HYPE_GATEWAY), amountToWithdraw);
WRAPPED_HYPE_GATEWAY.withdrawHYPE(address(0), amountToWithdraw, to);
emit HYPEWithdrawnFromPool(amountToWithdraw, to, block.timestamp);
}
/**
* @notice Close the perpetual loan and withdraw all supplied HYPE
* @param to The recipient address for the withdrawn HYPE
* @dev Only callable by owner
*/
function closeLoanAndWithdrawAll(address payable to) external onlyOwner nonReentrant {
require(to != address(0), "Invalid recipient");
// First, repay all debt if there is any
uint256 currentDebt = _getCurrentDebt();
if (currentDebt > 0) {
IPool pool = IPool(ADDRESSES_PROVIDER.getPool());
USDXL_TOKEN.approve(address(pool), currentDebt);
try pool.repay(
USDXL_RESERVE,
currentDebt,
2, // Variable rate mode
address(this)
) {
perpetualLoanActive = false;
perpetualLoanDebt = 0;
} catch {
revert("Failed to repay debt");
}
} else {
perpetualLoanActive = false;
perpetualLoanDebt = 0;
}
// Withdraw all supplied HYPE
_withdrawSuppliedHYPE(type(uint256).max, to);
emit LoanClosed(block.timestamp);
}
/**
* @notice Get the current supplied HYPE balance
* @return The current aWHYPE balance
*/
function getSuppliedHYPEBalance() external view returns (uint256) {
IPool pool = IPool(ADDRESSES_PROVIDER.getPool());
address whypeAddress = WRAPPED_HYPE_GATEWAY.getWHYPEAddress();
DataTypes.ReserveData memory reserveData = pool.getReserveData(whypeAddress);
address aWhypeAddress = reserveData.aTokenAddress;
if (aWhypeAddress == address(0)) {
return 0;
}
IAToken aWhype = IAToken(aWhypeAddress);
return aWhype.balanceOf(address(this));
}
/**
* @notice Withdraw HYPE from the controller
* @param amount The amount to withdraw
* @param to The recipient address
* @dev Only callable by owner
*/
function withdrawHYPE(uint256 amount, address payable to) external onlyOwner {
require(to != address(0), "Invalid recipient");
require(amount > 0, "Invalid amount");
require(address(this).balance >= amount, "Insufficient HYPE balance");
(bool success, ) = to.call{value: amount}("");
require(success, "HYPE transfer failed");
emit HYPEWithdrawn(to, amount);
}
/**
* @dev Fallback function to receive HYPE
*/
receive() external payable {
emit HYPEReceived(msg.sender, msg.value);
}
/**
* @notice Add or remove an executor from the whitelist
* @param executor The address to add/remove
* @param enabled True to add, false to remove
* @dev Only callable by owner
*/
function updateExecutor(address executor, bool enabled) external onlyOwner {
require(executor != address(0), "Invalid executor address");
executors[executor] = enabled;
emit ExecutorUpdated(executor, enabled, block.timestamp);
}
/**
* @notice Batch update multiple executors
* @param executors_ Array of executor addresses
* @param enabled Array of boolean values (true to add, false to remove)
* @dev Only callable by owner
*/
function batchUpdateExecutors(address[] calldata executors_, bool[] calldata enabled) external onlyOwner {
require(executors_.length == enabled.length, "Arrays length mismatch");
require(executors_.length > 0, "Empty arrays");
for (uint256 i = 0; i < executors_.length; i++) {
require(executors_[i] != address(0), "Invalid executor address");
executors[executors_[i]] = enabled[i];
emit ExecutorUpdated(executors_[i], enabled[i], block.timestamp);
}
}
/**
* @notice Check if an address is an authorized executor
* @param executor The address to check
* @return True if the address is owner or whitelisted executor
*/
function isAuthorizedExecutor(address executor) external view returns (bool) {
return executor == owner() || executors[executor];
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// 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
// 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: AGPL-3.0
pragma solidity ^0.8.0;
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title IPool
* @author Aave
* @notice Defines the basic interface for an Aave Pool.
*/
interface IPool {
/**
* @dev Emitted on mintUnbacked()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the supply
* @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens
* @param amount The amount of supplied assets
* @param referralCode The referral code used
*/
event MintUnbacked(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referralCode
);
/**
* @dev Emitted on backUnbacked()
* @param reserve The address of the underlying asset of the reserve
* @param backer The address paying for the backing
* @param amount The amount added as backing
* @param fee The amount paid in fees
*/
event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee);
/**
* @dev Emitted on supply()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the supply
* @param onBehalfOf The beneficiary of the supply, receiving the aTokens
* @param amount The amount supplied
* @param referralCode The referral code used
*/
event Supply(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referralCode
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlying asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to The address that will receive the underlying
* @param amount The amount to be withdrawn
*/
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
/**
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param interestRateMode The rate mode: 1 for Stable, 2 for Variable
* @param borrowRate The numeric rate at which the user has borrowed, expressed in ray
* @param referralCode The referral code used
*/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
DataTypes.InterestRateMode interestRateMode,
uint256 borrowRate,
uint16 indexed referralCode
);
/**
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
* @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly
*/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount,
bool useATokens
);
/**
* @dev Emitted on swapBorrowRateMode()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user swapping his rate mode
* @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable
*/
event SwapBorrowRateMode(
address indexed reserve,
address indexed user,
DataTypes.InterestRateMode interestRateMode
);
/**
* @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets
* @param asset The address of the underlying asset of the reserve
* @param totalDebt The total isolation mode debt for the reserve
*/
event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt);
/**
* @dev Emitted when the user selects a certain asset category for eMode
* @param user The address of the user
* @param categoryId The category id
*/
event UserEModeSet(address indexed user, uint8 categoryId);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
*/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
*/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on rebalanceStableBorrowRate()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user for which the rebalance has been executed
*/
event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
/**
* @dev Emitted on flashLoan()
* @param target The address of the flash loan receiver contract
* @param initiator The address initiating the flash loan
* @param asset The address of the asset being flash borrowed
* @param amount The amount flash borrowed
* @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt
* @param premium The fee flash borrowed
* @param referralCode The referral code used
*/
event FlashLoan(
address indexed target,
address initiator,
address indexed asset,
uint256 amount,
DataTypes.InterestRateMode interestRateMode,
uint256 premium,
uint16 indexed referralCode
);
/**
* @dev Emitted when a borrower is liquidated.
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param liquidatedCollateralAmount The amount of collateral received by the liquidator
* @param liquidator The address of the liquidator
* @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
*/
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev Emitted when the state of a reserve is updated.
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The next liquidity rate
* @param stableBorrowRate The next stable borrow rate
* @param variableBorrowRate The next variable borrow rate
* @param liquidityIndex The next liquidity index
* @param variableBorrowIndex The next variable borrow index
*/
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
/**
* @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.
* @param reserve The address of the reserve
* @param amountMinted The amount minted to the treasury
*/
event MintedToTreasury(address indexed reserve, uint256 amountMinted);
/**
* @notice Mints an `amount` of aTokens to the `onBehalfOf`
* @param asset The address of the underlying asset to mint
* @param amount The amount to mint
* @param onBehalfOf The address that will receive the aTokens
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function mintUnbacked(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @notice Back the current unbacked underlying with `amount` and pay `fee`.
* @param asset The address of the underlying asset to back
* @param amount The amount to back
* @param fee The amount paid in fees
* @return The backed amount
*/
function backUnbacked(address asset, uint256 amount, uint256 fee) external returns (uint256);
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
/**
* @notice Supply with transfer approval of asset to be supplied done via permit function
* see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param deadline The deadline timestamp that the permit is valid
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
*/
function supplyWithPermit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external;
/**
* @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to The address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
*/
function withdraw(address asset, uint256 amount, address to) external returns (uint256);
/**
* @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already supplied enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
*/
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
address onBehalfOf
) external;
/**
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @return The final amount repaid
*/
function repay(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf
) external returns (uint256);
/**
* @notice Repay with transfer approval of asset to be repaid done via permit function
* see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @param deadline The deadline timestamp that the permit is valid
* @param permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
* @return The final amount repaid
*/
function repayWithPermit(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external returns (uint256);
/**
* @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the
* equivalent debt tokens
* - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens
* @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken
* balance is not enough to cover the whole debt
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @return The final amount repaid
*/
function repayWithATokens(
address asset,
uint256 amount,
uint256 interestRateMode
) external returns (uint256);
/**
* @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa
* @param asset The address of the underlying asset borrowed
* @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable
*/
function swapBorrowRateMode(address asset, uint256 interestRateMode) external;
/**
* @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
* - Users can be rebalanced if the following conditions are satisfied:
* 1. Usage ratio is above 95%
* 2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too
* much has been borrowed at a stable rate and suppliers are not earning enough
* @param asset The address of the underlying asset borrowed
* @param user The address of the user to be rebalanced
*/
function rebalanceStableBorrowRate(address asset, address user) external;
/**
* @notice Allows suppliers to enable/disable a specific supplied asset as collateral
* @param asset The address of the underlying asset supplied
* @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise
*/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
*/
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover,
bool receiveAToken
) external;
/**
* @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
* into consideration. For further details please visit https://docs.aave.com/developers/
* @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts of the assets being flash-borrowed
* @param interestRateModes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function flashLoan(
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata interestRateModes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/**
* @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
* into consideration. For further details please visit https://docs.aave.com/developers/
* @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface
* @param asset The address of the asset being flash-borrowed
* @param amount The amount of the asset being flash-borrowed
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function flashLoanSimple(
address receiverAddress,
address asset,
uint256 amount,
bytes calldata params,
uint16 referralCode
) external;
/**
* @notice Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralBase The total collateral of the user in the base currency used by the price feed
* @return totalDebtBase The total debt of the user in the base currency used by the price feed
* @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed
* @return currentLiquidationThreshold The liquidation threshold of the user
* @return ltv The loan to value of The user
* @return healthFactor The current health factor of the user
*/
function getUserAccountData(
address user
)
external
view
returns (
uint256 totalCollateralBase,
uint256 totalDebtBase,
uint256 availableBorrowsBase,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
/**
* @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an
* interest rate strategy
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param aTokenAddress The address of the aToken that will be assigned to the reserve
* @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve
* @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve
* @param interestRateStrategyAddress The address of the interest rate strategy contract
*/
function initReserve(
address asset,
address aTokenAddress,
address stableDebtAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
/**
* @notice Drop a reserve
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
*/
function dropReserve(address asset) external;
/**
* @notice Updates the address of the interest rate strategy contract
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param rateStrategyAddress The address of the interest rate strategy contract
*/
function setReserveInterestRateStrategyAddress(
address asset,
address rateStrategyAddress
) external;
/**
* @notice Sets the configuration bitmap of the reserve as a whole
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param configuration The new configuration bitmap
*/
function setConfiguration(
address asset,
DataTypes.ReserveConfigurationMap calldata configuration
) external;
/**
* @notice Returns the configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The configuration of the reserve
*/
function getConfiguration(
address asset
) external view returns (DataTypes.ReserveConfigurationMap memory);
/**
* @notice Returns the configuration of the user across all the reserves
* @param user The user address
* @return The configuration of the user
*/
function getUserConfiguration(
address user
) external view returns (DataTypes.UserConfigurationMap memory);
/**
* @notice Returns the normalized income of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset) external view returns (uint256);
/**
* @notice Returns the normalized variable debt per unit of asset
* @dev WARNING: This function is intended to be used primarily by the protocol itself to get a
* "dynamic" variable index based on time, current stored index and virtual rate at the current
* moment (approx. a borrower would get if opening a position). This means that is always used in
* combination with variable debt supply/balances.
* If using this function externally, consider that is possible to have an increasing normalized
* variable debt that is not equivalent to how the variable debt index would be updated in storage
* (e.g. only updates with non-zero variable debt supply)
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
/**
* @notice Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state and configuration data of the reserve
*/
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
/**
* @notice Validates and finalizes an aToken transfer
* @dev Only callable by the overlying aToken of the `asset`
* @param asset The address of the underlying asset of the aToken
* @param from The user from which the aTokens are transferred
* @param to The user receiving the aTokens
* @param amount The amount being transferred/withdrawn
* @param balanceFromBefore The aToken balance of the `from` user before the transfer
* @param balanceToBefore The aToken balance of the `to` user before the transfer
*/
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromBefore,
uint256 balanceToBefore
) external;
/**
* @notice Returns the list of the underlying assets of all the initialized reserves
* @dev It does not include dropped reserves
* @return The addresses of the underlying assets of the initialized reserves
*/
function getReservesList() external view returns (address[] memory);
/**
* @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct
* @param id The id of the reserve as stored in the DataTypes.ReserveData struct
* @return The address of the reserve associated with id
*/
function getReserveAddressById(uint16 id) external view returns (address);
/**
* @notice Returns the PoolAddressesProvider connected to this contract
* @return The address of the PoolAddressesProvider
*/
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Updates the protocol fee on the bridging
* @param bridgeProtocolFee The part of the premium sent to the protocol treasury
*/
function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external;
/**
* @notice Updates flash loan premiums. Flash loan premium consists of two parts:
* - A part is sent to aToken holders as extra, one time accumulated interest
* - A part is collected by the protocol treasury
* @dev The total premium is calculated on the total borrowed amount
* @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal`
* @dev Only callable by the PoolConfigurator contract
* @param flashLoanPremiumTotal The total premium, expressed in bps
* @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps
*/
function updateFlashloanPremiums(
uint128 flashLoanPremiumTotal,
uint128 flashLoanPremiumToProtocol
) external;
/**
* @notice Configures a new category for the eMode.
* @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.
* The category 0 is reserved as it's the default for volatile assets
* @param id The id of the category
* @param config The configuration of the category
*/
function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory config) external;
/**
* @notice Returns the data of an eMode category
* @param id The id of the category
* @return The configuration data of the category
*/
function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory);
/**
* @notice Allows a user to use the protocol in eMode
* @param categoryId The id of the category
*/
function setUserEMode(uint8 categoryId) external;
/**
* @notice Returns the eMode the user is using
* @param user The address of the user
* @return The eMode id
*/
function getUserEMode(address user) external view returns (uint256);
/**
* @notice Resets the isolation mode total debt of the given asset to zero
* @dev It requires the given asset has zero debt ceiling
* @param asset The address of the underlying asset to reset the isolationModeTotalDebt
*/
function resetIsolationModeTotalDebt(address asset) external;
/**
* @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate
* @return The percentage of available liquidity to borrow, expressed in bps
*/
function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256);
/**
* @notice Returns the total fee on flash loans
* @return The total fee on flashloans
*/
function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);
/**
* @notice Returns the part of the bridge fees sent to protocol
* @return The bridge fee sent to the protocol treasury
*/
function BRIDGE_PROTOCOL_FEE() external view returns (uint256);
/**
* @notice Returns the part of the flashloan fees sent to protocol
* @return The flashloan fee sent to the protocol treasury
*/
function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128);
/**
* @notice Returns the maximum number of reserves supported to be listed in this Pool
* @return The maximum number of reserves supported
*/
function MAX_NUMBER_RESERVES() external view returns (uint16);
/**
* @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens
* @param assets The list of reserves for which the minting needs to be executed
*/
function mintToTreasury(address[] calldata assets) external;
/**
* @notice Rescue and transfer tokens locked in this contract
* @param token The address of the token
* @param to The address of the recipient
* @param amount The amount of token to transfer
*/
function rescueTokens(address token, address to, uint256 amount) external;
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @dev Deprecated: Use the `supply` function instead
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {ConfiguratorInputTypes} from '../protocol/libraries/types/ConfiguratorInputTypes.sol';
/**
* @title IPoolConfigurator
* @author Aave
* @notice Defines the basic interface for a Pool configurator.
*/
interface IPoolConfigurator {
/**
* @dev Emitted when a reserve is initialized.
* @param asset The address of the underlying asset of the reserve
* @param aToken The address of the associated aToken contract
* @param stableDebtToken The address of the associated stable rate debt token
* @param variableDebtToken The address of the associated variable rate debt token
* @param interestRateStrategyAddress The address of the interest rate strategy for the reserve
*/
event ReserveInitialized(
address indexed asset,
address indexed aToken,
address stableDebtToken,
address variableDebtToken,
address interestRateStrategyAddress
);
/**
* @dev Emitted when borrowing is enabled or disabled on a reserve.
* @param asset The address of the underlying asset of the reserve
* @param enabled True if borrowing is enabled, false otherwise
*/
event ReserveBorrowing(address indexed asset, bool enabled);
/**
* @dev Emitted when flashloans are enabled or disabled on a reserve.
* @param asset The address of the underlying asset of the reserve
* @param enabled True if flashloans are enabled, false otherwise
*/
event ReserveFlashLoaning(address indexed asset, bool enabled);
/**
* @dev Emitted when the collateralization risk parameters for the specified asset are updated.
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
*/
event CollateralConfigurationChanged(
address indexed asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
);
/**
* @dev Emitted when stable rate borrowing is enabled or disabled on a reserve
* @param asset The address of the underlying asset of the reserve
* @param enabled True if stable rate borrowing is enabled, false otherwise
*/
event ReserveStableRateBorrowing(address indexed asset, bool enabled);
/**
* @dev Emitted when a reserve is activated or deactivated
* @param asset The address of the underlying asset of the reserve
* @param active True if reserve is active, false otherwise
*/
event ReserveActive(address indexed asset, bool active);
/**
* @dev Emitted when a reserve is frozen or unfrozen
* @param asset The address of the underlying asset of the reserve
* @param frozen True if reserve is frozen, false otherwise
*/
event ReserveFrozen(address indexed asset, bool frozen);
/**
* @dev Emitted when a reserve is paused or unpaused
* @param asset The address of the underlying asset of the reserve
* @param paused True if reserve is paused, false otherwise
*/
event ReservePaused(address indexed asset, bool paused);
/**
* @dev Emitted when a reserve is dropped.
* @param asset The address of the underlying asset of the reserve
*/
event ReserveDropped(address indexed asset);
/**
* @dev Emitted when a reserve factor is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldReserveFactor The old reserve factor, expressed in bps
* @param newReserveFactor The new reserve factor, expressed in bps
*/
event ReserveFactorChanged(
address indexed asset,
uint256 oldReserveFactor,
uint256 newReserveFactor
);
/**
* @dev Emitted when the borrow cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldBorrowCap The old borrow cap
* @param newBorrowCap The new borrow cap
*/
event BorrowCapChanged(address indexed asset, uint256 oldBorrowCap, uint256 newBorrowCap);
/**
* @dev Emitted when the supply cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldSupplyCap The old supply cap
* @param newSupplyCap The new supply cap
*/
event SupplyCapChanged(address indexed asset, uint256 oldSupplyCap, uint256 newSupplyCap);
/**
* @dev Emitted when the liquidation protocol fee of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldFee The old liquidation protocol fee, expressed in bps
* @param newFee The new liquidation protocol fee, expressed in bps
*/
event LiquidationProtocolFeeChanged(address indexed asset, uint256 oldFee, uint256 newFee);
/**
* @dev Emitted when the unbacked mint cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldUnbackedMintCap The old unbacked mint cap
* @param newUnbackedMintCap The new unbacked mint cap
*/
event UnbackedMintCapChanged(
address indexed asset,
uint256 oldUnbackedMintCap,
uint256 newUnbackedMintCap
);
/**
* @dev Emitted when the category of an asset in eMode is changed.
* @param asset The address of the underlying asset of the reserve
* @param oldCategoryId The old eMode asset category
* @param newCategoryId The new eMode asset category
*/
event EModeAssetCategoryChanged(address indexed asset, uint8 oldCategoryId, uint8 newCategoryId);
/**
* @dev Emitted when a new eMode category is added.
* @param categoryId The new eMode category id
* @param ltv The ltv for the asset category in eMode
* @param liquidationThreshold The liquidationThreshold for the asset category in eMode
* @param liquidationBonus The liquidationBonus for the asset category in eMode
* @param oracle The optional address of the price oracle specific for this category
* @param label A human readable identifier for the category
*/
event EModeCategoryAdded(
uint8 indexed categoryId,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus,
address oracle,
string label
);
/**
* @dev Emitted when a reserve interest strategy contract is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldStrategy The address of the old interest strategy contract
* @param newStrategy The address of the new interest strategy contract
*/
event ReserveInterestRateStrategyChanged(
address indexed asset,
address oldStrategy,
address newStrategy
);
/**
* @dev Emitted when an aToken implementation is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The aToken proxy address
* @param implementation The new aToken implementation
*/
event ATokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a stable debt token is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The stable debt token proxy address
* @param implementation The new aToken implementation
*/
event StableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a variable debt token is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The variable debt token proxy address
* @param implementation The new aToken implementation
*/
event VariableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the debt ceiling of an asset is set.
* @param asset The address of the underlying asset of the reserve
* @param oldDebtCeiling The old debt ceiling
* @param newDebtCeiling The new debt ceiling
*/
event DebtCeilingChanged(address indexed asset, uint256 oldDebtCeiling, uint256 newDebtCeiling);
/**
* @dev Emitted when the the siloed borrowing state for an asset is changed.
* @param asset The address of the underlying asset of the reserve
* @param oldState The old siloed borrowing state
* @param newState The new siloed borrowing state
*/
event SiloedBorrowingChanged(address indexed asset, bool oldState, bool newState);
/**
* @dev Emitted when the bridge protocol fee is updated.
* @param oldBridgeProtocolFee The old protocol fee, expressed in bps
* @param newBridgeProtocolFee The new protocol fee, expressed in bps
*/
event BridgeProtocolFeeUpdated(uint256 oldBridgeProtocolFee, uint256 newBridgeProtocolFee);
/**
* @dev Emitted when the total premium on flashloans is updated.
* @param oldFlashloanPremiumTotal The old premium, expressed in bps
* @param newFlashloanPremiumTotal The new premium, expressed in bps
*/
event FlashloanPremiumTotalUpdated(
uint128 oldFlashloanPremiumTotal,
uint128 newFlashloanPremiumTotal
);
/**
* @dev Emitted when the part of the premium that goes to protocol is updated.
* @param oldFlashloanPremiumToProtocol The old premium, expressed in bps
* @param newFlashloanPremiumToProtocol The new premium, expressed in bps
*/
event FlashloanPremiumToProtocolUpdated(
uint128 oldFlashloanPremiumToProtocol,
uint128 newFlashloanPremiumToProtocol
);
/**
* @dev Emitted when the reserve is set as borrowable/non borrowable in isolation mode.
* @param asset The address of the underlying asset of the reserve
* @param borrowable True if the reserve is borrowable in isolation, false otherwise
*/
event BorrowableInIsolationChanged(address asset, bool borrowable);
/**
* @notice Initializes multiple reserves.
* @param input The array of initialization parameters
*/
function initReserves(ConfiguratorInputTypes.InitReserveInput[] calldata input) external;
/**
* @dev Updates the aToken implementation for the reserve.
* @param input The aToken update parameters
*/
function updateAToken(ConfiguratorInputTypes.UpdateATokenInput calldata input) external;
/**
* @notice Updates the stable debt token implementation for the reserve.
* @param input The stableDebtToken update parameters
*/
function updateStableDebtToken(
ConfiguratorInputTypes.UpdateDebtTokenInput calldata input
) external;
/**
* @notice Updates the variable debt token implementation for the asset.
* @param input The variableDebtToken update parameters
*/
function updateVariableDebtToken(
ConfiguratorInputTypes.UpdateDebtTokenInput calldata input
) external;
/**
* @notice Configures borrowing on a reserve.
* @dev Can only be disabled (set to false) if stable borrowing is disabled
* @param asset The address of the underlying asset of the reserve
* @param enabled True if borrowing needs to be enabled, false otherwise
*/
function setReserveBorrowing(address asset, bool enabled) external;
/**
* @notice Configures the reserve collateralization parameters.
* @dev All the values are expressed in bps. A value of 10000, results in 100.00%
* @dev The `liquidationBonus` is always above 100%. A value of 105% means the liquidator will receive a 5% bonus
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
*/
function configureReserveAsCollateral(
address asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
) external;
/**
* @notice Enable or disable stable rate borrowing on a reserve.
* @dev Can only be enabled (set to true) if borrowing is enabled
* @param asset The address of the underlying asset of the reserve
* @param enabled True if stable rate borrowing needs to be enabled, false otherwise
*/
function setReserveStableRateBorrowing(address asset, bool enabled) external;
/**
* @notice Enable or disable flashloans on a reserve
* @param asset The address of the underlying asset of the reserve
* @param enabled True if flashloans need to be enabled, false otherwise
*/
function setReserveFlashLoaning(address asset, bool enabled) external;
/**
* @notice Activate or deactivate a reserve
* @param asset The address of the underlying asset of the reserve
* @param active True if the reserve needs to be active, false otherwise
*/
function setReserveActive(address asset, bool active) external;
/**
* @notice Freeze or unfreeze a reserve. A frozen reserve doesn't allow any new supply, borrow
* or rate swap but allows repayments, liquidations, rate rebalances and withdrawals.
* @param asset The address of the underlying asset of the reserve
* @param freeze True if the reserve needs to be frozen, false otherwise
*/
function setReserveFreeze(address asset, bool freeze) external;
/**
* @notice Sets the borrowable in isolation flag for the reserve.
* @dev When this flag is set to true, the asset will be borrowable against isolated collaterals and the
* borrowed amount will be accumulated in the isolated collateral's total debt exposure
* @dev Only assets of the same family (e.g. USD stablecoins) should be borrowable in isolation mode to keep
* consistency in the debt ceiling calculations
* @param asset The address of the underlying asset of the reserve
* @param borrowable True if the asset should be borrowable in isolation, false otherwise
*/
function setBorrowableInIsolation(address asset, bool borrowable) external;
/**
* @notice Pauses a reserve. A paused reserve does not allow any interaction (supply, borrow, repay,
* swap interest rate, liquidate, atoken transfers).
* @param asset The address of the underlying asset of the reserve
* @param paused True if pausing the reserve, false if unpausing
*/
function setReservePause(address asset, bool paused) external;
/**
* @notice Updates the reserve factor of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newReserveFactor The new reserve factor of the reserve
*/
function setReserveFactor(address asset, uint256 newReserveFactor) external;
/**
* @notice Sets the interest rate strategy of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newRateStrategyAddress The address of the new interest strategy contract
*/
function setReserveInterestRateStrategyAddress(
address asset,
address newRateStrategyAddress
) external;
/**
* @notice Pauses or unpauses all the protocol reserves. In the paused state all the protocol interactions
* are suspended.
* @param paused True if protocol needs to be paused, false otherwise
*/
function setPoolPause(bool paused) external;
/**
* @notice Updates the borrow cap of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newBorrowCap The new borrow cap of the reserve
*/
function setBorrowCap(address asset, uint256 newBorrowCap) external;
/**
* @notice Updates the supply cap of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newSupplyCap The new supply cap of the reserve
*/
function setSupplyCap(address asset, uint256 newSupplyCap) external;
/**
* @notice Updates the liquidation protocol fee of reserve.
* @param asset The address of the underlying asset of the reserve
* @param newFee The new liquidation protocol fee of the reserve, expressed in bps
*/
function setLiquidationProtocolFee(address asset, uint256 newFee) external;
/**
* @notice Updates the unbacked mint cap of reserve.
* @param asset The address of the underlying asset of the reserve
* @param newUnbackedMintCap The new unbacked mint cap of the reserve
*/
function setUnbackedMintCap(address asset, uint256 newUnbackedMintCap) external;
/**
* @notice Assign an efficiency mode (eMode) category to asset.
* @param asset The address of the underlying asset of the reserve
* @param newCategoryId The new category id of the asset
*/
function setAssetEModeCategory(address asset, uint8 newCategoryId) external;
/**
* @notice Adds a new efficiency mode (eMode) category.
* @dev If zero is provided as oracle address, the default asset oracles will be used to compute the overall debt and
* overcollateralization of the users using this category.
* @dev The new ltv and liquidation threshold must be greater than the base
* ltvs and liquidation thresholds of all assets within the eMode category
* @param categoryId The id of the category to be configured
* @param ltv The ltv associated with the category
* @param liquidationThreshold The liquidation threshold associated with the category
* @param liquidationBonus The liquidation bonus associated with the category
* @param oracle The oracle associated with the category
* @param label A label identifying the category
*/
function setEModeCategory(
uint8 categoryId,
uint16 ltv,
uint16 liquidationThreshold,
uint16 liquidationBonus,
address oracle,
string calldata label
) external;
/**
* @notice Drops a reserve entirely.
* @param asset The address of the reserve to drop
*/
function dropReserve(address asset) external;
/**
* @notice Updates the bridge fee collected by the protocol reserves.
* @param newBridgeProtocolFee The part of the fee sent to the protocol treasury, expressed in bps
*/
function updateBridgeProtocolFee(uint256 newBridgeProtocolFee) external;
/**
* @notice Updates the total flash loan premium.
* Total flash loan premium consists of two parts:
* - A part is sent to aToken holders as extra balance
* - A part is collected by the protocol reserves
* @dev Expressed in bps
* @dev The premium is calculated on the total amount borrowed
* @param newFlashloanPremiumTotal The total flashloan premium
*/
function updateFlashloanPremiumTotal(uint128 newFlashloanPremiumTotal) external;
/**
* @notice Updates the flash loan premium collected by protocol reserves
* @dev Expressed in bps
* @dev The premium to protocol is calculated on the total flashloan premium
* @param newFlashloanPremiumToProtocol The part of the flashloan premium sent to the protocol treasury
*/
function updateFlashloanPremiumToProtocol(uint128 newFlashloanPremiumToProtocol) external;
/**
* @notice Sets the debt ceiling for an asset.
* @param newDebtCeiling The new debt ceiling
*/
function setDebtCeiling(address asset, uint256 newDebtCeiling) external;
/**
* @notice Sets siloed borrowing for an asset
* @param siloed The new siloed borrowing state
*/
function setSiloedBorrowing(address asset, bool siloed) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IPoolAddressesProvider
* @author Aave
* @notice Defines the basic interface for a Pool Addresses Provider.
*/
interface IPoolAddressesProvider {
/**
* @dev Emitted when the market identifier is updated.
* @param oldMarketId The old id of the market
* @param newMarketId The new id of the market
*/
event MarketIdSet(string indexed oldMarketId, string indexed newMarketId);
/**
* @dev Emitted when the pool is updated.
* @param oldAddress The old address of the Pool
* @param newAddress The new address of the Pool
*/
event PoolUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the pool configurator is updated.
* @param oldAddress The old address of the PoolConfigurator
* @param newAddress The new address of the PoolConfigurator
*/
event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle is updated.
* @param oldAddress The old address of the PriceOracle
* @param newAddress The new address of the PriceOracle
*/
event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL manager is updated.
* @param oldAddress The old address of the ACLManager
* @param newAddress The new address of the ACLManager
*/
event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL admin is updated.
* @param oldAddress The old address of the ACLAdmin
* @param newAddress The new address of the ACLAdmin
*/
event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle sentinel is updated.
* @param oldAddress The old address of the PriceOracleSentinel
* @param newAddress The new address of the PriceOracleSentinel
*/
event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the pool data provider is updated.
* @param oldAddress The old address of the PoolDataProvider
* @param newAddress The new address of the PoolDataProvider
*/
event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when a new proxy is created.
* @param id The identifier of the proxy
* @param proxyAddress The address of the created proxy contract
* @param implementationAddress The address of the implementation contract
*/
event ProxyCreated(
bytes32 indexed id,
address indexed proxyAddress,
address indexed implementationAddress
);
/**
* @dev Emitted when a new non-proxied contract address is registered.
* @param id The identifier of the contract
* @param oldAddress The address of the old contract
* @param newAddress The address of the new contract
*/
event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the implementation of the proxy registered with id is updated
* @param id The identifier of the contract
* @param proxyAddress The address of the proxy contract
* @param oldImplementationAddress The address of the old implementation contract
* @param newImplementationAddress The address of the new implementation contract
*/
event AddressSetAsProxy(
bytes32 indexed id,
address indexed proxyAddress,
address oldImplementationAddress,
address indexed newImplementationAddress
);
/**
* @notice Returns the id of the Aave market to which this contract points to.
* @return The market id
*/
function getMarketId() external view returns (string memory);
/**
* @notice Associates an id with a specific PoolAddressesProvider.
* @dev This can be used to create an onchain registry of PoolAddressesProviders to
* identify and validate multiple Aave markets.
* @param newMarketId The market id
*/
function setMarketId(string calldata newMarketId) external;
/**
* @notice Returns an address by its identifier.
* @dev The returned address might be an EOA or a contract, potentially proxied
* @dev It returns ZERO if there is no registered address with the given id
* @param id The id
* @return The address of the registered for the specified id
*/
function getAddress(bytes32 id) external view returns (address);
/**
* @notice General function to update the implementation of a proxy registered with
* certain `id`. If there is no proxy registered, it will instantiate one and
* set as implementation the `newImplementationAddress`.
* @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit
* setter function, in order to avoid unexpected consequences
* @param id The id
* @param newImplementationAddress The address of the new implementation
*/
function setAddressAsProxy(bytes32 id, address newImplementationAddress) external;
/**
* @notice Sets an address for an id replacing the address saved in the addresses map.
* @dev IMPORTANT Use this function carefully, as it will do a hard replacement
* @param id The id
* @param newAddress The address to set
*/
function setAddress(bytes32 id, address newAddress) external;
/**
* @notice Returns the address of the Pool proxy.
* @return The Pool proxy address
*/
function getPool() external view returns (address);
/**
* @notice Updates the implementation of the Pool, or creates a proxy
* setting the new `pool` implementation when the function is called for the first time.
* @param newPoolImpl The new Pool implementation
*/
function setPoolImpl(address newPoolImpl) external;
/**
* @notice Returns the address of the PoolConfigurator proxy.
* @return The PoolConfigurator proxy address
*/
function getPoolConfigurator() external view returns (address);
/**
* @notice Updates the implementation of the PoolConfigurator, or creates a proxy
* setting the new `PoolConfigurator` implementation when the function is called for the first time.
* @param newPoolConfiguratorImpl The new PoolConfigurator implementation
*/
function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external;
/**
* @notice Returns the address of the price oracle.
* @return The address of the PriceOracle
*/
function getPriceOracle() external view returns (address);
/**
* @notice Updates the address of the price oracle.
* @param newPriceOracle The address of the new PriceOracle
*/
function setPriceOracle(address newPriceOracle) external;
/**
* @notice Returns the address of the ACL manager.
* @return The address of the ACLManager
*/
function getACLManager() external view returns (address);
/**
* @notice Updates the address of the ACL manager.
* @param newAclManager The address of the new ACLManager
*/
function setACLManager(address newAclManager) external;
/**
* @notice Returns the address of the ACL admin.
* @return The address of the ACL admin
*/
function getACLAdmin() external view returns (address);
/**
* @notice Updates the address of the ACL admin.
* @param newAclAdmin The address of the new ACL admin
*/
function setACLAdmin(address newAclAdmin) external;
/**
* @notice Returns the address of the price oracle sentinel.
* @return The address of the PriceOracleSentinel
*/
function getPriceOracleSentinel() external view returns (address);
/**
* @notice Updates the address of the price oracle sentinel.
* @param newPriceOracleSentinel The address of the new PriceOracleSentinel
*/
function setPriceOracleSentinel(address newPriceOracleSentinel) external;
/**
* @notice Returns the address of the data provider.
* @return The address of the DataProvider
*/
function getPoolDataProvider() external view returns (address);
/**
* @notice Updates the address of the data provider.
* @param newDataProvider The address of the new DataProvider
*/
function setPoolDataProvider(address newDataProvider) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
library DataTypes {
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
//timestamp of last update
uint40 lastUpdateTimestamp;
//the id of the reserve. Represents the position in the list of the active reserves
uint16 id;
//aToken address
address aTokenAddress;
//stableDebtToken address
address stableDebtTokenAddress;
//variableDebtToken address
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the current treasury balance, scaled
uint128 accruedToTreasury;
//the outstanding unbacked aTokens minted through the bridging feature
uint128 unbacked;
//the outstanding debt borrowed against this asset in isolation mode
uint128 isolationModeTotalDebt;
}
struct ReserveConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: stable rate borrowing enabled
//bit 60: asset is paused
//bit 61: borrowing in isolation mode is enabled
//bit 62-63: reserved
//bit 64-79: reserve factor
//bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap
//bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap
//bit 152-167 liquidation protocol fee
//bit 168-175 eMode category
//bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled
//bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals
//bit 252-255 unused
uint256 data;
}
struct UserConfigurationMap {
/**
* @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset.
* The first bit indicates if an asset is used as collateral by the user, the second whether an
* asset is borrowed by the user.
*/
uint256 data;
}
struct EModeCategory {
// each eMode category has a custom ltv and liquidation threshold
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
// each eMode category may or may not have a custom oracle to override the individual assets price oracles
address priceSource;
string label;
}
enum InterestRateMode {NONE, STABLE, VARIABLE}
struct ReserveCache {
uint256 currScaledVariableDebt;
uint256 nextScaledVariableDebt;
uint256 currPrincipalStableDebt;
uint256 currAvgStableBorrowRate;
uint256 currTotalStableDebt;
uint256 nextAvgStableBorrowRate;
uint256 nextTotalStableDebt;
uint256 currLiquidityIndex;
uint256 nextLiquidityIndex;
uint256 currVariableBorrowIndex;
uint256 nextVariableBorrowIndex;
uint256 currLiquidityRate;
uint256 currVariableBorrowRate;
uint256 reserveFactor;
ReserveConfigurationMap reserveConfiguration;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
uint40 reserveLastUpdateTimestamp;
uint40 stableDebtLastUpdateTimestamp;
}
struct ExecuteLiquidationCallParams {
uint256 reservesCount;
uint256 debtToCover;
address collateralAsset;
address debtAsset;
address user;
bool receiveAToken;
address priceOracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteSupplyParams {
address asset;
uint256 amount;
address onBehalfOf;
uint16 referralCode;
}
struct ExecuteBorrowParams {
address asset;
address user;
address onBehalfOf;
uint256 amount;
InterestRateMode interestRateMode;
uint16 referralCode;
bool releaseUnderlying;
uint256 maxStableRateBorrowSizePercent;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteRepayParams {
address asset;
uint256 amount;
InterestRateMode interestRateMode;
address onBehalfOf;
bool useATokens;
}
struct ExecuteWithdrawParams {
address asset;
uint256 amount;
address to;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
}
struct ExecuteSetUserEModeParams {
uint256 reservesCount;
address oracle;
uint8 categoryId;
}
struct FinalizeTransferParams {
address asset;
address from;
address to;
uint256 amount;
uint256 balanceFromBefore;
uint256 balanceToBefore;
uint256 reservesCount;
address oracle;
uint8 fromEModeCategory;
}
struct FlashloanParams {
address receiverAddress;
address[] assets;
uint256[] amounts;
uint256[] interestRateModes;
address onBehalfOf;
bytes params;
uint16 referralCode;
uint256 flashLoanPremiumToProtocol;
uint256 flashLoanPremiumTotal;
uint256 maxStableRateBorrowSizePercent;
uint256 reservesCount;
address addressesProvider;
uint8 userEModeCategory;
bool isAuthorizedFlashBorrower;
}
struct FlashloanSimpleParams {
address receiverAddress;
address asset;
uint256 amount;
bytes params;
uint16 referralCode;
uint256 flashLoanPremiumToProtocol;
uint256 flashLoanPremiumTotal;
}
struct FlashLoanRepaymentParams {
uint256 amount;
uint256 totalPremium;
uint256 flashLoanPremiumToProtocol;
address asset;
address receiverAddress;
uint16 referralCode;
}
struct CalculateUserAccountDataParams {
UserConfigurationMap userConfig;
uint256 reservesCount;
address user;
address oracle;
uint8 userEModeCategory;
}
struct ValidateBorrowParams {
ReserveCache reserveCache;
UserConfigurationMap userConfig;
address asset;
address userAddress;
uint256 amount;
InterestRateMode interestRateMode;
uint256 maxStableLoanPercent;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
bool isolationModeActive;
address isolationModeCollateralAddress;
uint256 isolationModeDebtCeiling;
}
struct ValidateLiquidationCallParams {
ReserveCache debtReserveCache;
uint256 totalDebt;
uint256 healthFactor;
address priceOracleSentinel;
}
struct CalculateInterestRatesParams {
uint256 unbacked;
uint256 liquidityAdded;
uint256 liquidityTaken;
uint256 totalStableDebt;
uint256 totalVariableDebt;
uint256 averageStableBorrowRate;
uint256 reserveFactor;
address reserve;
address aToken;
}
struct InitReserveParams {
address asset;
address aTokenAddress;
address stableDebtAddress;
address variableDebtAddress;
address interestRateStrategyAddress;
uint16 reservesCount;
uint16 maxNumberReserves;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IAccessControl} from '@openzeppelin/contracts/access/IAccessControl.sol';
/**
* @title IGhoToken
* @author Aave
*/
interface IUsdxlToken is IERC20, IAccessControl {
struct Facilitator {
uint128 bucketCapacity;
uint128 bucketLevel;
string label;
}
/**
* @dev Emitted when a new facilitator is added
* @param facilitatorAddress The address of the new facilitator
* @param label A hashed human readable identifier for the facilitator
* @param bucketCapacity The initial capacity of the facilitator's bucket
*/
event FacilitatorAdded(
address indexed facilitatorAddress,
bytes32 indexed label,
uint256 bucketCapacity
);
/**
* @dev Emitted when a facilitator is removed
* @param facilitatorAddress The address of the removed facilitator
*/
event FacilitatorRemoved(address indexed facilitatorAddress);
/**
* @dev Emitted when the bucket capacity of a facilitator is updated
* @param facilitatorAddress The address of the facilitator whose bucket capacity is being changed
* @param oldCapacity The old capacity of the bucket
* @param newCapacity The new capacity of the bucket
*/
event FacilitatorBucketCapacityUpdated(
address indexed facilitatorAddress,
uint256 oldCapacity,
uint256 newCapacity
);
/**
* @dev Emitted when the bucket level changed
* @param facilitatorAddress The address of the facilitator whose bucket level is being changed
* @param oldLevel The old level of the bucket
* @param newLevel The new level of the bucket
*/
event FacilitatorBucketLevelUpdated(
address indexed facilitatorAddress,
uint256 oldLevel,
uint256 newLevel
);
/**
* @notice Returns the identifier of the Facilitator Manager Role
* @return The bytes32 id hash of the FacilitatorManager role
*/
function FACILITATOR_MANAGER_ROLE() external pure returns (bytes32);
/**
* @notice Returns the identifier of the Bucket Manager Role
* @return The bytes32 id hash of the BucketManager role
*/
function BUCKET_MANAGER_ROLE() external pure returns (bytes32);
/**
* @notice Mints the requested amount of tokens to the account address.
* @dev Only facilitators with enough bucket capacity available can mint.
* @dev The bucket level is increased upon minting.
* @param account The address receiving the GHO tokens
* @param amount The amount to mint
*/
function mint(address account, uint256 amount) external;
/**
* @notice Burns the requested amount of tokens from the account address.
* @dev Only active facilitators (bucket level > 0) can burn.
* @dev The bucket level is decreased upon burning.
* @param amount The amount to burn
*/
function burn(uint256 amount) external;
/**
* @notice Add the facilitator passed with the parameters to the facilitators list.
* @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function
* @param facilitatorAddress The address of the facilitator to add
* @param facilitatorLabel A human readable identifier for the facilitator
* @param bucketCapacity The upward limit of GHO can be minted by the facilitator
*/
function addFacilitator(
address facilitatorAddress,
string calldata facilitatorLabel,
uint128 bucketCapacity
) external;
/**
* @notice Remove the facilitator from the facilitators list.
* @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function
* @param facilitatorAddress The address of the facilitator to remove
*/
function removeFacilitator(address facilitatorAddress) external;
/**
* @notice Set the bucket capacity of the facilitator.
* @dev Only accounts with `BUCKET_MANAGER_ROLE` role can call this function
* @param facilitator The address of the facilitator
* @param newCapacity The new capacity of the bucket
*/
function setFacilitatorBucketCapacity(address facilitator, uint128 newCapacity) external;
/**
* @notice Returns the facilitator data
* @param facilitator The address of the facilitator
* @return The facilitator configuration
*/
function getFacilitator(address facilitator) external view returns (Facilitator memory);
/**
* @notice Returns the bucket configuration of the facilitator
* @param facilitator The address of the facilitator
* @return The capacity of the facilitator's bucket
* @return The level of the facilitator's bucket
*/
function getFacilitatorBucket(address facilitator) external view returns (uint256, uint256);
/**
* @notice Returns the list of the addresses of the active facilitator
* @return The list of the facilitators addresses
*/
function getFacilitatorsList() external view returns (address[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {DataTypes} from '@aave/core-v3/contracts/protocol/libraries/types/DataTypes.sol';
import {IDefaultInterestRateStrategy} from '@aave/core-v3/contracts/interfaces/IDefaultInterestRateStrategy.sol';
import {IReserveInterestRateStrategy} from '@aave/core-v3/contracts/interfaces/IReserveInterestRateStrategy.sol';
import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol';
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
/**
* @title UsdxlMutableInterestRateStrategy
* @author Aave
* @notice Implements the calculation of USDXL interest rates with mutable variable borrow rate.
* @dev The variable borrow interest rate can be updated by the owner. The rest of parameters are zeroed.
*/
contract UsdxlMutableInterestRateStrategy is IDefaultInterestRateStrategy, Ownable {
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public constant OPTIMAL_USAGE_RATIO = 0;
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public constant OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO = 0;
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public constant MAX_EXCESS_USAGE_RATIO = 0;
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public constant MAX_EXCESS_STABLE_TO_TOTAL_DEBT_RATIO = 0;
/// @inheritdoc IDefaultInterestRateStrategy
IPoolAddressesProvider public immutable ADDRESSES_PROVIDER;
// Base variable borrow rate when usage rate = 0. Expressed in ray
uint256 internal _baseVariableBorrowRate;
// Events
event InterestRateUpdated(uint256 oldRate, uint256 newRate, uint256 timestamp);
/**
* @dev Constructor
* @param addressesProvider The address of the PoolAddressesProvider
* @param borrowRate The variable borrow rate (expressed in ray)
* @param owner The owner of the contract who can update rates
*/
constructor(address addressesProvider, uint256 borrowRate, address owner) {
ADDRESSES_PROVIDER = IPoolAddressesProvider(addressesProvider);
_baseVariableBorrowRate = borrowRate;
_transferOwnership(owner);
}
/**
* @notice Update the base variable borrow rate
* @param newRate The new variable borrow rate (expressed in ray)
* @dev Only callable by owner
*/
function updateBaseVariableBorrowRate(uint256 newRate) external onlyOwner {
uint256 oldRate = _baseVariableBorrowRate;
_baseVariableBorrowRate = newRate;
emit InterestRateUpdated(oldRate, newRate, block.timestamp);
}
function getVariableRateSlope1() external pure returns (uint256) {
return 0;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getVariableRateSlope2() external pure returns (uint256) {
return 0;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateSlope1() external pure returns (uint256) {
return 0;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateSlope2() external pure returns (uint256) {
return 0;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateExcessOffset() external pure returns (uint256) {
return 0;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getBaseStableBorrowRate() public pure returns (uint256) {
return 0;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getBaseVariableBorrowRate() external view override returns (uint256) {
return _baseVariableBorrowRate;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getMaxVariableBorrowRate() external view override returns (uint256) {
return _baseVariableBorrowRate;
}
/// @inheritdoc IReserveInterestRateStrategy
function calculateInterestRates(
DataTypes.CalculateInterestRatesParams memory
) public view override returns (uint256, uint256, uint256) {
return (0, 0, _baseVariableBorrowRate);
}
function setInterestRateParams(address reserve, bytes calldata rateData) external {}
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IWrappedHypeGateway
* @author HypurrFi
* @notice Defines the basic interface for a WHYPE Gateway
*/
interface IWrappedHypeGateway {
/**
* @dev Deposits HYPE into the protocol
* @param onBehalfOf The address that will receive the aTokens
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function depositHYPE(address, address onBehalfOf, uint16 referralCode) external payable;
/**
* @dev Withdraws HYPE from the protocol to the recipient address
* @param amount The amount of WHYPE to withdraw
* @param to The address that will receive the HYPE
*/
function withdrawHYPE(address, uint256 amount, address to) external;
/**
* @dev Withdraws HYPE from the protocol with permit signature
* @param amount The amount of WHYPE to withdraw
* @param to The address that will receive the HYPE
* @param deadline The deadline timestamp for the signature
* @param permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
*/
function withdrawHYPEWithPermit(
address,
uint256 amount,
address to,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external;
/**
* @dev Borrows HYPE from the protocol
* @param amount The amount of HYPE to borrow
* @param interestRateMode The interest rate mode (Stable = 1, Variable = 2)
* @param referralCode The referral code for potential rewards
*/
function borrowHYPE(address, uint256 amount, uint256 interestRateMode, uint16 referralCode) external;
/**
* @dev Repays HYPE to the protocol
* @param amount The amount to repay
* @param rateMode The interest rate mode (Stable = 1, Variable = 2)
* @param onBehalfOf The address of the user who will get their debt reduced
*/
function repayHYPE(address, uint256 amount, uint256 rateMode, address onBehalfOf) external payable;
/**
* @dev Returns the WHYPE address used by the gateway
* @return The address of the WHYPE token
*/
function getWHYPEAddress() external view returns (address);
/**
* @dev Allows owner to rescue tokens sent to the contract
* @param token The address of the token
* @param to The address that will receive the tokens
* @param amount The amount of tokens to transfer
*/
function emergencyTokenTransfer(address token, address to, uint256 amount) external;
/**
* @dev Allows owner to rescue native tokens sent to the contract
* @param to The address that will receive the native tokens
* @param amount The amount to transfer
*/
function emergencyEtherTransfer(address to, uint256 amount) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
import {IInitializableAToken} from './IInitializableAToken.sol';
/**
* @title IAToken
* @author Aave
* @notice Defines the basic interface for an AToken.
*/
interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken {
/**
* @dev Emitted during the transfer action
* @param from The user whose tokens are being transferred
* @param to The recipient
* @param value The scaled amount being transferred
* @param index The next liquidity index of the reserve
*/
event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);
/**
* @notice Mints `amount` aTokens to `user`
* @param caller The address performing the mint
* @param onBehalfOf The address of the user that will receive the minted aTokens
* @param amount The amount of tokens getting minted
* @param index The next liquidity index of the reserve
* @return `true` if the the previous balance of the user was 0
*/
function mint(
address caller,
address onBehalfOf,
uint256 amount,
uint256 index
) external returns (bool);
/**
* @notice Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`
* @dev In some instances, the mint event could be emitted from a burn transaction
* if the amount to burn is less than the interest that the user accrued
* @param from The address from which the aTokens will be burned
* @param receiverOfUnderlying The address that will receive the underlying
* @param amount The amount being burned
* @param index The next liquidity index of the reserve
*/
function burn(address from, address receiverOfUnderlying, uint256 amount, uint256 index) external;
/**
* @notice Mints aTokens to the reserve treasury
* @param amount The amount of tokens getting minted
* @param index The next liquidity index of the reserve
*/
function mintToTreasury(uint256 amount, uint256 index) external;
/**
* @notice Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken
* @param from The address getting liquidated, current owner of the aTokens
* @param to The recipient
* @param value The amount of tokens getting transferred
*/
function transferOnLiquidation(address from, address to, uint256 value) external;
/**
* @notice Transfers the underlying asset to `target`.
* @dev Used by the Pool to transfer assets in borrow(), withdraw() and flashLoan()
* @param target The recipient of the underlying
* @param amount The amount getting transferred
*/
function transferUnderlyingTo(address target, uint256 amount) external;
/**
* @notice Handles the underlying received by the aToken after the transfer has been completed.
* @dev The default implementation is empty as with standard ERC20 tokens, nothing needs to be done after the
* transfer is concluded. However in the future there may be aTokens that allow for example to stake the underlying
* to receive LM rewards. In that case, `handleRepayment()` would perform the staking of the underlying asset.
* @param user The user executing the repayment
* @param onBehalfOf The address of the user who will get his debt reduced/removed
* @param amount The amount getting repaid
*/
function handleRepayment(address user, address onBehalfOf, uint256 amount) external;
/**
* @notice Allow passing a signed message to approve spending
* @dev implements the permit function as for
* https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
* @param owner The owner of the funds
* @param spender The spender
* @param value The amount
* @param deadline The deadline timestamp, type(uint256).max for max deadline
* @param v Signature param
* @param s Signature param
* @param r Signature param
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @return The address of the underlying asset
*/
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
/**
* @notice Returns the address of the Aave treasury, receiving the fees on this aToken.
* @return Address of the Aave treasury
*/
function RESERVE_TREASURY_ADDRESS() external view returns (address);
/**
* @notice Get the domain separator for the token
* @dev Return cached value if chainId matches cache, otherwise recomputes separator
* @return The domain separator of the token at current chain
*/
function DOMAIN_SEPARATOR() external view returns (bytes32);
/**
* @notice Returns the nonce for owner.
* @param owner The address of the owner
* @return The nonce of the owner
*/
function nonces(address owner) external view returns (uint256);
/**
* @notice Rescue and transfer tokens locked in this contract
* @param token The address of the token
* @param to The address of the recipient
* @param amount The amount of token to transfer
*/
function rescueTokens(address token, address to, uint256 amount) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// 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: BUSL-1.1
pragma solidity ^0.8.0;
library ConfiguratorInputTypes {
struct InitReserveInput {
address aTokenImpl;
address stableDebtTokenImpl;
address variableDebtTokenImpl;
uint8 underlyingAssetDecimals;
address interestRateStrategyAddress;
address underlyingAsset;
address treasury;
address incentivesController;
string aTokenName;
string aTokenSymbol;
string variableDebtTokenName;
string variableDebtTokenSymbol;
string stableDebtTokenName;
string stableDebtTokenSymbol;
bytes params;
}
struct UpdateATokenInput {
address asset;
address treasury;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
struct UpdateDebtTokenInput {
address asset;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IReserveInterestRateStrategy} from './IReserveInterestRateStrategy.sol';
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
/**
* @title IDefaultInterestRateStrategy
* @author Aave
* @notice Defines the basic interface of the DefaultReserveInterestRateStrategy
*/
interface IDefaultInterestRateStrategy is IReserveInterestRateStrategy {
/**
* @notice Returns the usage ratio at which the pool aims to obtain most competitive borrow rates.
* @return The optimal usage ratio, expressed in ray.
*/
function OPTIMAL_USAGE_RATIO() external view returns (uint256);
/**
* @notice Returns the optimal stable to total debt ratio of the reserve.
* @return The optimal stable to total debt ratio, expressed in ray.
*/
function OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO() external view returns (uint256);
/**
* @notice Returns the excess usage ratio above the optimal.
* @dev It's always equal to 1-optimal usage ratio (added as constant for gas optimizations)
* @return The max excess usage ratio, expressed in ray.
*/
function MAX_EXCESS_USAGE_RATIO() external view returns (uint256);
/**
* @notice Returns the excess stable debt ratio above the optimal.
* @dev It's always equal to 1-optimal stable to total debt ratio (added as constant for gas optimizations)
* @return The max excess stable to total debt ratio, expressed in ray.
*/
function MAX_EXCESS_STABLE_TO_TOTAL_DEBT_RATIO() external view returns (uint256);
/**
* @notice Returns the address of the PoolAddressesProvider
* @return The address of the PoolAddressesProvider contract
*/
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Returns the variable rate slope below optimal usage ratio
* @dev It's the variable rate when usage ratio > 0 and <= OPTIMAL_USAGE_RATIO
* @return The variable rate slope, expressed in ray
*/
function getVariableRateSlope1() external view returns (uint256);
/**
* @notice Returns the variable rate slope above optimal usage ratio
* @dev It's the variable rate when usage ratio > OPTIMAL_USAGE_RATIO
* @return The variable rate slope, expressed in ray
*/
function getVariableRateSlope2() external view returns (uint256);
/**
* @notice Returns the stable rate slope below optimal usage ratio
* @dev It's the stable rate when usage ratio > 0 and <= OPTIMAL_USAGE_RATIO
* @return The stable rate slope, expressed in ray
*/
function getStableRateSlope1() external view returns (uint256);
/**
* @notice Returns the stable rate slope above optimal usage ratio
* @dev It's the variable rate when usage ratio > OPTIMAL_USAGE_RATIO
* @return The stable rate slope, expressed in ray
*/
function getStableRateSlope2() external view returns (uint256);
/**
* @notice Returns the stable rate excess offset
* @dev It's an additional premium applied to the stable when stable debt > OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO
* @return The stable rate excess offset, expressed in ray
*/
function getStableRateExcessOffset() external view returns (uint256);
/**
* @notice Returns the base stable borrow rate
* @return The base stable borrow rate, expressed in ray
*/
function getBaseStableBorrowRate() external view returns (uint256);
/**
* @notice Returns the base variable borrow rate
* @return The base variable borrow rate, expressed in ray
*/
function getBaseVariableBorrowRate() external view returns (uint256);
/**
* @notice Returns the maximum variable borrow rate
* @return The maximum variable borrow rate, expressed in ray
*/
function getMaxVariableBorrowRate() external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title IReserveInterestRateStrategy
* @author Aave
* @notice Interface for the calculation of the interest rates
*/
interface IReserveInterestRateStrategy {
/**
* @notice Calculates the interest rates depending on the reserve's state and configurations
* @param params The parameters needed to calculate interest rates
* @return liquidityRate The liquidity rate expressed in rays
* @return stableBorrowRate The stable borrow rate expressed in rays
* @return variableBorrowRate The variable borrow rate expressed in rays
*/
function calculateInterestRates(
DataTypes.CalculateInterestRatesParams memory params
) external view returns (uint256, uint256, uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);
/**
* @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);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IScaledBalanceToken
* @author Aave
* @notice Defines the basic interface for a scaled-balance token.
*/
interface IScaledBalanceToken {
/**
* @dev Emitted after the mint action
* @param caller The address performing the mint
* @param onBehalfOf The address of the user that will receive the minted tokens
* @param value The scaled-up amount being minted (based on user entered amount and balance increase from interest)
* @param balanceIncrease The increase in scaled-up balance since the last action of 'onBehalfOf'
* @param index The next liquidity index of the reserve
*/
event Mint(
address indexed caller,
address indexed onBehalfOf,
uint256 value,
uint256 balanceIncrease,
uint256 index
);
/**
* @dev Emitted after the burn action
* @dev If the burn function does not involve a transfer of the underlying asset, the target defaults to zero address
* @param from The address from which the tokens will be burned
* @param target The address that will receive the underlying, if any
* @param value The scaled-up amount being burned (user entered amount - balance increase from interest)
* @param balanceIncrease The increase in scaled-up balance since the last action of 'from'
* @param index The next liquidity index of the reserve
*/
event Burn(
address indexed from,
address indexed target,
uint256 value,
uint256 balanceIncrease,
uint256 index
);
/**
* @notice Returns the scaled balance of the user.
* @dev The scaled balance is the sum of all the updated stored balance divided by the reserve's liquidity index
* at the moment of the update
* @param user The user whose balance is calculated
* @return The scaled balance of the user
*/
function scaledBalanceOf(address user) external view returns (uint256);
/**
* @notice Returns the scaled balance of the user and the scaled total supply.
* @param user The address of the user
* @return The scaled balance of the user
* @return The scaled total supply
*/
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
/**
* @notice Returns the scaled total supply of the scaled balance token. Represents sum(debt/index)
* @return The scaled total supply
*/
function scaledTotalSupply() external view returns (uint256);
/**
* @notice Returns last index interest was accrued to the user's balance
* @param user The address of the user
* @return The last index interest was accrued to the user's balance, expressed in ray
*/
function getPreviousIndex(address user) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IAaveIncentivesController} from './IAaveIncentivesController.sol';
import {IPool} from './IPool.sol';
/**
* @title IInitializableAToken
* @author Aave
* @notice Interface for the initialize function on AToken
*/
interface IInitializableAToken {
/**
* @dev Emitted when an aToken is initialized
* @param underlyingAsset The address of the underlying asset
* @param pool The address of the associated pool
* @param treasury The address of the treasury
* @param incentivesController The address of the incentives controller for this aToken
* @param aTokenDecimals The decimals of the underlying
* @param aTokenName The name of the aToken
* @param aTokenSymbol The symbol of the aToken
* @param params A set of encoded parameters for additional initialization
*/
event Initialized(
address indexed underlyingAsset,
address indexed pool,
address treasury,
address incentivesController,
uint8 aTokenDecimals,
string aTokenName,
string aTokenSymbol,
bytes params
);
/**
* @notice Initializes the aToken
* @param pool The pool contract that is initializing this contract
* @param treasury The address of the Aave treasury, receiving the fees on this aToken
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @param incentivesController The smart contract managing potential incentives distribution
* @param aTokenDecimals The decimals of the aToken, same as the underlying asset's
* @param aTokenName The name of the aToken
* @param aTokenSymbol The symbol of the aToken
* @param params A set of encoded parameters for additional initialization
*/
function initialize(
IPool pool,
address treasury,
address underlyingAsset,
IAaveIncentivesController incentivesController,
uint8 aTokenDecimals,
string calldata aTokenName,
string calldata aTokenSymbol,
bytes calldata params
) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IAaveIncentivesController
* @author Aave
* @notice Defines the basic interface for an Aave Incentives Controller.
* @dev It only contains one single function, needed as a hook on aToken and debtToken transfers.
*/
interface IAaveIncentivesController {
/**
* @dev Called by the corresponding asset on transfer hook in order to update the rewards distribution.
* @dev The units of `totalSupply` and `userBalance` should be the same.
* @param user The address of the user whose asset balance has changed
* @param totalSupply The total supply of the asset prior to user balance change
* @param userBalance The previous user balance prior to balance change
*/
function handleAction(address user, uint256 totalSupply, uint256 userBalance) external;
}{
"remappings": [
"@aave/v3-core/=lib/hypurrfi-deployments/lib/aave-v3-core/",
"@aave/core-v3/=lib/hypurrfi-deployments/lib/aave-v3-core/",
"@aave/v3-periphery/=lib/hypurrfi-deployments/lib/aave-v3-periphery/",
"@aave/stk-v1-5/=lib/hypurrfi-deployments/src/contracts/staking/v1-5/",
"ds-test/=lib/hypurrfi-deployments/lib/forge-std/lib/ds-test/src/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"forge-std/=lib/hypurrfi-deployments/lib/forge-std/src/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"hardhat/=node_modules/hardhat/",
"aave-address-book/=src/deployments/addresses/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"solidity-utils/=lib/hypurrfi-deployments/lib/aave-helpers/lib/solidity-utils/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@hypurrfi/deployments/=lib/hypurrfi-deployments/src/deployments/",
"@hypurrfi/contracts/=lib/hypurrfi-deployments/src/contracts/",
"@hypurrfi/core/=lib/hypurrfi-deployments/src/core/",
"@hypurrfi/periphery/=lib/hypurrfi-deployments/src/periphery/",
"@aave/periphery-v3/=lib/hypurrfi-deployments/lib/aave-v3-periphery/",
"@uniswap/v3-core/=lib/hypurrfi-deployments/lib/v3-core/",
"V2-V3-migration-helpers/=lib/hypurrfi-deployments/lib/V2-V3-migration-helpers/",
"aave-helpers/=lib/hypurrfi-deployments/lib/aave-helpers/",
"aave-v3-core/=lib/hypurrfi-deployments/lib/aave-v3-core/",
"aave-v3-periphery/=lib/hypurrfi-deployments/lib/aave-v3-periphery/contracts/",
"dss-interfaces/=lib/hypurrfi-deployments/lib/dss-test/lib/dss-interfaces/src/",
"dss-test/=lib/hypurrfi-deployments/lib/dss-test/src/",
"governance-crosschain-bridges/=lib/hypurrfi-deployments/lib/aave-helpers/lib/governance-crosschain-bridges/",
"halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"hypurrfi-deployments/=lib/hypurrfi-deployments/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"addressesProvider","type":"address"},{"internalType":"address","name":"usdxlToken","type":"address"},{"internalType":"address","name":"usdxlOracleAddress","type":"address"},{"internalType":"address","name":"usdxlReserve","type":"address"},{"internalType":"uint256","name":"initialRate","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"initialPerpetualLoanAmount","type":"uint256"},{"internalType":"address","name":"wrappedHypeGateway","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"ExecutionTooEarly","type":"error"},{"inputs":[],"name":"InvalidOraclePrice","type":"error"},{"inputs":[],"name":"InvalidParameter","type":"error"},{"inputs":[],"name":"PerpetualLoanFailed","type":"error"},{"inputs":[],"name":"RateUpdateFailed","type":"error"},{"inputs":[],"name":"UnauthorizedExecutor","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldInterval","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newInterval","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ExecutionIntervalUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reason","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ExecutionSkipped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"executor","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ExecutorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"HYPEReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"HYPESupplied","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"HYPEWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"HYPEWithdrawnFromPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"InterestRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LoanClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMaxRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MaxRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rateIncreaseAdjustment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rateDecreaseAdjustment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ParametersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PerpetualLoanAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PerpetualLoanCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PerpetualLoanRefreshed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"offchainPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"onchainPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PriceDataEmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdxlPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"RateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOracle","type":"address"},{"indexed":false,"internalType":"address","name":"newOracle","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UsdxlOracleUpdated","type":"event"},{"inputs":[],"name":"ADDRESSES_PROVIDER","outputs":[{"internalType":"contract IPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_EXCESS_STABLE_TO_TOTAL_DEBT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_EXCESS_USAGE_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTIMAL_USAGE_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDXL_RESERVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDXL_TOKEN","outputs":[{"internalType":"contract IUsdxlToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WRAPPED_HYPE_GATEWAY","outputs":[{"internalType":"contract IWrappedHypeGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_callOracle","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"executors_","type":"address[]"},{"internalType":"bool[]","name":"enabled","type":"bool[]"}],"name":"batchUpdateExecutors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"unbacked","type":"uint256"},{"internalType":"uint256","name":"liquidityAdded","type":"uint256"},{"internalType":"uint256","name":"liquidityTaken","type":"uint256"},{"internalType":"uint256","name":"totalStableDebt","type":"uint256"},{"internalType":"uint256","name":"totalVariableDebt","type":"uint256"},{"internalType":"uint256","name":"averageStableBorrowRate","type":"uint256"},{"internalType":"uint256","name":"reserveFactor","type":"uint256"},{"internalType":"address","name":"reserve","type":"address"},{"internalType":"address","name":"aToken","type":"address"}],"internalType":"struct DataTypes.CalculateInterestRatesParams","name":"","type":"tuple"}],"name":"calculateInterestRates","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"}],"name":"closeLoanAndWithdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyRepayAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"emergencyUpdateRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"offchainPrice","type":"int256"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"executionInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"executors","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseStableBorrowRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getBaseVariableBorrowRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentInterestRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxVariableBorrowRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextExecutionTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getParameters","outputs":[{"internalType":"uint256","name":"minRate_","type":"uint256"},{"internalType":"uint256","name":"maxRate_","type":"uint256"},{"internalType":"uint256","name":"rateIncreaseAdjustment_","type":"uint256"},{"internalType":"uint256","name":"rateDecreaseAdjustment_","type":"uint256"},{"internalType":"uint256","name":"priceThreshold_","type":"uint256"},{"internalType":"uint256","name":"targetPrice_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerpetualLoanStatus","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"debt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStableRateExcessOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getStableRateSlope1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getStableRateSlope2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getSuppliedHYPEBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUsdxlPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVariableRateSlope1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getVariableRateSlope2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"executor","type":"address"}],"name":"isAuthorizedExecutor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isExecutionDue","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastExecutionTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"perpetualLoanActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"perpetualLoanAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"perpetualLoanDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rateDecreaseAdjustment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rateIncreaseAdjustment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reserve","type":"address"},{"internalType":"bytes","name":"rateData","type":"bytes"}],"name":"setInterestRateParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"updateBaseVariableBorrowRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newInterval","type":"uint256"}],"name":"updateExecutionInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"executor","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"updateExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxRate","type":"uint256"}],"name":"updateMaxRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMinRate","type":"uint256"}],"name":"updateMinRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMinRate","type":"uint256"},{"internalType":"uint256","name":"newMaxRate","type":"uint256"},{"internalType":"uint256","name":"newRateIncreaseAdjustment","type":"uint256"},{"internalType":"uint256","name":"newRateDecreaseAdjustment","type":"uint256"},{"internalType":"uint256","name":"newPriceThreshold","type":"uint256"},{"internalType":"uint256","name":"newTargetPrice","type":"uint256"}],"name":"updateParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"updatePerpetualLoanAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPriceThreshold","type":"uint256"}],"name":"updatePriceThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRateDecreaseAdjustment","type":"uint256"}],"name":"updateRateDecreaseAdjustment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRateIncreaseAdjustment","type":"uint256"}],"name":"updateRateIncreaseAdjustment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newTargetPrice","type":"uint256"}],"name":"updateTargetPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOracle","type":"address"}],"name":"updateUsdxlOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdxlOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"to","type":"address"}],"name":"withdrawHYPE","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"to","type":"address"}],"name":"withdrawSuppliedHYPE","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawUsdxl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101006040526a464f733baa0ae6750000006003556b019d971e4fe8401e740000006004556a01a784379d99db4200000060055569d3c21bcecceda10000006006556305ee3fe06007556305f5e100600855604051620041e2380380620041e2833981016040819052620000739162000465565b8784846200008133620003f8565b6001600160a01b03831660805260018290556200009e81620003f8565b50506001600255506001600160a01b038716620001025760405162461bcd60e51b815260206004820152601360248201527f496e76616c696420555344584c20746f6b656e0000000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b0386166200015a5760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420555344584c206f7261636c650000000000000000000000006044820152606401620000f9565b6001600160a01b038516620001b25760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420555344584c207265736572766500000000000000000000006044820152606401620000f9565b6001600160a01b0381166200020a5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c6964205772617070656448797065476174657761790000000000006044820152606401620000f9565b600354841015620002535760405162461bcd60e51b8152602060048201526012602482015271526174652062656c6f77206d696e696d756d60701b6044820152606401620000f9565b6004548411156200029c5760405162461bcd60e51b8152602060048201526012602482015271526174652061626f7665206d6178696d756d60701b6044820152606401620000f9565b60008211620002ee5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c69642070657270657475616c206c6f616e20616d6f756e740000006044820152606401620000f9565b6001600160a01b0387811660a05285811660c05281811660e052600d85905542600c556009839055613840600a55600b80546001600160a01b0319169188169190911790553415620003ea5760e051604051639c15174560e01b815260006004820181905230602483015260448201526001600160a01b0390911690639c1517459034906064016000604051808303818588803b1580156200038f57600080fd5b505af1158015620003a4573d6000803e3d6000fd5b5050604080513481524260208201527f67a068931a4abc547555f12ffcdd391ad9e7086ceb1677eb992db80af461009d9450019150620003e19050565b60405180910390a15b5050505050505050620004fb565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200046057600080fd5b919050565b600080600080600080600080610100898b0312156200048357600080fd5b6200048e8962000448565b97506200049e60208a0162000448565b9650620004ae60408a0162000448565b9550620004be60608a0162000448565b945060808901519350620004d560a08a0162000448565b925060c08901519150620004ec60e08a0162000448565b90509295985092959890939650565b60805160a05160c05160e051613c0c620005d66000396000818161093901528181610b680152818161296a01528181612beb0152612c950152600081816109ef01528181611b2c01528181611dd0015281816126e701528181612e7701528181612f0e015281816130ee015281816131a5015261323a015260008181610528015281816118860152818161196401528181611a9801528181611d3c015261305c01526000818161041d01528181610ae2015281816119ef01528181611c9301528181612650015281816128e40152612dc30152613c0c6000f3fe6080604052600436106103c75760003560e01c80639761f8ce116101f2578063d5cd73911161010d578063f4202409116100a0578063facdc09e1161006f578063facdc09e14610a9d578063fe5fd698146105fc578063fe64330714610abd578063ff516c49146104e157600080fd5b8063f420240914610480578063f6d3151614610a47578063f84578ea14610a67578063f9f8bdb714610a8757600080fd5b8063ece1d6e5116100dc578063ece1d6e5146109c7578063ee7ad162146109dd578063f19f1e0014610a11578063f2fde38b14610a2757600080fd5b8063d5cd739114610480578063dc38679c14610971578063dedd8cac14610987578063ea2f496a146109a757600080fd5b8063acd7868611610185578063bd51675311610154578063bd516753146108f2578063be10aba014610912578063c28eaa7814610927578063cc2f60931461095b57600080fd5b8063acd7868614610480578063add575a7146108bd578063bb922916146108d2578063bc6269081461048057600080fd5b8063a5ea11da116101c1578063a5ea11da14610831578063a8d9e56f1461087d578063a9c622f8146105fc578063ac060cf91461089d57600080fd5b80639761f8ce146107895780639ac2a0111461079f578063a04d2faf146107cf578063a5898709146107ef57600080fd5b806357272272116102e257806380031e37116102755780638da5cb5b116102445780638da5cb5b146107115780638eef960f1461072f578063904122951461074957806396d8054e1461076957600080fd5b806380031e37146104e157806385137585146106c65780638608794a146106dc5780638ad34914146106fc57600080fd5b80636e0f69e3116102b15780636e0f69e3146106865780636fb92589146105fc578063715018a61461069b57806373b379bd146106b057600080fd5b806357272272146106115780635add639f146106315780635e3ae238146106515780636bc78cb51461067157600080fd5b806334b85e741161035a57806349d22a771161032957806349d22a771461059a5780634a2beaf9146105c65780634c709cca146105dc57806354c365c6146105fc57600080fd5b806334b85e74146104f6578063389d14a714610516578063426ca1b51461054a578063462bdfa61461056a57600080fd5b806314e32da41161039657806314e32da4146104805780632164447d146104aa57806328b80bc8146104bf57806334762ca5146104e157600080fd5b80630542975c1461040b5780630616c86a1461045c5780630b3429a2146104805780630cb604431461049457600080fd5b3661040657604080513381523460208201527f09f7c073563f4b0adf29248cf8ac6e5733395ce2ae6fbdd90e3a609ecefb0b1c910160405180910390a1005b600080fd5b34801561041757600080fd5b5061043f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561046857600080fd5b5061047260095481565b604051908152602001610453565b34801561048c57600080fd5b506000610472565b3480156104a057600080fd5b5061047260035481565b3480156104b657600080fd5b50610472610add565b3480156104cb57600080fd5b506104df6104da3660046133d5565b610cef565b005b3480156104ed57600080fd5b50600154610472565b34801561050257600080fd5b506104df61051136600461341e565b610e78565b34801561052257600080fd5b5061043f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561055657600080fd5b506104df61056536600461344c565b610f3c565b34801561057657600080fd5b5061058a610585366004613465565b610f8c565b6040519015158152602001610453565b3480156105a657600080fd5b506105af610fc7565b604080519215158352602083019190915201610453565b3480156105d257600080fd5b5061047260065481565b3480156105e857600080fd5b506104df6105f736600461344c565b610fe2565b34801561060857600080fd5b50610472600081565b34801561061d57600080fd5b506104df61062c366004613465565b6110a1565b34801561063d57600080fd5b506104df61064c36600461344c565b61115a565b34801561065d57600080fd5b506104df61066c36600461344c565b611257565b34801561067d57600080fd5b506104726112f7565b34801561069257600080fd5b5061058a61130e565b3480156106a757600080fd5b506104df611328565b3480156106bc57600080fd5b50610472600c5481565b3480156106d257600080fd5b50610472600f5481565b3480156106e857600080fd5b506104df6106f73660046133d5565b61133c565b34801561070857600080fd5b50610472611364565b34801561071d57600080fd5b506000546001600160a01b031661043f565b34801561073b57600080fd5b50600e5461058a9060ff1681565b34801561075557600080fd5b506104df610764366004613489565b61136e565b34801561077557600080fd5b50600b5461043f906001600160a01b031681565b34801561079557600080fd5b50610472600a5481565b3480156107ab57600080fd5b5061058a6107ba366004613465565b60106020526000908152604090205460ff1681565b3480156107db57600080fd5b506104df6107ea36600461344c565b611617565b3480156107fb57600080fd5b5061081661080a366004613536565b50600154600091829190565b60408051938452602084019290925290820152606001610453565b34801561083d57600080fd5b50600354600454600554600654600754600854604080519687526020870195909552938501929092526060840152608083015260a082015260c001610453565b34801561088957600080fd5b506104df6108983660046135bb565b505050565b3480156108a957600080fd5b506104df6108b83660046133d5565b611821565b3480156108c957600080fd5b506104df6119d1565b3480156108de57600080fd5b506104df6108ed36600461344c565b611be5565b3480156108fe57600080fd5b506104df61090d366004613465565b611c47565b34801561091e57600080fd5b50610472611eed565b34801561093357600080fd5b5061043f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561096757600080fd5b5061047260075481565b34801561097d57600080fd5b5061047260085481565b34801561099357600080fd5b506104df6109a236600461368c565b611fb1565b3480156109b357600080fd5b506104df6109c236600461344c565b6121ee565b3480156109d357600080fd5b5061047260045481565b3480156109e957600080fd5b5061043f7f000000000000000000000000000000000000000000000000000000000000000081565b348015610a1d57600080fd5b5061047260055481565b348015610a3357600080fd5b506104df610a42366004613465565b6122d9565b348015610a5357600080fd5b506104df610a6236600461344c565b61234f565b348015610a7357600080fd5b506104df610a8236600461344c565b6123b1565b348015610a9357600080fd5b50610472600d5481565b348015610aa957600080fd5b506104df610ab836600461344c565b612465565b348015610ac957600080fd5b506104df610ad836600461344c565b612545565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b629190613703565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca6cabf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be89190613703565b6040516335ea6a7560e01b81526001600160a01b0380831660048301529192506000918416906335ea6a75906024016101e060405180830381865afa158015610c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5991906137b7565b6101008101519091506001600160a01b038116610c7b57600094505050505090565b6040516370a0823160e01b815230600482015281906001600160a01b038216906370a0823190602401602060405180830381865afa158015610cc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce591906138cf565b9550505050505090565b610cf76125f1565b6001600160a01b038116610d265760405162461bcd60e51b8152600401610d1d906138e8565b60405180910390fd5b60008211610d465760405162461bcd60e51b8152600401610d1d90613913565b81471015610d965760405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e7420485950452062616c616e6365000000000000006044820152606401610d1d565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610de3576040519150601f19603f3d011682016040523d82523d6000602084013e610de8565b606091505b5050905080610e305760405162461bcd60e51b815260206004820152601460248201527312165411481d1c985b9cd9995c8819985a5b195960621b6044820152606401610d1d565b604080516001600160a01b0384168152602081018590527f33985deaffacd3ddd807c7b19f8547a1bbdde83b81bb162d9de7e330c897136e91015b60405180910390a1505050565b610e806125f1565b6001600160a01b038216610ed15760405162461bcd60e51b8152602060048201526018602482015277496e76616c6964206578656375746f72206164647265737360401b6044820152606401610d1d565b6001600160a01b038216600081815260106020908152604091829020805460ff191685151590811790915582519384529083015242908201527fdee89cbd403a5d71d16b5fd869d30791145a11ef4ea6faed0c6f1e0d207c0740906060015b60405180910390a15050565b610f446125f1565b6001805490829055604080518281526020810184905242918101919091527fae105abe8db839281c90b44a9f60cf111b2217cf082514ef8db4786387753d8890606001610f30565b600080546001600160a01b0383811691161480610fc157506001600160a01b03821660009081526010602052604090205460ff165b92915050565b600e54600090819060ff16610fda61264b565b915091509091565b610fea6125f1565b6000811161103a5760405162461bcd60e51b815260206004820181905260248201527f5072696365207468726573686f6c64206d75737420626520706f7369746976656044820152606401610d1d565b60085481111561105c5760405162461bcd60e51b8152600401610d1d9061393b565b80600781905550600080516020613bb783398151915260035460045460055460065485600854426040516110969796959493929190613972565b60405180910390a150565b6110a96125f1565b6001600160a01b0381166110f65760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420555344584c206f7261636c6560601b6044820152606401610d1d565b600b80546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935242918101919091527faaecfe3bdac21e1937025e18a5bb7a072a7c4ffa13c2e330663152f1f83ee17290606001610f30565b6111626125f1565b600081116111ae5760405162461bcd60e51b81526020600482015260196024820152784d61782072617465206d75737420626520706f73697469766560381b6044820152606401610d1d565b60035481116111ff5760405162461bcd60e51b815260206004820152601d60248201527f4d61782072617465206d75737420657863656564206d696e20726174650000006044820152606401610d1d565b80600d54111561120f57600d8190555b6004805490829055604080518281526020810184905242918101919091527fb5e18a5f25a9f30f9b0b7097b5337669f12771ba3ef967ba06fce096ecd8c3ad90606001610f30565b61125f6125f1565b600081116112af5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c69642070657270657475616c206c6f616e20616d6f756e740000006044820152606401610d1d565b6009805490829055604080518281526020810184905242918101919091527f25a169c83d01e8e148e016e3ceb340b3387511cf6aac042f3ba44c6ea4e355b990606001610f30565b6000600a54600c5461130991906139b8565b905090565b6000600a54600c5461132091906139b8565b421015905090565b6113306125f1565b61133a60006127f2565b565b6113446125f1565b61134c612842565b611356828261289a565b6113606001600255565b5050565b6000611309612d44565b6113766125f1565b600086116113c25760405162461bcd60e51b81526020600482015260196024820152784d696e2072617465206d75737420626520706f73697469766560381b6044820152606401610d1d565b6000851161140e5760405162461bcd60e51b81526020600482015260196024820152784d61782072617465206d75737420626520706f73697469766560381b6044820152606401610d1d565b85851161145d5760405162461bcd60e51b815260206004820152601d60248201527f4d61782072617465206d75737420657863656564206d696e20726174650000006044820152606401610d1d565b6000841161147d5760405162461bcd60e51b8152600401610d1d906139d0565b6000831161149d5760405162461bcd60e51b8152600401610d1d90613a14565b600082116114ed5760405162461bcd60e51b815260206004820181905260248201527f5072696365207468726573686f6c64206d75737420626520706f7369746976656044820152606401610d1d565b6000811161153d5760405162461bcd60e51b815260206004820152601d60248201527f546172676574207072696365206d75737420626520706f7369746976650000006044820152606401610d1d565b8082111561155d5760405162461bcd60e51b8152600401610d1d9061393b565b85600d5410156115af5760405162461bcd60e51b815260206004820152601e60248201527f43757272656e7420726174652062656c6f77206e6577206d696e696d756d00006044820152606401610d1d565b84600d5411156115bf57600d8590555b600386905560048590556005849055600683905560078290556008819055604051600080516020613bb783398151915290611607908890889088908890889088904290613972565b60405180910390a1505050505050565b61161f612842565b6000546001600160a01b031633148061164757503360009081526010602052604090205460ff165b61168b5760405162461bcd60e51b81526020600482015260156024820152742ab730baba3437b934bd32b21032bc32b1baba37b960591b6044820152606401610d1d565b600a54600c5461169b91906139b8565b4210156116ce576040805160018152426020820152600080516020613b97833981519152910160405180910390a1611814565b600081136117175760405162461bcd60e51b81526020600482015260166024820152754f6666636861696e207072696365206973207a65726f60501b6044820152606401610d1d565b6000611721612d44565b90508180611757576040805160028152426020820152600080516020613b97833981519152910160405180910390a15050611814565b6040805184815260208101849052428183015290517ffe0113fb0a73b6ea465e3096745b04edda6906c41c398df592dde86af42442b89181900360600190a161179e612dbf565b60006117a982613336565b9050600d54811461180c576117bd81600155565b600d54604080519182526020820183905281018390524260608201527fdd8196f9280a887c2cda9ceaa0c9f147ee5931086cfa28738c70c45ce383f1cb9060800160405180910390a1600d8190555b505042600c55505b61181e6001600255565b50565b6118296125f1565b6001600160a01b03811661184f5760405162461bcd60e51b8152600401610d1d906138e8565b6000821161186f5760405162461bcd60e51b8152600401610d1d90613913565b6040516370a0823160e01b815230600482015282907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f991906138cf565b101561193e5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610d1d565b60405163a9059cbb60e01b81526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156119ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190613a58565b6119d96125f1565b60006119e361264b565b9050801561181e5760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6f9190613703565b60405163095ea7b360e01b81526001600160a01b038083166004830152602482018590529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b079190613a58565b5060405163573ade8160e01b81526001600160a01b0382169063573ade8190611b5b907f00000000000000000000000000000000000000000000000000000000000000009086906002903090600401613a75565b6020604051808303816000875af1925050508015611b96575060408051601f3d908101601f19168201909252611b93918101906138cf565b60015b611bd15760405162461bcd60e51b815260206004820152600c60248201526b14995c185e4819985a5b195960a21b6044820152606401610d1d565b50600e805460ff191690556000600f555050565b611bed6125f1565b60008111611c0d5760405162461bcd60e51b8152600401610d1d906139d0565b80600581905550600080516020613bb783398151915260035460045483600654600754600854426040516110969796959493929190613972565b611c4f6125f1565b611c57612842565b6001600160a01b038116611c7d5760405162461bcd60e51b8152600401610d1d906138e8565b6000611c8761264b565b90508015611e935760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d139190613703565b60405163095ea7b360e01b81526001600160a01b038083166004830152602482018590529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611d87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dab9190613a58565b5060405163573ade8160e01b81526001600160a01b0382169063573ade8190611dff907f00000000000000000000000000000000000000000000000000000000000000009086906002903090600401613a75565b6020604051808303816000875af1925050508015611e3a575060408051601f3d908101601f19168201909252611e37918101906138cf565b60015b611e7d5760405162461bcd60e51b815260206004820152601460248201527311985a5b1959081d1bc81c995c185e481919589d60621b6044820152606401610d1d565b50600e805460ff191690556000600f5550611ea3565b600e805460ff191690556000600f555b611eaf6000198361289a565b6040514281527f50d3f9b87161fe68d44f1df9c50ec05198e280f710299688dccdd0dea547266c9060200160405180910390a15061181e6001600255565b600b5460408051600481526024810182526020810180516001600160e01b03166350d25bcd60e01b1790529051600092839283926001600160a01b0390921691611f379190613aa0565b600060405180830381855afa9150503d8060008114611f72576040519150601f19603f3d011682016040523d82523d6000602084013e611f77565b606091505b5091509150811580611f8857508051155b15611f965760009250505090565b80806020019051810190611faa91906138cf565b9250505090565b611fb96125f1565b8281146120015760405162461bcd60e51b8152602060048201526016602482015275082e4e4c2f2e640d8cadccee8d040dad2e6dac2e8c6d60531b6044820152606401610d1d565b8261203d5760405162461bcd60e51b815260206004820152600c60248201526b456d7074792061727261797360a01b6044820152606401610d1d565b60005b838110156121e757600085858381811061205c5761205c613adb565b90506020020160208101906120719190613465565b6001600160a01b031614156120c35760405162461bcd60e51b8152602060048201526018602482015277496e76616c6964206578656375746f72206164647265737360401b6044820152606401610d1d565b8282828181106120d5576120d5613adb565b90506020020160208101906120ea9190613af1565b6010600087878581811061210057612100613adb565b90506020020160208101906121159190613465565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790557fdee89cbd403a5d71d16b5fd869d30791145a11ef4ea6faed0c6f1e0d207c074085858381811061217057612170613adb565b90506020020160208101906121859190613465565b84848481811061219757612197613adb565b90506020020160208101906121ac9190613af1565b604080516001600160a01b0390931683529015156020830152429082015260600160405180910390a1806121df81613b0e565b915050612040565b5050505050565b6121f66125f1565b60035481101561223d5760405162461bcd60e51b8152602060048201526012602482015271526174652062656c6f77206d696e696d756d60701b6044820152606401610d1d565b6004548111156122845760405162461bcd60e51b8152602060048201526012602482015271526174652061626f7665206d6178696d756d60701b6044820152606401610d1d565b61228d81600155565b600d81905560408051828152602081018390526000918101919091524260608201527fdd8196f9280a887c2cda9ceaa0c9f147ee5931086cfa28738c70c45ce383f1cb90608001611096565b6122e16125f1565b6001600160a01b0381166123465760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d1d565b61181e816127f2565b6123576125f1565b600081116123775760405162461bcd60e51b8152600401610d1d90613a14565b80600681905550600080516020613bb783398151915260035460045460055484600754600854426040516110969796959493929190613972565b6123b96125f1565b600081116124095760405162461bcd60e51b815260206004820152601d60248201527f546172676574207072696365206d75737420626520706f7369746976650000006044820152606401610d1d565b80600754111561242b5760405162461bcd60e51b8152600401610d1d9061393b565b80600881905550600080516020613bb783398151915260035460045460055460065460075486426040516110969796959493929190613972565b61246d6125f1565b600081116124b95760405162461bcd60e51b81526020600482015260196024820152784d696e2072617465206d75737420626520706f73697469766560381b6044820152606401610d1d565b80600d54101561250b5760405162461bcd60e51b815260206004820152601e60248201527f43757272656e7420726174652062656c6f77206e6577206d696e696d756d00006044820152606401610d1d565b80600381905550600080516020613bb783398151915281600454600554600654600754600854426040516110969796959493929190613972565b61254d6125f1565b600081116125a95760405162461bcd60e51b815260206004820152602360248201527f457865637574696f6e20696e74657276616c206d75737420626520706f73697460448201526269766560e81b6064820152608401610d1d565b600a805490829055604080518281526020810184905242918101919091527f3f270eceb5b4127539ba3b0318b668db0a68260fd04bccd7c6705452084832e890606001610f30565b6000546001600160a01b0316331461133a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d1d565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d09190613703565b6040516335ea6a7560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000918316906335ea6a75906024016101e060405180830381865afa15801561273d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061276191906137b7565b6101408101519091506001600160a01b038116612782576000935050505090565b6040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156127c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ea91906138cf565b935050505090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6002805414156128945760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d1d565b60028055565b6001600160a01b0381166128c05760405162461bcd60e51b8152600401610d1d906138e8565b600082116128e05760405162461bcd60e51b8152600401610d1d90613913565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612940573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129649190613703565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca6cabf56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ea9190613703565b6040516335ea6a7560e01b81526001600160a01b0380831660048301529192506000918416906335ea6a75906024016101e060405180830381865afa158015612a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5b91906137b7565b6101008101519091506001600160a01b038116612ab35760405162461bcd60e51b81526020600482015260166024820152751855d2165411481d1bdad95b881b9bdd08199bdd5b9960521b6044820152606401610d1d565b6040516370a0823160e01b815230600482015281906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015612afc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2091906138cf565b905060008111612b725760405162461bcd60e51b815260206004820152601c60248201527f4e6f20737570706c696564204859504520746f207769746864726177000000006044820152606401610d1d565b87600019811415612b84575080612bd4565b81891115612bd45760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e74206157485950452062616c616e636500000000006044820152606401610d1d565b60405163095ea7b360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820183905284169063095ea7b3906044016020604051808303816000875af1158015612c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c679190613a58565b50604051637d05e65760e11b815260006004820152602481018290526001600160a01b0389811660448301527f0000000000000000000000000000000000000000000000000000000000000000169063fa0bccae90606401600060405180830381600087803b158015612cd957600080fd5b505af1158015612ced573d6000803e3d6000fd5b5050604080518481526001600160a01b038c166020820152428183015290517fa456360b32d69444bac6d8135b2fc74d4ea3ada831137055da97c17ecce0540d9350908190036060019150a1505050505050505050565b6000306001600160a01b031663be10aba06040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612da0575060408051601f3d908101601f19168201909252612d9d918101906138cf565b60015b612daa5750600090565b60008113612dba57600091505090565b919050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e439190613703565b600e5490915060ff166130245760095460405163a415bcad60e01b81526001600160a01b0383169163a415bcad91612ea7917f0000000000000000000000000000000000000000000000000000000000000000916002906000903090600401613b29565b600060405180830381600087803b158015612ec157600080fd5b505af1925050508015612ed2575060015b612fda576000600a600954612ee79190613b5d565b60405163a415bcad60e01b81529091506001600160a01b0383169063a415bcad90612f40907f00000000000000000000000000000000000000000000000000000000000000009085906002906000903090600401613b29565b600060405180830381600087803b158015612f5a57600080fd5b505af1925050508015612f6b575060015b612f93576040805160038152426020820152600080516020613b978339815191529101610f30565b600e805460ff19166001179055600f819055604080518281524260208201527f1b2bf01de22db633e18d8b704f3e11ea6d294d690a9b3c2de306d04eacf1b2899101610f30565b600e805460ff19166001179055600954600f819055604080519182524260208301527f1b2bf01de22db633e18d8b704f3e11ea6d294d690a9b3c2de306d04eacf1b2899101611096565b600061302e61264b565b905080156113605760405163095ea7b360e01b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af11580156130a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c99190613a58565b5060405163573ade8160e01b81526001600160a01b0383169063573ade819061311d907f00000000000000000000000000000000000000000000000000000000000000009085906002903090600401613a75565b6020604051808303816000875af1925050508015613158575060408051601f3d908101601f19168201909252613155918101906138cf565b60015b613180576040805160058152426020820152600080516020613b978339815191529101610f30565b5060405163a415bcad60e01b81526001600160a01b0383169063a415bcad906131d7907f00000000000000000000000000000000000000000000000000000000000000009085906002906000903090600401613b29565b600060405180830381600087803b1580156131f157600080fd5b505af1925050508015613202575060015b613301576000613213600283613b5d565b60405163a415bcad60e01b81529091506001600160a01b0384169063a415bcad9061326c907f00000000000000000000000000000000000000000000000000000000000000009085906002906000903090600401613b29565b600060405180830381600087803b15801561328657600080fd5b505af1925050508015613297575060015b6132c7576040805160048152426020820152600080516020613b97833981519152910160405180910390a1505050565b600f819055604080518281524260208201527f3f7fd57369099a2eb7970f3bae765cdd92012a3912e26ae5d4f634510815b9bb9101610e6b565b604080518281524260208201527f3f7fd57369099a2eb7970f3bae765cdd92012a3912e26ae5d4f634510815b9bb9101610f30565b600d546007546000919083101561336d57600554600d5461335791906139b8565b905060045481111561336857506004545b610fc1565b60075483101580156133825750600354600d54115b15610fc157600654600d541161339a576003546133aa565b600654600d546133aa9190613b7f565b9050600354811015610fc1575060035492915050565b6001600160a01b038116811461181e57600080fd5b600080604083850312156133e857600080fd5b8235915060208301356133fa816133c0565b809150509250929050565b8035612dba816133c0565b801515811461181e57600080fd5b6000806040838503121561343157600080fd5b823561343c816133c0565b915060208301356133fa81613410565b60006020828403121561345e57600080fd5b5035919050565b60006020828403121561347757600080fd5b8135613482816133c0565b9392505050565b60008060008060008060c087890312156134a257600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b604051610120810167ffffffffffffffff811182821017156134fe57634e487b7160e01b600052604160045260246000fd5b60405290565b6040516101e0810167ffffffffffffffff811182821017156134fe57634e487b7160e01b600052604160045260246000fd5b6000610120828403121561354957600080fd5b6135516134cc565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015261359d60e08401613405565b60e08201526101006135b0818501613405565b908201529392505050565b6000806000604084860312156135d057600080fd5b83356135db816133c0565b9250602084013567ffffffffffffffff808211156135f857600080fd5b818601915086601f83011261360c57600080fd5b81358181111561361b57600080fd5b87602082850101111561362d57600080fd5b6020830194508093505050509250925092565b60008083601f84011261365257600080fd5b50813567ffffffffffffffff81111561366a57600080fd5b6020830191508360208260051b850101111561368557600080fd5b9250929050565b600080600080604085870312156136a257600080fd5b843567ffffffffffffffff808211156136ba57600080fd5b6136c688838901613640565b909650945060208701359150808211156136df57600080fd5b506136ec87828801613640565b95989497509550505050565b8051612dba816133c0565b60006020828403121561371557600080fd5b8151613482816133c0565b60006020828403121561373257600080fd5b6040516020810181811067ffffffffffffffff8211171561376357634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff81168114612dba57600080fd5b805164ffffffffff81168114612dba57600080fd5b805161ffff81168114612dba57600080fd5b60006101e082840312156137ca57600080fd5b6137d2613504565b6137dc8484613720565b81526137ea60208401613770565b60208201526137fb60408401613770565b604082015261380c60608401613770565b606082015261381d60808401613770565b608082015261382e60a08401613770565b60a082015261383f60c08401613790565b60c082015261385060e084016137a5565b60e08201526101006138638185016136f8565b908201526101206138758482016136f8565b908201526101406138878482016136f8565b908201526101606138998482016136f8565b908201526101806138ab848201613770565b908201526101a06138bd848201613770565b908201526101c06135b0848201613770565b6000602082840312156138e157600080fd5b5051919050565b602080825260119082015270125b9d985b1a59081c9958da5c1a595b9d607a1b604082015260600190565b6020808252600e908201526d125b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b6020808252601e908201527f5468726573686f6c642063616e6e6f7420657863656564207461726765740000604082015260600190565b968752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b634e487b7160e01b600052601160045260246000fd5b600082198211156139cb576139cb6139a2565b500190565b60208082526024908201527f496e6372656173652061646a7573746d656e74206d75737420626520706f73696040820152637469766560e01b606082015260800190565b60208082526024908201527f44656372656173652061646a7573746d656e74206d75737420626520706f73696040820152637469766560e01b606082015260800190565b600060208284031215613a6a57600080fd5b815161348281613410565b6001600160a01b03948516815260208101939093526040830191909152909116606082015260800190565b6000825160005b81811015613ac15760208186018101518583015201613aa7565b81811115613ad0576000828501525b509190910192915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613b0357600080fd5b813561348281613410565b6000600019821415613b2257613b226139a2565b5060010190565b6001600160a01b0395861681526020810194909452604084019290925261ffff166060830152909116608082015260a00190565b600082613b7a57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015613b9157613b916139a2565b50039056fe6a7e30b1d18177663daff1c1684bc81a8054d0f1a232cb7d189fe08a93fe9db13d74e607b6fd730acbea4d47a114bafaa8f32af5d4a29e0b720f850c86aec308a2646970667358221220a3e02ec17253188222a2f04c87ff1ca5e8b0e858dd1a253b2393d7efd6a025f764736f6c634300080a0033000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd5594000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645000000000000000000000000e52085b9bbc0bef8294ecd0546f8cb5158bb2eaa000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645000000000000000000000000000000000000000000707f1ec5dcde3d88000000000000000000000000000000528c211dce38d3d9005bad04af8a3201876205a2000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000d1ef87fefa83154f83541b68bd09185e15463972
Deployed Bytecode
0x6080604052600436106103c75760003560e01c80639761f8ce116101f2578063d5cd73911161010d578063f4202409116100a0578063facdc09e1161006f578063facdc09e14610a9d578063fe5fd698146105fc578063fe64330714610abd578063ff516c49146104e157600080fd5b8063f420240914610480578063f6d3151614610a47578063f84578ea14610a67578063f9f8bdb714610a8757600080fd5b8063ece1d6e5116100dc578063ece1d6e5146109c7578063ee7ad162146109dd578063f19f1e0014610a11578063f2fde38b14610a2757600080fd5b8063d5cd739114610480578063dc38679c14610971578063dedd8cac14610987578063ea2f496a146109a757600080fd5b8063acd7868611610185578063bd51675311610154578063bd516753146108f2578063be10aba014610912578063c28eaa7814610927578063cc2f60931461095b57600080fd5b8063acd7868614610480578063add575a7146108bd578063bb922916146108d2578063bc6269081461048057600080fd5b8063a5ea11da116101c1578063a5ea11da14610831578063a8d9e56f1461087d578063a9c622f8146105fc578063ac060cf91461089d57600080fd5b80639761f8ce146107895780639ac2a0111461079f578063a04d2faf146107cf578063a5898709146107ef57600080fd5b806357272272116102e257806380031e37116102755780638da5cb5b116102445780638da5cb5b146107115780638eef960f1461072f578063904122951461074957806396d8054e1461076957600080fd5b806380031e37146104e157806385137585146106c65780638608794a146106dc5780638ad34914146106fc57600080fd5b80636e0f69e3116102b15780636e0f69e3146106865780636fb92589146105fc578063715018a61461069b57806373b379bd146106b057600080fd5b806357272272146106115780635add639f146106315780635e3ae238146106515780636bc78cb51461067157600080fd5b806334b85e741161035a57806349d22a771161032957806349d22a771461059a5780634a2beaf9146105c65780634c709cca146105dc57806354c365c6146105fc57600080fd5b806334b85e74146104f6578063389d14a714610516578063426ca1b51461054a578063462bdfa61461056a57600080fd5b806314e32da41161039657806314e32da4146104805780632164447d146104aa57806328b80bc8146104bf57806334762ca5146104e157600080fd5b80630542975c1461040b5780630616c86a1461045c5780630b3429a2146104805780630cb604431461049457600080fd5b3661040657604080513381523460208201527f09f7c073563f4b0adf29248cf8ac6e5733395ce2ae6fbdd90e3a609ecefb0b1c910160405180910390a1005b600080fd5b34801561041757600080fd5b5061043f7f000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd559481565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561046857600080fd5b5061047260095481565b604051908152602001610453565b34801561048c57600080fd5b506000610472565b3480156104a057600080fd5b5061047260035481565b3480156104b657600080fd5b50610472610add565b3480156104cb57600080fd5b506104df6104da3660046133d5565b610cef565b005b3480156104ed57600080fd5b50600154610472565b34801561050257600080fd5b506104df61051136600461341e565b610e78565b34801561052257600080fd5b5061043f7f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc64581565b34801561055657600080fd5b506104df61056536600461344c565b610f3c565b34801561057657600080fd5b5061058a610585366004613465565b610f8c565b6040519015158152602001610453565b3480156105a657600080fd5b506105af610fc7565b604080519215158352602083019190915201610453565b3480156105d257600080fd5b5061047260065481565b3480156105e857600080fd5b506104df6105f736600461344c565b610fe2565b34801561060857600080fd5b50610472600081565b34801561061d57600080fd5b506104df61062c366004613465565b6110a1565b34801561063d57600080fd5b506104df61064c36600461344c565b61115a565b34801561065d57600080fd5b506104df61066c36600461344c565b611257565b34801561067d57600080fd5b506104726112f7565b34801561069257600080fd5b5061058a61130e565b3480156106a757600080fd5b506104df611328565b3480156106bc57600080fd5b50610472600c5481565b3480156106d257600080fd5b50610472600f5481565b3480156106e857600080fd5b506104df6106f73660046133d5565b61133c565b34801561070857600080fd5b50610472611364565b34801561071d57600080fd5b506000546001600160a01b031661043f565b34801561073b57600080fd5b50600e5461058a9060ff1681565b34801561075557600080fd5b506104df610764366004613489565b61136e565b34801561077557600080fd5b50600b5461043f906001600160a01b031681565b34801561079557600080fd5b50610472600a5481565b3480156107ab57600080fd5b5061058a6107ba366004613465565b60106020526000908152604090205460ff1681565b3480156107db57600080fd5b506104df6107ea36600461344c565b611617565b3480156107fb57600080fd5b5061081661080a366004613536565b50600154600091829190565b60408051938452602084019290925290820152606001610453565b34801561083d57600080fd5b50600354600454600554600654600754600854604080519687526020870195909552938501929092526060840152608083015260a082015260c001610453565b34801561088957600080fd5b506104df6108983660046135bb565b505050565b3480156108a957600080fd5b506104df6108b83660046133d5565b611821565b3480156108c957600080fd5b506104df6119d1565b3480156108de57600080fd5b506104df6108ed36600461344c565b611be5565b3480156108fe57600080fd5b506104df61090d366004613465565b611c47565b34801561091e57600080fd5b50610472611eed565b34801561093357600080fd5b5061043f7f000000000000000000000000d1ef87fefa83154f83541b68bd09185e1546397281565b34801561096757600080fd5b5061047260075481565b34801561097d57600080fd5b5061047260085481565b34801561099357600080fd5b506104df6109a236600461368c565b611fb1565b3480156109b357600080fd5b506104df6109c236600461344c565b6121ee565b3480156109d357600080fd5b5061047260045481565b3480156109e957600080fd5b5061043f7f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc64581565b348015610a1d57600080fd5b5061047260055481565b348015610a3357600080fd5b506104df610a42366004613465565b6122d9565b348015610a5357600080fd5b506104df610a6236600461344c565b61234f565b348015610a7357600080fd5b506104df610a8236600461344c565b6123b1565b348015610a9357600080fd5b50610472600d5481565b348015610aa957600080fd5b506104df610ab836600461344c565b612465565b348015610ac957600080fd5b506104df610ad836600461344c565b612545565b6000807f000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd55946001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b629190613703565b905060007f000000000000000000000000d1ef87fefa83154f83541b68bd09185e154639726001600160a01b031663ca6cabf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be89190613703565b6040516335ea6a7560e01b81526001600160a01b0380831660048301529192506000918416906335ea6a75906024016101e060405180830381865afa158015610c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5991906137b7565b6101008101519091506001600160a01b038116610c7b57600094505050505090565b6040516370a0823160e01b815230600482015281906001600160a01b038216906370a0823190602401602060405180830381865afa158015610cc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce591906138cf565b9550505050505090565b610cf76125f1565b6001600160a01b038116610d265760405162461bcd60e51b8152600401610d1d906138e8565b60405180910390fd5b60008211610d465760405162461bcd60e51b8152600401610d1d90613913565b81471015610d965760405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e7420485950452062616c616e6365000000000000006044820152606401610d1d565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610de3576040519150601f19603f3d011682016040523d82523d6000602084013e610de8565b606091505b5050905080610e305760405162461bcd60e51b815260206004820152601460248201527312165411481d1c985b9cd9995c8819985a5b195960621b6044820152606401610d1d565b604080516001600160a01b0384168152602081018590527f33985deaffacd3ddd807c7b19f8547a1bbdde83b81bb162d9de7e330c897136e91015b60405180910390a1505050565b610e806125f1565b6001600160a01b038216610ed15760405162461bcd60e51b8152602060048201526018602482015277496e76616c6964206578656375746f72206164647265737360401b6044820152606401610d1d565b6001600160a01b038216600081815260106020908152604091829020805460ff191685151590811790915582519384529083015242908201527fdee89cbd403a5d71d16b5fd869d30791145a11ef4ea6faed0c6f1e0d207c0740906060015b60405180910390a15050565b610f446125f1565b6001805490829055604080518281526020810184905242918101919091527fae105abe8db839281c90b44a9f60cf111b2217cf082514ef8db4786387753d8890606001610f30565b600080546001600160a01b0383811691161480610fc157506001600160a01b03821660009081526010602052604090205460ff165b92915050565b600e54600090819060ff16610fda61264b565b915091509091565b610fea6125f1565b6000811161103a5760405162461bcd60e51b815260206004820181905260248201527f5072696365207468726573686f6c64206d75737420626520706f7369746976656044820152606401610d1d565b60085481111561105c5760405162461bcd60e51b8152600401610d1d9061393b565b80600781905550600080516020613bb783398151915260035460045460055460065485600854426040516110969796959493929190613972565b60405180910390a150565b6110a96125f1565b6001600160a01b0381166110f65760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420555344584c206f7261636c6560601b6044820152606401610d1d565b600b80546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935242918101919091527faaecfe3bdac21e1937025e18a5bb7a072a7c4ffa13c2e330663152f1f83ee17290606001610f30565b6111626125f1565b600081116111ae5760405162461bcd60e51b81526020600482015260196024820152784d61782072617465206d75737420626520706f73697469766560381b6044820152606401610d1d565b60035481116111ff5760405162461bcd60e51b815260206004820152601d60248201527f4d61782072617465206d75737420657863656564206d696e20726174650000006044820152606401610d1d565b80600d54111561120f57600d8190555b6004805490829055604080518281526020810184905242918101919091527fb5e18a5f25a9f30f9b0b7097b5337669f12771ba3ef967ba06fce096ecd8c3ad90606001610f30565b61125f6125f1565b600081116112af5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c69642070657270657475616c206c6f616e20616d6f756e740000006044820152606401610d1d565b6009805490829055604080518281526020810184905242918101919091527f25a169c83d01e8e148e016e3ceb340b3387511cf6aac042f3ba44c6ea4e355b990606001610f30565b6000600a54600c5461130991906139b8565b905090565b6000600a54600c5461132091906139b8565b421015905090565b6113306125f1565b61133a60006127f2565b565b6113446125f1565b61134c612842565b611356828261289a565b6113606001600255565b5050565b6000611309612d44565b6113766125f1565b600086116113c25760405162461bcd60e51b81526020600482015260196024820152784d696e2072617465206d75737420626520706f73697469766560381b6044820152606401610d1d565b6000851161140e5760405162461bcd60e51b81526020600482015260196024820152784d61782072617465206d75737420626520706f73697469766560381b6044820152606401610d1d565b85851161145d5760405162461bcd60e51b815260206004820152601d60248201527f4d61782072617465206d75737420657863656564206d696e20726174650000006044820152606401610d1d565b6000841161147d5760405162461bcd60e51b8152600401610d1d906139d0565b6000831161149d5760405162461bcd60e51b8152600401610d1d90613a14565b600082116114ed5760405162461bcd60e51b815260206004820181905260248201527f5072696365207468726573686f6c64206d75737420626520706f7369746976656044820152606401610d1d565b6000811161153d5760405162461bcd60e51b815260206004820152601d60248201527f546172676574207072696365206d75737420626520706f7369746976650000006044820152606401610d1d565b8082111561155d5760405162461bcd60e51b8152600401610d1d9061393b565b85600d5410156115af5760405162461bcd60e51b815260206004820152601e60248201527f43757272656e7420726174652062656c6f77206e6577206d696e696d756d00006044820152606401610d1d565b84600d5411156115bf57600d8590555b600386905560048590556005849055600683905560078290556008819055604051600080516020613bb783398151915290611607908890889088908890889088904290613972565b60405180910390a1505050505050565b61161f612842565b6000546001600160a01b031633148061164757503360009081526010602052604090205460ff165b61168b5760405162461bcd60e51b81526020600482015260156024820152742ab730baba3437b934bd32b21032bc32b1baba37b960591b6044820152606401610d1d565b600a54600c5461169b91906139b8565b4210156116ce576040805160018152426020820152600080516020613b97833981519152910160405180910390a1611814565b600081136117175760405162461bcd60e51b81526020600482015260166024820152754f6666636861696e207072696365206973207a65726f60501b6044820152606401610d1d565b6000611721612d44565b90508180611757576040805160028152426020820152600080516020613b97833981519152910160405180910390a15050611814565b6040805184815260208101849052428183015290517ffe0113fb0a73b6ea465e3096745b04edda6906c41c398df592dde86af42442b89181900360600190a161179e612dbf565b60006117a982613336565b9050600d54811461180c576117bd81600155565b600d54604080519182526020820183905281018390524260608201527fdd8196f9280a887c2cda9ceaa0c9f147ee5931086cfa28738c70c45ce383f1cb9060800160405180910390a1600d8190555b505042600c55505b61181e6001600255565b50565b6118296125f1565b6001600160a01b03811661184f5760405162461bcd60e51b8152600401610d1d906138e8565b6000821161186f5760405162461bcd60e51b8152600401610d1d90613913565b6040516370a0823160e01b815230600482015282907f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6456001600160a01b0316906370a0823190602401602060405180830381865afa1580156118d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f991906138cf565b101561193e5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610d1d565b60405163a9059cbb60e01b81526001600160a01b038281166004830152602482018490527f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645169063a9059cbb906044016020604051808303816000875af11580156119ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190613a58565b6119d96125f1565b60006119e361264b565b9050801561181e5760007f000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd55946001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6f9190613703565b60405163095ea7b360e01b81526001600160a01b038083166004830152602482018590529192507f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6459091169063095ea7b3906044016020604051808303816000875af1158015611ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b079190613a58565b5060405163573ade8160e01b81526001600160a01b0382169063573ade8190611b5b907f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6459086906002903090600401613a75565b6020604051808303816000875af1925050508015611b96575060408051601f3d908101601f19168201909252611b93918101906138cf565b60015b611bd15760405162461bcd60e51b815260206004820152600c60248201526b14995c185e4819985a5b195960a21b6044820152606401610d1d565b50600e805460ff191690556000600f555050565b611bed6125f1565b60008111611c0d5760405162461bcd60e51b8152600401610d1d906139d0565b80600581905550600080516020613bb783398151915260035460045483600654600754600854426040516110969796959493929190613972565b611c4f6125f1565b611c57612842565b6001600160a01b038116611c7d5760405162461bcd60e51b8152600401610d1d906138e8565b6000611c8761264b565b90508015611e935760007f000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd55946001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d139190613703565b60405163095ea7b360e01b81526001600160a01b038083166004830152602482018590529192507f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6459091169063095ea7b3906044016020604051808303816000875af1158015611d87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dab9190613a58565b5060405163573ade8160e01b81526001600160a01b0382169063573ade8190611dff907f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6459086906002903090600401613a75565b6020604051808303816000875af1925050508015611e3a575060408051601f3d908101601f19168201909252611e37918101906138cf565b60015b611e7d5760405162461bcd60e51b815260206004820152601460248201527311985a5b1959081d1bc81c995c185e481919589d60621b6044820152606401610d1d565b50600e805460ff191690556000600f5550611ea3565b600e805460ff191690556000600f555b611eaf6000198361289a565b6040514281527f50d3f9b87161fe68d44f1df9c50ec05198e280f710299688dccdd0dea547266c9060200160405180910390a15061181e6001600255565b600b5460408051600481526024810182526020810180516001600160e01b03166350d25bcd60e01b1790529051600092839283926001600160a01b0390921691611f379190613aa0565b600060405180830381855afa9150503d8060008114611f72576040519150601f19603f3d011682016040523d82523d6000602084013e611f77565b606091505b5091509150811580611f8857508051155b15611f965760009250505090565b80806020019051810190611faa91906138cf565b9250505090565b611fb96125f1565b8281146120015760405162461bcd60e51b8152602060048201526016602482015275082e4e4c2f2e640d8cadccee8d040dad2e6dac2e8c6d60531b6044820152606401610d1d565b8261203d5760405162461bcd60e51b815260206004820152600c60248201526b456d7074792061727261797360a01b6044820152606401610d1d565b60005b838110156121e757600085858381811061205c5761205c613adb565b90506020020160208101906120719190613465565b6001600160a01b031614156120c35760405162461bcd60e51b8152602060048201526018602482015277496e76616c6964206578656375746f72206164647265737360401b6044820152606401610d1d565b8282828181106120d5576120d5613adb565b90506020020160208101906120ea9190613af1565b6010600087878581811061210057612100613adb565b90506020020160208101906121159190613465565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790557fdee89cbd403a5d71d16b5fd869d30791145a11ef4ea6faed0c6f1e0d207c074085858381811061217057612170613adb565b90506020020160208101906121859190613465565b84848481811061219757612197613adb565b90506020020160208101906121ac9190613af1565b604080516001600160a01b0390931683529015156020830152429082015260600160405180910390a1806121df81613b0e565b915050612040565b5050505050565b6121f66125f1565b60035481101561223d5760405162461bcd60e51b8152602060048201526012602482015271526174652062656c6f77206d696e696d756d60701b6044820152606401610d1d565b6004548111156122845760405162461bcd60e51b8152602060048201526012602482015271526174652061626f7665206d6178696d756d60701b6044820152606401610d1d565b61228d81600155565b600d81905560408051828152602081018390526000918101919091524260608201527fdd8196f9280a887c2cda9ceaa0c9f147ee5931086cfa28738c70c45ce383f1cb90608001611096565b6122e16125f1565b6001600160a01b0381166123465760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d1d565b61181e816127f2565b6123576125f1565b600081116123775760405162461bcd60e51b8152600401610d1d90613a14565b80600681905550600080516020613bb783398151915260035460045460055484600754600854426040516110969796959493929190613972565b6123b96125f1565b600081116124095760405162461bcd60e51b815260206004820152601d60248201527f546172676574207072696365206d75737420626520706f7369746976650000006044820152606401610d1d565b80600754111561242b5760405162461bcd60e51b8152600401610d1d9061393b565b80600881905550600080516020613bb783398151915260035460045460055460065460075486426040516110969796959493929190613972565b61246d6125f1565b600081116124b95760405162461bcd60e51b81526020600482015260196024820152784d696e2072617465206d75737420626520706f73697469766560381b6044820152606401610d1d565b80600d54101561250b5760405162461bcd60e51b815260206004820152601e60248201527f43757272656e7420726174652062656c6f77206e6577206d696e696d756d00006044820152606401610d1d565b80600381905550600080516020613bb783398151915281600454600554600654600754600854426040516110969796959493929190613972565b61254d6125f1565b600081116125a95760405162461bcd60e51b815260206004820152602360248201527f457865637574696f6e20696e74657276616c206d75737420626520706f73697460448201526269766560e81b6064820152608401610d1d565b600a805490829055604080518281526020810184905242918101919091527f3f270eceb5b4127539ba3b0318b668db0a68260fd04bccd7c6705452084832e890606001610f30565b6000546001600160a01b0316331461133a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d1d565b6000807f000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd55946001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d09190613703565b6040516335ea6a7560e01b81526001600160a01b037f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645811660048301529192506000918316906335ea6a75906024016101e060405180830381865afa15801561273d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061276191906137b7565b6101408101519091506001600160a01b038116612782576000935050505090565b6040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156127c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ea91906138cf565b935050505090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6002805414156128945760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d1d565b60028055565b6001600160a01b0381166128c05760405162461bcd60e51b8152600401610d1d906138e8565b600082116128e05760405162461bcd60e51b8152600401610d1d90613913565b60007f000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd55946001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612940573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129649190613703565b905060007f000000000000000000000000d1ef87fefa83154f83541b68bd09185e154639726001600160a01b031663ca6cabf56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ea9190613703565b6040516335ea6a7560e01b81526001600160a01b0380831660048301529192506000918416906335ea6a75906024016101e060405180830381865afa158015612a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5b91906137b7565b6101008101519091506001600160a01b038116612ab35760405162461bcd60e51b81526020600482015260166024820152751855d2165411481d1bdad95b881b9bdd08199bdd5b9960521b6044820152606401610d1d565b6040516370a0823160e01b815230600482015281906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015612afc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2091906138cf565b905060008111612b725760405162461bcd60e51b815260206004820152601c60248201527f4e6f20737570706c696564204859504520746f207769746864726177000000006044820152606401610d1d565b87600019811415612b84575080612bd4565b81891115612bd45760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e74206157485950452062616c616e636500000000006044820152606401610d1d565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000d1ef87fefa83154f83541b68bd09185e15463972811660048301526024820183905284169063095ea7b3906044016020604051808303816000875af1158015612c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c679190613a58565b50604051637d05e65760e11b815260006004820152602481018290526001600160a01b0389811660448301527f000000000000000000000000d1ef87fefa83154f83541b68bd09185e15463972169063fa0bccae90606401600060405180830381600087803b158015612cd957600080fd5b505af1158015612ced573d6000803e3d6000fd5b5050604080518481526001600160a01b038c166020820152428183015290517fa456360b32d69444bac6d8135b2fc74d4ea3ada831137055da97c17ecce0540d9350908190036060019150a1505050505050505050565b6000306001600160a01b031663be10aba06040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612da0575060408051601f3d908101601f19168201909252612d9d918101906138cf565b60015b612daa5750600090565b60008113612dba57600091505090565b919050565b60007f000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd55946001600160a01b031663026b1d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e439190613703565b600e5490915060ff166130245760095460405163a415bcad60e01b81526001600160a01b0383169163a415bcad91612ea7917f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645916002906000903090600401613b29565b600060405180830381600087803b158015612ec157600080fd5b505af1925050508015612ed2575060015b612fda576000600a600954612ee79190613b5d565b60405163a415bcad60e01b81529091506001600160a01b0383169063a415bcad90612f40907f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6459085906002906000903090600401613b29565b600060405180830381600087803b158015612f5a57600080fd5b505af1925050508015612f6b575060015b612f93576040805160038152426020820152600080516020613b978339815191529101610f30565b600e805460ff19166001179055600f819055604080518281524260208201527f1b2bf01de22db633e18d8b704f3e11ea6d294d690a9b3c2de306d04eacf1b2899101610f30565b600e805460ff19166001179055600954600f819055604080519182524260208301527f1b2bf01de22db633e18d8b704f3e11ea6d294d690a9b3c2de306d04eacf1b2899101611096565b600061302e61264b565b905080156113605760405163095ea7b360e01b81526001600160a01b038381166004830152602482018390527f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645169063095ea7b3906044016020604051808303816000875af11580156130a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c99190613a58565b5060405163573ade8160e01b81526001600160a01b0383169063573ade819061311d907f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6459085906002903090600401613a75565b6020604051808303816000875af1925050508015613158575060408051601f3d908101601f19168201909252613155918101906138cf565b60015b613180576040805160058152426020820152600080516020613b978339815191529101610f30565b5060405163a415bcad60e01b81526001600160a01b0383169063a415bcad906131d7907f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6459085906002906000903090600401613b29565b600060405180830381600087803b1580156131f157600080fd5b505af1925050508015613202575060015b613301576000613213600283613b5d565b60405163a415bcad60e01b81529091506001600160a01b0384169063a415bcad9061326c907f000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc6459085906002906000903090600401613b29565b600060405180830381600087803b15801561328657600080fd5b505af1925050508015613297575060015b6132c7576040805160048152426020820152600080516020613b97833981519152910160405180910390a1505050565b600f819055604080518281524260208201527f3f7fd57369099a2eb7970f3bae765cdd92012a3912e26ae5d4f634510815b9bb9101610e6b565b604080518281524260208201527f3f7fd57369099a2eb7970f3bae765cdd92012a3912e26ae5d4f634510815b9bb9101610f30565b600d546007546000919083101561336d57600554600d5461335791906139b8565b905060045481111561336857506004545b610fc1565b60075483101580156133825750600354600d54115b15610fc157600654600d541161339a576003546133aa565b600654600d546133aa9190613b7f565b9050600354811015610fc1575060035492915050565b6001600160a01b038116811461181e57600080fd5b600080604083850312156133e857600080fd5b8235915060208301356133fa816133c0565b809150509250929050565b8035612dba816133c0565b801515811461181e57600080fd5b6000806040838503121561343157600080fd5b823561343c816133c0565b915060208301356133fa81613410565b60006020828403121561345e57600080fd5b5035919050565b60006020828403121561347757600080fd5b8135613482816133c0565b9392505050565b60008060008060008060c087890312156134a257600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b604051610120810167ffffffffffffffff811182821017156134fe57634e487b7160e01b600052604160045260246000fd5b60405290565b6040516101e0810167ffffffffffffffff811182821017156134fe57634e487b7160e01b600052604160045260246000fd5b6000610120828403121561354957600080fd5b6135516134cc565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015261359d60e08401613405565b60e08201526101006135b0818501613405565b908201529392505050565b6000806000604084860312156135d057600080fd5b83356135db816133c0565b9250602084013567ffffffffffffffff808211156135f857600080fd5b818601915086601f83011261360c57600080fd5b81358181111561361b57600080fd5b87602082850101111561362d57600080fd5b6020830194508093505050509250925092565b60008083601f84011261365257600080fd5b50813567ffffffffffffffff81111561366a57600080fd5b6020830191508360208260051b850101111561368557600080fd5b9250929050565b600080600080604085870312156136a257600080fd5b843567ffffffffffffffff808211156136ba57600080fd5b6136c688838901613640565b909650945060208701359150808211156136df57600080fd5b506136ec87828801613640565b95989497509550505050565b8051612dba816133c0565b60006020828403121561371557600080fd5b8151613482816133c0565b60006020828403121561373257600080fd5b6040516020810181811067ffffffffffffffff8211171561376357634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff81168114612dba57600080fd5b805164ffffffffff81168114612dba57600080fd5b805161ffff81168114612dba57600080fd5b60006101e082840312156137ca57600080fd5b6137d2613504565b6137dc8484613720565b81526137ea60208401613770565b60208201526137fb60408401613770565b604082015261380c60608401613770565b606082015261381d60808401613770565b608082015261382e60a08401613770565b60a082015261383f60c08401613790565b60c082015261385060e084016137a5565b60e08201526101006138638185016136f8565b908201526101206138758482016136f8565b908201526101406138878482016136f8565b908201526101606138998482016136f8565b908201526101806138ab848201613770565b908201526101a06138bd848201613770565b908201526101c06135b0848201613770565b6000602082840312156138e157600080fd5b5051919050565b602080825260119082015270125b9d985b1a59081c9958da5c1a595b9d607a1b604082015260600190565b6020808252600e908201526d125b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b6020808252601e908201527f5468726573686f6c642063616e6e6f7420657863656564207461726765740000604082015260600190565b968752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b634e487b7160e01b600052601160045260246000fd5b600082198211156139cb576139cb6139a2565b500190565b60208082526024908201527f496e6372656173652061646a7573746d656e74206d75737420626520706f73696040820152637469766560e01b606082015260800190565b60208082526024908201527f44656372656173652061646a7573746d656e74206d75737420626520706f73696040820152637469766560e01b606082015260800190565b600060208284031215613a6a57600080fd5b815161348281613410565b6001600160a01b03948516815260208101939093526040830191909152909116606082015260800190565b6000825160005b81811015613ac15760208186018101518583015201613aa7565b81811115613ad0576000828501525b509190910192915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613b0357600080fd5b813561348281613410565b6000600019821415613b2257613b226139a2565b5060010190565b6001600160a01b0395861681526020810194909452604084019290925261ffff166060830152909116608082015260a00190565b600082613b7a57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015613b9157613b916139a2565b50039056fe6a7e30b1d18177663daff1c1684bc81a8054d0f1a232cb7d189fe08a93fe9db13d74e607b6fd730acbea4d47a114bafaa8f32af5d4a29e0b720f850c86aec308a2646970667358221220a3e02ec17253188222a2f04c87ff1ca5e8b0e858dd1a253b2393d7efd6a025f764736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd5594000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645000000000000000000000000e52085b9bbc0bef8294ecd0546f8cb5158bb2eaa000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645000000000000000000000000000000000000000000707f1ec5dcde3d88000000000000000000000000000000528c211dce38d3d9005bad04af8a3201876205a2000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000d1ef87fefa83154f83541b68bd09185e15463972
-----Decoded View---------------
Arg [0] : addressesProvider (address): 0xA73ff12D177D8F1Ec938c3ba0e87D33524dD5594
Arg [1] : usdxlToken (address): 0xca79db4B49f608eF54a5CB813FbEd3a6387bC645
Arg [2] : usdxlOracleAddress (address): 0xe52085B9BBc0beF8294ecD0546f8cb5158BB2eAA
Arg [3] : usdxlReserve (address): 0xca79db4B49f608eF54a5CB813FbEd3a6387bC645
Arg [4] : initialRate (uint256): 136000000000000000000000000
Arg [5] : owner (address): 0x528c211dCe38D3d9005baD04af8a3201876205a2
Arg [6] : initialPerpetualLoanAmount (uint256): 10000000000000000
Arg [7] : wrappedHypeGateway (address): 0xd1EF87FeFA83154F83541b68BD09185e15463972
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000a73ff12d177d8f1ec938c3ba0e87d33524dd5594
Arg [1] : 000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645
Arg [2] : 000000000000000000000000e52085b9bbc0bef8294ecd0546f8cb5158bb2eaa
Arg [3] : 000000000000000000000000ca79db4b49f608ef54a5cb813fbed3a6387bc645
Arg [4] : 000000000000000000000000000000000000000000707f1ec5dcde3d88000000
Arg [5] : 000000000000000000000000528c211dce38d3d9005bad04af8a3201876205a2
Arg [6] : 000000000000000000000000000000000000000000000000002386f26fc10000
Arg [7] : 000000000000000000000000d1ef87fefa83154f83541b68bd09185e15463972
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$1.01
Net Worth in HYPE
Token Allocations
USDXL
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| HYPEREVM | 100.00% | $0.995136 | 1.01 | $1.01 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
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.