Address Details
contract
0xeC98172BcF583f2A40e7414cD9252404550fda87
- Contract Name
- StableAndVariableTokensHelper
- Creator
- 0x643c57–e72624 at 0xece355–00083b
- Balance
- 0 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- 3 Transactions
- Transfers
- 0 Transfers
- Gas Used
- 155,452
- Last Balance Update
- 15221364
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- StableAndVariableTokensHelper
- Optimization enabled
- true
- Compiler version
- v0.6.12+commit.27d51765
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2022-01-13T20:26:01.144718Z
contracts/deployments/StableAndVariableTokensHelper.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; pragma experimental ABIEncoderV2; import {StableDebtToken} from '../protocol/tokenization/StableDebtToken.sol'; import {VariableDebtToken} from '../protocol/tokenization/VariableDebtToken.sol'; import {LendingRateOracle} from '../mocks/oracle/LendingRateOracle.sol'; import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; import {StringLib} from './StringLib.sol'; contract StableAndVariableTokensHelper is Ownable { address payable private pool; address private addressesProvider; event deployedContracts(address stableToken, address variableToken); constructor(address payable _pool, address _addressesProvider) public { pool = _pool; addressesProvider = _addressesProvider; } function initDeployment(address[] calldata tokens, string[] calldata symbols) external onlyOwner { require(tokens.length == symbols.length, 'Arrays not same length'); require(pool != address(0), 'Pool can not be zero address'); for (uint256 i = 0; i < tokens.length; i++) { emit deployedContracts(address(new StableDebtToken()), address(new VariableDebtToken())); } } function setOracleBorrowRates( address[] calldata assets, uint256[] calldata rates, address oracle ) external onlyOwner { require(assets.length == rates.length, 'Arrays not same length'); for (uint256 i = 0; i < assets.length; i++) { // LendingRateOracle owner must be this contract LendingRateOracle(oracle).setMarketBorrowRate(assets[i], rates[i]); } } function setOracleOwnership(address oracle, address admin) external onlyOwner { require(admin != address(0), 'owner can not be zero'); require(LendingRateOracle(oracle).owner() == address(this), 'helper is not owner'); LendingRateOracle(oracle).transferOwnership(admin); } }
/contracts/dependencies/openzeppelin/contracts/Context.sol
// SPDX-License-Identifier: MIT pragma solidity 0.6.12; /* * @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 GSN 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 payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
/contracts/dependencies/openzeppelin/contracts/IERC20.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; /** * @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); }
/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {IERC20} from './IERC20.sol'; interface IERC20Detailed is IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); }
/contracts/dependencies/openzeppelin/contracts/Ownable.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import './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. */ 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() internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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 { emit OwnershipTransferred(_owner, address(0)); _owner = 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'); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
/contracts/dependencies/openzeppelin/contracts/SafeMath.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, 'SafeMath: addition overflow'); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, 'SafeMath: subtraction overflow'); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, 'SafeMath: multiplication overflow'); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, 'SafeMath: division by zero'); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, 'SafeMath: modulo by zero'); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
/contracts/deployments/StringLib.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; library StringLib { function concat(string memory a, string memory b) internal pure returns (string memory) { return string(abi.encodePacked(a, b)); } }
/contracts/interfaces/IAaveIncentivesController.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; pragma experimental ABIEncoderV2; interface IAaveIncentivesController { function handleAction( address user, uint256 userBalance, uint256 totalSupply ) external; }
/contracts/interfaces/ICreditDelegationToken.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; interface ICreditDelegationToken { event BorrowAllowanceDelegated( address indexed fromUser, address indexed toUser, address asset, uint256 amount ); /** * @dev delegates borrowing power to a user on the specific debt token * @param delegatee the address receiving the delegated borrowing power * @param amount the maximum amount being delegated. Delegation will still * respect the liquidation constraints (even if delegated, a delegatee cannot * force a delegator HF to go below 1) **/ function approveDelegation(address delegatee, uint256 amount) external; /** * @dev returns the borrow allowance of the user * @param fromUser The user to giving allowance * @param toUser The user to give allowance to * @return the current allowance of toUser **/ function borrowAllowance(address fromUser, address toUser) external view returns (uint256); }
/contracts/interfaces/IInitializableDebtToken.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {ILendingPool} from './ILendingPool.sol'; import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; /** * @title IInitializableDebtToken * @notice Interface for the initialize function common between debt tokens * @author Aave **/ interface IInitializableDebtToken { /** * @dev Emitted when a debt token is initialized * @param underlyingAsset The address of the underlying asset * @param pool The address of the associated lending pool * @param incentivesController The address of the incentives controller for this aToken * @param debtTokenDecimals the decimals of the debt token * @param debtTokenName the name of the debt token * @param debtTokenSymbol the symbol of the debt token * @param params A set of encoded parameters for additional initialization **/ event Initialized( address indexed underlyingAsset, address indexed pool, address incentivesController, uint8 debtTokenDecimals, string debtTokenName, string debtTokenSymbol, bytes params ); /** * @dev Initializes the debt token. * @param pool The address of the lending pool where this aToken will be used * @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 debtTokenDecimals The decimals of the debtToken, same as the underlying asset's * @param debtTokenName The name of the token * @param debtTokenSymbol The symbol of the token */ function initialize( ILendingPool pool, address underlyingAsset, IAaveIncentivesController incentivesController, uint8 debtTokenDecimals, string memory debtTokenName, string memory debtTokenSymbol, bytes calldata params ) external; }
/contracts/interfaces/ILendingPool.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; pragma experimental ABIEncoderV2; import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol'; import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; interface ILendingPool { /** * @dev Emitted on deposit() * @param reserve The address of the underlying asset of the reserve * @param user The address initiating the deposit * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens * @param amount The amount deposited * @param referral The referral code used **/ event Deposit( address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referral ); /** * @dev Emitted on withdraw() * @param reserve The address of the underlyng asset being withdrawn * @param user The address initiating the withdrawal, owner of aTokens * @param to 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 borrowRateMode The rate mode: 1 for Stable, 2 for Variable * @param borrowRate The numeric rate at which the user has borrowed * @param referral The referral code used **/ event Borrow( address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint256 borrowRateMode, uint256 borrowRate, uint16 indexed referral ); /** * @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 **/ event Repay( address indexed reserve, address indexed user, address indexed repayer, uint256 amount ); /** * @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 rateMode The rate mode that the user wants to swap to **/ event Swap(address indexed reserve, address indexed user, uint256 rateMode); /** * @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 premium The fee flash borrowed * @param referralCode The referral code used **/ event FlashLoan( address indexed target, address indexed initiator, address indexed asset, uint256 amount, uint256 premium, uint16 referralCode ); /** * @dev Emitted when the pause is triggered. */ event Paused(); /** * @dev Emitted when the pause is lifted. */ event Unpaused(); /** * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via * LendingPoolCollateral manager using a DELEGATECALL * This allows to have the events in the generated ABI for LendingPool. * @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 liiquidator * @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. NOTE: This event is actually declared * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal, * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it * gets added to the LendingPool ABI * @param reserve The address of the underlying asset of the reserve * @param liquidityRate The new liquidity rate * @param stableBorrowRate The new stable borrow rate * @param variableBorrowRate The new variable borrow rate * @param liquidityIndex The new liquidity index * @param variableBorrowIndex The new variable borrow index **/ event ReserveDataUpdated( address indexed reserve, uint256 liquidityRate, uint256 stableBorrowRate, uint256 variableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex ); /** * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. * - E.g. User deposits 100 USDC and gets in return 100 aUSDC * @param asset The address of the underlying asset to deposit * @param amount The amount to be deposited * @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; /** * @dev 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 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); /** * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower * already deposited 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 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 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 rateMode 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 * @return The final amount repaid **/ function repay( address asset, uint256 amount, uint256 rateMode, address onBehalfOf ) external returns (uint256); /** * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa * @param asset The address of the underlying asset borrowed * @param rateMode The rate mode that the user wants to swap to **/ function swapBorrowRateMode(address asset, uint256 rateMode) external; /** * @dev 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 deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been * borrowed at a stable rate and depositors 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; /** * @dev Allows depositors to enable/disable a specific deposited asset as collateral * @param asset The address of the underlying asset deposited * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise **/ function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; /** * @dev 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; /** * @dev Allows smartcontracts to access the liquidity of the pool within one transaction, * as long as the amount taken plus a fee is returned. * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration. * For further details please visit https://developers.aave.com * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface * @param assets The addresses of the assets being flash-borrowed * @param amounts The amounts amounts being flash-borrowed * @param modes 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 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 modes, address onBehalfOf, bytes calldata params, uint16 referralCode ) external; /** * @dev Returns the user account data across all the reserves * @param user The address of the user * @return totalCollateralETH the total collateral in ETH of the user * @return totalDebtETH the total debt in ETH of the user * @return availableBorrowsETH the borrowing power left of the user * @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 totalCollateralETH, uint256 totalDebtETH, uint256 availableBorrowsETH, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor ); function initReserve( address reserve, address aTokenAddress, address stableDebtAddress, address variableDebtAddress, address interestRateStrategyAddress ) external; function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) external; function setConfiguration(address reserve, uint256 configuration) external; /** * @dev 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); /** * @dev 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); /** * @dev Returns the normalized income 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); /** * @dev Returns the normalized variable debt per unit of asset * @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); /** * @dev Returns the state and configuration of the reserve * @param asset The address of the underlying asset of the reserve * @return The state of the reserve **/ function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); function finalizeTransfer( address asset, address from, address to, uint256 amount, uint256 balanceFromAfter, uint256 balanceToBefore ) external; function getReservesList() external view returns (address[] memory); function getAddressesProvider() external view returns (ILendingPoolAddressesProvider); function setPause(bool val) external; function paused() external view returns (bool); }
/contracts/interfaces/ILendingPoolAddressesProvider.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; /** * @title LendingPoolAddressesProvider contract * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles * - Acting also as factory of proxies and admin of those, so with right to change its implementations * - Owned by the Aave Governance * @author Aave **/ interface ILendingPoolAddressesProvider { event MarketIdSet(string newMarketId); event LendingPoolUpdated(address indexed newAddress); event ConfigurationAdminUpdated(address indexed newAddress); event EmergencyAdminUpdated(address indexed newAddress); event LendingPoolConfiguratorUpdated(address indexed newAddress); event LendingPoolCollateralManagerUpdated(address indexed newAddress); event PriceOracleUpdated(address indexed newAddress); event LendingRateOracleUpdated(address indexed newAddress); event ProxyCreated(bytes32 id, address indexed newAddress); event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy); function getMarketId() external view returns (string memory); function setMarketId(string calldata marketId) external; function setAddress(bytes32 id, address newAddress) external; function setAddressAsProxy(bytes32 id, address impl) external; function getAddress(bytes32 id) external view returns (address); function getLendingPool() external view returns (address); function setLendingPoolImpl(address pool) external; function getLendingPoolConfigurator() external view returns (address); function setLendingPoolConfiguratorImpl(address configurator) external; function getLendingPoolCollateralManager() external view returns (address); function setLendingPoolCollateralManager(address manager) external; function getPoolAdmin() external view returns (address); function setPoolAdmin(address admin) external; function getEmergencyAdmin() external view returns (address); function setEmergencyAdmin(address admin) external; function getPriceOracle() external view returns (address); function setPriceOracle(address priceOracle) external; function getLendingRateOracle() external view returns (address); function setLendingRateOracle(address lendingRateOracle) external; }
/contracts/interfaces/ILendingRateOracle.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; /** * @title ILendingRateOracle interface * @notice Interface for the Aave borrow rate oracle. Provides the average market borrow rate to be used as a base for the stable borrow rate calculations **/ interface ILendingRateOracle { /** @dev returns the market borrow rate in ray **/ function getMarketBorrowRate(address asset) external view returns (uint256); /** @dev sets the market borrow rate. Rate value must be in ray **/ function setMarketBorrowRate(address asset, uint256 rate) external; }
/contracts/interfaces/IScaledBalanceToken.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; interface IScaledBalanceToken { /** * @dev Returns the scaled balance of the user. 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); /** * @dev 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 balance and the scaled total supply **/ function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256); /** * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index) * @return The scaled total supply **/ function scaledTotalSupply() external view returns (uint256); }
/contracts/interfaces/IStableDebtToken.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; /** * @title IStableDebtToken * @notice Defines the interface for the stable debt token * @dev It does not inherit from IERC20 to save in code size * @author Aave **/ interface IStableDebtToken is IInitializableDebtToken { /** * @dev Emitted when new stable debt is minted * @param user The address of the user who triggered the minting * @param onBehalfOf The recipient of stable debt tokens * @param amount The amount minted * @param currentBalance The current balance of the user * @param balanceIncrease The increase in balance since the last action of the user * @param newRate The rate of the debt after the minting * @param avgStableRate The new average stable rate after the minting * @param newTotalSupply The new total supply of the stable debt token after the action **/ event Mint( address indexed user, address indexed onBehalfOf, uint256 amount, uint256 currentBalance, uint256 balanceIncrease, uint256 newRate, uint256 avgStableRate, uint256 newTotalSupply ); /** * @dev Emitted when new stable debt is burned * @param user The address of the user * @param amount The amount being burned * @param currentBalance The current balance of the user * @param balanceIncrease The the increase in balance since the last action of the user * @param avgStableRate The new average stable rate after the burning * @param newTotalSupply The new total supply of the stable debt token after the action **/ event Burn( address indexed user, uint256 amount, uint256 currentBalance, uint256 balanceIncrease, uint256 avgStableRate, uint256 newTotalSupply ); /** * @dev Mints debt token to the `onBehalfOf` address. * - The resulting rate is the weighted average between the rate of the new debt * and the rate of the previous debt * @param user The address receiving the borrowed underlying, being the delegatee in case * of credit delegate, or same as `onBehalfOf` otherwise * @param onBehalfOf The address receiving the debt tokens * @param amount The amount of debt tokens to mint * @param rate The rate of the debt being minted **/ function mint( address user, address onBehalfOf, uint256 amount, uint256 rate ) external returns (bool); /** * @dev Burns debt of `user` * - The resulting rate is the weighted average between the rate of the new debt * and the rate of the previous debt * @param user The address of the user getting his debt burned * @param amount The amount of debt tokens getting burned **/ function burn(address user, uint256 amount) external; /** * @dev Returns the average rate of all the stable rate loans. * @return The average stable rate **/ function getAverageStableRate() external view returns (uint256); /** * @dev Returns the stable rate of the user debt * @return The stable rate of the user **/ function getUserStableRate(address user) external view returns (uint256); /** * @dev Returns the timestamp of the last update of the user * @return The timestamp **/ function getUserLastUpdated(address user) external view returns (uint40); /** * @dev Returns the principal, the total supply and the average stable rate **/ function getSupplyData() external view returns ( uint256, uint256, uint256, uint40 ); /** * @dev Returns the timestamp of the last update of the total supply * @return The timestamp **/ function getTotalSupplyLastUpdated() external view returns (uint40); /** * @dev Returns the total supply and the average stable rate **/ function getTotalSupplyAndAvgRate() external view returns (uint256, uint256); /** * @dev Returns the principal debt balance of the user * @return The debt balance of the user since the last burn/mint action **/ function principalBalanceOf(address user) external view returns (uint256); /** * @dev Returns the address of the incentives controller contract **/ function getIncentivesController() external view returns (IAaveIncentivesController); }
/contracts/interfaces/IVariableDebtToken.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; /** * @title IVariableDebtToken * @author Aave * @notice Defines the basic interface for a variable debt token. **/ interface IVariableDebtToken is IScaledBalanceToken, IInitializableDebtToken { /** * @dev Emitted after the mint action * @param from The address performing the mint * @param onBehalfOf The address of the user on which behalf minting has been performed * @param value The amount to be minted * @param index The last index of the reserve **/ event Mint(address indexed from, address indexed onBehalfOf, uint256 value, uint256 index); /** * @dev Mints debt token to the `onBehalfOf` address * @param user The address receiving the borrowed underlying, being the delegatee in case * of credit delegate, or same as `onBehalfOf` otherwise * @param onBehalfOf The address receiving the debt tokens * @param amount The amount of debt being minted * @param index The variable debt index of the reserve * @return `true` if the the previous balance of the user is 0 **/ function mint( address user, address onBehalfOf, uint256 amount, uint256 index ) external returns (bool); /** * @dev Emitted when variable debt is burnt * @param user The user which debt has been burned * @param amount The amount of debt being burned * @param index The index of the user **/ event Burn(address indexed user, uint256 amount, uint256 index); /** * @dev Burns user variable debt * @param user The user which debt is burnt * @param index The variable debt index of the reserve **/ function burn( address user, uint256 amount, uint256 index ) external; /** * @dev Returns the address of the incentives controller contract **/ function getIncentivesController() external view returns (IAaveIncentivesController); }
/contracts/mocks/oracle/LendingRateOracle.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol'; import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol'; contract LendingRateOracle is ILendingRateOracle, Ownable { mapping(address => uint256) borrowRates; mapping(address => uint256) liquidityRates; function getMarketBorrowRate(address _asset) external view override returns (uint256) { return borrowRates[_asset]; } function setMarketBorrowRate(address _asset, uint256 _rate) external override onlyOwner { borrowRates[_asset] = _rate; } function getMarketLiquidityRate(address _asset) external view returns (uint256) { return liquidityRates[_asset]; } function setMarketLiquidityRate(address _asset, uint256 _rate) external onlyOwner { liquidityRates[_asset] = _rate; } }
/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; /** * @title VersionedInitializable * * @dev Helper contract to implement initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. * * @author Aave, inspired by the OpenZeppelin Initializable contract */ abstract contract VersionedInitializable { /** * @dev Indicates that the contract has been initialized. */ uint256 private lastInitializedRevision = 0; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { uint256 revision = getRevision(); require( initializing || isConstructor() || revision > lastInitializedRevision, 'Contract instance has already been initialized' ); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; lastInitializedRevision = revision; } _; if (isTopLevelCall) { initializing = false; } } /** * @dev returns the revision number of the contract * Needs to be defined in the inherited class as a constant. **/ function getRevision() internal pure virtual returns (uint256); /** * @dev Returns true if and only if the function is running in the constructor **/ function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. uint256 cs; //solium-disable-next-line assembly { cs := extcodesize(address()) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
/contracts/protocol/libraries/helpers/Errors.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; /** * @title Errors library * @author Aave * @notice Defines the error messages emitted by the different contracts of the Aave protocol * @dev Error messages prefix glossary: * - VL = ValidationLogic * - MATH = Math libraries * - CT = Common errors between tokens (AToken, VariableDebtToken and StableDebtToken) * - AT = AToken * - SDT = StableDebtToken * - VDT = VariableDebtToken * - LP = LendingPool * - LPAPR = LendingPoolAddressesProviderRegistry * - LPC = LendingPoolConfiguration * - RL = ReserveLogic * - LPCM = LendingPoolCollateralManager * - P = Pausable */ library Errors { //common errors string public constant CALLER_NOT_POOL_ADMIN = '33'; // 'The caller must be the pool admin' string public constant BORROW_ALLOWANCE_NOT_ENOUGH = '59'; // User borrows on behalf, but allowance are too small //contract specific errors string public constant VL_INVALID_AMOUNT = '1'; // 'Amount must be greater than 0' string public constant VL_NO_ACTIVE_RESERVE = '2'; // 'Action requires an active reserve' string public constant VL_RESERVE_FROZEN = '3'; // 'Action cannot be performed because the reserve is frozen' string public constant VL_CURRENT_AVAILABLE_LIQUIDITY_NOT_ENOUGH = '4'; // 'The current liquidity is not enough' string public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = '5'; // 'User cannot withdraw more than the available balance' string public constant VL_TRANSFER_NOT_ALLOWED = '6'; // 'Transfer cannot be allowed.' string public constant VL_BORROWING_NOT_ENABLED = '7'; // 'Borrowing is not enabled' string public constant VL_INVALID_INTEREST_RATE_MODE_SELECTED = '8'; // 'Invalid interest rate mode selected' string public constant VL_COLLATERAL_BALANCE_IS_0 = '9'; // 'The collateral balance is 0' string public constant VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '10'; // 'Health factor is lesser than the liquidation threshold' string public constant VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = '11'; // 'There is not enough collateral to cover a new borrow' string public constant VL_STABLE_BORROWING_NOT_ENABLED = '12'; // stable borrowing not enabled string public constant VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY = '13'; // collateral is (mostly) the same currency that is being borrowed string public constant VL_AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = '14'; // 'The requested amount is greater than the max loan size in stable rate mode string public constant VL_NO_DEBT_OF_SELECTED_TYPE = '15'; // 'for repayment of stable debt, the user needs to have stable debt, otherwise, he needs to have variable debt' string public constant VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = '16'; // 'To repay on behalf of an user an explicit amount to repay is needed' string public constant VL_NO_STABLE_RATE_LOAN_IN_RESERVE = '17'; // 'User does not have a stable rate loan in progress on this reserve' string public constant VL_NO_VARIABLE_RATE_LOAN_IN_RESERVE = '18'; // 'User does not have a variable rate loan in progress on this reserve' string public constant VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0 = '19'; // 'The underlying balance needs to be greater than 0' string public constant VL_DEPOSIT_ALREADY_IN_USE = '20'; // 'User deposit is already being used as collateral' string public constant LP_NOT_ENOUGH_STABLE_BORROW_BALANCE = '21'; // 'User does not have any stable rate loan for this reserve' string public constant LP_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = '22'; // 'Interest rate rebalance conditions were not met' string public constant LP_LIQUIDATION_CALL_FAILED = '23'; // 'Liquidation call failed' string public constant LP_NOT_ENOUGH_LIQUIDITY_TO_BORROW = '24'; // 'There is not enough liquidity available to borrow' string public constant LP_REQUESTED_AMOUNT_TOO_SMALL = '25'; // 'The requested amount is too small for a FlashLoan.' string public constant LP_INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26'; // 'The actual balance of the protocol is inconsistent' string public constant LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27'; // 'The caller of the function is not the lending pool configurator' string public constant LP_INCONSISTENT_FLASHLOAN_PARAMS = '28'; string public constant CT_CALLER_MUST_BE_LENDING_POOL = '29'; // 'The caller of this function must be a lending pool' string public constant CT_CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself' string public constant CT_TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero' string public constant RL_RESERVE_ALREADY_INITIALIZED = '32'; // 'Reserve has already been initialized' string public constant LPC_RESERVE_LIQUIDITY_NOT_0 = '34'; // 'The liquidity of the reserve needs to be 0' string public constant LPC_INVALID_ATOKEN_POOL_ADDRESS = '35'; // 'The liquidity of the reserve needs to be 0' string public constant LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = '36'; // 'The liquidity of the reserve needs to be 0' string public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS = '37'; // 'The liquidity of the reserve needs to be 0' string public constant LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '38'; // 'The liquidity of the reserve needs to be 0' string public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '39'; // 'The liquidity of the reserve needs to be 0' string public constant LPC_INVALID_ADDRESSES_PROVIDER_ID = '40'; // 'The liquidity of the reserve needs to be 0' string public constant LPC_INVALID_CONFIGURATION = '75'; // 'Invalid risk parameters for the reserve' string public constant LPC_CALLER_NOT_EMERGENCY_ADMIN = '76'; // 'The caller must be the emergency admin' string public constant LPAPR_PROVIDER_NOT_REGISTERED = '41'; // 'Provider is not registered' string public constant LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '42'; // 'Health factor is not below the threshold' string public constant LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = '43'; // 'The collateral chosen cannot be liquidated' string public constant LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = '44'; // 'User did not borrow the specified currency' string public constant LPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE = '45'; // "There isn't enough liquidity available to liquidate" string public constant LPCM_NO_ERRORS = '46'; // 'No errors' string public constant LP_INVALID_FLASHLOAN_MODE = '47'; //Invalid flashloan mode selected string public constant MATH_MULTIPLICATION_OVERFLOW = '48'; string public constant MATH_ADDITION_OVERFLOW = '49'; string public constant MATH_DIVISION_BY_ZERO = '50'; string public constant RL_LIQUIDITY_INDEX_OVERFLOW = '51'; // Liquidity index overflows uint128 string public constant RL_VARIABLE_BORROW_INDEX_OVERFLOW = '52'; // Variable borrow index overflows uint128 string public constant RL_LIQUIDITY_RATE_OVERFLOW = '53'; // Liquidity rate overflows uint128 string public constant RL_VARIABLE_BORROW_RATE_OVERFLOW = '54'; // Variable borrow rate overflows uint128 string public constant RL_STABLE_BORROW_RATE_OVERFLOW = '55'; // Stable borrow rate overflows uint128 string public constant CT_INVALID_MINT_AMOUNT = '56'; //invalid amount to mint string public constant LP_FAILED_REPAY_WITH_COLLATERAL = '57'; string public constant CT_INVALID_BURN_AMOUNT = '58'; //invalid amount to burn string public constant LP_FAILED_COLLATERAL_SWAP = '60'; string public constant LP_INVALID_EQUAL_ASSETS_TO_SWAP = '61'; string public constant LP_REENTRANCY_NOT_ALLOWED = '62'; string public constant LP_CALLER_MUST_BE_AN_ATOKEN = '63'; string public constant LP_IS_PAUSED = '64'; // 'Pool is paused' string public constant LP_NO_MORE_RESERVES_ALLOWED = '65'; string public constant LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = '66'; string public constant RC_INVALID_LTV = '67'; string public constant RC_INVALID_LIQ_THRESHOLD = '68'; string public constant RC_INVALID_LIQ_BONUS = '69'; string public constant RC_INVALID_DECIMALS = '70'; string public constant RC_INVALID_RESERVE_FACTOR = '71'; string public constant LPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72'; string public constant VL_INCONSISTENT_FLASHLOAN_PARAMS = '73'; string public constant LP_INCONSISTENT_PARAMS_LENGTH = '74'; string public constant UL_INVALID_INDEX = '77'; string public constant LP_NOT_CONTRACT = '78'; string public constant SDT_STABLE_DEBT_OVERFLOW = '79'; string public constant SDT_BURN_EXCEEDS_BALANCE = '80'; enum CollateralManagerErrors { NO_ERROR, NO_COLLATERAL_AVAILABLE, COLLATERAL_CANNOT_BE_LIQUIDATED, CURRRENCY_NOT_BORROWED, HEALTH_FACTOR_ABOVE_THRESHOLD, NOT_ENOUGH_LIQUIDITY, NO_ACTIVE_RESERVE, HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD, INVALID_EQUAL_ASSETS_TO_SWAP, FROZEN_RESERVE } }
/contracts/protocol/libraries/math/MathUtils.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol'; import {WadRayMath} from './WadRayMath.sol'; library MathUtils { using SafeMath for uint256; using WadRayMath for uint256; /// @dev Ignoring leap years uint256 internal constant SECONDS_PER_YEAR = 365 days; /** * @dev Function to calculate the interest accumulated using a linear interest rate formula * @param rate The interest rate, in ray * @param lastUpdateTimestamp The timestamp of the last update of the interest * @return The interest rate linearly accumulated during the timeDelta, in ray **/ function calculateLinearInterest(uint256 rate, uint40 lastUpdateTimestamp) internal view returns (uint256) { //solium-disable-next-line uint256 timeDifference = block.timestamp.sub(uint256(lastUpdateTimestamp)); return (rate.mul(timeDifference) / SECONDS_PER_YEAR).add(WadRayMath.ray()); } /** * @dev Function to calculate the interest using a compounded interest rate formula * To avoid expensive exponentiation, the calculation is performed using a binomial approximation: * * (1+x)^n = 1+n*x+[n/2*(n-1)]*x^2+[n/6*(n-1)*(n-2)*x^3... * * The approximation slightly underpays liquidity providers and undercharges borrowers, with the advantage of great gas cost reductions * The whitepaper contains reference to the approximation and a table showing the margin of error per different time periods * * @param rate The interest rate, in ray * @param lastUpdateTimestamp The timestamp of the last update of the interest * @return The interest rate compounded during the timeDelta, in ray **/ function calculateCompoundedInterest( uint256 rate, uint40 lastUpdateTimestamp, uint256 currentTimestamp ) internal pure returns (uint256) { //solium-disable-next-line uint256 exp = currentTimestamp.sub(uint256(lastUpdateTimestamp)); if (exp == 0) { return WadRayMath.ray(); } uint256 expMinusOne = exp - 1; uint256 expMinusTwo = exp > 2 ? exp - 2 : 0; uint256 ratePerSecond = rate / SECONDS_PER_YEAR; uint256 basePowerTwo = ratePerSecond.rayMul(ratePerSecond); uint256 basePowerThree = basePowerTwo.rayMul(ratePerSecond); uint256 secondTerm = exp.mul(expMinusOne).mul(basePowerTwo) / 2; uint256 thirdTerm = exp.mul(expMinusOne).mul(expMinusTwo).mul(basePowerThree) / 6; return WadRayMath.ray().add(ratePerSecond.mul(exp)).add(secondTerm).add(thirdTerm); } /** * @dev Calculates the compounded interest between the timestamp of the last update and the current block timestamp * @param rate The interest rate (in ray) * @param lastUpdateTimestamp The timestamp from which the interest accumulation needs to be calculated **/ function calculateCompoundedInterest(uint256 rate, uint40 lastUpdateTimestamp) internal view returns (uint256) { return calculateCompoundedInterest(rate, lastUpdateTimestamp, block.timestamp); } }
/contracts/protocol/libraries/math/WadRayMath.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {Errors} from '../helpers/Errors.sol'; /** * @title WadRayMath library * @author Aave * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits) **/ library WadRayMath { uint256 internal constant WAD = 1e18; uint256 internal constant halfWAD = WAD / 2; uint256 internal constant RAY = 1e27; uint256 internal constant halfRAY = RAY / 2; uint256 internal constant WAD_RAY_RATIO = 1e9; /** * @return One ray, 1e27 **/ function ray() internal pure returns (uint256) { return RAY; } /** * @return One wad, 1e18 **/ function wad() internal pure returns (uint256) { return WAD; } /** * @return Half ray, 1e27/2 **/ function halfRay() internal pure returns (uint256) { return halfRAY; } /** * @return Half ray, 1e18/2 **/ function halfWad() internal pure returns (uint256) { return halfWAD; } /** * @dev Multiplies two wad, rounding half up to the nearest wad * @param a Wad * @param b Wad * @return The result of a*b, in wad **/ function wadMul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0 || b == 0) { return 0; } require(a <= (type(uint256).max - halfWAD) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); return (a * b + halfWAD) / WAD; } /** * @dev Divides two wad, rounding half up to the nearest wad * @param a Wad * @param b Wad * @return The result of a/b, in wad **/ function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, Errors.MATH_DIVISION_BY_ZERO); uint256 halfB = b / 2; require(a <= (type(uint256).max - halfB) / WAD, Errors.MATH_MULTIPLICATION_OVERFLOW); return (a * WAD + halfB) / b; } /** * @dev Multiplies two ray, rounding half up to the nearest ray * @param a Ray * @param b Ray * @return The result of a*b, in ray **/ function rayMul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0 || b == 0) { return 0; } require(a <= (type(uint256).max - halfRAY) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); return (a * b + halfRAY) / RAY; } /** * @dev Divides two ray, rounding half up to the nearest ray * @param a Ray * @param b Ray * @return The result of a/b, in ray **/ function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, Errors.MATH_DIVISION_BY_ZERO); uint256 halfB = b / 2; require(a <= (type(uint256).max - halfB) / RAY, Errors.MATH_MULTIPLICATION_OVERFLOW); return (a * RAY + halfB) / b; } /** * @dev Casts ray down to wad * @param a Ray * @return a casted to wad, rounded half up to the nearest wad **/ function rayToWad(uint256 a) internal pure returns (uint256) { uint256 halfRatio = WAD_RAY_RATIO / 2; uint256 result = halfRatio + a; require(result >= halfRatio, Errors.MATH_ADDITION_OVERFLOW); return result / WAD_RAY_RATIO; } /** * @dev Converts wad up to ray * @param a Wad * @return a converted in ray **/ function wadToRay(uint256 a) internal pure returns (uint256) { uint256 result = a * WAD_RAY_RATIO; require(result / WAD_RAY_RATIO == a, Errors.MATH_MULTIPLICATION_OVERFLOW); return result; } }
/contracts/protocol/libraries/types/DataTypes.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; library DataTypes { // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. struct ReserveData { //stores the reserve configuration ReserveConfigurationMap configuration; //the liquidity index. Expressed in ray uint128 liquidityIndex; //variable borrow index. Expressed in ray uint128 variableBorrowIndex; //the current supply rate. Expressed in ray uint128 currentLiquidityRate; //the current variable borrow rate. Expressed in ray uint128 currentVariableBorrowRate; //the current stable borrow rate. Expressed in ray uint128 currentStableBorrowRate; uint40 lastUpdateTimestamp; //tokens addresses address aTokenAddress; address stableDebtTokenAddress; address variableDebtTokenAddress; //address of the interest rate strategy address interestRateStrategyAddress; //the id of the reserve. Represents the position in the list of the active reserves uint8 id; } 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-63: reserved //bit 64-79: reserve factor uint256 data; } struct UserConfigurationMap { uint256 data; } enum InterestRateMode {NONE, STABLE, VARIABLE} }
/contracts/protocol/tokenization/IncentivizedERC20.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {Context} from '../../dependencies/openzeppelin/contracts/Context.sol'; import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; import {IERC20Detailed} from '../../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol'; import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; /** * @title ERC20 * @notice Basic ERC20 implementation * @author Aave, inspired by the Openzeppelin ERC20 implementation **/ abstract contract IncentivizedERC20 is Context, IERC20, IERC20Detailed { using SafeMath for uint256; mapping(address => uint256) internal _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 internal _totalSupply; string private _name; string private _symbol; uint8 private _decimals; constructor( string memory name, string memory symbol, uint8 decimals ) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @return The name of the token **/ function name() public view override returns (string memory) { return _name; } /** * @return The symbol of the token **/ function symbol() public view override returns (string memory) { return _symbol; } /** * @return The decimals of the token **/ function decimals() public view override returns (uint8) { return _decimals; } /** * @return The total supply of the token **/ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @return The balance of the token **/ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @return Abstract function implemented by the child aToken/debtToken. * Done this way in order to not break compatibility with previous versions of aTokens/debtTokens **/ function _getIncentivesController() internal view virtual returns(IAaveIncentivesController); /** * @dev Executes a transfer of tokens from _msgSender() to recipient * @param recipient The recipient of the tokens * @param amount The amount of tokens being transferred * @return `true` if the transfer succeeds, `false` otherwise **/ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); emit Transfer(_msgSender(), recipient, amount); return true; } /** * @dev Returns the allowance of spender on the tokens owned by owner * @param owner The owner of the tokens * @param spender The user allowed to spend the owner's tokens * @return The amount of owner's tokens spender is allowed to spend **/ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev Allows `spender` to spend the tokens owned by _msgSender() * @param spender The user allowed to spend _msgSender() tokens * @return `true` **/ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev Executes a transfer of token from sender to recipient, if _msgSender() is allowed to do so * @param sender The owner of the tokens * @param recipient The recipient of the tokens * @param amount The amount of tokens being transferred * @return `true` if the transfer succeeds, `false` otherwise **/ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve( sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, 'ERC20: transfer amount exceeds allowance') ); emit Transfer(sender, recipient, amount); return true; } /** * @dev Increases the allowance of spender to spend _msgSender() tokens * @param spender The user allowed to spend on behalf of _msgSender() * @param addedValue The amount being added to the allowance * @return `true` **/ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Decreases the allowance of spender to spend _msgSender() tokens * @param spender The user allowed to spend on behalf of _msgSender() * @param subtractedValue The amount being subtracted to the allowance * @return `true` **/ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve( _msgSender(), spender, _allowances[_msgSender()][spender].sub( subtractedValue, 'ERC20: decreased allowance below zero' ) ); return true; } function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), 'ERC20: transfer from the zero address'); require(recipient != address(0), 'ERC20: transfer to the zero address'); _beforeTokenTransfer(sender, recipient, amount); uint256 oldSenderBalance = _balances[sender]; _balances[sender] = oldSenderBalance.sub(amount, 'ERC20: transfer amount exceeds balance'); uint256 oldRecipientBalance = _balances[recipient]; _balances[recipient] = _balances[recipient].add(amount); if (address(_getIncentivesController()) != address(0)) { uint256 currentTotalSupply = _totalSupply; _getIncentivesController().handleAction(sender, currentTotalSupply, oldSenderBalance); if (sender != recipient) { _getIncentivesController().handleAction(recipient, currentTotalSupply, oldRecipientBalance); } } } function _mint(address account, uint256 amount) internal virtual { require(account != address(0), 'ERC20: mint to the zero address'); _beforeTokenTransfer(address(0), account, amount); uint256 oldTotalSupply = _totalSupply; _totalSupply = oldTotalSupply.add(amount); uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.add(amount); if (address(_getIncentivesController()) != address(0)) { _getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance); } } function _burn(address account, uint256 amount) internal virtual { require(account != address(0), 'ERC20: burn from the zero address'); _beforeTokenTransfer(account, address(0), amount); uint256 oldTotalSupply = _totalSupply; _totalSupply = oldTotalSupply.sub(amount); uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.sub(amount, 'ERC20: burn amount exceeds balance'); if (address(_getIncentivesController()) != address(0)) { _getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance); } } function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), 'ERC20: approve from the zero address'); require(spender != address(0), 'ERC20: approve to the zero address'); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } function _setName(string memory newName) internal { _name = newName; } function _setSymbol(string memory newSymbol) internal { _symbol = newSymbol; } function _setDecimals(uint8 newDecimals) internal { _decimals = newDecimals; } function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
/contracts/protocol/tokenization/StableDebtToken.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {DebtTokenBase} from './base/DebtTokenBase.sol'; import {MathUtils} from '../libraries/math/MathUtils.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {IStableDebtToken} from '../../interfaces/IStableDebtToken.sol'; import {ILendingPool} from '../../interfaces/ILendingPool.sol'; import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; /** * @title StableDebtToken * @notice Implements a stable debt token to track the borrowing positions of users * at stable rate mode * @author Aave **/ contract StableDebtToken is IStableDebtToken, DebtTokenBase { using WadRayMath for uint256; uint256 public constant DEBT_TOKEN_REVISION = 0x1; uint256 internal _avgStableRate; mapping(address => uint40) internal _timestamps; mapping(address => uint256) internal _usersStableRate; uint40 internal _totalSupplyTimestamp; ILendingPool internal _pool; address internal _underlyingAsset; IAaveIncentivesController internal _incentivesController; /** * @dev Initializes the debt token. * @param pool The address of the lending pool where this aToken will be used * @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 debtTokenDecimals The decimals of the debtToken, same as the underlying asset's * @param debtTokenName The name of the token * @param debtTokenSymbol The symbol of the token */ function initialize( ILendingPool pool, address underlyingAsset, IAaveIncentivesController incentivesController, uint8 debtTokenDecimals, string memory debtTokenName, string memory debtTokenSymbol, bytes calldata params ) public override initializer { _setName(debtTokenName); _setSymbol(debtTokenSymbol); _setDecimals(debtTokenDecimals); _pool = pool; _underlyingAsset = underlyingAsset; _incentivesController = incentivesController; emit Initialized( underlyingAsset, address(pool), address(incentivesController), debtTokenDecimals, debtTokenName, debtTokenSymbol, params ); } /** * @dev Gets the revision of the stable debt token implementation * @return The debt token implementation revision **/ function getRevision() internal pure virtual override returns (uint256) { return DEBT_TOKEN_REVISION; } /** * @dev Returns the average stable rate across all the stable rate debt * @return the average stable rate **/ function getAverageStableRate() external view virtual override returns (uint256) { return _avgStableRate; } /** * @dev Returns the timestamp of the last user action * @return The last update timestamp **/ function getUserLastUpdated(address user) external view virtual override returns (uint40) { return _timestamps[user]; } /** * @dev Returns the stable rate of the user * @param user The address of the user * @return The stable rate of user **/ function getUserStableRate(address user) external view virtual override returns (uint256) { return _usersStableRate[user]; } /** * @dev Calculates the current user debt balance * @return The accumulated debt of the user **/ function balanceOf(address account) public view virtual override returns (uint256) { uint256 accountBalance = super.balanceOf(account); uint256 stableRate = _usersStableRate[account]; if (accountBalance == 0) { return 0; } uint256 cumulatedInterest = MathUtils.calculateCompoundedInterest(stableRate, _timestamps[account]); return accountBalance.rayMul(cumulatedInterest); } struct MintLocalVars { uint256 previousSupply; uint256 nextSupply; uint256 amountInRay; uint256 newStableRate; uint256 currentAvgStableRate; } /** * @dev Mints debt token to the `onBehalfOf` address. * - Only callable by the LendingPool * - The resulting rate is the weighted average between the rate of the new debt * and the rate of the previous debt * @param user The address receiving the borrowed underlying, being the delegatee in case * of credit delegate, or same as `onBehalfOf` otherwise * @param onBehalfOf The address receiving the debt tokens * @param amount The amount of debt tokens to mint * @param rate The rate of the debt being minted **/ function mint( address user, address onBehalfOf, uint256 amount, uint256 rate ) external override onlyLendingPool returns (bool) { MintLocalVars memory vars; if (user != onBehalfOf) { _decreaseBorrowAllowance(onBehalfOf, user, amount); } (, uint256 currentBalance, uint256 balanceIncrease) = _calculateBalanceIncrease(onBehalfOf); vars.previousSupply = totalSupply(); vars.currentAvgStableRate = _avgStableRate; vars.nextSupply = _totalSupply = vars.previousSupply.add(amount); vars.amountInRay = amount.wadToRay(); vars.newStableRate = _usersStableRate[onBehalfOf] .rayMul(currentBalance.wadToRay()) .add(vars.amountInRay.rayMul(rate)) .rayDiv(currentBalance.add(amount).wadToRay()); require(vars.newStableRate <= type(uint128).max, Errors.SDT_STABLE_DEBT_OVERFLOW); _usersStableRate[onBehalfOf] = vars.newStableRate; //solium-disable-next-line _totalSupplyTimestamp = _timestamps[onBehalfOf] = uint40(block.timestamp); // Calculates the updated average stable rate vars.currentAvgStableRate = _avgStableRate = vars .currentAvgStableRate .rayMul(vars.previousSupply.wadToRay()) .add(rate.rayMul(vars.amountInRay)) .rayDiv(vars.nextSupply.wadToRay()); _mint(onBehalfOf, amount.add(balanceIncrease), vars.previousSupply); emit Transfer(address(0), onBehalfOf, amount); emit Mint( user, onBehalfOf, amount, currentBalance, balanceIncrease, vars.newStableRate, vars.currentAvgStableRate, vars.nextSupply ); return currentBalance == 0; } /** * @dev Burns debt of `user` * @param user The address of the user getting his debt burned * @param amount The amount of debt tokens getting burned **/ function burn(address user, uint256 amount) external override onlyLendingPool { (, uint256 currentBalance, uint256 balanceIncrease) = _calculateBalanceIncrease(user); uint256 previousSupply = totalSupply(); uint256 newAvgStableRate = 0; uint256 nextSupply = 0; uint256 userStableRate = _usersStableRate[user]; // Since the total supply and each single user debt accrue separately, // there might be accumulation errors so that the last borrower repaying // mght actually try to repay more than the available debt supply. // In this case we simply set the total supply and the avg stable rate to 0 if (previousSupply <= amount) { _avgStableRate = 0; _totalSupply = 0; } else { nextSupply = _totalSupply = previousSupply.sub(amount); uint256 firstTerm = _avgStableRate.rayMul(previousSupply.wadToRay()); uint256 secondTerm = userStableRate.rayMul(amount.wadToRay()); // For the same reason described above, when the last user is repaying it might // happen that user rate * user balance > avg rate * total supply. In that case, // we simply set the avg rate to 0 if (secondTerm >= firstTerm) { newAvgStableRate = _avgStableRate = _totalSupply = 0; } else { newAvgStableRate = _avgStableRate = firstTerm.sub(secondTerm).rayDiv(nextSupply.wadToRay()); } } if (amount == currentBalance) { _usersStableRate[user] = 0; _timestamps[user] = 0; } else { //solium-disable-next-line _timestamps[user] = uint40(block.timestamp); } //solium-disable-next-line _totalSupplyTimestamp = uint40(block.timestamp); if (balanceIncrease > amount) { uint256 amountToMint = balanceIncrease.sub(amount); _mint(user, amountToMint, previousSupply); emit Mint( user, user, amountToMint, currentBalance, balanceIncrease, userStableRate, newAvgStableRate, nextSupply ); } else { uint256 amountToBurn = amount.sub(balanceIncrease); _burn(user, amountToBurn, previousSupply); emit Burn(user, amountToBurn, currentBalance, balanceIncrease, newAvgStableRate, nextSupply); } emit Transfer(user, address(0), amount); } /** * @dev Calculates the increase in balance since the last user interaction * @param user The address of the user for which the interest is being accumulated * @return The previous principal balance, the new principal balance and the balance increase **/ function _calculateBalanceIncrease(address user) internal view returns ( uint256, uint256, uint256 ) { uint256 previousPrincipalBalance = super.balanceOf(user); if (previousPrincipalBalance == 0) { return (0, 0, 0); } // Calculation of the accrued interest since the last accumulation uint256 balanceIncrease = balanceOf(user).sub(previousPrincipalBalance); return ( previousPrincipalBalance, previousPrincipalBalance.add(balanceIncrease), balanceIncrease ); } /** * @dev Returns the principal and total supply, the average borrow rate and the last supply update timestamp **/ function getSupplyData() public view override returns ( uint256, uint256, uint256, uint40 ) { uint256 avgRate = _avgStableRate; return (super.totalSupply(), _calcTotalSupply(avgRate), avgRate, _totalSupplyTimestamp); } /** * @dev Returns the the total supply and the average stable rate **/ function getTotalSupplyAndAvgRate() public view override returns (uint256, uint256) { uint256 avgRate = _avgStableRate; return (_calcTotalSupply(avgRate), avgRate); } /** * @dev Returns the total supply **/ function totalSupply() public view override returns (uint256) { return _calcTotalSupply(_avgStableRate); } /** * @dev Returns the timestamp at which the total supply was updated **/ function getTotalSupplyLastUpdated() public view override returns (uint40) { return _totalSupplyTimestamp; } /** * @dev Returns the principal debt balance of the user from * @param user The user's address * @return The debt balance of the user since the last burn/mint action **/ function principalBalanceOf(address user) external view virtual override returns (uint256) { return super.balanceOf(user); } /** * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) **/ function UNDERLYING_ASSET_ADDRESS() public view returns (address) { return _underlyingAsset; } /** * @dev Returns the address of the lending pool where this aToken is used **/ function POOL() public view returns (ILendingPool) { return _pool; } /** * @dev Returns the address of the incentives controller contract **/ function getIncentivesController() external view override returns (IAaveIncentivesController) { return _getIncentivesController(); } /** * @dev For internal usage in the logic of the parent contracts **/ function _getIncentivesController() internal view override returns (IAaveIncentivesController) { return _incentivesController; } /** * @dev For internal usage in the logic of the parent contracts **/ function _getUnderlyingAssetAddress() internal view override returns (address) { return _underlyingAsset; } /** * @dev For internal usage in the logic of the parent contracts **/ function _getLendingPool() internal view override returns (ILendingPool) { return _pool; } /** * @dev Calculates the total supply * @param avgRate The average rate at which the total supply increases * @return The debt balance of the user since the last burn/mint action **/ function _calcTotalSupply(uint256 avgRate) internal view virtual returns (uint256) { uint256 principalSupply = super.totalSupply(); if (principalSupply == 0) { return 0; } uint256 cumulatedInterest = MathUtils.calculateCompoundedInterest(avgRate, _totalSupplyTimestamp); return principalSupply.rayMul(cumulatedInterest); } /** * @dev Mints stable debt tokens to an user * @param account The account receiving the debt tokens * @param amount The amount being minted * @param oldTotalSupply the total supply before the minting event **/ function _mint( address account, uint256 amount, uint256 oldTotalSupply ) internal { uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.add(amount); if (address(_incentivesController) != address(0)) { _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); } } /** * @dev Burns stable debt tokens of an user * @param account The user getting his debt burned * @param amount The amount being burned * @param oldTotalSupply The total supply before the burning event **/ function _burn( address account, uint256 amount, uint256 oldTotalSupply ) internal { uint256 oldAccountBalance = _balances[account]; _balances[account] = oldAccountBalance.sub(amount, Errors.SDT_BURN_EXCEEDS_BALANCE); if (address(_incentivesController) != address(0)) { _incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance); } } }
/contracts/protocol/tokenization/VariableDebtToken.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {Errors} from '../libraries/helpers/Errors.sol'; import {DebtTokenBase} from './base/DebtTokenBase.sol'; import {ILendingPool} from '../../interfaces/ILendingPool.sol'; import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; /** * @title VariableDebtToken * @notice Implements a variable debt token to track the borrowing positions of users * at variable rate mode * @author Aave **/ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { using WadRayMath for uint256; uint256 public constant DEBT_TOKEN_REVISION = 0x1; ILendingPool internal _pool; address internal _underlyingAsset; IAaveIncentivesController internal _incentivesController; /** * @dev Initializes the debt token. * @param pool The address of the lending pool where this aToken will be used * @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 debtTokenDecimals The decimals of the debtToken, same as the underlying asset's * @param debtTokenName The name of the token * @param debtTokenSymbol The symbol of the token */ function initialize( ILendingPool pool, address underlyingAsset, IAaveIncentivesController incentivesController, uint8 debtTokenDecimals, string memory debtTokenName, string memory debtTokenSymbol, bytes calldata params ) public override initializer { _setName(debtTokenName); _setSymbol(debtTokenSymbol); _setDecimals(debtTokenDecimals); _pool = pool; _underlyingAsset = underlyingAsset; _incentivesController = incentivesController; emit Initialized( underlyingAsset, address(pool), address(incentivesController), debtTokenDecimals, debtTokenName, debtTokenSymbol, params ); } /** * @dev Gets the revision of the stable debt token implementation * @return The debt token implementation revision **/ function getRevision() internal pure virtual override returns (uint256) { return DEBT_TOKEN_REVISION; } /** * @dev Calculates the accumulated debt balance of the user * @return The debt balance of the user **/ function balanceOf(address user) public view virtual override returns (uint256) { uint256 scaledBalance = super.balanceOf(user); if (scaledBalance == 0) { return 0; } return scaledBalance.rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset)); } /** * @dev Mints debt token to the `onBehalfOf` address * - Only callable by the LendingPool * @param user The address receiving the borrowed underlying, being the delegatee in case * of credit delegate, or same as `onBehalfOf` otherwise * @param onBehalfOf The address receiving the debt tokens * @param amount The amount of debt being minted * @param index The variable debt index of the reserve * @return `true` if the the previous balance of the user is 0 **/ function mint( address user, address onBehalfOf, uint256 amount, uint256 index ) external override onlyLendingPool returns (bool) { if (user != onBehalfOf) { _decreaseBorrowAllowance(onBehalfOf, user, amount); } uint256 previousBalance = super.balanceOf(onBehalfOf); uint256 amountScaled = amount.rayDiv(index); require(amountScaled != 0, Errors.CT_INVALID_MINT_AMOUNT); _mint(onBehalfOf, amountScaled); emit Transfer(address(0), onBehalfOf, amount); emit Mint(user, onBehalfOf, amount, index); return previousBalance == 0; } /** * @dev Burns user variable debt * - Only callable by the LendingPool * @param user The user whose debt is getting burned * @param amount The amount getting burned * @param index The variable debt index of the reserve **/ function burn( address user, uint256 amount, uint256 index ) external override onlyLendingPool { uint256 amountScaled = amount.rayDiv(index); require(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT); _burn(user, amountScaled); emit Transfer(user, address(0), amount); emit Burn(user, amount, index); } /** * @dev Returns the principal debt balance of the user from * @return The debt balance of the user since the last burn/mint action **/ function scaledBalanceOf(address user) public view virtual override returns (uint256) { return super.balanceOf(user); } /** * @dev Returns the total supply of the variable debt token. Represents the total debt accrued by the users * @return The total supply **/ function totalSupply() public view virtual override returns (uint256) { return super.totalSupply().rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset)); } /** * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index) * @return the scaled total supply **/ function scaledTotalSupply() public view virtual override returns (uint256) { return super.totalSupply(); } /** * @dev Returns the principal balance of the user and principal total supply. * @param user The address of the user * @return The principal balance of the user * @return The principal total supply **/ function getScaledUserBalanceAndSupply(address user) external view override returns (uint256, uint256) { return (super.balanceOf(user), super.totalSupply()); } /** * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) **/ function UNDERLYING_ASSET_ADDRESS() public view returns (address) { return _underlyingAsset; } /** * @dev Returns the address of the incentives controller contract **/ function getIncentivesController() external view override returns (IAaveIncentivesController) { return _getIncentivesController(); } /** * @dev Returns the address of the lending pool where this aToken is used **/ function POOL() public view returns (ILendingPool) { return _pool; } function _getIncentivesController() internal view override returns (IAaveIncentivesController) { return _incentivesController; } function _getUnderlyingAssetAddress() internal view override returns (address) { return _underlyingAsset; } function _getLendingPool() internal view override returns (ILendingPool) { return _pool; } }
/contracts/protocol/tokenization/base/DebtTokenBase.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {ILendingPool} from '../../../interfaces/ILendingPool.sol'; import {ICreditDelegationToken} from '../../../interfaces/ICreditDelegationToken.sol'; import { VersionedInitializable } from '../../libraries/aave-upgradeability/VersionedInitializable.sol'; import {IncentivizedERC20} from '../IncentivizedERC20.sol'; import {Errors} from '../../libraries/helpers/Errors.sol'; /** * @title DebtTokenBase * @notice Base contract for different types of debt tokens, like StableDebtToken or VariableDebtToken * @author Aave */ abstract contract DebtTokenBase is IncentivizedERC20('DEBTTOKEN_IMPL', 'DEBTTOKEN_IMPL', 0), VersionedInitializable, ICreditDelegationToken { mapping(address => mapping(address => uint256)) internal _borrowAllowances; /** * @dev Only lending pool can call functions marked by this modifier **/ modifier onlyLendingPool { require(_msgSender() == address(_getLendingPool()), Errors.CT_CALLER_MUST_BE_LENDING_POOL); _; } /** * @dev delegates borrowing power to a user on the specific debt token * @param delegatee the address receiving the delegated borrowing power * @param amount the maximum amount being delegated. Delegation will still * respect the liquidation constraints (even if delegated, a delegatee cannot * force a delegator HF to go below 1) **/ function approveDelegation(address delegatee, uint256 amount) external override { _borrowAllowances[_msgSender()][delegatee] = amount; emit BorrowAllowanceDelegated(_msgSender(), delegatee, _getUnderlyingAssetAddress(), amount); } /** * @dev returns the borrow allowance of the user * @param fromUser The user to giving allowance * @param toUser The user to give allowance to * @return the current allowance of toUser **/ function borrowAllowance(address fromUser, address toUser) external view override returns (uint256) { return _borrowAllowances[fromUser][toUser]; } /** * @dev Being non transferrable, the debt token does not implement any of the * standard ERC20 functions for transfer and allowance. **/ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { recipient; amount; revert('TRANSFER_NOT_SUPPORTED'); } function allowance(address owner, address spender) public view virtual override returns (uint256) { owner; spender; revert('ALLOWANCE_NOT_SUPPORTED'); } function approve(address spender, uint256 amount) public virtual override returns (bool) { spender; amount; revert('APPROVAL_NOT_SUPPORTED'); } function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { sender; recipient; amount; revert('TRANSFER_NOT_SUPPORTED'); } function increaseAllowance(address spender, uint256 addedValue) public virtual override returns (bool) { spender; addedValue; revert('ALLOWANCE_NOT_SUPPORTED'); } function decreaseAllowance(address spender, uint256 subtractedValue) public virtual override returns (bool) { spender; subtractedValue; revert('ALLOWANCE_NOT_SUPPORTED'); } function _decreaseBorrowAllowance( address delegator, address delegatee, uint256 amount ) internal { uint256 newAllowance = _borrowAllowances[delegator][delegatee].sub(amount, Errors.BORROW_ALLOWANCE_NOT_ENOUGH); _borrowAllowances[delegator][delegatee] = newAllowance; emit BorrowAllowanceDelegated(delegator, delegatee, _getUnderlyingAssetAddress(), newAllowance); } function _getUnderlyingAssetAddress() internal view virtual returns (address); function _getLendingPool() internal view virtual returns (ILendingPool); }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_pool","internalType":"address payable"},{"type":"address","name":"_addressesProvider","internalType":"address"}]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"deployedContracts","inputs":[{"type":"address","name":"stableToken","internalType":"address","indexed":false},{"type":"address","name":"variableToken","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initDeployment","inputs":[{"type":"address[]","name":"tokens","internalType":"address[]"},{"type":"string[]","name":"symbols","internalType":"string[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOracleBorrowRates","inputs":[{"type":"address[]","name":"assets","internalType":"address[]"},{"type":"uint256[]","name":"rates","internalType":"uint256[]"},{"type":"address","name":"oracle","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOracleOwnership","inputs":[{"type":"address","name":"oracle","internalType":"address"},{"type":"address","name":"admin","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b506040516141c43803806141c483398101604081905261002f916100b8565b60006100396100b4565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055610109565b3390565b600080604083850312156100ca578182fd5b82516100d5816100f1565b60208401519092506100e6816100f1565b809150509250929050565b6001600160a01b038116811461010657600080fd5b50565b6140ac806101186000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806354fe1c9414610067578063563b1cb31461007c578063715018a61461008f5780638da5cb5b14610097578063c2d30321146100b5578063f2fde38b146100c8575b600080fd5b61007a610075366004610680565b6100db565b005b61007a61008a366004610648565b610203565b61007a610361565b61009f6103e0565b6040516100ac919061076a565b60405180910390f35b61007a6100c33660046106e9565b6103ef565b61007a6100d6366004610609565b6104ec565b6100e36105a2565b6000546001600160a01b039081169116146101195760405162461bcd60e51b8152600401610110906107f7565b60405180910390fd5b8281146101385760405162461bcd60e51b8152600401610110906108bf565b6001546001600160a01b03166101605760405162461bcd60e51b81526004016101109061082c565b60005b838110156101fc577f1c1768aab1796270c7034dc781c2951065e6afb7a946269746521002443b8ea4604051610198906105a6565b604051809103906000f0801580156101b4573d6000803e3d6000fd5b506040516101c1906105b3565b604051809103906000f0801580156101dd573d6000803e3d6000fd5b506040516101ec92919061077e565b60405180910390a1600101610163565b5050505050565b61020b6105a2565b6000546001600160a01b039081169116146102385760405162461bcd60e51b8152600401610110906107f7565b6001600160a01b03811661025e5760405162461bcd60e51b815260040161011090610890565b306001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102a157600080fd5b505afa1580156102b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d9919061062c565b6001600160a01b0316146102ff5760405162461bcd60e51b815260040161011090610863565b60405163f2fde38b60e01b81526001600160a01b0383169063f2fde38b9061032b90849060040161076a565b600060405180830381600087803b15801561034557600080fd5b505af1158015610359573d6000803e3d6000fd5b505050505050565b6103696105a2565b6000546001600160a01b039081169116146103965760405162461bcd60e51b8152600401610110906107f7565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6103f76105a2565b6000546001600160a01b039081169116146104245760405162461bcd60e51b8152600401610110906107f7565b8382146104435760405162461bcd60e51b8152600401610110906108bf565b60005b8481101561035957816001600160a01b03166372eb293d87878481811061046957fe5b905060200201602081019061047e9190610609565b86868581811061048a57fe5b905060200201356040518363ffffffff1660e01b81526004016104ae929190610798565b600060405180830381600087803b1580156104c857600080fd5b505af11580156104dc573d6000803e3d6000fd5b5050600190920191506104469050565b6104f46105a2565b6000546001600160a01b039081169116146105215760405162461bcd60e51b8152600401610110906107f7565b6001600160a01b0381166105475760405162461bcd60e51b8152600401610110906107b1565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b611e648061090883390190565b61190b8061276c83390190565b60008083601f8401126105d1578182fd5b50813567ffffffffffffffff8111156105e8578182fd5b602083019150836020808302850101111561060257600080fd5b9250929050565b60006020828403121561061a578081fd5b8135610625816108ef565b9392505050565b60006020828403121561063d578081fd5b8151610625816108ef565b6000806040838503121561065a578081fd5b8235610665816108ef565b91506020830135610675816108ef565b809150509250929050565b60008060008060408587031215610695578182fd5b843567ffffffffffffffff808211156106ac578384fd5b6106b8888389016105c0565b909650945060208701359150808211156106d0578384fd5b506106dd878288016105c0565b95989497509550505050565b600080600080600060608688031215610700578081fd5b853567ffffffffffffffff80821115610717578283fd5b61072389838a016105c0565b9097509550602088013591508082111561073b578283fd5b50610748888289016105c0565b909450925050604086013561075c816108ef565b809150509295509295909350565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601c908201527f506f6f6c2063616e206e6f74206265207a65726f206164647265737300000000604082015260600190565b6020808252601390820152723432b63832b91034b9903737ba1037bbb732b960691b604082015260600190565b6020808252601590820152746f776e65722063616e206e6f74206265207a65726f60581b604082015260600190565b602080825260169082015275082e4e4c2f2e640dcdee840e6c2daca40d8cadccee8d60531b604082015260600190565b6001600160a01b038116811461090457600080fd5b5056fe608060405260006006553480156200001657600080fd5b50604080518082018252600e8082526d111150951513d2d15397d253541360921b60208084018281528551808701909652928552840152815191929160009162000064916003919062000098565b5081516200007a90600490602085019062000098565b506005805460ff191660ff9290921691909117905550620001349050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000db57805160ff19168380011785556200010b565b828001600101855582156200010b579182015b828111156200010b578251825591602001919060010190620000ee565b50620001199291506200011d565b5090565b5b808211156200011957600081556001016200011e565b611d2080620001446000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806395d89b41116100f9578063c04a8a1011610097578063dd62ed3e11610071578063dd62ed3e146106ab578063e7484890146106d9578063e78c9b3b146106e1578063f731e9be14610707576101a9565b8063c04a8a10146104b0578063c222ec8a146104dc578063c634dfaa14610685576101a9565b8063a9059cbb116100d3578063a9059cbb14610438578063b16a19de14610464578063b3f1c93d1461046c578063b9a7b622146104a8576101a9565b806395d89b41146104025780639dc29fac1461040a578063a457c2d7146102d9576101a9565b80636bd76d241161016657806375d264131161014057806375d264131461037d578063797743381461038557806379ce6b8c146103ba57806390f6fcf2146103fa576101a9565b80636bd76d241461030557806370a08231146103335780637535d24614610359576101a9565b806306fdde03146101ae578063095ea7b31461022b57806318160ddd1461026b57806323b872dd14610285578063313ce567146102bb57806339509351146102d9575b600080fd5b6101b6610728565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f05781810151838201526020016101d8565b50505050905090810190601f16801561021d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102576004803603604081101561024157600080fd5b506001600160a01b0381351690602001356107be565b604080519115158252519081900360200190f35b610273610806565b60408051918252519081900360200190f35b6102576004803603606081101561029b57600080fd5b506001600160a01b03813581169160208101359091169060400135610818565b6102c3610860565b6040805160ff9092168252519081900360200190f35b610257600480360360408110156102ef57600080fd5b506001600160a01b038135169060200135610869565b6102736004803603604081101561031b57600080fd5b506001600160a01b03813581169160200135166108b8565b6102736004803603602081101561034957600080fd5b50356001600160a01b03166108e5565b61036161095f565b604080516001600160a01b039092168252519081900360200190f35b610361610977565b61038d610981565b6040805194855260208501939093528383019190915264ffffffffff166060830152519081900360800190f35b6103e0600480360360208110156103d057600080fd5b50356001600160a01b03166109b7565b6040805164ffffffffff9092168252519081900360200190f35b6102736109d9565b6101b66109df565b6104366004803603604081101561042057600080fd5b506001600160a01b038135169060200135610a40565b005b6102576004803603604081101561044e57600080fd5b506001600160a01b038135169060200135610818565b610361610da6565b6102576004803603608081101561048257600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135610db5565b61027361110d565b610436600480360360408110156104c657600080fd5b506001600160a01b038135169060200135611112565b610436600480360360e08110156104f257600080fd5b6001600160a01b038235811692602081013582169260408201359092169160ff606083013516919081019060a08101608082013564010000000081111561053857600080fd5b82018360208201111561054a57600080fd5b8035906020019184600183028401116401000000008311171561056c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156105bf57600080fd5b8201836020820111156105d157600080fd5b803590602001918460018302840111640100000000831117156105f357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561064657600080fd5b82018360208201111561065857600080fd5b8035906020019184600183028401116401000000008311171561067a57600080fd5b5090925090506111ae565b6102736004803603602081101561069b57600080fd5b50356001600160a01b0316611412565b610273600480360360408110156106c157600080fd5b506001600160a01b0381358116916020013516610869565b6103e061141d565b610273600480360360208110156106f757600080fd5b50356001600160a01b031661142a565b61070f611445565b6040805192835260208301919091528051918290030190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107b45780601f10610789576101008083540402835291602001916107b4565b820191906000526020600020905b81548152906001019060200180831161079757829003601f168201915b5050505050905090565b6040805162461bcd60e51b81526020600482015260166024820152751054141493d5905317d393d517d4d5541413d495115160521b6044820152905160009181900360640190fd5b6000610813603b5461145e565b905090565b6040805162461bcd60e51b81526020600482015260166024820152751514905394d1915497d393d517d4d5541413d495115160521b6044820152905160009181900360640190fd5b60055460ff1690565b6040805162461bcd60e51b815260206004820152601760248201527f414c4c4f57414e43455f4e4f545f535550504f525445440000000000000000006044820152905160009181900360640190fd5b6001600160a01b038083166000908152603a60209081526040808320938516835292905220545b92915050565b6000806108f1836114a6565b6001600160a01b0384166000908152603d60205260409020549091508161091d5760009250505061095a565b6001600160a01b0384166000908152603c602052604081205461094890839064ffffffffff166114c1565b905061095483826114d5565b93505050505b919050565b603e546501000000000090046001600160a01b031690565b6000610813611593565b6000806000806000603b5490506109966115a2565b61099f8261145e565b603e54919790965091945064ffffffffff1692509050565b6001600160a01b03166000908152603c602052604090205464ffffffffff1690565b603b5490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107b45780601f10610789576101008083540402835291602001916107b4565b610a4861095f565b6001600160a01b0316610a596115a8565b6001600160a01b03161460405180604001604052806002815260200161323960f01b81525090610b075760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610acc578181015183820152602001610ab4565b50505050905090810190601f168015610af95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600080610b14846115ac565b92509250506000610b23610806565b6001600160a01b0386166000908152603d6020526040812054919250908190868411610b58576000603b819055600255610bda565b610b628488611605565b600281905591506000610b80610b7786611647565b603b54906114d5565b90506000610b97610b908a611647565b84906114d5565b9050818110610bb35760006002819055603b8190559450610bd7565b610bcf610bbf85611647565b610bc98484611605565b906116c5565b603b81905594505b50505b85871415610c18576001600160a01b0388166000908152603d60209081526040808320839055603c9091529020805464ffffffffff19169055610c46565b6001600160a01b0388166000908152603c60205260409020805464ffffffffff19164264ffffffffff161790555b603e805464ffffffffff19164264ffffffffff1617905586851115610ce6576000610c718689611605565b9050610c7e8982876117cc565b6040805182815260208101899052808201889052606081018490526080810186905260a0810185905290516001600160a01b038b169182917fc16f4e4ca34d790de4c656c72fd015c667d688f20be64eea360618545c4c530f9181900360c00190a350610d5b565b6000610cf28887611605565b9050610cff898287611891565b6040805182815260208101899052808201889052606081018690526080810185905290516001600160a01b038b16917f44bd20a79e993bdcc7cbedf54a3b4d19fb78490124b6b90d04fe3242eea579e8919081900360a00190a2505b6040805188815290516000916001600160a01b038b16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050505050505050565b603f546001600160a01b031690565b6000610dbf61095f565b6001600160a01b0316610dd06115a8565b6001600160a01b03161460405180604001604052806002815260200161323960f01b81525090610e415760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b50610e4a611bd9565b846001600160a01b0316866001600160a01b031614610e6e57610e6e8587866118d3565b600080610e7a876115ac565b9250925050610e87610806565b808452603b546080850152610e9c908761199b565b60028190556020840152610eaf86611647565b6040840152610f0d610ec9610ec4848961199b565b611647565b6040850151610bc990610edc90896114d5565b610f07610ee887611647565b6001600160a01b038d166000908152603d6020526040902054906114d5565b9061199b565b60608401819052604080518082019091526002815261373960f01b6020820152906fffffffffffffffffffffffffffffffff1015610f8c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b5060608301516001600160a01b0388166000908152603d6020908152604080832093909355603c8152919020805464ffffffffff421664ffffffffff199182168117909255603e8054909116909117905583015161102290610fed90611647565b610bc96110078660400151896114d590919063ffffffff16565b610f076110178860000151611647565b6080890151906114d5565b603b81905560808401526110418761103a888461199b565b85516117cc565b6040805187815290516001600160a01b038916916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3866001600160a01b0316886001600160a01b03167fc16f4e4ca34d790de4c656c72fd015c667d688f20be64eea360618545c4c530f888585886060015189608001518a6020015160405180878152602001868152602001858152602001848152602001838152602001828152602001965050505050505060405180910390a350159695505050505050565b600181565b80603a600061111f6115a8565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120919091556111576115a8565b6001600160a01b03167fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e1611189610da6565b604080516001600160a01b039092168252602082018690528051918290030190a35050565b60006111b86119f5565b60075490915060ff16806111cf57506111cf6119fa565b806111db575060065481115b6112165760405162461bcd60e51b815260040180806020018281038252602e815260200180611cbd602e913960400191505060405180910390fd5b60075460ff16158015611236576007805460ff1916600117905560068290555b61123f86611a00565b61124885611a17565b61125187611a2a565b603e805465010000000000600160c81b031916650100000000006001600160a01b038d811691820292909217909255603f80546001600160a01b03199081168d841690811790925560408054909116928c169283178155805192835260ff8b1660208085019190915260a09184018281528b51928501929092528a5192937f40251fbfb6656cfa65a00d7879029fec1fad21d28fdcff2f4f68f52795b74f2c938e938e938e938e938e938e9390916060840191608085019160c08601918a019080838360005b8381101561132f578181015183820152602001611317565b50505050905090810190601f16801561135c5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b8381101561138f578181015183820152602001611377565b50505050905090810190601f1680156113bc5780820380516001836020036101000a031916815260200191505b508481038252858152602001868680828437600083820152604051601f909101601f19169092018290039b50909950505050505050505050a38015611406576007805460ff191690555b50505050505050505050565b60006108df826114a6565b603e5464ffffffffff1690565b6001600160a01b03166000908152603d602052604090205490565b603b5460009081906114568161145e565b925090509091565b6000806114696115a2565b90508061147a57600091505061095a565b603e5460009061149290859064ffffffffff166114c1565b905061149e82826114d5565b949350505050565b6001600160a01b031660009081526020819052604090205490565b60006114ce838342611a40565b9392505050565b60008215806114e2575081155b156114ef575060006108df565b816b019d971e4fe8401e74000000198161150557fe5b0483111560405180604001604052806002815260200161068760f31b815250906115705760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b50506b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b6040546001600160a01b031690565b60025490565b3390565b6000806000806115bb856114a6565b9050806115d3576000806000935093509350506115fe565b60006115e8826115e2886108e5565b90611605565b9050816115f5818361199b565b90955093509150505b9193909250565b60006114ce83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611b16565b6000633b9aca0082810290839082041460405180604001604052806002815260200161068760f31b815250906116be5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b5092915050565b604080518082019091526002815261035360f41b60208201526000908261172d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b5060408051808201909152600280825261068760f31b60208301528304906b033b2e3c9fd0803ce80000008219048511156117a95760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b5082816b033b2e3c9fd0803ce8000000860201816117c357fe5b04949350505050565b6001600160a01b0383166000908152602081905260409020546117ef818461199b565b6001600160a01b0380861660009081526020819052604090819020929092559054161561188b576040805481516318c39f1760e11b81526001600160a01b0387811660048301526024820186905260448201859052925192909116916331873e2e9160648082019260009290919082900301818387803b15801561187257600080fd5b505af1158015611886573d6000803e3d6000fd5b505050505b50505050565b6001600160a01b038316600090815260208181526040918290205482518084019093526002835261038360f41b91830191909152906117ef9082908590611b16565b6040805180820182526002815261353960f01b6020808301919091526001600160a01b038087166000908152603a8352848120918716815291529182205461191c918490611b16565b6001600160a01b038086166000818152603a60209081526040808320948916808452949091529020839055919250907fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e1611974610da6565b604080516001600160a01b039092168252602082018690528051918290030190a350505050565b6000828201838110156114ce576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600190565b303b1590565b8051611a13906003906020840190611c08565b5050565b8051611a13906004906020840190611c08565b6005805460ff191660ff92909216919091179055565b600080611a548364ffffffffff8616611605565b905080611a6b57611a63611b70565b9150506114ce565b6000198101600060028311611a81576000611a86565b600283035b90506301e1338087046000611a9b82806114d5565b90506000611aa982846114d5565b905060006002611ac384611abd8a8a611b80565b90611b80565b81611aca57fe5b04905060006006611ae184611abd89818d8d611b80565b81611ae857fe5b049050611b0681610f078481611afe8a8e611b80565b610f07611b70565b9c9b505050505050505050505050565b60008184841115611b685760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b505050900390565b6b033b2e3c9fd0803ce800000090565b600082611b8f575060006108df565b82820282848281611b9c57fe5b04146114ce5760405162461bcd60e51b8152600401808060200182810382526021815260200180611c9c6021913960400191505060405180910390fd5b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c4957805160ff1916838001178555611c76565b82800160010185558215611c76579182015b82811115611c76578251825591602001919060010190611c5b565b50611c82929150611c86565b5090565b5b80821115611c825760008155600101611c8756fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a26469706673582212205a38daaf60cf3988dfa2e08f6294463d91362b7a15ac9fc890825cdc6b71b7f964736f6c634300060c0033608060405260006006553480156200001657600080fd5b50604080518082018252600e8082526d111150951513d2d15397d253541360921b60208084018281528551808701909652928552840152815191929160009162000064916003919062000098565b5081516200007a90600490602085019062000098565b506005805460ff191660ff9290921691909117905550620001349050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000db57805160ff19168380011785556200010b565b828001600101855582156200010b579182015b828111156200010b578251825591602001919060010190620000ee565b50620001199291506200011d565b5090565b5b808211156200011957600081556001016200011e565b6117c780620001446000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806375d26413116100c3578063b3f1c93d1161007c578063b3f1c93d146103d2578063b9a7b6221461040e578063c04a8a1014610416578063c222ec8a14610444578063dd62ed3e146105ed578063f5298aca1461061b5761014d565b806375d264131461038657806395d89b411461038e578063a457c2d7146102e2578063a9059cbb14610396578063b16a19de146103c2578063b1bf962d146103ca5761014d565b806323b872dd1161011557806323b872dd1461028e578063313ce567146102c457806339509351146102e25780636bd76d241461030e57806370a082311461033c5780637535d246146103625761014d565b806306fdde0314610152578063095ea7b3146101cf5780630afbcdc91461020f57806318160ddd1461024e5780631da24f3e14610268575b600080fd5b61015a61064d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561019457818101518382015260200161017c565b50505050905090810190601f1680156101c15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101fb600480360360408110156101e557600080fd5b506001600160a01b0381351690602001356106e3565b604080519115158252519081900360200190f35b6102356004803603602081101561022557600080fd5b50356001600160a01b031661072b565b6040805192835260208301919091528051918290030190f35b610256610748565b60408051918252519081900360200190f35b6102566004803603602081101561027e57600080fd5b50356001600160a01b03166107db565b6101fb600480360360608110156102a457600080fd5b506001600160a01b038135811691602081013590911690604001356107ee565b6102cc610836565b6040805160ff9092168252519081900360200190f35b6101fb600480360360408110156102f857600080fd5b506001600160a01b03813516906020013561083f565b6102566004803603604081101561032457600080fd5b506001600160a01b038135811691602001351661088e565b6102566004803603602081101561035257600080fd5b50356001600160a01b03166108bb565b61036a610967565b604080516001600160a01b039092168252519081900360200190f35b61036a610976565b61015a610980565b6101fb600480360360408110156103ac57600080fd5b506001600160a01b0381351690602001356107ee565b61036a6109e1565b6102566109f0565b6101fb600480360360808110156103e857600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356109fa565b610256610c13565b6104426004803603604081101561042c57600080fd5b506001600160a01b038135169060200135610c18565b005b610442600480360360e081101561045a57600080fd5b6001600160a01b038235811692602081013582169260408201359092169160ff606083013516919081019060a0810160808201356401000000008111156104a057600080fd5b8201836020820111156104b257600080fd5b803590602001918460018302840111640100000000831117156104d457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561052757600080fd5b82018360208201111561053957600080fd5b8035906020019184600183028401116401000000008311171561055b57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156105ae57600080fd5b8201836020820111156105c057600080fd5b803590602001918460018302840111640100000000831117156105e257600080fd5b509092509050610cb4565b6102566004803603604081101561060357600080fd5b506001600160a01b038135811691602001351661083f565b6104426004803603606081101561063157600080fd5b506001600160a01b038135169060208101359060400135610f03565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106d95780601f106106ae576101008083540402835291602001916106d9565b820191906000526020600020905b8154815290600101906020018083116106bc57829003601f168201915b5050505050905090565b6040805162461bcd60e51b81526020600482015260166024820152751054141493d5905317d393d517d4d5541413d495115160521b6044820152905160009181900360640190fd5b60008061073783611097565b61073f6110b2565b91509150915091565b603b54603c546040805163386497fd60e01b81526001600160a01b03928316600482015290516000936107d693169163386497fd916024808301926020929190829003018186803b15801561079c57600080fd5b505afa1580156107b0573d6000803e3d6000fd5b505050506040513d60208110156107c657600080fd5b50516107d06110b2565b906110b8565b905090565b60006107e682611097565b90505b919050565b6040805162461bcd60e51b81526020600482015260166024820152751514905394d1915497d393d517d4d5541413d495115160521b6044820152905160009181900360640190fd5b60055460ff1690565b6040805162461bcd60e51b815260206004820152601760248201527f414c4c4f57414e43455f4e4f545f535550504f525445440000000000000000006044820152905160009181900360640190fd5b6001600160a01b038083166000908152603a60209081526040808320938516835292905220545b92915050565b6000806108c783611097565b9050806108d85760009150506107e9565b603b54603c546040805163386497fd60e01b81526001600160a01b039283166004820152905161096093929092169163386497fd91602480820192602092909190829003018186803b15801561092d57600080fd5b505afa158015610941573d6000803e3d6000fd5b505050506040513d602081101561095757600080fd5b505182906110b8565b9392505050565b603b546001600160a01b031690565b60006107d6611176565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106d95780601f106106ae576101008083540402835291602001916106d9565b603c546001600160a01b031690565b60006107d66110b2565b6000610a04610967565b6001600160a01b0316610a15611185565b6001600160a01b03161460405180604001604052806002815260200161323960f01b81525090610ac35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610a88578181015183820152602001610a70565b50505050905090810190601f168015610ab55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50836001600160a01b0316856001600160a01b031614610ae857610ae8848685611189565b6000610af385611097565b90506000610b018585611251565b6040805180820190915260028152611a9b60f11b602082015290915081610b695760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b50610b748682611358565b6040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3856001600160a01b0316876001600160a01b03167f2f00e3cdd69a77be7ed215ec7b2a36784dd158f921fca79ac29deffa353fe6ee8787604051808381526020018281526020019250505060405180910390a3501595945050505050565b600181565b80603a6000610c25611185565b6001600160a01b0390811682526020808301939093526040918201600090812091871680825291909352912091909155610c5d611185565b6001600160a01b03167fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e1610c8f6109e1565b604080516001600160a01b039092168252602082018690528051918290030190a35050565b6000610cbe6114a9565b60075490915060ff1680610cd55750610cd56114ae565b80610ce1575060065481115b610d1c5760405162461bcd60e51b815260040180806020018281038252602e815260200180611743602e913960400191505060405180910390fd5b60075460ff16158015610d3c576007805460ff1916600117905560068290555b610d45866114b4565b610d4e856114cb565b610d57876114de565b603b80546001600160a01b03808d166001600160a01b03199283168117909355603c80548d83169084168117909155603d8054928d169290931682179092556040805191825260ff8b1660208084019190915260a09183018281528b51928401929092528a517f40251fbfb6656cfa65a00d7879029fec1fad21d28fdcff2f4f68f52795b74f2c938e938e938e938e938e938e93919290916060840191608085019160c0860191908a019080838360005b83811015610e20578181015183820152602001610e08565b50505050905090810190601f168015610e4d5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610e80578181015183820152602001610e68565b50505050905090810190601f168015610ead5780820380516001836020036101000a031916815260200191505b508481038252858152602001868680828437600083820152604051601f909101601f19169092018290039b50909950505050505050505050a38015610ef7576007805460ff191690555b50505050505050505050565b610f0b610967565b6001600160a01b0316610f1c611185565b6001600160a01b03161460405180604001604052806002815260200161323960f01b81525090610f8d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b506000610f9a8383611251565b60408051808201909152600281526106a760f31b6020820152909150816110025760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b5061100d84826114f4565b6040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3604080518481526020810184905281516001600160a01b038716927f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a928290030190a250505050565b6001600160a01b031660009081526020819052604090205490565b60025490565b60008215806110c5575081155b156110d2575060006108b5565b816b019d971e4fe8401e7400000019816110e857fe5b0483111560405180604001604052806002815260200161068760f31b815250906111535760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b50506b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b603d546001600160a01b031690565b3390565b6040805180820182526002815261353960f01b6020808301919091526001600160a01b038087166000908152603a835284812091871681529152918220546111d2918490611592565b6001600160a01b038086166000818152603a60209081526040808320948916808452949091529020839055919250907fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e161122a6109e1565b604080516001600160a01b039092168252602082018690528051918290030190a350505050565b604080518082019091526002815261035360f41b6020820152600090826112b95760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b5060408051808201909152600280825261068760f31b60208301528304906b033b2e3c9fd0803ce80000008219048511156113355760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b5082816b033b2e3c9fd0803ce80000008602018161134f57fe5b04949350505050565b6001600160a01b0382166113b3576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6113bf600083836115ec565b6002546113cc81836115f1565b6002556001600160a01b0383166000908152602081905260409020546113f281846115f1565b6001600160a01b038516600090815260208190526040812091909155611416611176565b6001600160a01b0316146114a35761142c611176565b6001600160a01b03166331873e2e8584846040518463ffffffff1660e01b815260040180846001600160a01b031681526020018381526020018281526020019350505050600060405180830381600087803b15801561148a57600080fd5b505af115801561149e573d6000803e3d6000fd5b505050505b50505050565b600190565b303b1590565b80516114c790600390602084019061168d565b5050565b80516114c790600490602084019061168d565b6005805460ff191660ff92909216919091179055565b6001600160a01b0382166115395760405162461bcd60e51b81526004018080602001828103825260218152602001806117716021913960400191505060405180910390fd5b611545826000836115ec565b600254611552818361164b565b6002556001600160a01b0383166000908152602081815260409182902054825160608101909352602280845290926113f292869290611721908301398391905b600081848411156115e45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b505050900390565b505050565b600082820183811015610960576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061096083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611592565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106116ce57805160ff19168380011785556116fb565b828001600101855582156116fb579182015b828111156116fb5782518255916020019190600101906116e0565b5061170792915061170b565b5090565b5b80821115611707576000815560010161170c56fe45524332303a206275726e20616d6f756e7420657863656564732062616c616e6365436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e2066726f6d20746865207a65726f2061646472657373a264697066735822122017bccf702f4b07d646e52ec9c0185e3fbd2829929227226dc1a67c52115cd39264736f6c634300060c0033a26469706673582212204ffa22708343138ee631cdfba68dd2250a65e797a473789cffa6e2d5cb36b63f64736f6c634300060c0033000000000000000000000000970b12522ca9b4054807a2c5b736149a5be6f670000000000000000000000000d1088091a174d33412a968fa34cb67131188b332
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100625760003560e01c806354fe1c9414610067578063563b1cb31461007c578063715018a61461008f5780638da5cb5b14610097578063c2d30321146100b5578063f2fde38b146100c8575b600080fd5b61007a610075366004610680565b6100db565b005b61007a61008a366004610648565b610203565b61007a610361565b61009f6103e0565b6040516100ac919061076a565b60405180910390f35b61007a6100c33660046106e9565b6103ef565b61007a6100d6366004610609565b6104ec565b6100e36105a2565b6000546001600160a01b039081169116146101195760405162461bcd60e51b8152600401610110906107f7565b60405180910390fd5b8281146101385760405162461bcd60e51b8152600401610110906108bf565b6001546001600160a01b03166101605760405162461bcd60e51b81526004016101109061082c565b60005b838110156101fc577f1c1768aab1796270c7034dc781c2951065e6afb7a946269746521002443b8ea4604051610198906105a6565b604051809103906000f0801580156101b4573d6000803e3d6000fd5b506040516101c1906105b3565b604051809103906000f0801580156101dd573d6000803e3d6000fd5b506040516101ec92919061077e565b60405180910390a1600101610163565b5050505050565b61020b6105a2565b6000546001600160a01b039081169116146102385760405162461bcd60e51b8152600401610110906107f7565b6001600160a01b03811661025e5760405162461bcd60e51b815260040161011090610890565b306001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102a157600080fd5b505afa1580156102b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d9919061062c565b6001600160a01b0316146102ff5760405162461bcd60e51b815260040161011090610863565b60405163f2fde38b60e01b81526001600160a01b0383169063f2fde38b9061032b90849060040161076a565b600060405180830381600087803b15801561034557600080fd5b505af1158015610359573d6000803e3d6000fd5b505050505050565b6103696105a2565b6000546001600160a01b039081169116146103965760405162461bcd60e51b8152600401610110906107f7565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6103f76105a2565b6000546001600160a01b039081169116146104245760405162461bcd60e51b8152600401610110906107f7565b8382146104435760405162461bcd60e51b8152600401610110906108bf565b60005b8481101561035957816001600160a01b03166372eb293d87878481811061046957fe5b905060200201602081019061047e9190610609565b86868581811061048a57fe5b905060200201356040518363ffffffff1660e01b81526004016104ae929190610798565b600060405180830381600087803b1580156104c857600080fd5b505af11580156104dc573d6000803e3d6000fd5b5050600190920191506104469050565b6104f46105a2565b6000546001600160a01b039081169116146105215760405162461bcd60e51b8152600401610110906107f7565b6001600160a01b0381166105475760405162461bcd60e51b8152600401610110906107b1565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b611e648061090883390190565b61190b8061276c83390190565b60008083601f8401126105d1578182fd5b50813567ffffffffffffffff8111156105e8578182fd5b602083019150836020808302850101111561060257600080fd5b9250929050565b60006020828403121561061a578081fd5b8135610625816108ef565b9392505050565b60006020828403121561063d578081fd5b8151610625816108ef565b6000806040838503121561065a578081fd5b8235610665816108ef565b91506020830135610675816108ef565b809150509250929050565b60008060008060408587031215610695578182fd5b843567ffffffffffffffff808211156106ac578384fd5b6106b8888389016105c0565b909650945060208701359150808211156106d0578384fd5b506106dd878288016105c0565b95989497509550505050565b600080600080600060608688031215610700578081fd5b853567ffffffffffffffff80821115610717578283fd5b61072389838a016105c0565b9097509550602088013591508082111561073b578283fd5b50610748888289016105c0565b909450925050604086013561075c816108ef565b809150509295509295909350565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601c908201527f506f6f6c2063616e206e6f74206265207a65726f206164647265737300000000604082015260600190565b6020808252601390820152723432b63832b91034b9903737ba1037bbb732b960691b604082015260600190565b6020808252601590820152746f776e65722063616e206e6f74206265207a65726f60581b604082015260600190565b602080825260169082015275082e4e4c2f2e640dcdee840e6c2daca40d8cadccee8d60531b604082015260600190565b6001600160a01b038116811461090457600080fd5b5056fe608060405260006006553480156200001657600080fd5b50604080518082018252600e8082526d111150951513d2d15397d253541360921b60208084018281528551808701909652928552840152815191929160009162000064916003919062000098565b5081516200007a90600490602085019062000098565b506005805460ff191660ff9290921691909117905550620001349050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000db57805160ff19168380011785556200010b565b828001600101855582156200010b579182015b828111156200010b578251825591602001919060010190620000ee565b50620001199291506200011d565b5090565b5b808211156200011957600081556001016200011e565b611d2080620001446000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806395d89b41116100f9578063c04a8a1011610097578063dd62ed3e11610071578063dd62ed3e146106ab578063e7484890146106d9578063e78c9b3b146106e1578063f731e9be14610707576101a9565b8063c04a8a10146104b0578063c222ec8a146104dc578063c634dfaa14610685576101a9565b8063a9059cbb116100d3578063a9059cbb14610438578063b16a19de14610464578063b3f1c93d1461046c578063b9a7b622146104a8576101a9565b806395d89b41146104025780639dc29fac1461040a578063a457c2d7146102d9576101a9565b80636bd76d241161016657806375d264131161014057806375d264131461037d578063797743381461038557806379ce6b8c146103ba57806390f6fcf2146103fa576101a9565b80636bd76d241461030557806370a08231146103335780637535d24614610359576101a9565b806306fdde03146101ae578063095ea7b31461022b57806318160ddd1461026b57806323b872dd14610285578063313ce567146102bb57806339509351146102d9575b600080fd5b6101b6610728565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f05781810151838201526020016101d8565b50505050905090810190601f16801561021d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102576004803603604081101561024157600080fd5b506001600160a01b0381351690602001356107be565b604080519115158252519081900360200190f35b610273610806565b60408051918252519081900360200190f35b6102576004803603606081101561029b57600080fd5b506001600160a01b03813581169160208101359091169060400135610818565b6102c3610860565b6040805160ff9092168252519081900360200190f35b610257600480360360408110156102ef57600080fd5b506001600160a01b038135169060200135610869565b6102736004803603604081101561031b57600080fd5b506001600160a01b03813581169160200135166108b8565b6102736004803603602081101561034957600080fd5b50356001600160a01b03166108e5565b61036161095f565b604080516001600160a01b039092168252519081900360200190f35b610361610977565b61038d610981565b6040805194855260208501939093528383019190915264ffffffffff166060830152519081900360800190f35b6103e0600480360360208110156103d057600080fd5b50356001600160a01b03166109b7565b6040805164ffffffffff9092168252519081900360200190f35b6102736109d9565b6101b66109df565b6104366004803603604081101561042057600080fd5b506001600160a01b038135169060200135610a40565b005b6102576004803603604081101561044e57600080fd5b506001600160a01b038135169060200135610818565b610361610da6565b6102576004803603608081101561048257600080fd5b506001600160a01b03813581169160208101359091169060408101359060600135610db5565b61027361110d565b610436600480360360408110156104c657600080fd5b506001600160a01b038135169060200135611112565b610436600480360360e08110156104f257600080fd5b6001600160a01b038235811692602081013582169260408201359092169160ff606083013516919081019060a08101608082013564010000000081111561053857600080fd5b82018360208201111561054a57600080fd5b8035906020019184600183028401116401000000008311171561056c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156105bf57600080fd5b8201836020820111156105d157600080fd5b803590602001918460018302840111640100000000831117156105f357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561064657600080fd5b82018360208201111561065857600080fd5b8035906020019184600183028401116401000000008311171561067a57600080fd5b5090925090506111ae565b6102736004803603602081101561069b57600080fd5b50356001600160a01b0316611412565b610273600480360360408110156106c157600080fd5b506001600160a01b0381358116916020013516610869565b6103e061141d565b610273600480360360208110156106f757600080fd5b50356001600160a01b031661142a565b61070f611445565b6040805192835260208301919091528051918290030190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107b45780601f10610789576101008083540402835291602001916107b4565b820191906000526020600020905b81548152906001019060200180831161079757829003601f168201915b5050505050905090565b6040805162461bcd60e51b81526020600482015260166024820152751054141493d5905317d393d517d4d5541413d495115160521b6044820152905160009181900360640190fd5b6000610813603b5461145e565b905090565b6040805162461bcd60e51b81526020600482015260166024820152751514905394d1915497d393d517d4d5541413d495115160521b6044820152905160009181900360640190fd5b60055460ff1690565b6040805162461bcd60e51b815260206004820152601760248201527f414c4c4f57414e43455f4e4f545f535550504f525445440000000000000000006044820152905160009181900360640190fd5b6001600160a01b038083166000908152603a60209081526040808320938516835292905220545b92915050565b6000806108f1836114a6565b6001600160a01b0384166000908152603d60205260409020549091508161091d5760009250505061095a565b6001600160a01b0384166000908152603c602052604081205461094890839064ffffffffff166114c1565b905061095483826114d5565b93505050505b919050565b603e546501000000000090046001600160a01b031690565b6000610813611593565b6000806000806000603b5490506109966115a2565b61099f8261145e565b603e54919790965091945064ffffffffff1692509050565b6001600160a01b03166000908152603c602052604090205464ffffffffff1690565b603b5490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107b45780601f10610789576101008083540402835291602001916107b4565b610a4861095f565b6001600160a01b0316610a596115a8565b6001600160a01b03161460405180604001604052806002815260200161323960f01b81525090610b075760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610acc578181015183820152602001610ab4565b50505050905090810190601f168015610af95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600080610b14846115ac565b92509250506000610b23610806565b6001600160a01b0386166000908152603d6020526040812054919250908190868411610b58576000603b819055600255610bda565b610b628488611605565b600281905591506000610b80610b7786611647565b603b54906114d5565b90506000610b97610b908a611647565b84906114d5565b9050818110610bb35760006002819055603b8190559450610bd7565b610bcf610bbf85611647565b610bc98484611605565b906116c5565b603b81905594505b50505b85871415610c18576001600160a01b0388166000908152603d60209081526040808320839055603c9091529020805464ffffffffff19169055610c46565b6001600160a01b0388166000908152603c60205260409020805464ffffffffff19164264ffffffffff161790555b603e805464ffffffffff19164264ffffffffff1617905586851115610ce6576000610c718689611605565b9050610c7e8982876117cc565b6040805182815260208101899052808201889052606081018490526080810186905260a0810185905290516001600160a01b038b169182917fc16f4e4ca34d790de4c656c72fd015c667d688f20be64eea360618545c4c530f9181900360c00190a350610d5b565b6000610cf28887611605565b9050610cff898287611891565b6040805182815260208101899052808201889052606081018690526080810185905290516001600160a01b038b16917f44bd20a79e993bdcc7cbedf54a3b4d19fb78490124b6b90d04fe3242eea579e8919081900360a00190a2505b6040805188815290516000916001600160a01b038b16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050505050505050565b603f546001600160a01b031690565b6000610dbf61095f565b6001600160a01b0316610dd06115a8565b6001600160a01b03161460405180604001604052806002815260200161323960f01b81525090610e415760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b50610e4a611bd9565b846001600160a01b0316866001600160a01b031614610e6e57610e6e8587866118d3565b600080610e7a876115ac565b9250925050610e87610806565b808452603b546080850152610e9c908761199b565b60028190556020840152610eaf86611647565b6040840152610f0d610ec9610ec4848961199b565b611647565b6040850151610bc990610edc90896114d5565b610f07610ee887611647565b6001600160a01b038d166000908152603d6020526040902054906114d5565b9061199b565b60608401819052604080518082019091526002815261373960f01b6020820152906fffffffffffffffffffffffffffffffff1015610f8c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b5060608301516001600160a01b0388166000908152603d6020908152604080832093909355603c8152919020805464ffffffffff421664ffffffffff199182168117909255603e8054909116909117905583015161102290610fed90611647565b610bc96110078660400151896114d590919063ffffffff16565b610f076110178860000151611647565b6080890151906114d5565b603b81905560808401526110418761103a888461199b565b85516117cc565b6040805187815290516001600160a01b038916916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3866001600160a01b0316886001600160a01b03167fc16f4e4ca34d790de4c656c72fd015c667d688f20be64eea360618545c4c530f888585886060015189608001518a6020015160405180878152602001868152602001858152602001848152602001838152602001828152602001965050505050505060405180910390a350159695505050505050565b600181565b80603a600061111f6115a8565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120919091556111576115a8565b6001600160a01b03167fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e1611189610da6565b604080516001600160a01b039092168252602082018690528051918290030190a35050565b60006111b86119f5565b60075490915060ff16806111cf57506111cf6119fa565b806111db575060065481115b6112165760405162461bcd60e51b815260040180806020018281038252602e815260200180611cbd602e913960400191505060405180910390fd5b60075460ff16158015611236576007805460ff1916600117905560068290555b61123f86611a00565b61124885611a17565b61125187611a2a565b603e805465010000000000600160c81b031916650100000000006001600160a01b038d811691820292909217909255603f80546001600160a01b03199081168d841690811790925560408054909116928c169283178155805192835260ff8b1660208085019190915260a09184018281528b51928501929092528a5192937f40251fbfb6656cfa65a00d7879029fec1fad21d28fdcff2f4f68f52795b74f2c938e938e938e938e938e938e9390916060840191608085019160c08601918a019080838360005b8381101561132f578181015183820152602001611317565b50505050905090810190601f16801561135c5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b8381101561138f578181015183820152602001611377565b50505050905090810190601f1680156113bc5780820380516001836020036101000a031916815260200191505b508481038252858152602001868680828437600083820152604051601f909101601f19169092018290039b50909950505050505050505050a38015611406576007805460ff191690555b50505050505050505050565b60006108df826114a6565b603e5464ffffffffff1690565b6001600160a01b03166000908152603d602052604090205490565b603b5460009081906114568161145e565b925090509091565b6000806114696115a2565b90508061147a57600091505061095a565b603e5460009061149290859064ffffffffff166114c1565b905061149e82826114d5565b949350505050565b6001600160a01b031660009081526020819052604090205490565b60006114ce838342611a40565b9392505050565b60008215806114e2575081155b156114ef575060006108df565b816b019d971e4fe8401e74000000198161150557fe5b0483111560405180604001604052806002815260200161068760f31b815250906115705760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b50506b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b6040546001600160a01b031690565b60025490565b3390565b6000806000806115bb856114a6565b9050806115d3576000806000935093509350506115fe565b60006115e8826115e2886108e5565b90611605565b9050816115f5818361199b565b90955093509150505b9193909250565b60006114ce83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611b16565b6000633b9aca0082810290839082041460405180604001604052806002815260200161068760f31b815250906116be5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b5092915050565b604080518082019091526002815261035360f41b60208201526000908261172d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b5060408051808201909152600280825261068760f31b60208301528304906b033b2e3c9fd0803ce80000008219048511156117a95760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b5082816b033b2e3c9fd0803ce8000000860201816117c357fe5b04949350505050565b6001600160a01b0383166000908152602081905260409020546117ef818461199b565b6001600160a01b0380861660009081526020819052604090819020929092559054161561188b576040805481516318c39f1760e11b81526001600160a01b0387811660048301526024820186905260448201859052925192909116916331873e2e9160648082019260009290919082900301818387803b15801561187257600080fd5b505af1158015611886573d6000803e3d6000fd5b505050505b50505050565b6001600160a01b038316600090815260208181526040918290205482518084019093526002835261038360f41b91830191909152906117ef9082908590611b16565b6040805180820182526002815261353960f01b6020808301919091526001600160a01b038087166000908152603a8352848120918716815291529182205461191c918490611b16565b6001600160a01b038086166000818152603a60209081526040808320948916808452949091529020839055919250907fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e1611974610da6565b604080516001600160a01b039092168252602082018690528051918290030190a350505050565b6000828201838110156114ce576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600190565b303b1590565b8051611a13906003906020840190611c08565b5050565b8051611a13906004906020840190611c08565b6005805460ff191660ff92909216919091179055565b600080611a548364ffffffffff8616611605565b905080611a6b57611a63611b70565b9150506114ce565b6000198101600060028311611a81576000611a86565b600283035b90506301e1338087046000611a9b82806114d5565b90506000611aa982846114d5565b905060006002611ac384611abd8a8a611b80565b90611b80565b81611aca57fe5b04905060006006611ae184611abd89818d8d611b80565b81611ae857fe5b049050611b0681610f078481611afe8a8e611b80565b610f07611b70565b9c9b505050505050505050505050565b60008184841115611b685760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610acc578181015183820152602001610ab4565b505050900390565b6b033b2e3c9fd0803ce800000090565b600082611b8f575060006108df565b82820282848281611b9c57fe5b04146114ce5760405162461bcd60e51b8152600401808060200182810382526021815260200180611c9c6021913960400191505060405180910390fd5b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c4957805160ff1916838001178555611c76565b82800160010185558215611c76579182015b82811115611c76578251825591602001919060010190611c5b565b50611c82929150611c86565b5090565b5b80821115611c825760008155600101611c8756fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a26469706673582212205a38daaf60cf3988dfa2e08f6294463d91362b7a15ac9fc890825cdc6b71b7f964736f6c634300060c0033608060405260006006553480156200001657600080fd5b50604080518082018252600e8082526d111150951513d2d15397d253541360921b60208084018281528551808701909652928552840152815191929160009162000064916003919062000098565b5081516200007a90600490602085019062000098565b506005805460ff191660ff9290921691909117905550620001349050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000db57805160ff19168380011785556200010b565b828001600101855582156200010b579182015b828111156200010b578251825591602001919060010190620000ee565b50620001199291506200011d565b5090565b5b808211156200011957600081556001016200011e565b6117c780620001446000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806375d26413116100c3578063b3f1c93d1161007c578063b3f1c93d146103d2578063b9a7b6221461040e578063c04a8a1014610416578063c222ec8a14610444578063dd62ed3e146105ed578063f5298aca1461061b5761014d565b806375d264131461038657806395d89b411461038e578063a457c2d7146102e2578063a9059cbb14610396578063b16a19de146103c2578063b1bf962d146103ca5761014d565b806323b872dd1161011557806323b872dd1461028e578063313ce567146102c457806339509351146102e25780636bd76d241461030e57806370a082311461033c5780637535d246146103625761014d565b806306fdde0314610152578063095ea7b3146101cf5780630afbcdc91461020f57806318160ddd1461024e5780631da24f3e14610268575b600080fd5b61015a61064d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561019457818101518382015260200161017c565b50505050905090810190601f1680156101c15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101fb600480360360408110156101e557600080fd5b506001600160a01b0381351690602001356106e3565b604080519115158252519081900360200190f35b6102356004803603602081101561022557600080fd5b50356001600160a01b031661072b565b6040805192835260208301919091528051918290030190f35b610256610748565b60408051918252519081900360200190f35b6102566004803603602081101561027e57600080fd5b50356001600160a01b03166107db565b6101fb600480360360608110156102a457600080fd5b506001600160a01b038135811691602081013590911690604001356107ee565b6102cc610836565b6040805160ff9092168252519081900360200190f35b6101fb600480360360408110156102f857600080fd5b506001600160a01b03813516906020013561083f565b6102566004803603604081101561032457600080fd5b506001600160a01b038135811691602001351661088e565b6102566004803603602081101561035257600080fd5b50356001600160a01b03166108bb565b61036a610967565b604080516001600160a01b039092168252519081900360200190f35b61036a610976565b61015a610980565b6101fb600480360360408110156103ac57600080fd5b506001600160a01b0381351690602001356107ee565b61036a6109e1565b6102566109f0565b6101fb600480360360808110156103e857600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356109fa565b610256610c13565b6104426004803603604081101561042c57600080fd5b506001600160a01b038135169060200135610c18565b005b610442600480360360e081101561045a57600080fd5b6001600160a01b038235811692602081013582169260408201359092169160ff606083013516919081019060a0810160808201356401000000008111156104a057600080fd5b8201836020820111156104b257600080fd5b803590602001918460018302840111640100000000831117156104d457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561052757600080fd5b82018360208201111561053957600080fd5b8035906020019184600183028401116401000000008311171561055b57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156105ae57600080fd5b8201836020820111156105c057600080fd5b803590602001918460018302840111640100000000831117156105e257600080fd5b509092509050610cb4565b6102566004803603604081101561060357600080fd5b506001600160a01b038135811691602001351661083f565b6104426004803603606081101561063157600080fd5b506001600160a01b038135169060208101359060400135610f03565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106d95780601f106106ae576101008083540402835291602001916106d9565b820191906000526020600020905b8154815290600101906020018083116106bc57829003601f168201915b5050505050905090565b6040805162461bcd60e51b81526020600482015260166024820152751054141493d5905317d393d517d4d5541413d495115160521b6044820152905160009181900360640190fd5b60008061073783611097565b61073f6110b2565b91509150915091565b603b54603c546040805163386497fd60e01b81526001600160a01b03928316600482015290516000936107d693169163386497fd916024808301926020929190829003018186803b15801561079c57600080fd5b505afa1580156107b0573d6000803e3d6000fd5b505050506040513d60208110156107c657600080fd5b50516107d06110b2565b906110b8565b905090565b60006107e682611097565b90505b919050565b6040805162461bcd60e51b81526020600482015260166024820152751514905394d1915497d393d517d4d5541413d495115160521b6044820152905160009181900360640190fd5b60055460ff1690565b6040805162461bcd60e51b815260206004820152601760248201527f414c4c4f57414e43455f4e4f545f535550504f525445440000000000000000006044820152905160009181900360640190fd5b6001600160a01b038083166000908152603a60209081526040808320938516835292905220545b92915050565b6000806108c783611097565b9050806108d85760009150506107e9565b603b54603c546040805163386497fd60e01b81526001600160a01b039283166004820152905161096093929092169163386497fd91602480820192602092909190829003018186803b15801561092d57600080fd5b505afa158015610941573d6000803e3d6000fd5b505050506040513d602081101561095757600080fd5b505182906110b8565b9392505050565b603b546001600160a01b031690565b60006107d6611176565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106d95780601f106106ae576101008083540402835291602001916106d9565b603c546001600160a01b031690565b60006107d66110b2565b6000610a04610967565b6001600160a01b0316610a15611185565b6001600160a01b03161460405180604001604052806002815260200161323960f01b81525090610ac35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610a88578181015183820152602001610a70565b50505050905090810190601f168015610ab55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50836001600160a01b0316856001600160a01b031614610ae857610ae8848685611189565b6000610af385611097565b90506000610b018585611251565b6040805180820190915260028152611a9b60f11b602082015290915081610b695760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b50610b748682611358565b6040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3856001600160a01b0316876001600160a01b03167f2f00e3cdd69a77be7ed215ec7b2a36784dd158f921fca79ac29deffa353fe6ee8787604051808381526020018281526020019250505060405180910390a3501595945050505050565b600181565b80603a6000610c25611185565b6001600160a01b0390811682526020808301939093526040918201600090812091871680825291909352912091909155610c5d611185565b6001600160a01b03167fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e1610c8f6109e1565b604080516001600160a01b039092168252602082018690528051918290030190a35050565b6000610cbe6114a9565b60075490915060ff1680610cd55750610cd56114ae565b80610ce1575060065481115b610d1c5760405162461bcd60e51b815260040180806020018281038252602e815260200180611743602e913960400191505060405180910390fd5b60075460ff16158015610d3c576007805460ff1916600117905560068290555b610d45866114b4565b610d4e856114cb565b610d57876114de565b603b80546001600160a01b03808d166001600160a01b03199283168117909355603c80548d83169084168117909155603d8054928d169290931682179092556040805191825260ff8b1660208084019190915260a09183018281528b51928401929092528a517f40251fbfb6656cfa65a00d7879029fec1fad21d28fdcff2f4f68f52795b74f2c938e938e938e938e938e938e93919290916060840191608085019160c0860191908a019080838360005b83811015610e20578181015183820152602001610e08565b50505050905090810190601f168015610e4d5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015610e80578181015183820152602001610e68565b50505050905090810190601f168015610ead5780820380516001836020036101000a031916815260200191505b508481038252858152602001868680828437600083820152604051601f909101601f19169092018290039b50909950505050505050505050a38015610ef7576007805460ff191690555b50505050505050505050565b610f0b610967565b6001600160a01b0316610f1c611185565b6001600160a01b03161460405180604001604052806002815260200161323960f01b81525090610f8d5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b506000610f9a8383611251565b60408051808201909152600281526106a760f31b6020820152909150816110025760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b5061100d84826114f4565b6040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3604080518481526020810184905281516001600160a01b038716927f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a928290030190a250505050565b6001600160a01b031660009081526020819052604090205490565b60025490565b60008215806110c5575081155b156110d2575060006108b5565b816b019d971e4fe8401e7400000019816110e857fe5b0483111560405180604001604052806002815260200161068760f31b815250906111535760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b50506b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b603d546001600160a01b031690565b3390565b6040805180820182526002815261353960f01b6020808301919091526001600160a01b038087166000908152603a835284812091871681529152918220546111d2918490611592565b6001600160a01b038086166000818152603a60209081526040808320948916808452949091529020839055919250907fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e161122a6109e1565b604080516001600160a01b039092168252602082018690528051918290030190a350505050565b604080518082019091526002815261035360f41b6020820152600090826112b95760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b5060408051808201909152600280825261068760f31b60208301528304906b033b2e3c9fd0803ce80000008219048511156113355760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b5082816b033b2e3c9fd0803ce80000008602018161134f57fe5b04949350505050565b6001600160a01b0382166113b3576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6113bf600083836115ec565b6002546113cc81836115f1565b6002556001600160a01b0383166000908152602081905260409020546113f281846115f1565b6001600160a01b038516600090815260208190526040812091909155611416611176565b6001600160a01b0316146114a35761142c611176565b6001600160a01b03166331873e2e8584846040518463ffffffff1660e01b815260040180846001600160a01b031681526020018381526020018281526020019350505050600060405180830381600087803b15801561148a57600080fd5b505af115801561149e573d6000803e3d6000fd5b505050505b50505050565b600190565b303b1590565b80516114c790600390602084019061168d565b5050565b80516114c790600490602084019061168d565b6005805460ff191660ff92909216919091179055565b6001600160a01b0382166115395760405162461bcd60e51b81526004018080602001828103825260218152602001806117716021913960400191505060405180910390fd5b611545826000836115ec565b600254611552818361164b565b6002556001600160a01b0383166000908152602081815260409182902054825160608101909352602280845290926113f292869290611721908301398391905b600081848411156115e45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610a88578181015183820152602001610a70565b505050900390565b505050565b600082820183811015610960576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061096083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611592565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106116ce57805160ff19168380011785556116fb565b828001600101855582156116fb579182015b828111156116fb5782518255916020019190600101906116e0565b5061170792915061170b565b5090565b5b80821115611707576000815560010161170c56fe45524332303a206275726e20616d6f756e7420657863656564732062616c616e6365436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e2066726f6d20746865207a65726f2061646472657373a264697066735822122017bccf702f4b07d646e52ec9c0185e3fbd2829929227226dc1a67c52115cd39264736f6c634300060c0033a26469706673582212204ffa22708343138ee631cdfba68dd2250a65e797a473789cffa6e2d5cb36b63f64736f6c634300060c0033