Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x4064d4ad8db2db95501ac483902c3048f0e98a9179e867734fe635de5f10e990 | Initialize | 239102 | 523 days 11 hrs ago | dForce: Deployer 2 | IN | 0xbfb0b7caec2a133f5661b7ffb3f40b1cfa99f872 | 0 ETH | 0.000939057167 ETH | |
0x8996816e1389a2860346ca7441945b43823df6f8d5737261a277cd1849e6f987 | 0x60806040 | 239100 | 523 days 11 hrs ago | dForce: Deployer 2 | IN | Create: Controller | 0 ETH | 0.18271354663 ETH |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
Controller
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT pragma solidity 0.6.12; import "@openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol"; import "./interface/IControllerInterface.sol"; import "./interface/IPriceOracle.sol"; import "./interface/IiToken.sol"; import "./interface/IRewardDistributor.sol"; import "./library/Initializable.sol"; import "./library/Ownable.sol"; import "./library/SafeRatioMath.sol"; /** * @title dForce's lending controller Contract * @author dForce */ contract Controller is Initializable, Ownable, IControllerInterface { using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; using SafeRatioMath for uint256; using SafeMathUpgradeable for uint256; using SafeERC20Upgradeable for IERC20Upgradeable; /// @dev EnumerableSet of all iTokens EnumerableSetUpgradeable.AddressSet internal iTokens; struct Market { /* * Multiplier representing the most one can borrow against their collateral in this market. * For instance, 0.9 to allow borrowing 90% of collateral value. * Must be in [0, 0.9], and stored as a mantissa. */ uint256 collateralFactorMantissa; /* * Multiplier representing the most one can borrow the asset. * For instance, 0.5 to allow borrowing this asset 50% * collateral value * collateralFactor. * When calculating equity, 0.5 with 100 borrow balance will produce 200 borrow value * Must be between (0, 1], and stored as a mantissa. */ uint256 borrowFactorMantissa; /* * The borrow capacity of the asset, will be checked in beforeBorrow() * -1 means there is no limit on the capacity * 0 means the asset can not be borrowed any more */ uint256 borrowCapacity; /* * The supply capacity of the asset, will be checked in beforeMint() * -1 means there is no limit on the capacity * 0 means the asset can not be supplied any more */ uint256 supplyCapacity; // Whether market's mint is paused bool mintPaused; // Whether market's redeem is paused bool redeemPaused; // Whether market's borrow is paused bool borrowPaused; } /// @notice Mapping of iTokens to corresponding markets mapping(address => Market) public markets; struct AccountData { // Account's collateral assets EnumerableSetUpgradeable.AddressSet collaterals; // Account's borrowed assets EnumerableSetUpgradeable.AddressSet borrowed; } /// @dev Mapping of accounts' data, including collateral and borrowed assets mapping(address => AccountData) internal accountsData; /** * @notice Oracle to query the price of a given asset */ address public priceOracle; /** * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow */ uint256 public closeFactorMantissa; // closeFactorMantissa must be strictly greater than this value uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05 // closeFactorMantissa must not exceed this value uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9 /** * @notice Multiplier representing the discount on collateral that a liquidator receives */ uint256 public liquidationIncentiveMantissa; // liquidationIncentiveMantissa must be no less than this value uint256 internal constant liquidationIncentiveMinMantissa = 1.0e18; // 1.0 // liquidationIncentiveMantissa must be no greater than this value uint256 internal constant liquidationIncentiveMaxMantissa = 1.5e18; // 1.5 // collateralFactorMantissa must not exceed this value uint256 internal constant collateralFactorMaxMantissa = 1e18; // 1.0 // borrowFactorMantissa must not exceed this value uint256 internal constant borrowFactorMaxMantissa = 1e18; // 1.0 /** * @notice Guardian who can pause mint/borrow/liquidate/transfer in case of emergency */ address public pauseGuardian; /// @notice whether global transfer is paused bool public transferPaused; /// @notice whether global seize is paused bool public seizePaused; /** * @notice the address of reward distributor */ address public rewardDistributor; /** * @dev Check if called by owner or pauseGuardian, and only owner can unpause */ modifier checkPauser(bool _paused) { require( msg.sender == owner || (msg.sender == pauseGuardian && _paused), "Only owner and guardian can pause and only owner can unpause" ); _; } /** * @notice Initializes the contract. */ function initialize() external initializer { __Ownable_init(); } /*********************************/ /******** Security Check *********/ /*********************************/ /** * @notice Ensure this is a Controller contract. */ function isController() external view override returns (bool) { return true; } /*********************************/ /******** Admin Operations *******/ /*********************************/ /** * @notice Admin function to add iToken into supported markets * Checks if the iToken already exsits * Will `revert()` if any check fails * @param _iToken The _iToken to add * @param _collateralFactor The _collateralFactor of _iToken * @param _borrowFactor The _borrowFactor of _iToken * @param _supplyCapacity The _supplyCapacity of _iToken * @param _distributionFactor The _distributionFactor of _iToken */ function _addMarket( address _iToken, uint256 _collateralFactor, uint256 _borrowFactor, uint256 _supplyCapacity, uint256 _borrowCapacity, uint256 _distributionFactor ) external override onlyOwner { require(IiToken(_iToken).isSupported(), "Token is not supported"); // Market must not have been listed, EnumerableSet.add() will return false if it exsits require(iTokens.add(_iToken), "Token has already been listed"); require( _collateralFactor <= collateralFactorMaxMantissa, "Collateral factor invalid" ); require( _borrowFactor > 0 && _borrowFactor <= borrowFactorMaxMantissa, "Borrow factor invalid" ); // Its value will be taken into account when calculate account equity // Check if the price is available for the calculation require( IPriceOracle(priceOracle).getUnderlyingPrice(_iToken) != 0, "Underlying price is unavailable" ); markets[_iToken] = Market({ collateralFactorMantissa: _collateralFactor, borrowFactorMantissa: _borrowFactor, borrowCapacity: _borrowCapacity, supplyCapacity: _supplyCapacity, mintPaused: false, redeemPaused: false, borrowPaused: false }); IRewardDistributor(rewardDistributor)._addRecipient( _iToken, _distributionFactor ); emit MarketAdded( _iToken, _collateralFactor, _borrowFactor, _supplyCapacity, _borrowCapacity, _distributionFactor ); } /** * @notice Sets price oracle * @dev Admin function to set price oracle * @param _newOracle New oracle contract */ function _setPriceOracle(address _newOracle) external override onlyOwner { address _oldOracle = priceOracle; require( _newOracle != address(0) && _newOracle != _oldOracle, "Oracle address invalid" ); priceOracle = _newOracle; emit NewPriceOracle(_oldOracle, _newOracle); } /** * @notice Sets the closeFactor used when liquidating borrows * @dev Admin function to set closeFactor * @param _newCloseFactorMantissa New close factor, scaled by 1e18 */ function _setCloseFactor(uint256 _newCloseFactorMantissa) external override onlyOwner { require( _newCloseFactorMantissa >= closeFactorMinMantissa && _newCloseFactorMantissa <= closeFactorMaxMantissa, "Close factor invalid" ); uint256 _oldCloseFactorMantissa = closeFactorMantissa; closeFactorMantissa = _newCloseFactorMantissa; emit NewCloseFactor(_oldCloseFactorMantissa, _newCloseFactorMantissa); } /** * @notice Sets liquidationIncentive * @dev Admin function to set liquidationIncentive * @param _newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18 */ function _setLiquidationIncentive(uint256 _newLiquidationIncentiveMantissa) external override onlyOwner { require( _newLiquidationIncentiveMantissa >= liquidationIncentiveMinMantissa && _newLiquidationIncentiveMantissa <= liquidationIncentiveMaxMantissa, "Liquidation incentive invalid" ); uint256 _oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa; liquidationIncentiveMantissa = _newLiquidationIncentiveMantissa; emit NewLiquidationIncentive( _oldLiquidationIncentiveMantissa, _newLiquidationIncentiveMantissa ); } /** * @notice Sets the collateralFactor for a iToken * @dev Admin function to set collateralFactor for a iToken * @param _iToken The token to set the factor on * @param _newCollateralFactorMantissa The new collateral factor, scaled by 1e18 */ function _setCollateralFactor( address _iToken, uint256 _newCollateralFactorMantissa ) external override onlyOwner { _checkiTokenListed(_iToken); require( _newCollateralFactorMantissa <= collateralFactorMaxMantissa, "Collateral factor invalid" ); // Its value will be taken into account when calculate account equity // Check if the price is available for the calculation require( IPriceOracle(priceOracle).getUnderlyingPrice(_iToken) != 0, "Failed to set collateral factor, underlying price is unavailable" ); Market storage _market = markets[_iToken]; uint256 _oldCollateralFactorMantissa = _market.collateralFactorMantissa; _market.collateralFactorMantissa = _newCollateralFactorMantissa; emit NewCollateralFactor( _iToken, _oldCollateralFactorMantissa, _newCollateralFactorMantissa ); } /** * @notice Sets the borrowFactor for a iToken * @dev Admin function to set borrowFactor for a iToken * @param _iToken The token to set the factor on * @param _newBorrowFactorMantissa The new borrow factor, scaled by 1e18 */ function _setBorrowFactor(address _iToken, uint256 _newBorrowFactorMantissa) external override onlyOwner { _checkiTokenListed(_iToken); require( _newBorrowFactorMantissa > 0 && _newBorrowFactorMantissa <= borrowFactorMaxMantissa, "Borrow factor invalid" ); // Its value will be taken into account when calculate account equity // Check if the price is available for the calculation require( IPriceOracle(priceOracle).getUnderlyingPrice(_iToken) != 0, "Failed to set borrow factor, underlying price is unavailable" ); Market storage _market = markets[_iToken]; uint256 _oldBorrowFactorMantissa = _market.borrowFactorMantissa; _market.borrowFactorMantissa = _newBorrowFactorMantissa; emit NewBorrowFactor( _iToken, _oldBorrowFactorMantissa, _newBorrowFactorMantissa ); } /** * @notice Sets the borrowCapacity for a iToken * @dev Admin function to set borrowCapacity for a iToken * @param _iToken The token to set the capacity on * @param _newBorrowCapacity The new borrow capacity */ function _setBorrowCapacity(address _iToken, uint256 _newBorrowCapacity) external override onlyOwner { _checkiTokenListed(_iToken); Market storage _market = markets[_iToken]; uint256 oldBorrowCapacity = _market.borrowCapacity; _market.borrowCapacity = _newBorrowCapacity; emit NewBorrowCapacity(_iToken, oldBorrowCapacity, _newBorrowCapacity); } /** * @notice Sets the supplyCapacity for a iToken * @dev Admin function to set supplyCapacity for a iToken * @param _iToken The token to set the capacity on * @param _newSupplyCapacity The new supply capacity */ function _setSupplyCapacity(address _iToken, uint256 _newSupplyCapacity) external override onlyOwner { _checkiTokenListed(_iToken); Market storage _market = markets[_iToken]; uint256 oldSupplyCapacity = _market.supplyCapacity; _market.supplyCapacity = _newSupplyCapacity; emit NewSupplyCapacity(_iToken, oldSupplyCapacity, _newSupplyCapacity); } /** * @notice Sets the pauseGuardian * @dev Admin function to set pauseGuardian * @param _newPauseGuardian The new pause guardian */ function _setPauseGuardian(address _newPauseGuardian) external override onlyOwner { address _oldPauseGuardian = pauseGuardian; require( _newPauseGuardian != address(0) && _newPauseGuardian != _oldPauseGuardian, "Pause guardian address invalid" ); pauseGuardian = _newPauseGuardian; emit NewPauseGuardian(_oldPauseGuardian, _newPauseGuardian); } /** * @notice pause/unpause mint() for all iTokens * @dev Admin function, only owner and pauseGuardian can call this * @param _paused whether to pause or unpause */ function _setAllMintPaused(bool _paused) external override checkPauser(_paused) { EnumerableSetUpgradeable.AddressSet storage _iTokens = iTokens; uint256 _len = _iTokens.length(); for (uint256 i = 0; i < _len; i++) { _setMintPausedInternal(_iTokens.at(i), _paused); } } /** * @notice pause/unpause mint() for the iToken * @dev Admin function, only owner and pauseGuardian can call this * @param _iToken The iToken to pause/unpause * @param _paused whether to pause or unpause */ function _setMintPaused(address _iToken, bool _paused) external override checkPauser(_paused) { _checkiTokenListed(_iToken); _setMintPausedInternal(_iToken, _paused); } function _setMintPausedInternal(address _iToken, bool _paused) internal { markets[_iToken].mintPaused = _paused; emit MintPaused(_iToken, _paused); } /** * @notice pause/unpause redeem() for all iTokens * @dev Admin function, only owner and pauseGuardian can call this * @param _paused whether to pause or unpause */ function _setAllRedeemPaused(bool _paused) external override checkPauser(_paused) { EnumerableSetUpgradeable.AddressSet storage _iTokens = iTokens; uint256 _len = _iTokens.length(); for (uint256 i = 0; i < _len; i++) { _setRedeemPausedInternal(_iTokens.at(i), _paused); } } /** * @notice pause/unpause redeem() for the iToken * @dev Admin function, only owner and pauseGuardian can call this * @param _iToken The iToken to pause/unpause * @param _paused whether to pause or unpause */ function _setRedeemPaused(address _iToken, bool _paused) external override checkPauser(_paused) { _checkiTokenListed(_iToken); _setRedeemPausedInternal(_iToken, _paused); } function _setRedeemPausedInternal(address _iToken, bool _paused) internal { markets[_iToken].redeemPaused = _paused; emit RedeemPaused(_iToken, _paused); } /** * @notice pause/unpause borrow() for all iTokens * @dev Admin function, only owner and pauseGuardian can call this * @param _paused whether to pause or unpause */ function _setAllBorrowPaused(bool _paused) external override checkPauser(_paused) { EnumerableSetUpgradeable.AddressSet storage _iTokens = iTokens; uint256 _len = _iTokens.length(); for (uint256 i = 0; i < _len; i++) { _setBorrowPausedInternal(_iTokens.at(i), _paused); } } /** * @notice pause/unpause borrow() for the iToken * @dev Admin function, only owner and pauseGuardian can call this * @param _iToken The iToken to pause/unpause * @param _paused whether to pause or unpause */ function _setBorrowPaused(address _iToken, bool _paused) external override checkPauser(_paused) { _checkiTokenListed(_iToken); _setBorrowPausedInternal(_iToken, _paused); } function _setBorrowPausedInternal(address _iToken, bool _paused) internal { markets[_iToken].borrowPaused = _paused; emit BorrowPaused(_iToken, _paused); } /** * @notice pause/unpause global transfer() * @dev Admin function, only owner and pauseGuardian can call this * @param _paused whether to pause or unpause */ function _setTransferPaused(bool _paused) external override checkPauser(_paused) { _setTransferPausedInternal(_paused); } function _setTransferPausedInternal(bool _paused) internal { transferPaused = _paused; emit TransferPaused(_paused); } /** * @notice pause/unpause global seize() * @dev Admin function, only owner and pauseGuardian can call this * @param _paused whether to pause or unpause */ function _setSeizePaused(bool _paused) external override checkPauser(_paused) { _setSeizePausedInternal(_paused); } function _setSeizePausedInternal(bool _paused) internal { seizePaused = _paused; emit SeizePaused(_paused); } /** * @notice pause/unpause all actions iToken, including mint/redeem/borrow * @dev Admin function, only owner and pauseGuardian can call this * @param _paused whether to pause or unpause */ function _setiTokenPaused(address _iToken, bool _paused) external override checkPauser(_paused) { _checkiTokenListed(_iToken); _setiTokenPausedInternal(_iToken, _paused); } function _setiTokenPausedInternal(address _iToken, bool _paused) internal { Market storage _market = markets[_iToken]; _market.mintPaused = _paused; emit MintPaused(_iToken, _paused); _market.redeemPaused = _paused; emit RedeemPaused(_iToken, _paused); _market.borrowPaused = _paused; emit BorrowPaused(_iToken, _paused); } /** * @notice pause/unpause entire protocol, including mint/redeem/borrow/seize/transfer * @dev Admin function, only owner and pauseGuardian can call this * @param _paused whether to pause or unpause */ function _setProtocolPaused(bool _paused) external override checkPauser(_paused) { EnumerableSetUpgradeable.AddressSet storage _iTokens = iTokens; uint256 _len = _iTokens.length(); for (uint256 i = 0; i < _len; i++) { address _iToken = _iTokens.at(i); _setiTokenPausedInternal(_iToken, _paused); } _setTransferPausedInternal(_paused); _setSeizePausedInternal(_paused); } /** * @notice Sets Reward Distributor * @dev Admin function to set reward distributor * @param _newRewardDistributor new reward distributor */ function _setRewardDistributor(address _newRewardDistributor) external override onlyOwner { address _oldRewardDistributor = rewardDistributor; require( _newRewardDistributor != address(0) && _newRewardDistributor != _oldRewardDistributor, "Reward Distributor address invalid" ); rewardDistributor = _newRewardDistributor; emit NewRewardDistributor(_oldRewardDistributor, _newRewardDistributor); } /*********************************/ /******** Poclicy Hooks **********/ /*********************************/ /** * @notice Hook function before iToken `mint()` * Checks if the account should be allowed to mint the given iToken * Will `revert()` if any check fails * @param _iToken The iToken to check the mint against * @param _minter The account which would get the minted tokens * @param _mintAmount The amount of underlying being minted to iToken */ function beforeMint( address _iToken, address _minter, uint256 _mintAmount ) external override { _checkiTokenListed(_iToken); Market storage _market = markets[_iToken]; require(!_market.mintPaused, "Token mint has been paused"); // Check the iToken's supply capacity, -1 means no limit uint256 _totalSupplyUnderlying = IERC20Upgradeable(_iToken).totalSupply().rmul( IiToken(_iToken).exchangeRateStored() ); require( _totalSupplyUnderlying.add(_mintAmount) <= _market.supplyCapacity, "Token supply capacity reached" ); // Update the Reward Distribution Supply state and distribute reward to suppplier IRewardDistributor(rewardDistributor).updateDistributionState( _iToken, false ); IRewardDistributor(rewardDistributor).updateReward( _iToken, _minter, false ); } /** * @notice Hook function after iToken `mint()` * Will `revert()` if any operation fails * @param _iToken The iToken being minted * @param _minter The account which would get the minted tokens * @param _mintAmount The amount of underlying being minted to iToken * @param _mintedAmount The amount of iToken being minted */ function afterMint( address _iToken, address _minter, uint256 _mintAmount, uint256 _mintedAmount ) external override { _iToken; _minter; _mintAmount; _mintedAmount; } /** * @notice Hook function before iToken `redeem()` * Checks if the account should be allowed to redeem the given iToken * Will `revert()` if any check fails * @param _iToken The iToken to check the redeem against * @param _redeemer The account which would redeem iToken * @param _redeemAmount The amount of iToken to redeem */ function beforeRedeem( address _iToken, address _redeemer, uint256 _redeemAmount ) external override { // _redeemAllowed below will check whether _iToken is listed require(!markets[_iToken].redeemPaused, "Token redeem has been paused"); _redeemAllowed(_iToken, _redeemer, _redeemAmount); // Update the Reward Distribution Supply state and distribute reward to suppplier IRewardDistributor(rewardDistributor).updateDistributionState( _iToken, false ); IRewardDistributor(rewardDistributor).updateReward( _iToken, _redeemer, false ); } /** * @notice Hook function after iToken `redeem()` * Will `revert()` if any operation fails * @param _iToken The iToken being redeemed * @param _redeemer The account which redeemed iToken * @param _redeemAmount The amount of iToken being redeemed * @param _redeemedUnderlying The amount of underlying being redeemed */ function afterRedeem( address _iToken, address _redeemer, uint256 _redeemAmount, uint256 _redeemedUnderlying ) external override { _iToken; _redeemer; _redeemAmount; _redeemedUnderlying; } /** * @notice Hook function before iToken `borrow()` * Checks if the account should be allowed to borrow the given iToken * Will `revert()` if any check fails * @param _iToken The iToken to check the borrow against * @param _borrower The account which would borrow iToken * @param _borrowAmount The amount of underlying to borrow */ function beforeBorrow( address _iToken, address _borrower, uint256 _borrowAmount ) external override { _checkiTokenListed(_iToken); Market storage _market = markets[_iToken]; require(!_market.borrowPaused, "Token borrow has been paused"); if (!hasBorrowed(_borrower, _iToken)) { // Unlike collaterals, borrowed asset can only be added by iToken, // rather than enabled by user directly. require(msg.sender == _iToken, "sender must be iToken"); // Have checked _iToken is listed, just add it _addToBorrowed(_borrower, _iToken); } // Check borrower's equity (, uint256 _shortfall, , ) = calcAccountEquityWithEffect(_borrower, _iToken, 0, _borrowAmount); require(_shortfall == 0, "Account has some shortfall"); // Check the iToken's borrow capacity, -1 means no limit uint256 _totalBorrows = IiToken(_iToken).totalBorrows(); require( _totalBorrows.add(_borrowAmount) <= _market.borrowCapacity, "Token borrow capacity reached" ); // Update the Reward Distribution Borrow state and distribute reward to borrower IRewardDistributor(rewardDistributor).updateDistributionState( _iToken, true ); IRewardDistributor(rewardDistributor).updateReward( _iToken, _borrower, true ); } /** * @notice Hook function after iToken `borrow()` * Will `revert()` if any operation fails * @param _iToken The iToken being borrewd * @param _borrower The account which borrowed iToken * @param _borrowedAmount The amount of underlying being borrowed */ function afterBorrow( address _iToken, address _borrower, uint256 _borrowedAmount ) external override { _iToken; _borrower; _borrowedAmount; } /** * @notice Hook function before iToken `repayBorrow()` * Checks if the account should be allowed to repay the given iToken * for the borrower. Will `revert()` if any check fails * @param _iToken The iToken to verify the repay against * @param _payer The account which would repay iToken * @param _borrower The account which has borrowed * @param _repayAmount The amount of underlying to repay */ function beforeRepayBorrow( address _iToken, address _payer, address _borrower, uint256 _repayAmount ) external override { _checkiTokenListed(_iToken); // Update the Reward Distribution Borrow state and distribute reward to borrower IRewardDistributor(rewardDistributor).updateDistributionState( _iToken, true ); IRewardDistributor(rewardDistributor).updateReward( _iToken, _borrower, true ); _payer; _repayAmount; } /** * @notice Hook function after iToken `repayBorrow()` * Will `revert()` if any operation fails * @param _iToken The iToken being repaid * @param _payer The account which would repay * @param _borrower The account which has borrowed * @param _repayAmount The amount of underlying being repaied */ function afterRepayBorrow( address _iToken, address _payer, address _borrower, uint256 _repayAmount ) external override { _checkiTokenListed(_iToken); // Remove _iToken from borrowed list if new borrow balance is 0 if (IiToken(_iToken).borrowBalanceStored(_borrower) == 0) { // Only allow called by iToken as we are going to remove this token from borrower's borrowed list require(msg.sender == _iToken, "sender must be iToken"); // Have checked _iToken is listed, just remove it _removeFromBorrowed(_borrower, _iToken); } _payer; _repayAmount; } /** * @notice Hook function before iToken `liquidateBorrow()` * Checks if the account should be allowed to liquidate the given iToken * for the borrower. Will `revert()` if any check fails * @param _iTokenBorrowed The iToken was borrowed * @param _iTokenCollateral The collateral iToken to be liqudate with * @param _liquidator The account which would repay the borrowed iToken * @param _borrower The account which has borrowed * @param _repayAmount The amount of underlying to repay */ function beforeLiquidateBorrow( address _iTokenBorrowed, address _iTokenCollateral, address _liquidator, address _borrower, uint256 _repayAmount ) external override { // Tokens must have been listed require( iTokens.contains(_iTokenBorrowed) && iTokens.contains(_iTokenCollateral), "Tokens have not been listed" ); (, uint256 _shortfall, , ) = calcAccountEquity(_borrower); require(_shortfall > 0, "Account does not have shortfall"); // Only allowed to repay the borrow balance's close factor uint256 _borrowBalance = IiToken(_iTokenBorrowed).borrowBalanceStored(_borrower); uint256 _maxRepay = _borrowBalance.rmul(closeFactorMantissa); require(_repayAmount <= _maxRepay, "Repay exceeds max repay allowed"); _liquidator; } /** * @notice Hook function after iToken `liquidateBorrow()` * Will `revert()` if any operation fails * @param _iTokenBorrowed The iToken was borrowed * @param _iTokenCollateral The collateral iToken to be seized * @param _liquidator The account which would repay and seize * @param _borrower The account which has borrowed * @param _repaidAmount The amount of underlying being repaied * @param _seizedAmount The amount of collateral being seized */ function afterLiquidateBorrow( address _iTokenBorrowed, address _iTokenCollateral, address _liquidator, address _borrower, uint256 _repaidAmount, uint256 _seizedAmount ) external override { _iTokenBorrowed; _iTokenCollateral; _liquidator; _borrower; _repaidAmount; _seizedAmount; // Unlike repayBorrow, liquidateBorrow does not allow to repay all borrow balance // No need to check whether should remove from borrowed asset list } /** * @notice Hook function before iToken `seize()` * Checks if the liquidator should be allowed to seize the collateral iToken * Will `revert()` if any check fails * @param _iTokenCollateral The collateral iToken to be seize * @param _iTokenBorrowed The iToken was borrowed * @param _liquidator The account which has repaid the borrowed iToken * @param _borrower The account which has borrowed * @param _seizeAmount The amount of collateral iToken to seize */ function beforeSeize( address _iTokenCollateral, address _iTokenBorrowed, address _liquidator, address _borrower, uint256 _seizeAmount ) external override { require(!seizePaused, "Seize has been paused"); // Markets must have been listed require( iTokens.contains(_iTokenBorrowed) && iTokens.contains(_iTokenCollateral), "Tokens have not been listed" ); // Sanity Check the controllers require( IiToken(_iTokenBorrowed).controller() == IiToken(_iTokenCollateral).controller(), "Controller mismatch between Borrowed and Collateral" ); // Update the Reward Distribution Supply state on collateral IRewardDistributor(rewardDistributor).updateDistributionState( _iTokenCollateral, false ); // Update reward of liquidator and borrower on collateral IRewardDistributor(rewardDistributor).updateReward( _iTokenCollateral, _liquidator, false ); IRewardDistributor(rewardDistributor).updateReward( _iTokenCollateral, _borrower, false ); _seizeAmount; } /** * @notice Hook function after iToken `seize()` * Will `revert()` if any operation fails * @param _iTokenCollateral The collateral iToken to be seized * @param _iTokenBorrowed The iToken was borrowed * @param _liquidator The account which has repaid and seized * @param _borrower The account which has borrowed * @param _seizedAmount The amount of collateral being seized */ function afterSeize( address _iTokenCollateral, address _iTokenBorrowed, address _liquidator, address _borrower, uint256 _seizedAmount ) external override { _iTokenBorrowed; _iTokenCollateral; _liquidator; _borrower; _seizedAmount; } /** * @notice Hook function before iToken `transfer()` * Checks if the transfer should be allowed * Will `revert()` if any check fails * @param _iToken The iToken to be transfered * @param _from The account to be transfered from * @param _to The account to be transfered to * @param _amount The amount to be transfered */ function beforeTransfer( address _iToken, address _from, address _to, uint256 _amount ) external override { // _redeemAllowed below will check whether _iToken is listed require(!transferPaused, "Transfer has been paused"); // Check account equity with this amount to decide whether the transfer is allowed _redeemAllowed(_iToken, _from, _amount); // Update the Reward Distribution supply state IRewardDistributor(rewardDistributor).updateDistributionState( _iToken, false ); // Update reward of from and to IRewardDistributor(rewardDistributor).updateReward( _iToken, _from, false ); IRewardDistributor(rewardDistributor).updateReward(_iToken, _to, false); } /** * @notice Hook function after iToken `transfer()` * Will `revert()` if any operation fails * @param _iToken The iToken was transfered * @param _from The account was transfer from * @param _to The account was transfer to * @param _amount The amount was transfered */ function afterTransfer( address _iToken, address _from, address _to, uint256 _amount ) external override { _iToken; _from; _to; _amount; } /** * @notice Hook function before iToken `flashloan()` * Checks if the flashloan should be allowed * Will `revert()` if any check fails * @param _iToken The iToken to be flashloaned * @param _to The account flashloaned transfer to * @param _amount The amount to be flashloaned */ function beforeFlashloan( address _iToken, address _to, uint256 _amount ) external override { // Flashloan share the same pause state with borrow require(!markets[_iToken].borrowPaused, "Token borrow has been paused"); _checkiTokenListed(_iToken); _to; _amount; // Update the Reward Distribution Borrow state IRewardDistributor(rewardDistributor).updateDistributionState( _iToken, true ); } /** * @notice Hook function after iToken `flashloan()` * Will `revert()` if any operation fails * @param _iToken The iToken was flashloaned * @param _to The account flashloan transfer to * @param _amount The amount was flashloaned */ function afterFlashloan( address _iToken, address _to, uint256 _amount ) external override { _iToken; _to; _amount; } /*********************************/ /***** Internal Functions *******/ /*********************************/ function _redeemAllowed( address _iToken, address _redeemer, uint256 _amount ) private view { _checkiTokenListed(_iToken); // No need to check liquidity if _redeemer has not used _iToken as collateral if (!accountsData[_redeemer].collaterals.contains(_iToken)) { return; } (, uint256 _shortfall, , ) = calcAccountEquityWithEffect(_redeemer, _iToken, _amount, 0); require(_shortfall == 0, "Account has some shortfall"); } /** * @dev Check if _iToken is listed */ function _checkiTokenListed(address _iToken) private view { require(iTokens.contains(_iToken), "Token has not been listed"); } /*********************************/ /** Account equity calculation ***/ /*********************************/ /** * @notice Calculates current account equity * @param _account The account to query equity of * @return account equity, shortfall, collateral value, borrowed value. */ function calcAccountEquity(address _account) public view override returns ( uint256, uint256, uint256, uint256 ) { return calcAccountEquityWithEffect(_account, address(0), 0, 0); } /** * @dev Local vars for avoiding stack-depth limits in calculating account liquidity. * Note that `iTokenBalance` is the number of iTokens the account owns in the collateral, * whereas `borrowBalance` is the amount of underlying that the account has borrowed. */ struct AccountEquityLocalVars { uint256 sumCollateral; uint256 sumBorrowed; uint256 iTokenBalance; uint256 borrowBalance; uint256 exchangeRateMantissa; uint256 underlyingPrice; uint256 collateralValue; uint256 borrowValue; } /** * @notice Calculates current account equity plus some token and amount to effect * @param _account The account to query equity of * @param _tokenToEffect The token address to add some additional redeeem/borrow * @param _redeemAmount The additional amount to redeem * @param _borrowAmount The additional amount to borrow * @return account euqity, shortfall, collateral value, borrowed value plus the effect. */ function calcAccountEquityWithEffect( address _account, address _tokenToEffect, uint256 _redeemAmount, uint256 _borrowAmount ) internal view virtual returns ( uint256, uint256, uint256, uint256 ) { AccountEquityLocalVars memory _local; AccountData storage _accountData = accountsData[_account]; // Calculate value of all collaterals // collateralValuePerToken = underlyingPrice * exchangeRate * collateralFactor // collateralValue = balance * collateralValuePerToken // sumCollateral += collateralValue uint256 _len = _accountData.collaterals.length(); for (uint256 i = 0; i < _len; i++) { IiToken _token = IiToken(_accountData.collaterals.at(i)); _local.iTokenBalance = IERC20Upgradeable(address(_token)).balanceOf( _account ); _local.exchangeRateMantissa = _token.exchangeRateStored(); if (_tokenToEffect == address(_token) && _redeemAmount > 0) { _local.iTokenBalance = _local.iTokenBalance.sub(_redeemAmount); } _local.underlyingPrice = IPriceOracle(priceOracle) .getUnderlyingPrice(address(_token)); require( _local.underlyingPrice != 0, "Invalid price to calculate account equity" ); _local.collateralValue = _local .iTokenBalance .mul(_local.underlyingPrice) .rmul(_local.exchangeRateMantissa) .rmul(markets[address(_token)].collateralFactorMantissa); _local.sumCollateral = _local.sumCollateral.add( _local.collateralValue ); } // Calculate all borrowed value // borrowValue = underlyingPrice * underlyingBorrowed / borrowFactor // sumBorrowed += borrowValue _len = _accountData.borrowed.length(); for (uint256 i = 0; i < _len; i++) { IiToken _token = IiToken(_accountData.borrowed.at(i)); _local.borrowBalance = _token.borrowBalanceStored(_account); if (_tokenToEffect == address(_token) && _borrowAmount > 0) { _local.borrowBalance = _local.borrowBalance.add(_borrowAmount); } _local.underlyingPrice = IPriceOracle(priceOracle) .getUnderlyingPrice(address(_token)); require( _local.underlyingPrice != 0, "Invalid price to calculate account equity" ); // borrowFactorMantissa can not be set to 0 _local.borrowValue = _local .borrowBalance .mul(_local.underlyingPrice) .rdiv(markets[address(_token)].borrowFactorMantissa); _local.sumBorrowed = _local.sumBorrowed.add(_local.borrowValue); } // Should never underflow return _local.sumCollateral > _local.sumBorrowed ? ( _local.sumCollateral - _local.sumBorrowed, uint256(0), _local.sumCollateral, _local.sumBorrowed ) : ( uint256(0), _local.sumBorrowed - _local.sumCollateral, _local.sumCollateral, _local.sumBorrowed ); } /** * @notice Calculate amount of collateral iToken to seize after repaying an underlying amount * @dev Used in liquidation * @param _iTokenBorrowed The iToken was borrowed * @param _iTokenCollateral The collateral iToken to be seized * @param _actualRepayAmount The amount of underlying token liquidator has repaied * @return _seizedTokenCollateral amount of iTokenCollateral tokens to be seized */ function liquidateCalculateSeizeTokens( address _iTokenBorrowed, address _iTokenCollateral, uint256 _actualRepayAmount ) external view virtual override returns (uint256 _seizedTokenCollateral) { /* Read oracle prices for borrowed and collateral assets */ uint256 _priceBorrowed = IPriceOracle(priceOracle).getUnderlyingPrice(_iTokenBorrowed); uint256 _priceCollateral = IPriceOracle(priceOracle).getUnderlyingPrice(_iTokenCollateral); require( _priceBorrowed != 0 && _priceCollateral != 0, "Borrowed or Collateral asset price is invalid" ); uint256 _valueRepayPlusIncentive = _actualRepayAmount.mul(_priceBorrowed).rmul( liquidationIncentiveMantissa ); // Use stored value here as it is view function uint256 _exchangeRateMantissa = IiToken(_iTokenCollateral).exchangeRateStored(); // seizedTokenCollateral = valueRepayPlusIncentive / valuePerTokenCollateral // valuePerTokenCollateral = exchangeRateMantissa * priceCollateral _seizedTokenCollateral = _valueRepayPlusIncentive .rdiv(_exchangeRateMantissa) .div(_priceCollateral); } /*********************************/ /*** Account Markets Operation ***/ /*********************************/ /** * @notice Returns the markets list the account has entered * @param _account The address of the account to query * @return _accountCollaterals The markets list the account has entered */ function getEnteredMarkets(address _account) external view override returns (address[] memory _accountCollaterals) { AccountData storage _accountData = accountsData[_account]; uint256 _len = _accountData.collaterals.length(); _accountCollaterals = new address[](_len); for (uint256 i = 0; i < _len; i++) { _accountCollaterals[i] = _accountData.collaterals.at(i); } } /** * @notice Add markets to `msg.sender`'s markets list for liquidity calculations * @param _iTokens The list of addresses of the iToken markets to be entered * @return _results Success indicator for whether each corresponding market was entered */ function enterMarkets(address[] calldata _iTokens) external override returns (bool[] memory _results) { uint256 _len = _iTokens.length; _results = new bool[](_len); for (uint256 i = 0; i < _len; i++) { _results[i] = _enterMarket(_iTokens[i], msg.sender); } } /** * @notice Add the market to the account's markets list for liquidity calculations * @param _iToken The market to enter * @param _account The address of the account to modify * @return True if entered successfully, false for non-listed market or other errors */ function _enterMarket(address _iToken, address _account) internal returns (bool) { // Market not listed, skip it if (!iTokens.contains(_iToken)) { return false; } // add() will return false if iToken is in account's market list if (accountsData[_account].collaterals.add(_iToken)) { emit MarketEntered(_iToken, _account); } return true; } /** * @notice Only expect to be called by iToken contract. * @dev Add the market to the account's markets list for liquidity calculations * @param _account The address of the account to modify */ function enterMarketFromiToken(address _account) external override { require( _enterMarket(msg.sender, _account), "enterMarketFromiToken: Only can be called by a supported iToken!" ); } /** * @notice Returns whether the given account has entered the market * @param _account The address of the account to check * @param _iToken The iToken to check against * @return True if the account has entered the market, otherwise false. */ function hasEnteredMarket(address _account, address _iToken) external view override returns (bool) { return accountsData[_account].collaterals.contains(_iToken); } /** * @notice Remove markets from `msg.sender`'s collaterals for liquidity calculations * @param _iTokens The list of addresses of the iToken to exit * @return _results Success indicators for whether each corresponding market was exited */ function exitMarkets(address[] calldata _iTokens) external override returns (bool[] memory _results) { uint256 _len = _iTokens.length; _results = new bool[](_len); for (uint256 i = 0; i < _len; i++) { _results[i] = _exitMarket(_iTokens[i], msg.sender); } } /** * @notice Remove the market to the account's markets list for liquidity calculations * @param _iToken The market to exit * @param _account The address of the account to modify * @return True if exit successfully, false for non-listed market or other errors */ function _exitMarket(address _iToken, address _account) internal returns (bool) { // Market not listed, skip it if (!iTokens.contains(_iToken)) { return true; } // Account has not entered this market, skip it if (!accountsData[_account].collaterals.contains(_iToken)) { return true; } // Get the iToken balance uint256 _balance = IERC20Upgradeable(_iToken).balanceOf(_account); // Check account's equity if all balance are redeemed // which means iToken can be removed from collaterals _redeemAllowed(_iToken, _account, _balance); // Have checked account has entered market before accountsData[_account].collaterals.remove(_iToken); emit MarketExited(_iToken, _account); return true; } /** * @notice Returns the asset list the account has borrowed * @param _account The address of the account to query * @return _borrowedAssets The asset list the account has borrowed */ function getBorrowedAssets(address _account) external view override returns (address[] memory _borrowedAssets) { AccountData storage _accountData = accountsData[_account]; uint256 _len = _accountData.borrowed.length(); _borrowedAssets = new address[](_len); for (uint256 i = 0; i < _len; i++) { _borrowedAssets[i] = _accountData.borrowed.at(i); } } /** * @notice Add the market to the account's borrowed list for equity calculations * @param _iToken The iToken of underlying to borrow * @param _account The address of the account to modify */ function _addToBorrowed(address _account, address _iToken) internal { // add() will return false if iToken is in account's market list if (accountsData[_account].borrowed.add(_iToken)) { emit BorrowedAdded(_iToken, _account); } } /** * @notice Returns whether the given account has borrowed the given iToken * @param _account The address of the account to check * @param _iToken The iToken to check against * @return True if the account has borrowed the iToken, otherwise false. */ function hasBorrowed(address _account, address _iToken) public view override returns (bool) { return accountsData[_account].borrowed.contains(_iToken); } /** * @notice Remove the iToken from the account's borrowed list * @param _iToken The iToken to remove * @param _account The address of the account to modify */ function _removeFromBorrowed(address _account, address _iToken) internal { // remove() will return false if iToken does not exist in account's borrowed list if (accountsData[_account].borrowed.remove(_iToken)) { emit BorrowedRemoved(_iToken, _account); } } /*********************************/ /****** General Information ******/ /*********************************/ /** * @notice Return all of the iTokens * @return _alliTokens The list of iToken addresses */ function getAlliTokens() public view override returns (address[] memory _alliTokens) { EnumerableSetUpgradeable.AddressSet storage _iTokens = iTokens; uint256 _len = _iTokens.length(); _alliTokens = new address[](_len); for (uint256 i = 0; i < _len; i++) { _alliTokens[i] = _iTokens.at(i); } } /** * @notice Check whether a iToken is listed in controller * @param _iToken The iToken to check for * @return true if the iToken is listed otherwise false */ function hasiToken(address _iToken) public view override returns (bool) { return iTokens.contains(_iToken); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20Upgradeable.sol"; import "../../math/SafeMathUpgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20Upgradeable { using SafeMathUpgradeable for uint256; using AddressUpgradeable for address; function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSetUpgradeable { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(value))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(value))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(value))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint256(_at(set._inner, index))); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } }
//SPDX-License-Identifier: MIT pragma solidity 0.6.12; interface IControllerAdminInterface { /// @notice Emitted when an admin supports a market event MarketAdded( address iToken, uint256 collateralFactor, uint256 borrowFactor, uint256 supplyCapacity, uint256 borrowCapacity, uint256 distributionFactor ); function _addMarket( address _iToken, uint256 _collateralFactor, uint256 _borrowFactor, uint256 _supplyCapacity, uint256 _borrowCapacity, uint256 _distributionFactor ) external; /// @notice Emitted when new price oracle is set event NewPriceOracle(address oldPriceOracle, address newPriceOracle); function _setPriceOracle(address newOracle) external; /// @notice Emitted when close factor is changed by admin event NewCloseFactor( uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa ); function _setCloseFactor(uint256 newCloseFactorMantissa) external; /// @notice Emitted when liquidation incentive is changed by admin event NewLiquidationIncentive( uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa ); function _setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external; /// @notice Emitted when iToken's collateral factor is changed by admin event NewCollateralFactor( address iToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa ); function _setCollateralFactor( address iToken, uint256 newCollateralFactorMantissa ) external; /// @notice Emitted when iToken's borrow factor is changed by admin event NewBorrowFactor( address iToken, uint256 oldBorrowFactorMantissa, uint256 newBorrowFactorMantissa ); function _setBorrowFactor(address iToken, uint256 newBorrowFactorMantissa) external; /// @notice Emitted when iToken's borrow capacity is changed by admin event NewBorrowCapacity( address iToken, uint256 oldBorrowCapacity, uint256 newBorrowCapacity ); function _setBorrowCapacity(address iToken, uint256 newBorrowCapacity) external; /// @notice Emitted when iToken's supply capacity is changed by admin event NewSupplyCapacity( address iToken, uint256 oldSupplyCapacity, uint256 newSupplyCapacity ); function _setSupplyCapacity(address iToken, uint256 newSupplyCapacity) external; /// @notice Emitted when pause guardian is changed by admin event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian); function _setPauseGuardian(address newPauseGuardian) external; /// @notice Emitted when mint is paused/unpaused by admin or pause guardian event MintPaused(address iToken, bool paused); function _setMintPaused(address iToken, bool paused) external; function _setAllMintPaused(bool paused) external; /// @notice Emitted when redeem is paused/unpaused by admin or pause guardian event RedeemPaused(address iToken, bool paused); function _setRedeemPaused(address iToken, bool paused) external; function _setAllRedeemPaused(bool paused) external; /// @notice Emitted when borrow is paused/unpaused by admin or pause guardian event BorrowPaused(address iToken, bool paused); function _setBorrowPaused(address iToken, bool paused) external; function _setAllBorrowPaused(bool paused) external; /// @notice Emitted when transfer is paused/unpaused by admin or pause guardian event TransferPaused(bool paused); function _setTransferPaused(bool paused) external; /// @notice Emitted when seize is paused/unpaused by admin or pause guardian event SeizePaused(bool paused); function _setSeizePaused(bool paused) external; function _setiTokenPaused(address iToken, bool paused) external; function _setProtocolPaused(bool paused) external; event NewRewardDistributor( address oldRewardDistributor, address _newRewardDistributor ); function _setRewardDistributor(address _newRewardDistributor) external; } interface IControllerPolicyInterface { function beforeMint( address iToken, address account, uint256 mintAmount ) external; function afterMint( address iToken, address minter, uint256 mintAmount, uint256 mintedAmount ) external; function beforeRedeem( address iToken, address redeemer, uint256 redeemAmount ) external; function afterRedeem( address iToken, address redeemer, uint256 redeemAmount, uint256 redeemedAmount ) external; function beforeBorrow( address iToken, address borrower, uint256 borrowAmount ) external; function afterBorrow( address iToken, address borrower, uint256 borrowedAmount ) external; function beforeRepayBorrow( address iToken, address payer, address borrower, uint256 repayAmount ) external; function afterRepayBorrow( address iToken, address payer, address borrower, uint256 repayAmount ) external; function beforeLiquidateBorrow( address iTokenBorrowed, address iTokenCollateral, address liquidator, address borrower, uint256 repayAmount ) external; function afterLiquidateBorrow( address iTokenBorrowed, address iTokenCollateral, address liquidator, address borrower, uint256 repaidAmount, uint256 seizedAmount ) external; function beforeSeize( address iTokenBorrowed, address iTokenCollateral, address liquidator, address borrower, uint256 seizeAmount ) external; function afterSeize( address iTokenBorrowed, address iTokenCollateral, address liquidator, address borrower, uint256 seizedAmount ) external; function beforeTransfer( address iToken, address from, address to, uint256 amount ) external; function afterTransfer( address iToken, address from, address to, uint256 amount ) external; function beforeFlashloan( address iToken, address to, uint256 amount ) external; function afterFlashloan( address iToken, address to, uint256 amount ) external; } interface IControllerAccountEquityInterface { function calcAccountEquity(address account) external view returns ( uint256, uint256, uint256, uint256 ); function liquidateCalculateSeizeTokens( address iTokenBorrowed, address iTokenCollateral, uint256 actualRepayAmount ) external view returns (uint256); } interface IControllerAccountInterface { function hasEnteredMarket(address account, address iToken) external view returns (bool); function getEnteredMarkets(address account) external view returns (address[] memory); /// @notice Emitted when an account enters a market event MarketEntered(address iToken, address account); function enterMarkets(address[] calldata iTokens) external returns (bool[] memory); function enterMarketFromiToken(address _account) external; /// @notice Emitted when an account exits a market event MarketExited(address iToken, address account); function exitMarkets(address[] calldata iTokens) external returns (bool[] memory); /// @notice Emitted when an account add a borrow asset event BorrowedAdded(address iToken, address account); /// @notice Emitted when an account remove a borrow asset event BorrowedRemoved(address iToken, address account); function hasBorrowed(address account, address iToken) external view returns (bool); function getBorrowedAssets(address account) external view returns (address[] memory); } interface IControllerInterface is IControllerAdminInterface, IControllerPolicyInterface, IControllerAccountEquityInterface, IControllerAccountInterface { /** * @notice Security checks when updating the comptroller of a market, always expect to return true. */ function isController() external view returns (bool); /** * @notice Return all of the iTokens * @return The list of iToken addresses */ function getAlliTokens() external view returns (address[] memory); /** * @notice Check whether a iToken is listed in controller * @param _iToken The iToken to check for * @return true if the iToken is listed otherwise false */ function hasiToken(address _iToken) external view returns (bool); }
//SPDX-License-Identifier: MIT pragma solidity 0.6.12; import "./IiToken.sol"; interface IPriceOracle { /** * @notice Get the underlying price of a iToken asset * @param _iToken The iToken to get the underlying price of * @return The underlying asset price mantissa (scaled by 1e18). * Zero means the price is unavailable. */ function getUnderlyingPrice(address _iToken) external view returns (uint256); /** * @notice Get the price of a underlying asset * @param _iToken The iToken to get the underlying price of * @return The underlying asset price mantissa (scaled by 1e18). * Zero means the price is unavailable and whether the price is valid. */ function getUnderlyingPriceAndStatus(address _iToken) external view returns (uint256, bool); }
//SPDX-License-Identifier: MIT pragma solidity 0.6.12; import "./IInterestRateModelInterface.sol"; import "./IControllerInterface.sol"; interface IiToken { function isSupported() external returns (bool); function isiToken() external returns (bool); //---------------------------------- //********* User Interface ********* //---------------------------------- function mint(address recipient, uint256 mintAmount) external; function mintForSelfAndEnterMarket(uint256 mintAmount) external; function redeem(address from, uint256 redeemTokens) external; function redeemUnderlying(address from, uint256 redeemAmount) external; function borrow(uint256 borrowAmount) external; function repayBorrow(uint256 repayAmount) external; function repayBorrowBehalf(address borrower, uint256 repayAmount) external; function liquidateBorrow( address borrower, uint256 repayAmount, address iTokenCollateral ) external; function flashloan( address recipient, uint256 loanAmount, bytes memory data ) external; function seize( address _liquidator, address _borrower, uint256 _seizeTokens ) external; function updateInterest() external returns (bool); function controller() external view returns (address); function exchangeRateCurrent() external returns (uint256); function exchangeRateStored() external view returns (uint256); function totalBorrowsCurrent() external returns (uint256); function totalBorrows() external view returns (uint256); function borrowBalanceCurrent(address _user) external returns (uint256); function borrowBalanceStored(address _user) external view returns (uint256); function borrowIndex() external view returns (uint256); function getAccountSnapshot(address _account) external view returns ( uint256, uint256, uint256 ); function borrowRatePerBlock() external view returns (uint256); function supplyRatePerBlock() external view returns (uint256); function getCash() external view returns (uint256); //---------------------------------- //********* Owner Actions ********** //---------------------------------- function _setNewReserveRatio(uint256 _newReserveRatio) external; function _setNewFlashloanFeeRatio(uint256 _newFlashloanFeeRatio) external; function _setNewProtocolFeeRatio(uint256 _newProtocolFeeRatio) external; function _setController(IControllerInterface _newController) external; function _setInterestRateModel( IInterestRateModelInterface _newInterestRateModel ) external; function _withdrawReserves(uint256 _withdrawAmount) external; }
//SPDX-License-Identifier: MIT pragma solidity 0.6.12; interface IRewardDistributor { function _setRewardToken(address newRewardToken) external; /// @notice Emitted reward token address is changed by admin event NewRewardToken(address oldRewardToken, address newRewardToken); function _addRecipient(address _iToken, uint256 _distributionFactor) external; event NewRecipient(address iToken, uint256 distributionFactor); /// @notice Emitted when mint is paused/unpaused by admin event Paused(bool paused); function _pause() external; function _unpause(uint256 _borrowSpeed, uint256 _supplySpeed) external; /// @notice Emitted when Global Distribution speed for both supply and borrow are updated event GlobalDistributionSpeedsUpdated( uint256 borrowSpeed, uint256 supplySpeed ); function _setGlobalDistributionSpeeds( uint256 borrowSpeed, uint256 supplySpeed ) external; /// @notice Emitted when iToken's Distribution speed is updated event DistributionSpeedsUpdated( address iToken, uint256 borrowSpeed, uint256 supplySpeed ); function updateDistributionSpeed() external; /// @notice Emitted when iToken's Distribution factor is changed by admin event NewDistributionFactor( address iToken, uint256 oldDistributionFactorMantissa, uint256 newDistributionFactorMantissa ); function _setDistributionFactors( address[] calldata iToken, uint256[] calldata distributionFactors ) external; function updateDistributionState(address _iToken, bool _isBorrow) external; function updateReward( address _iToken, address _account, bool _isBorrow ) external; function updateRewardBatch( address[] memory _holders, address[] memory _iTokens ) external; function claimReward(address[] memory _holders, address[] memory _iTokens) external; function claimAllReward(address[] memory _holders) external; /// @notice Emitted when reward of amount is distributed into account event RewardDistributed( address iToken, address account, uint256 amount, uint256 accountIndex ); }
// SPDX-License-Identifier: MIT pragma solidity 0.6.12; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require( !_initialized, "Initializable: contract is already initialized" ); _; _initialized = true; } }
//SPDX-License-Identifier: MIT pragma solidity 0.6.12; /** * @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 {_setPendingOwner} and {_acceptOwner}. */ contract Ownable { /** * @dev Returns the address of the current owner. */ address payable public owner; /** * @dev Returns the address of the current pending owner. */ address payable public pendingOwner; event NewOwner(address indexed previousOwner, address indexed newOwner); event NewPendingOwner( address indexed oldPendingOwner, address indexed newPendingOwner ); /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner == msg.sender, "onlyOwner: caller is not the owner"); _; } /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal { owner = msg.sender; emit NewOwner(address(0), msg.sender); } /** * @notice Base on the inputing parameter `newPendingOwner` to check the exact error reason. * @dev Transfer contract control to a new owner. The newPendingOwner must call `_acceptOwner` to finish the transfer. * @param newPendingOwner New pending owner. */ function _setPendingOwner(address payable newPendingOwner) external onlyOwner { require( newPendingOwner != address(0) && newPendingOwner != pendingOwner, "_setPendingOwner: New owenr can not be zero address and owner has been set!" ); // Gets current owner. address oldPendingOwner = pendingOwner; // Sets new pending owner. pendingOwner = newPendingOwner; emit NewPendingOwner(oldPendingOwner, newPendingOwner); } /** * @dev Accepts the admin rights, but only for pendingOwenr. */ function _acceptOwner() external { require( msg.sender == pendingOwner, "_acceptOwner: Only for pending owner!" ); // Gets current values for events. address oldOwner = owner; address oldPendingOwner = pendingOwner; // Set the new contract owner. owner = pendingOwner; // Clear the pendingOwner. pendingOwner = address(0); emit NewOwner(oldOwner, owner); emit NewPendingOwner(oldPendingOwner, pendingOwner); } uint256[50] private __gap; }
//SPDX-License-Identifier: MIT pragma solidity 0.6.12; import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; library SafeRatioMath { using SafeMathUpgradeable for uint256; uint256 private constant BASE = 10**18; uint256 private constant DOUBLE = 10**36; function divup(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x.add(y.sub(1)).div(y); } function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x.mul(y).div(BASE); } function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x.mul(BASE).div(y); } function rdivup(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x.mul(BASE).add(y.sub(1)).div(y); } function tmul( uint256 x, uint256 y, uint256 z ) internal pure returns (uint256 result) { result = x.mul(y).mul(z).div(DOUBLE); } function rpow( uint256 x, uint256 n, uint256 base ) internal pure returns (uint256 z) { assembly { switch x case 0 { switch n case 0 { z := base } default { z := 0 } } default { switch mod(n, 2) case 0 { z := base } default { z := x } let half := div(base, 2) // for rounding. for { n := div(n, 2) } n { n := div(n, 2) } { let xx := mul(x, x) if iszero(eq(div(xx, x), x)) { revert(0, 0) } let xxRound := add(xx, half) if lt(xxRound, xx) { revert(0, 0) } x := div(xxRound, base) if mod(n, 2) { let zx := mul(z, x) if and( iszero(iszero(x)), iszero(eq(div(zx, x), z)) ) { revert(0, 0) } let zxRound := add(zx, half) if lt(zxRound, zx) { revert(0, 0) } z := div(zxRound, base) } } } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @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 SafeMathUpgradeable { /** * @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) { 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; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
//SPDX-License-Identifier: MIT pragma solidity 0.6.12; /** * @title dForce Lending Protocol's InterestRateModel Interface. * @author dForce Team. */ interface IInterestRateModelInterface { function isInterestRateModel() external view returns (bool); /** * @dev Calculates the current borrow interest rate per block. * @param cash The total amount of cash the market has. * @param borrows The total amount of borrows the market has. * @param reserves The total amnount of reserves the market has. * @return The borrow rate per block (as a percentage, and scaled by 1e18). */ function getBorrowRate( uint256 cash, uint256 borrows, uint256 reserves ) external view returns (uint256); /** * @dev Calculates the current supply interest rate per block. * @param cash The total amount of cash the market has. * @param borrows The total amount of borrows the market has. * @param reserves The total amnount of reserves the market has. * @param reserveRatio The current reserve factor the market has. * @return The supply rate per block (as a percentage, and scaled by 1e18). */ function getSupplyRate( uint256 cash, uint256 borrows, uint256 reserves, uint256 reserveRatio ) external view returns (uint256); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"BorrowPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"BorrowedAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"BorrowedRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supplyCapacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowCapacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"distributionFactor","type":"uint256"}],"name":"MarketAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"MarketEntered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"MarketExited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"MintPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldBorrowCapacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBorrowCapacity","type":"uint256"}],"name":"NewBorrowCapacity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldBorrowFactorMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBorrowFactorMantissa","type":"uint256"}],"name":"NewBorrowFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCloseFactorMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCloseFactorMantissa","type":"uint256"}],"name":"NewCloseFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldCollateralFactorMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCollateralFactorMantissa","type":"uint256"}],"name":"NewCollateralFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldLiquidationIncentiveMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLiquidationIncentiveMantissa","type":"uint256"}],"name":"NewLiquidationIncentive","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPauseGuardian","type":"address"},{"indexed":false,"internalType":"address","name":"newPauseGuardian","type":"address"}],"name":"NewPauseGuardian","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPendingOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPriceOracle","type":"address"},{"indexed":false,"internalType":"address","name":"newPriceOracle","type":"address"}],"name":"NewPriceOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRewardDistributor","type":"address"},{"indexed":false,"internalType":"address","name":"_newRewardDistributor","type":"address"}],"name":"NewRewardDistributor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldSupplyCapacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSupplyCapacity","type":"uint256"}],"name":"NewSupplyCapacity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"iToken","type":"address"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"RedeemPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"SeizePaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"TransferPaused","type":"event"},{"inputs":[],"name":"_acceptOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"uint256","name":"_collateralFactor","type":"uint256"},{"internalType":"uint256","name":"_borrowFactor","type":"uint256"},{"internalType":"uint256","name":"_supplyCapacity","type":"uint256"},{"internalType":"uint256","name":"_borrowCapacity","type":"uint256"},{"internalType":"uint256","name":"_distributionFactor","type":"uint256"}],"name":"_addMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setAllBorrowPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setAllMintPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setAllRedeemPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"uint256","name":"_newBorrowCapacity","type":"uint256"}],"name":"_setBorrowCapacity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"uint256","name":"_newBorrowFactorMantissa","type":"uint256"}],"name":"_setBorrowFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setBorrowPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newCloseFactorMantissa","type":"uint256"}],"name":"_setCloseFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"uint256","name":"_newCollateralFactorMantissa","type":"uint256"}],"name":"_setCollateralFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newLiquidationIncentiveMantissa","type":"uint256"}],"name":"_setLiquidationIncentive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setMintPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPauseGuardian","type":"address"}],"name":"_setPauseGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newPendingOwner","type":"address"}],"name":"_setPendingOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOracle","type":"address"}],"name":"_setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setProtocolPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setRedeemPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newRewardDistributor","type":"address"}],"name":"_setRewardDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setSeizePaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"uint256","name":"_newSupplyCapacity","type":"uint256"}],"name":"_setSupplyCapacity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setTransferPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"bool","name":"_paused","type":"bool"}],"name":"_setiTokenPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_borrowedAmount","type":"uint256"}],"name":"afterBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"afterFlashloan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iTokenBorrowed","type":"address"},{"internalType":"address","name":"_iTokenCollateral","type":"address"},{"internalType":"address","name":"_liquidator","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_repaidAmount","type":"uint256"},{"internalType":"uint256","name":"_seizedAmount","type":"uint256"}],"name":"afterLiquidateBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_minter","type":"address"},{"internalType":"uint256","name":"_mintAmount","type":"uint256"},{"internalType":"uint256","name":"_mintedAmount","type":"uint256"}],"name":"afterMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_redeemer","type":"address"},{"internalType":"uint256","name":"_redeemAmount","type":"uint256"},{"internalType":"uint256","name":"_redeemedUnderlying","type":"uint256"}],"name":"afterRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_payer","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_repayAmount","type":"uint256"}],"name":"afterRepayBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iTokenCollateral","type":"address"},{"internalType":"address","name":"_iTokenBorrowed","type":"address"},{"internalType":"address","name":"_liquidator","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_seizedAmount","type":"uint256"}],"name":"afterSeize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"afterTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_borrowAmount","type":"uint256"}],"name":"beforeBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"beforeFlashloan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iTokenBorrowed","type":"address"},{"internalType":"address","name":"_iTokenCollateral","type":"address"},{"internalType":"address","name":"_liquidator","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_repayAmount","type":"uint256"}],"name":"beforeLiquidateBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_minter","type":"address"},{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"beforeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_redeemer","type":"address"},{"internalType":"uint256","name":"_redeemAmount","type":"uint256"}],"name":"beforeRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_payer","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_repayAmount","type":"uint256"}],"name":"beforeRepayBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iTokenCollateral","type":"address"},{"internalType":"address","name":"_iTokenBorrowed","type":"address"},{"internalType":"address","name":"_liquidator","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_seizeAmount","type":"uint256"}],"name":"beforeSeize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"beforeTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"calcAccountEquity","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeFactorMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"enterMarketFromiToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_iTokens","type":"address[]"}],"name":"enterMarkets","outputs":[{"internalType":"bool[]","name":"_results","type":"bool[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_iTokens","type":"address[]"}],"name":"exitMarkets","outputs":[{"internalType":"bool[]","name":"_results","type":"bool[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAlliTokens","outputs":[{"internalType":"address[]","name":"_alliTokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getBorrowedAssets","outputs":[{"internalType":"address[]","name":"_borrowedAssets","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getEnteredMarkets","outputs":[{"internalType":"address[]","name":"_accountCollaterals","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_iToken","type":"address"}],"name":"hasBorrowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_iToken","type":"address"}],"name":"hasEnteredMarket","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_iToken","type":"address"}],"name":"hasiToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isController","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_iTokenBorrowed","type":"address"},{"internalType":"address","name":"_iTokenCollateral","type":"address"},{"internalType":"uint256","name":"_actualRepayAmount","type":"uint256"}],"name":"liquidateCalculateSeizeTokens","outputs":[{"internalType":"uint256","name":"_seizedTokenCollateral","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidationIncentiveMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"markets","outputs":[{"internalType":"uint256","name":"collateralFactorMantissa","type":"uint256"},{"internalType":"uint256","name":"borrowFactorMantissa","type":"uint256"},{"internalType":"uint256","name":"borrowCapacity","type":"uint256"},{"internalType":"uint256","name":"supplyCapacity","type":"uint256"},{"internalType":"bool","name":"mintPaused","type":"bool"},{"internalType":"bool","name":"redeemPaused","type":"bool"},{"internalType":"bool","name":"borrowPaused","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseGuardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seizePaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50614f66806100206000396000f3fe608060405234801561001057600080fd5b50600436106103af5760003560e01c80638ebf6364116101f4578063d4d484731161011a578063e4028eee116100ad578063f079420a1161007c578063f079420a14610d80578063f1575f0814610dbc578063fb2cb34e14610dea578063fc4d33f914610df2576103af565b8063e4028eee14610d2d578063e715d96a14610d59578063e875544614610d78578063efced38514610b21576103af565b8063de65f41b116100e9578063de65f41b14610997578063e29f7f5e14610cca578063e30c397814610ce9578063e33af48a14610cf1576103af565b8063d4d4847314610c0d578063d5b4436014610c3b578063d79287d714610c67578063dbb32d6814610cab576103af565b8063acc2166a11610192578063c488847b11610161578063c488847b14610aeb578063ca498ad614610b21578063cb6db19c14610b57578063d0af413814610b9d576103af565b8063acc2166a14610a11578063af505ad914610a19578063bd8296c214610a4f578063c299823814610a7b576103af565b8063a09cf78b116101ce578063a09cf78b1461094b578063a2ddeb8514610997578063a8f4e9f6146109d3578063ab1777d214610a09576103af565b80638ebf6364146108da5780639142c34c146108f95780639d8cc5c41461091f576103af565b80634fd42e17116102d95780637160a8701161027757806386b841871161024657806386b84187146108125780638ccb720b146108485780638da5cb5b1461086e5780638e8f294b14610876576103af565b80637160a8701461077257806372b4304a146107a05780638129fc1c146107dc5780638283e3e2146107e4576103af565b80635f5af1aa116102b35780635f5af1aa146106d25780635f7bc006146106f857806360a8a931146107445780636e96dfd71461074c576103af565b80634fd42e171461066957806355ee1fe1146106865780635c254d11146106ac576103af565b80632a6a6065116103515780633bcf7ec1116103205780633bcf7ec1146105df5780634428e8621461060d5780634ada90af146106475780634e1647fb14610661576103af565b80632a6a60651461054e5780632b9553ce1461056d5780632d70db78146105a3578063317b0b77146105c2576103af565b80631637eefd1161038d5780631637eefd146104b857806318c882a5146104f457806324a3d622146105225780632630c12f14610546576103af565b8063061682de146103b4578063075aff36146103fc5780630d7f67a214610472575b600080fd5b6103fa600480360360a08110156103ca57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135610dfa565b005b6104226004803603602081101561041257600080fd5b50356001600160a01b0316610fbd565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561045e578181015183820152602001610446565b505050509050019250505060405180910390f35b6103fa600480360360a081101561048857600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611076565b6103fa600480360360808110156104ce57600080fd5b506001600160a01b0381358116916020810135821691604082013516906060013561107d565b6103fa6004803603604081101561050a57600080fd5b506001600160a01b0381351690602001351515611164565b61052a6111e9565b604080516001600160a01b039092168252519081900360200190f35b61052a6111f8565b6103fa6004803603602081101561056457600080fd5b50351515611207565b6103fa6004803603606081101561058357600080fd5b506001600160a01b038135811691602081013590911690604001356112c8565b6103fa600480360360208110156105b957600080fd5b503515156115d5565b6103fa600480360360208110156105d857600080fd5b503561164f565b6103fa600480360360408110156105f557600080fd5b506001600160a01b038135169060200135151561174b565b6106336004803603602081101561062357600080fd5b50356001600160a01b03166117cb565b604080519115158252519081900360200190f35b61064f6117de565b60408051918252519081900360200190f35b6106336117e4565b6103fa6004803603602081101561067f57600080fd5b50356117e9565b6103fa6004803603602081101561069c57600080fd5b50356001600160a01b03166118ef565b6103fa600480360360208110156106c257600080fd5b50356001600160a01b0316611a18565b6103fa600480360360208110156106e857600080fd5b50356001600160a01b0316611b32565b6103fa600480360360c081101561070e57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a00135611c62565b610422611c6a565b6103fa6004803603602081101561076257600080fd5b50356001600160a01b0316611d06565b6103fa6004803603604081101561078857600080fd5b506001600160a01b0381351690602001351515611e07565b6103fa600480360360808110156107b657600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135611e87565b6103fa612026565b610633600480360360408110156107fa57600080fd5b506001600160a01b038135811691602001351661207f565b6103fa6004803603606081101561082857600080fd5b506001600160a01b038135811691602081013590911690604001356120ab565b6104226004803603602081101561085e57600080fd5b50356001600160a01b031661234a565b61052a6123f5565b61089c6004803603602081101561088c57600080fd5b50356001600160a01b0316612409565b60408051978852602088019690965286860194909452606086019290925215156080850152151560a0840152151560c0830152519081900360e00190f35b6103fa600480360360208110156108f057600080fd5b5035151561244e565b6103fa6004803603602081101561090f57600080fd5b50356001600160a01b03166124c4565b6103fa6004803603604081101561093557600080fd5b506001600160a01b03813516906020013561250c565b6109716004803603602081101561096157600080fd5b50356001600160a01b03166126e5565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6103fa600480360360808110156109ad57600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356112c2565b6103fa600480360360608110156109e957600080fd5b506001600160a01b03813581169160208101359091169060400135612708565b6106336127fa565b61052a61280a565b6103fa60048036036060811015610a2f57600080fd5b506001600160a01b03813581169160208101359091169060400135612819565b6103fa60048036036040811015610a6557600080fd5b506001600160a01b03813516906020013561295e565b61042260048036036020811015610a9157600080fd5b810190602081018135640100000000811115610aac57600080fd5b820183602082011115610abe57600080fd5b80359060200191846020830284011164010000000083111715610ae057600080fd5b509092509050612a22565b61064f60048036036060811015610b0157600080fd5b506001600160a01b03813581169160208101359091169060400135612ac5565b6103fa60048036036060811015610b3757600080fd5b506001600160a01b038135811691602081013590911690604001356111e4565b6103fa600480360360a0811015610b6d57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135612caf565b61042260048036036020811015610bb357600080fd5b810190602081018135640100000000811115610bce57600080fd5b820183602082011115610be057600080fd5b80359060200191846020830284011164010000000083111715610c0257600080fd5b509092509050612fc3565b61063360048036036040811015610c2357600080fd5b506001600160a01b038135811691602001351661305e565b6103fa60048036036040811015610c5157600080fd5b506001600160a01b038135169060200135613080565b6103fa600480360360c0811015610c7d57600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a00135613144565b6103fa60048036036020811015610cc157600080fd5b503515156135fa565b6103fa60048036036020811015610ce057600080fd5b5035151561369c565b61052a61373e565b6103fa60048036036080811015610d0757600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356112c2565b6103fa60048036036040811015610d4357600080fd5b506001600160a01b03813516906020013561374d565b6103fa60048036036020811015610d6f57600080fd5b50351515613919565b61064f6139bb565b6103fa60048036036080811015610d9657600080fd5b506001600160a01b038135811691602081013582169160408201351690606001356139c1565b6103fa60048036036040811015610dd257600080fd5b506001600160a01b0381351690602001351515613aa6565b610633613b26565b6103fa613b36565b610e05603486613c2d565b8015610e175750610e17603485613c2d565b610e68576040805162461bcd60e51b815260206004820152601b60248201527f546f6b656e732068617665206e6f74206265656e206c69737465640000000000604482015290519081900360640190fd5b6000610e73836126e5565b505091505060008111610ecd576040805162461bcd60e51b815260206004820152601f60248201527f4163636f756e7420646f6573206e6f7420686176652073686f727466616c6c00604482015290519081900360640190fd5b6000866001600160a01b03166395dd9193856040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610f1c57600080fd5b505afa158015610f30573d6000803e3d6000fd5b505050506040513d6020811015610f4657600080fd5b5051603954909150600090610f5c908390613c42565b905080841115610fb3576040805162461bcd60e51b815260206004820152601f60248201527f52657061792065786365656473206d617820726570617920616c6c6f77656400604482015290519081900360640190fd5b5050505050505050565b6001600160a01b0381166000908152603760205260408120606091610fe460028301613c5a565b90508067ffffffffffffffff81118015610ffd57600080fd5b50604051908082528060200260200182016040528015611027578160200160208202803683370190505b50925060005b8181101561106e576110426002840182613c65565b84828151811061104e57fe5b6001600160a01b039092166020928302919091019091015260010161102d565b505050919050565b5050505050565b61108684613c71565b603c5460408051636576717f60e11b81526001600160a01b038781166004830152600160248301529151919092169163caece2fe91604480830192600092919082900301818387803b1580156110db57600080fd5b505af11580156110ef573d6000803e3d6000fd5b5050603c5460408051637d3572fd60e01b81526001600160a01b0389811660048301528781166024830152600160448301529151919092169350637d3572fd9250606480830192600092919082900301818387803b15801561115057600080fd5b505af1158015610fb3573d6000803e3d6000fd5b600054819061010090046001600160a01b03163314806111965750603b546001600160a01b0316331480156111965750805b6111d15760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b6111da83613c71565b6111e48383613ccd565b505050565b603b546001600160a01b031681565b6038546001600160a01b031681565b600054819061010090046001600160a01b03163314806112395750603b546001600160a01b0316331480156112395750805b6112745760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b6034600061128182613c5a565b905060005b818110156112af57600061129a8483613c65565b90506112a68187613d3e565b50600101611286565b506112b984613e6b565b6112c284613ebe565b50505050565b6112d183613c71565b6001600160a01b0383166000908152603660205260409020600481015462010000900460ff1615611349576040805162461bcd60e51b815260206004820152601c60248201527f546f6b656e20626f72726f7720686173206265656e2070617573656400000000604482015290519081900360640190fd5b611353838561207f565b6113b657336001600160a01b038516146113ac576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329034aa37b5b2b760591b604482015290519081900360640190fd5b6113b68385613f11565b60006113c58486600086613f84565b50509150508060001461141f576040805162461bcd60e51b815260206004820152601a60248201527f4163636f756e742068617320736f6d652073686f727466616c6c000000000000604482015290519081900360640190fd5b6000856001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561145a57600080fd5b505afa15801561146e573d6000803e3d6000fd5b505050506040513d602081101561148457600080fd5b505160028401549091506114988286614442565b11156114eb576040805162461bcd60e51b815260206004820152601d60248201527f546f6b656e20626f72726f772063617061636974792072656163686564000000604482015290519081900360640190fd5b603c5460408051636576717f60e11b81526001600160a01b038981166004830152600160248301529151919092169163caece2fe91604480830192600092919082900301818387803b15801561154057600080fd5b505af1158015611554573d6000803e3d6000fd5b5050603c5460408051637d3572fd60e01b81526001600160a01b038b811660048301528a81166024830152600160448301529151919092169350637d3572fd9250606480830192600092919082900301818387803b1580156115b557600080fd5b505af11580156115c9573d6000803e3d6000fd5b50505050505050505050565b600054819061010090046001600160a01b03163314806116075750603b546001600160a01b0316331480156116075750805b6116425760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b61164b82613ebe565b5050565b60005461010090046001600160a01b0316331461169d5760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b66b1a2bc2ec5000081101580156116bc5750670c7d713b49da00008111155b611704576040805162461bcd60e51b815260206004820152601460248201527310db1bdcd948199858dd1bdc881a5b9d985b1a5960621b604482015290519081900360640190fd5b6039805490829055604080518281526020810184905281517f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9929181900390910190a15050565b600054819061010090046001600160a01b031633148061177d5750603b546001600160a01b03163314801561177d5750805b6117b85760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b6117c183613c71565b6111e4838361449c565b60006117d8603483613c2d565b92915050565b603a5481565b600190565b60005461010090046001600160a01b031633146118375760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b670de0b6b3a7640000811015801561185757506714d1120d7b1600008111155b6118a8576040805162461bcd60e51b815260206004820152601d60248201527f4c69717569646174696f6e20696e63656e7469766520696e76616c6964000000604482015290519081900360640190fd5b603a805490829055604080518281526020810184905281517faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316929181900390910190a15050565b60005461010090046001600160a01b0316331461193d5760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b6038546001600160a01b039081169082161580159061196e5750806001600160a01b0316826001600160a01b031614155b6119b8576040805162461bcd60e51b815260206004820152601660248201527513dc9858db19481859191c995cdcc81a5b9d985b1a5960521b604482015290519081900360640190fd5b603880546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e229281900390910190a15050565b60005461010090046001600160a01b03163314611a665760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b603c546001600160a01b0390811690821615801590611a975750806001600160a01b0316826001600160a01b031614155b611ad25760405162461bcd60e51b8152600401808060200182810382526022815260200180614e6a6022913960400191505060405180910390fd5b603c80546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517f8ddca872a7a62d68235cff1a03badc845dc3007cfaa6145379f7bf3452ecb9b99281900390910190a15050565b60005461010090046001600160a01b03163314611b805760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b603b546001600160a01b0390811690821615801590611bb15750806001600160a01b0316826001600160a01b031614155b611c02576040805162461bcd60e51b815260206004820152601e60248201527f506175736520677561726469616e206164647265737320696e76616c69640000604482015290519081900360640190fd5b603b80546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e9281900390910190a15050565b505050505050565b606060346000611c7982613c5a565b90508067ffffffffffffffff81118015611c9257600080fd5b50604051908082528060200260200182016040528015611cbc578160200160208202803683370190505b50925060005b81811015611d0057611cd48382613c65565b848281518110611ce057fe5b6001600160a01b0390921660209283029190910190910152600101611cc2565b50505090565b60005461010090046001600160a01b03163314611d545760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b6001600160a01b03811615801590611d7a57506001546001600160a01b03828116911614155b611db55760405162461bcd60e51b815260040180806020018281038252604b815260200180614ce0604b913960600191505060405180910390fd5b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b600054819061010090046001600160a01b0316331480611e395750603b546001600160a01b031633148015611e395750805b611e745760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b611e7d83613c71565b6111e48383614503565b603b54600160a01b900460ff1615611ee6576040805162461bcd60e51b815260206004820152601860248201527f5472616e7366657220686173206265656e207061757365640000000000000000604482015290519081900360640190fd5b611ef1848483614572565b603c5460408051636576717f60e11b81526001600160a01b038781166004830152600060248301819052925193169263caece2fe9260448084019391929182900301818387803b158015611f4457600080fd5b505af1158015611f58573d6000803e3d6000fd5b5050603c5460408051637d3572fd60e01b81526001600160a01b0389811660048301528881166024830152600060448301819052925193169450637d3572fd93506064808201939182900301818387803b158015611fb557600080fd5b505af1158015611fc9573d6000803e3d6000fd5b5050603c5460408051637d3572fd60e01b81526001600160a01b0389811660048301528781166024830152600060448301819052925193169450637d3572fd93506064808201939182900301818387803b15801561115057600080fd5b60005460ff16156120685760405162461bcd60e51b815260040180806020018281038252602e815260200180614d90602e913960400191505060405180910390fd5b61207061460f565b6000805460ff19166001179055565b6001600160a01b03821660009081526037602052604081206120a49060020183613c2d565b9392505050565b6120b483613c71565b6001600160a01b0383166000908152603660205260409020600481015460ff1615612126576040805162461bcd60e51b815260206004820152601a60248201527f546f6b656e206d696e7420686173206265656e20706175736564000000000000604482015290519081900360640190fd5b6000612202856001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561216457600080fd5b505afa158015612178573d6000803e3d6000fd5b505050506040513d602081101561218e57600080fd5b5051604080516318160ddd60e01b815290516001600160a01b038916916318160ddd916004808301926020929190829003018186803b1580156121d057600080fd5b505afa1580156121e4573d6000803e3d6000fd5b505050506040513d60208110156121fa57600080fd5b505190613c42565b60038301549091506122148285614442565b1115612267576040805162461bcd60e51b815260206004820152601d60248201527f546f6b656e20737570706c792063617061636974792072656163686564000000604482015290519081900360640190fd5b603c5460408051636576717f60e11b81526001600160a01b038881166004830152600060248301819052925193169263caece2fe9260448084019391929182900301818387803b1580156122ba57600080fd5b505af11580156122ce573d6000803e3d6000fd5b5050603c5460408051637d3572fd60e01b81526001600160a01b038a811660048301528981166024830152600060448301819052925193169450637d3572fd93506064808201939182900301818387803b15801561232b57600080fd5b505af115801561233f573d6000803e3d6000fd5b505050505050505050565b6001600160a01b038116600090815260376020526040812060609161236e82613c5a565b90508067ffffffffffffffff8111801561238757600080fd5b506040519080825280602002602001820160405280156123b1578160200160208202803683370190505b50925060005b8181101561106e576123c98382613c65565b8482815181106123d557fe5b6001600160a01b03909216602092830291909101909101526001016123b7565b60005461010090046001600160a01b031681565b603660205260009081526040902080546001820154600283015460038401546004909401549293919290919060ff808216916101008104821691620100009091041687565b600054819061010090046001600160a01b03163314806124805750603b546001600160a01b0316331480156124805750805b6124bb5760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b61164b82613e6b565b6124ce3382614657565b6125095760405162461bcd60e51b8152600401808060200182810382526040815260200180614ef16040913960400191505060405180910390fd5b50565b60005461010090046001600160a01b0316331461255a5760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b61256382613c71565b60008111801561257b5750670de0b6b3a76400008111155b6125c4576040805162461bcd60e51b8152602060048201526015602482015274109bdc9c9bddc8199858dd1bdc881a5b9d985b1a59605a1b604482015290519081900360640190fd5b6038546040805163fc57d4df60e01b81526001600160a01b0385811660048301529151919092169163fc57d4df916024808301926020929190829003018186803b15801561261157600080fd5b505afa158015612625573d6000803e3d6000fd5b505050506040513d602081101561263b57600080fd5b50516126785760405162461bcd60e51b815260040180806020018281038252603c815260200180614ddf603c913960400191505060405180910390fd5b6001600160a01b0382166000818152603660209081526040918290206001810180549086905583519485529184018290528383018590529151919290917fd69d3c48186e96a0af0545cf26e970b49ed3e29a306a37118a5a787bae6b90be9181900360600190a150505050565b6000806000806126f9856000806000613f84565b93509350935093509193509193565b6001600160a01b03831660009081526036602052604090206004015462010000900460ff161561277f576040805162461bcd60e51b815260206004820152601c60248201527f546f6b656e20626f72726f7720686173206265656e2070617573656400000000604482015290519081900360640190fd5b61278883613c71565b603c5460408051636576717f60e11b81526001600160a01b038681166004830152600160248301529151919092169163caece2fe91604480830192600092919082900301818387803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b50505050505050565b603b54600160a81b900460ff1681565b603c546001600160a01b031681565b6001600160a01b038316600090815260366020526040902060040154610100900460ff161561288f576040805162461bcd60e51b815260206004820152601c60248201527f546f6b656e2072656465656d20686173206265656e2070617573656400000000604482015290519081900360640190fd5b61289a838383614572565b603c5460408051636576717f60e11b81526001600160a01b038681166004830152600060248301819052925193169263caece2fe9260448084019391929182900301818387803b1580156128ed57600080fd5b505af1158015612901573d6000803e3d6000fd5b5050603c5460408051637d3572fd60e01b81526001600160a01b0388811660048301528781166024830152600060448301819052925193169450637d3572fd93506064808201939182900301818387803b1580156127dd57600080fd5b60005461010090046001600160a01b031633146129ac5760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b6129b582613c71565b6001600160a01b0382166000818152603660209081526040918290206002810180549086905583519485529184018290528383018590529151919290917f6c07964980a680dc12652ccab077a57c65740bf2ebc204a7670438051ee6fa5b9181900360600190a150505050565b6060818067ffffffffffffffff81118015612a3c57600080fd5b50604051908082528060200260200182016040528015612a66578160200160208202803683370190505b50915060005b81811015612abd57612a99858583818110612a8357fe5b905060200201356001600160a01b031633614657565b838281518110612aa557fe5b91151560209283029190910190910152600101612a6c565b505092915050565b6038546040805163fc57d4df60e01b81526001600160a01b03868116600483015291516000938493169163fc57d4df916024808301926020929190829003018186803b158015612b1457600080fd5b505afa158015612b28573d6000803e3d6000fd5b505050506040513d6020811015612b3e57600080fd5b50516038546040805163fc57d4df60e01b81526001600160a01b0388811660048301529151939450600093919092169163fc57d4df916024808301926020929190829003018186803b158015612b9357600080fd5b505afa158015612ba7573d6000803e3d6000fd5b505050506040513d6020811015612bbd57600080fd5b505190508115801590612bcf57508015155b612c0a5760405162461bcd60e51b815260040180806020018281038252602d815260200180614e3d602d913960400191505060405180910390fd5b603a54600090612c2490612c1e87866146e6565b90613c42565b90506000866001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015612c6157600080fd5b505afa158015612c75573d6000803e3d6000fd5b505050506040513d6020811015612c8b57600080fd5b50519050612ca383612c9d848461473f565b90614757565b98975050505050505050565b603b54600160a81b900460ff1615612d06576040805162461bcd60e51b815260206004820152601560248201527414d95a5e99481a185cc81899595b881c185d5cd959605a1b604482015290519081900360640190fd5b612d11603485613c2d565b8015612d235750612d23603486613c2d565b612d74576040805162461bcd60e51b815260206004820152601b60248201527f546f6b656e732068617665206e6f74206265656e206c69737465640000000000604482015290519081900360640190fd5b846001600160a01b031663f77c47916040518163ffffffff1660e01b815260040160206040518083038186803b158015612dad57600080fd5b505afa158015612dc1573d6000803e3d6000fd5b505050506040513d6020811015612dd757600080fd5b50516040805163f77c479160e01b815290516001600160a01b039283169287169163f77c4791916004808301926020929190829003018186803b158015612e1d57600080fd5b505afa158015612e31573d6000803e3d6000fd5b505050506040513d6020811015612e4757600080fd5b50516001600160a01b031614612e8e5760405162461bcd60e51b8152600401808060200182810382526033815260200180614cad6033913960400191505060405180910390fd5b603c5460408051636576717f60e11b81526001600160a01b038881166004830152600060248301819052925193169263caece2fe9260448084019391929182900301818387803b158015612ee157600080fd5b505af1158015612ef5573d6000803e3d6000fd5b5050603c5460408051637d3572fd60e01b81526001600160a01b038a811660048301528881166024830152600060448301819052925193169450637d3572fd93506064808201939182900301818387803b158015612f5257600080fd5b505af1158015612f66573d6000803e3d6000fd5b5050603c5460408051637d3572fd60e01b81526001600160a01b038a811660048301528781166024830152600060448301819052925193169450637d3572fd93506064808201939182900301818387803b15801561232b57600080fd5b6060818067ffffffffffffffff81118015612fdd57600080fd5b50604051908082528060200260200182016040528015613007578160200160208202803683370190505b50915060005b81811015612abd5761303a85858381811061302457fe5b905060200201356001600160a01b031633614799565b83828151811061304657fe5b9115156020928302919091019091015260010161300d565b6001600160a01b03821660009081526037602052604081206120a49083613c2d565b60005461010090046001600160a01b031633146130ce5760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b6130d782613c71565b6001600160a01b0382166000818152603660209081526040918290206003810180549086905583519485529184018290528383018590529151919290917f6ffc41eacf6bc473fab68880680a35214210358ff10d45c53cee339f1547f0bb9181900360600190a150505050565b60005461010090046001600160a01b031633146131925760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b856001600160a01b031663744279376040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156131cd57600080fd5b505af11580156131e1573d6000803e3d6000fd5b505050506040513d60208110156131f757600080fd5b5051613243576040805162461bcd60e51b8152602060048201526016602482015275151bdad95b881a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b61324e6034876148da565b61329f576040805162461bcd60e51b815260206004820152601d60248201527f546f6b656e2068617320616c7265616479206265656e206c6973746564000000604482015290519081900360640190fd5b670de0b6b3a76400008511156132f8576040805162461bcd60e51b815260206004820152601960248201527810dbdb1b185d195c985b08199858dd1bdc881a5b9d985b1a59603a1b604482015290519081900360640190fd5b6000841180156133105750670de0b6b3a76400008411155b613359576040805162461bcd60e51b8152602060048201526015602482015274109bdc9c9bddc8199858dd1bdc881a5b9d985b1a59605a1b604482015290519081900360640190fd5b6038546040805163fc57d4df60e01b81526001600160a01b0389811660048301529151919092169163fc57d4df916024808301926020929190829003018186803b1580156133a657600080fd5b505afa1580156133ba573d6000803e3d6000fd5b505050506040513d60208110156133d057600080fd5b5051613423576040805162461bcd60e51b815260206004820152601f60248201527f556e6465726c79696e6720707269636520697320756e617661696c61626c6500604482015290519081900360640190fd5b6040518060e001604052808681526020018581526020018381526020018481526020016000151581526020016000151581526020016000151581525060366000886001600160a01b03166001600160a01b031681526020019081526020016000206000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160040160016101000a81548160ff02191690831515021790555060c08201518160040160026101000a81548160ff021916908315150217905550905050603c60009054906101000a90046001600160a01b03166001600160a01b0316635658fec387836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561357b57600080fd5b505af115801561358f573d6000803e3d6000fd5b5050604080516001600160a01b038a16815260208101899052808201889052606081018790526080810186905260a0810185905290517f96f15e56d27d14b82ed736fd9387871d60f721cd59f324699722b4f0d11ee1b193509081900360c0019150a1505050505050565b600054819061010090046001600160a01b031633148061362c5750603b546001600160a01b03163314801561362c5750805b6136675760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b6034600061367482613c5a565b905060005b818110156110765761369461368e8483613c65565b8661449c565b600101613679565b600054819061010090046001600160a01b03163314806136ce5750603b546001600160a01b0316331480156136ce5750805b6137095760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b6034600061371682613c5a565b905060005b81811015611076576137366137308483613c65565b86614503565b60010161371b565b6001546001600160a01b031681565b60005461010090046001600160a01b0316331461379b5760405162461bcd60e51b8152600401808060200182810382526022815260200180614e1b6022913960400191505060405180910390fd5b6137a482613c71565b670de0b6b3a76400008111156137fd576040805162461bcd60e51b815260206004820152601960248201527810dbdb1b185d195c985b08199858dd1bdc881a5b9d985b1a59603a1b604482015290519081900360640190fd5b6038546040805163fc57d4df60e01b81526001600160a01b0385811660048301529151919092169163fc57d4df916024808301926020929190829003018186803b15801561384a57600080fd5b505afa15801561385e573d6000803e3d6000fd5b505050506040513d602081101561387457600080fd5b50516138b15760405162461bcd60e51b8152600401808060200182810382526040815260200180614e8c6040913960400191505060405180910390fd5b6001600160a01b038216600081815260366020908152604091829020805485825583519485529184018290528383018590529151919290917f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59181900360600190a150505050565b600054819061010090046001600160a01b031633148061394b5750603b546001600160a01b03163314801561394b5750805b6139865760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b6034600061399382613c5a565b905060005b81811015611076576139b36139ad8483613c65565b86613ccd565b600101613998565b60395481565b6139ca84613c71565b836001600160a01b03166395dd9193836040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015613a1757600080fd5b505afa158015613a2b573d6000803e3d6000fd5b505050506040513d6020811015613a4157600080fd5b50516112c257336001600160a01b03851614613a9c576040805162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba1031329034aa37b5b2b760591b604482015290519081900360640190fd5b6112c282856148ef565b600054819061010090046001600160a01b0316331480613ad85750603b546001600160a01b031633148015613ad85750805b613b135760405162461bcd60e51b815260040180806020018281038252603c815260200180614d54603c913960400191505060405180910390fd5b613b1c83613c71565b6111e48383613d3e565b603b54600160a01b900460ff1681565b6001546001600160a01b03163314613b7f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614ecc6025913960400191505060405180910390fd5b60008054600180546001600160a01b03818116610100818102610100600160a81b03198716178088556001600160a01b031990941690945560405194849004821695909493909204169184917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36001546040516001600160a01b03918216918316907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b60006120a4836001600160a01b038416614962565b60006120a4670de0b6b3a7640000612c9d85856146e6565b60006117d88261497a565b60006120a4838361497e565b613c7c603482613c2d565b612509576040805162461bcd60e51b815260206004820152601960248201527f546f6b656e20686173206e6f74206265656e206c697374656400000000000000604482015290519081900360640190fd5b6001600160a01b038216600081815260366020908152604091829020600401805462ff00001916620100008615159081029190911790915582519384529083015280517fa501bd5ac3de9924ce0c13576750267130fd835780f1ec6e1ae9fb13ee7465039281900390910190a15050565b6001600160a01b03821660008181526036602090815260409182902060048101805460ff1916861515908117909155835194855291840191909152815190927f48cff1fdfe035051f817c77855362a92f96f941342d41008f2d596f530c4e96b92908290030190a160048101805461ff00191661010084151590810291909117909155604080516001600160a01b0386168152602081019290925280517f3d95d87adcb06de16ac0e322ea97a06e30967fedcc83a6d1d0b9fda60300801a9281900390910190a160048101805462ff000019166201000084151590810291909117909155604080516001600160a01b0386168152602081019290925280517fa501bd5ac3de9924ce0c13576750267130fd835780f1ec6e1ae9fb13ee7465039281900390910190a1505050565b603b8054821515600160a01b810260ff60a01b199092169190911790915560408051918252517f7b92c580e5b53e34f85950f4117143b86c4031ca9568a3cd30f4b3cd5bb95dc89181900360200190a150565b603b8054821515600160a81b810260ff60a81b199092169190911790915560408051918252517fcaf79886b466b41f609cc39fdc375ab5484cc3811570b7faa22fcb2b55516fdf9181900360200190a150565b6001600160a01b0382166000908152603760205260409020613f3690600201826148da565b1561164b57604080516001600160a01b0380841682528416602082015281517f61400a0050615e96f6a4a234e4fc162ab71775345f32f4641cd884601603a455929181900390910190a15050565b600080600080613f92614c45565b6001600160a01b038916600090815260376020526040812090613fb482613c5a565b905060005b81811015614206576000613fcd8483613c65565b9050806001600160a01b03166370a082318e6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561401c57600080fd5b505afa158015614030573d6000803e3d6000fd5b505050506040513d602081101561404657600080fd5b5051604080870191909152805163182df0f560e01b815290516001600160a01b0383169163182df0f5916004808301926020929190829003018186803b15801561408f57600080fd5b505afa1580156140a3573d6000803e3d6000fd5b505050506040513d60208110156140b957600080fd5b505160808601526001600160a01b038c81169082161480156140db575060008b115b156140f55760408501516140ef908c6149e2565b60408601525b6038546040805163fc57d4df60e01b81526001600160a01b0384811660048301529151919092169163fc57d4df916024808301926020929190829003018186803b15801561414257600080fd5b505afa158015614156573d6000803e3d6000fd5b505050506040513d602081101561416c57600080fd5b505160a086018190526141b05760405162461bcd60e51b8152600401808060200182810382526029815260200180614d2b6029913960400191505060405180910390fd5b6001600160a01b0381166000908152603660205260409081902054608087015160a0880151928801516141e993612c1e929183916146e6565b60c0860181905285516141fb91614442565b855250600101613fb9565b5061421382600201613c5a565b905060005b818110156143fd57600061422f6002850183613c65565b9050806001600160a01b03166395dd91938e6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561427e57600080fd5b505afa158015614292573d6000803e3d6000fd5b505050506040513d60208110156142a857600080fd5b505160608601526001600160a01b038c81169082161480156142ca575060008a115b156142e45760608501516142de908b614442565b60608601525b6038546040805163fc57d4df60e01b81526001600160a01b0384811660048301529151919092169163fc57d4df916024808301926020929190829003018186803b15801561433157600080fd5b505afa158015614345573d6000803e3d6000fd5b505050506040513d602081101561435b57600080fd5b505160a0860181905261439f5760405162461bcd60e51b8152600401808060200182810382526029815260200180614d2b6029913960400191505060405180910390fd5b6001600160a01b03811660009081526036602052604090206001015460a086015160608701516143da92916143d491906146e6565b9061473f565b60e0860181905260208601516143ef91614442565b602086015250600101614218565b50602083015183511161441d57825160208401516000918082039161442d565b6020830151835181810391600091905b929e919d509b50909950975050505050505050565b6000828201838110156120a4576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b038216600081815260366020908152604091829020600401805460ff191685151590811790915582519384529083015280517f48cff1fdfe035051f817c77855362a92f96f941342d41008f2d596f530c4e96b9281900390910190a15050565b6001600160a01b038216600081815260366020908152604091829020600401805461ff0019166101008615159081029190911790915582519384529083015280517f3d95d87adcb06de16ac0e322ea97a06e30967fedcc83a6d1d0b9fda60300801a9281900390910190a15050565b61457b83613c71565b6001600160a01b038216600090815260376020526040902061459d9084613c2d565b6145a6576111e4565b60006145b58385846000613f84565b5050915050806000146112c2576040805162461bcd60e51b815260206004820152601a60248201527f4163636f756e742068617320736f6d652073686f727466616c6c000000000000604482015290519081900360640190fd5b60008054610100600160a81b0319163361010081029190911782556040519091907f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b2364908290a3565b6000614664603484613c2d565b614670575060006117d8565b6001600160a01b038216600090815260376020526040902061469290846148da565b156146dd57604080516001600160a01b0380861682528416602082015281517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5929181900390910190a15b50600192915050565b6000826146f5575060006117d8565b8282028284828161470257fe5b04146120a45760405162461bcd60e51b8152600401808060200182810382526021815260200180614dbe6021913960400191505060405180910390fd5b60006120a482612c9d85670de0b6b3a76400006146e6565b60006120a483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614a24565b60006147a6603484613c2d565b6147b2575060016117d8565b6001600160a01b03821660009081526037602052604090206147d49084613c2d565b6147e0575060016117d8565b6000836001600160a01b03166370a08231846040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561482f57600080fd5b505afa158015614843573d6000803e3d6000fd5b505050506040513d602081101561485957600080fd5b50519050614868848483614572565b6001600160a01b038316600090815260376020526040902061488a9085614ac6565b50604080516001600160a01b0380871682528516602082015281517fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d929181900390910190a15060019392505050565b60006120a4836001600160a01b038416614adb565b6001600160a01b03821660009081526037602052604090206149149060020182614ac6565b1561164b57604080516001600160a01b0380841682528416602082015281517f6df0340c4ae9990f4b8f3c3e0e5408dcf6ba2c086b92966dfdbbef1f2f052e1a929181900390910190a15050565b60009081526001919091016020526040902054151590565b5490565b815460009082106149c05760405162461bcd60e51b8152600401808060200182810382526022815260200180614c8b6022913960400191505060405180910390fd5b8260000182815481106149cf57fe5b9060005260206000200154905092915050565b60006120a483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b25565b60008183614ab05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614a75578181015183820152602001614a5d565b50505050905090810190601f168015614aa25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581614abc57fe5b0495945050505050565b60006120a4836001600160a01b038416614b7f565b6000614ae78383614962565b614b1d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556117d8565b5060006117d8565b60008184841115614b775760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614a75578181015183820152602001614a5d565b505050900390565b60008181526001830160205260408120548015614c3b5783546000198083019190810190600090879083908110614bb257fe5b9060005260206000200154905080876000018481548110614bcf57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080614bff57fe5b600190038181906000526020600020016000905590558660010160008781526020019081526020016000206000905560019450505050506117d8565b60009150506117d8565b6040518061010001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152509056fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473436f6e74726f6c6c6572206d69736d61746368206265747765656e20426f72726f77656420616e6420436f6c6c61746572616c5f73657450656e64696e674f776e65723a204e6577206f77656e722063616e206e6f74206265207a65726f206164647265737320616e64206f776e657220686173206265656e2073657421496e76616c696420707269636520746f2063616c63756c617465206163636f756e74206571756974794f6e6c79206f776e657220616e6420677561726469616e2063616e20706175736520616e64206f6e6c79206f776e65722063616e20756e7061757365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774661696c656420746f2073657420626f72726f7720666163746f722c20756e6465726c79696e6720707269636520697320756e617661696c61626c656f6e6c794f776e65723a2063616c6c6572206973206e6f7420746865206f776e6572426f72726f776564206f7220436f6c6c61746572616c20617373657420707269636520697320696e76616c6964526577617264204469737472696275746f72206164647265737320696e76616c69644661696c656420746f2073657420636f6c6c61746572616c20666163746f722c20756e6465726c79696e6720707269636520697320756e617661696c61626c655f6163636570744f776e65723a204f6e6c7920666f722070656e64696e67206f776e657221656e7465724d61726b657446726f6d69546f6b656e3a204f6e6c792063616e2062652063616c6c6564206279206120737570706f727465642069546f6b656e21a2646970667358221220e81953e16f374459748653e7caae0da1ae2623baceff193bedcf6c1cd10405f564736f6c634300060c0033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.