Contract Overview
Balance:
0 Ether
EtherValue:
$0.00
More Info
Txn Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x484a765a48aebf6cfee0dc18f4bd159dc963dc556ae994defd5912cbebb846c7 | 0x60806040 | 13847106 | 240 days 6 hrs ago | Wild Credit: Deployer | IN | Create: LendingPair | 0 Ether | 0.21207105 |
[ Download CSV Export ]
View more zero value Internal Transactions in Advanced View mode
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
LendingPair
Compiler Version
v0.8.6+commit.11564f7e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED // Copyright (c) WildCredit - All rights reserved // https://twitter.com/WildCredit pragma solidity 0.8.6; import "IERC20.sol"; import "IERC721.sol"; import "ILPTokenMaster.sol"; import "ILendingPair.sol"; import "ILendingController.sol"; import "IInterestRateModel.sol"; import "IUniswapV3Helper.sol"; import "INonfungiblePositionManagerSimple.sol"; import "Math.sol"; import "Clones.sol"; import "ReentrancyGuard.sol"; import "AddressLibrary.sol"; import "LPTokenMaster.sol"; import "ERC721Receivable.sol"; import "TransferHelper.sol"; contract LendingPair is ILendingPair, ReentrancyGuard, TransferHelper, ERC721Receivable { INonfungiblePositionManagerSimple internal constant positionManager = INonfungiblePositionManagerSimple(0xC36442b4a4522E871399CD717aBDD847Ab11FE88); IERC721 internal constant uniPositions = IERC721(0xC36442b4a4522E871399CD717aBDD847Ab11FE88); uint public constant LIQ_MIN_HEALTH = 1e18; uint private constant MIN_DECIMALS = 6; using AddressLibrary for address; using Clones for address; mapping (address => mapping (address => uint)) public override supplySharesOf; mapping (address => mapping (address => uint)) public debtSharesOf; mapping (address => uint) public pendingSystemFees; mapping (address => uint) public lastBlockAccrued; mapping (address => uint) public override totalSupplyShares; mapping (address => uint) public override totalSupplyAmount; mapping (address => uint) public override totalDebtShares; mapping (address => uint) public override totalDebtAmount; mapping (address => uint) public uniPosition; mapping (address => uint) private decimals; mapping (address => address) public override lpToken; IUniswapV3Helper private uniV3Helper; ILendingController public lendingController; address public feeRecipient; address public override tokenA; address public override tokenB; event Liquidation( address indexed account, address indexed repayToken, address indexed supplyToken, uint repayAmount, uint supplyAmount ); event Deposit(address indexed account, address indexed token, uint amount); event Withdraw(address indexed account, address indexed token, uint amount); event Borrow(address indexed account, address indexed token, uint amount); event Repay(address indexed account, address indexed token, uint amount); event CollectSystemFee(address indexed token, uint amount); event DepositUniPosition(address indexed account, uint positionID); event WithdrawUniPosition(address indexed account, uint positionID); modifier onlyLpToken() { require(lpToken[tokenA] == msg.sender || lpToken[tokenB] == msg.sender, "LendingController: caller must be LP token"); _; } function initialize( address _lpTokenMaster, address _lendingController, address _uniV3Helper, address _feeRecipient, address _tokenA, address _tokenB ) external override { require(tokenA == address(0), "LendingPair: already initialized"); lendingController = ILendingController(_lendingController); uniV3Helper = IUniswapV3Helper(_uniV3Helper); feeRecipient = _feeRecipient; tokenA = _tokenA; tokenB = _tokenB; lastBlockAccrued[tokenA] = block.number; lastBlockAccrued[tokenB] = block.number; decimals[tokenA] = IERC20(tokenA).decimals(); decimals[tokenB] = IERC20(tokenB).decimals(); require(decimals[tokenA] >= MIN_DECIMALS && decimals[tokenB] >= MIN_DECIMALS, "LendingPair: MIN_DECIMALS"); lpToken[tokenA] = _createLpToken(_lpTokenMaster, tokenA); lpToken[tokenB] = _createLpToken(_lpTokenMaster, tokenB); } // Deposit limits do not apply to Uniswap positions function depositUniPosition(address _account, uint _positionID) external nonReentrant { _checkDepositsEnabled(); _validateUniPosition(_positionID); require(_positionID > 0, "LendingPair: invalid position"); require(uniPosition[_account] == 0, "LendingPair: one position per account"); uniPositions.safeTransferFrom(msg.sender, address(this), _positionID); uniPosition[_account] = _positionID; emit DepositUniPosition(_account, _positionID); } function withdrawUniPosition() external nonReentrant { uint positionID = uniPosition[msg.sender]; require(positionID > 0, "LendingPair: nothing to withdraw"); uniPositions.safeTransferFrom(address(this), msg.sender, positionID); uniPosition[msg.sender] = 0; accrue(tokenA); accrue(tokenB); checkAccountHealth(msg.sender); emit WithdrawUniPosition(msg.sender, positionID); } // claim & mint supply from uniswap fees function uniClaimDeposit() external nonReentrant { accrue(tokenA); accrue(tokenB); (uint amountA, uint amountB) = _uniCollectFees(msg.sender); _mintSupplyAmount(tokenA, msg.sender, amountA); _mintSupplyAmount(tokenB, msg.sender, amountB); } // claim & withdraw uniswap fees function uniClaimWithdraw() external nonReentrant { (uint amountA, uint amountB) = _uniCollectFees(msg.sender); _safeTransfer(tokenA, msg.sender, amountA); _safeTransfer(tokenB, msg.sender, amountB); } function depositRepay(address _account, address _token, uint _amount) external nonReentrant { _validateToken(_token); accrue(_token); _depositRepay(_account, _token, _amount); _safeTransferFrom(_token, msg.sender, _amount); } function depositRepayETH(address _account) external payable nonReentrant { _validateToken(address(WETH)); accrue(address(WETH)); _depositRepay(_account, address(WETH), msg.value); _depositWeth(); } function deposit(address _account, address _token, uint _amount) external override nonReentrant { _validateToken(_token); accrue(_token); _deposit(_account, _token, _amount); _safeTransferFrom(_token, msg.sender, _amount); } function withdrawBorrow(address _token, uint _amount) external nonReentrant { _validateToken(_token); accrue(_token); _withdrawBorrow(_token, _amount); _safeTransfer(_token, msg.sender, _amount); } function withdrawBorrowETH(uint _amount) external nonReentrant { _validateToken(address(WETH)); accrue(address(WETH)); _withdrawBorrow(address(WETH), _amount); _wethWithdrawTo(msg.sender, _amount); } function withdraw(address _token, uint _amount) external override nonReentrant { _validateToken(_token); accrue(_token); _withdrawShares(_token, _supplyToShares(_token, _amount)); _safeTransfer(_token, msg.sender, _amount); } function withdrawAll(address _token) external override nonReentrant { _validateToken(_token); accrue(_token); uint shares = supplySharesOf[_token][msg.sender]; uint amount = _sharesToSupply(_token, shares); _withdrawShares(_token, shares); _safeTransfer(_token, msg.sender, amount); } function withdrawAllETH() external nonReentrant { _validateToken(address(WETH)); accrue(address(WETH)); uint shares = supplySharesOf[address(WETH)][msg.sender]; uint amount = _sharesToSupply(address(WETH), shares); _withdrawShares(address(WETH), shares); _wethWithdrawTo(msg.sender, amount); } function borrow(address _token, uint _amount) external nonReentrant { _validateToken(_token); accrue(_token); _borrow(_token, _amount); _safeTransfer(_token, msg.sender, _amount); } function repayAll(address _account, address _token, uint _maxAmount) external nonReentrant { _validateToken(_token); accrue(_token); uint amount = _repayShares(_account, _token, debtSharesOf[_token][_account]); require(amount <= _maxAmount, "LendingPair: amount <= _maxAmount"); _safeTransferFrom(_token, msg.sender, amount); } function repayAllETH(address _account) external payable nonReentrant { _validateToken(address(WETH)); accrue(address(WETH)); uint amount = _repayShares(_account, address(WETH), debtSharesOf[address(WETH)][_account]); require(msg.value >= amount, "LendingPair: insufficient ETH deposit"); _depositWeth(); uint refundAmount = msg.value > amount ? (msg.value - amount) : 0; if (refundAmount > 0) { _wethWithdrawTo(msg.sender, refundAmount); } } function repay(address _account, address _token, uint _amount) external nonReentrant { _validateToken(_token); accrue(_token); _repayShares(_account, _token, _debtToShares(_token, _amount)); _safeTransferFrom(_token, msg.sender, _amount); } function accrue(address _token) public { if (lastBlockAccrued[_token] < block.number) { uint newDebt = _accrueDebt(_token); uint newSupply = newDebt * _lpRate(_token) / 100e18; totalSupplyAmount[_token] += newSupply; pendingSystemFees[_token] += (newDebt - newSupply); lastBlockAccrued[_token] = block.number; } } function collectSystemFee(address _token, uint _amount) external nonReentrant { _validateToken(_token); pendingSystemFees[_token] -= _amount; _safeTransfer(_token, feeRecipient, _amount); emit CollectSystemFee(_token, _amount); } function transferLp(address _token, address _from, address _to, uint _amount) external override onlyLpToken { require(debtSharesOf[_token][_to] == 0, "LendingPair: cannot receive borrowed token"); supplySharesOf[_token][_from] -= _amount; supplySharesOf[_token][_to] += _amount; checkAccountHealth(_from); } // Sell collateral to reduce debt and increase accountHealth // Set _repayAmount to type(uint).max to repay all debt, inc. pending interest function liquidateAccount( address _account, address _repayToken, uint _repayAmount, uint _minSupplyOutput ) external nonReentrant { // Input validation and adjustments _validateToken(_repayToken); address supplyToken = _repayToken == tokenA ? tokenB : tokenA; // Check account is underwater after interest accrue(supplyToken); accrue(_repayToken); uint health = accountHealth(_account); require(health < LIQ_MIN_HEALTH, "LendingPair: account health < LIQ_MIN_HEALTH"); // Fully unwrap Uni position - withdraw & mint supply _unwrapUniPosition(_account); // Calculate balance adjustments _repayAmount = Math.min(_repayAmount, _debtOf(_repayToken, _account)); (uint repayPrice, uint supplyPrice) = lendingController.tokenPrices(_repayToken, supplyToken); uint supplyDebt = _convertTokenValues(_repayToken, supplyToken, _repayAmount, repayPrice, supplyPrice); uint callerFee = supplyDebt * lendingController.liqFeeCaller(_repayToken) / 100e18; uint systemFee = supplyDebt * lendingController.liqFeeSystem(_repayToken) / 100e18; uint supplyBurn = supplyDebt + callerFee + systemFee; uint supplyOutput = supplyDebt + callerFee; require(supplyOutput >= _minSupplyOutput, "LendingPair: supplyOutput >= _minSupplyOutput"); // Adjust balances _burnSupplyShares(supplyToken, _account, _supplyToShares(supplyToken, supplyBurn)); pendingSystemFees[supplyToken] += systemFee; _burnDebtShares(_repayToken, _account, _debtToShares(_repayToken, _repayAmount)); // Uni position unwrapping can mint supply of already borrowed tokens _repayDebtFromSupply(_account, tokenA); _repayDebtFromSupply(_account, tokenB); // Settle token transfers _safeTransferFrom(_repayToken, msg.sender, _repayAmount); _mintSupplyAmount(supplyToken, msg.sender, supplyOutput); emit Liquidation(_account, _repayToken, supplyToken, _repayAmount, supplyOutput); } // Compare all supply & borrow balances converted into the the same token - tokenA function accountHealth(address _account) public view returns(uint) { if (debtSharesOf[tokenA][_account] == 0 && debtSharesOf[tokenB][_account] == 0) { return LIQ_MIN_HEALTH; } (uint priceA, uint priceB) = lendingController.tokenPrices(tokenA, tokenB); uint colFactorA = lendingController.colFactor(tokenA); uint colFactorB = lendingController.colFactor(tokenB); uint creditA = _supplyOf(tokenA, _account) * colFactorA / 100e18; uint creditB = _supplyBalanceConverted(_account, tokenB, tokenA, priceB, priceA) * colFactorB / 100e18; uint creditUni = _convertedCreditAUni(_account, priceA, priceB, colFactorA, colFactorB); uint totalAccountSupply = creditA + creditB + creditUni; uint totalAccountBorrow = _debtOf(tokenA, _account) + _borrowBalanceConverted(_account, tokenB, tokenA, priceB, priceA); return totalAccountSupply * 1e18 / totalAccountBorrow; } function debtOf(address _token, address _account) external view returns(uint) { _validateToken(_token); return _debtOf(_token, _account); } function supplyOf(address _token, address _account) external view override returns(uint) { _validateToken(_token); return _supplyOf(_token, _account); } // Get borow balance converted to the units of _returnToken function borrowBalanceConverted( address _account, address _borrowedToken, address _returnToken ) external view returns(uint) { _validateToken(_borrowedToken); _validateToken(_returnToken); (uint borrowPrice, uint returnPrice) = lendingController.tokenPrices(_borrowedToken, _returnToken); return _borrowBalanceConverted(_account, _borrowedToken, _returnToken, borrowPrice, returnPrice); } function supplyBalanceConverted( address _account, address _suppliedToken, address _returnToken ) external view override returns(uint) { _validateToken(_suppliedToken); _validateToken(_returnToken); (uint supplyPrice, uint returnPrice) = lendingController.tokenPrices(_suppliedToken, _returnToken); return _supplyBalanceConverted(_account, _suppliedToken, _returnToken, supplyPrice, returnPrice); } function supplyRatePerBlock(address _token) external view returns(uint) { _validateToken(_token); if (totalSupplyAmount[_token] == 0 || totalDebtAmount[_token] == 0) { return 0; } uint utilizationRate = totalDebtAmount[_token] * 100e18 / totalSupplyAmount[_token]; return _interestRatePerBlock(_token) * utilizationRate * _lpRate(_token) / 100e18 / 100e18; } function borrowRatePerBlock(address _token) external view returns(uint) { _validateToken(_token); return _interestRatePerBlock(_token); } function checkAccountHealth(address _account) public view { uint health = accountHealth(_account); require(health >= LIQ_MIN_HEALTH, "LendingPair: insufficient accountHealth"); } function convertTokenValues( address _fromToken, address _toToken, uint _inputAmount ) external view returns(uint) { _validateToken(_fromToken); _validateToken(_toToken); (uint fromPrice, uint toPrice) = lendingController.tokenPrices(_fromToken, _toToken); return _convertTokenValues(_fromToken, _toToken, _inputAmount, fromPrice, toPrice); } function _depositRepay(address _account, address _token, uint _amount) internal { uint debt = _debtOf(_token, _account); uint repayAmount = debt > _amount ? _amount : debt; uint depositAmount = _amount - repayAmount; if (repayAmount > 0) { _repayShares(_account, _token, _debtToShares(_token, repayAmount)); } if (depositAmount > 0) { _deposit(_account, _token, depositAmount); } } function _withdrawBorrow(address _token, uint _amount) internal { uint supplyAmount = _supplyOf(_token, msg.sender); uint withdrawAmount = supplyAmount > _amount ? _amount : supplyAmount; uint borrowAmount = _amount - withdrawAmount; if (withdrawAmount > 0) { _withdrawShares(_token, _supplyToShares(_token, withdrawAmount)); } if (borrowAmount > 0) { _borrow(_token, borrowAmount); } } // Uses price oracle to estimate min outputs to reduce MEV // Liquidation might be temporarily unavailable due to this function _unwrapUniPosition(address _account) internal { if (uniPosition[_account] > 0) { (uint priceA, uint priceB) = lendingController.tokenPrices(tokenA, tokenB); (uint amount0, uint amount1) = _positionAmounts(uniPosition[_account], priceA, priceB); uint uniMinOutput = lendingController.uniMinOutputPct(); uniPositions.approve(address(uniV3Helper), uniPosition[_account]); (uint amountA, uint amountB) = uniV3Helper.removeLiquidity( uniPosition[_account], amount0 * uniMinOutput / 100e18, amount1 * uniMinOutput / 100e18 ); uniPosition[_account] = 0; _mintSupplyAmount(tokenA, _account, amountA); _mintSupplyAmount(tokenB, _account, amountB); } } // Ensure we never have borrow + supply balances of the same token on the same account function _repayDebtFromSupply(address _account, address _token) internal { uint burnAmount = Math.min(_debtOf(_token, _account), _supplyOf(_token, _account)); if (burnAmount > 0) { _burnDebtShares(_token, _account, _debtToShares(_token, burnAmount)); _burnSupplyShares(_token, _account, _supplyToShares(_token, burnAmount)); } } function _uniCollectFees(address _account) internal returns(uint, uint) { uniPositions.approve(address(uniV3Helper), uniPosition[_account]); return uniV3Helper.collectFees(uniPosition[_account]); } function _mintSupplyAmount(address _token, address _account, uint _amount) internal returns(uint shares) { if (_amount > 0) { shares = _supplyToShares(_token, _amount); supplySharesOf[_token][_account] += shares; totalSupplyShares[_token] += shares; totalSupplyAmount[_token] += _amount; } } function _burnSupplyShares(address _token, address _account, uint _shares) internal returns(uint amount) { if (_shares > 0) { // Fix rounding error which can make issues during depositRepay / withdrawBorrow if (supplySharesOf[_token][_account] - _shares == 1) { _shares += 1; } amount = _sharesToSupply(_token, _shares); supplySharesOf[_token][_account] -= _shares; totalSupplyShares[_token] -= _shares; totalSupplyAmount[_token] -= amount; } } function _mintDebtAmount(address _token, address _account, uint _amount) internal returns(uint shares) { if (_amount > 0) { shares = _debtToShares(_token, _amount); debtSharesOf[_token][_account] += shares; totalDebtShares[_token] += shares; totalDebtAmount[_token] += _amount; } } function _burnDebtShares(address _token, address _account, uint _shares) internal returns(uint amount) { if (_shares > 0) { // Fix rounding error which can make issues during depositRepay / withdrawBorrow if (debtSharesOf[_token][_account] - _shares == 1) { _shares += 1; } amount = _sharesToDebt(_token, _shares); debtSharesOf[_token][_account] -= _shares; totalDebtShares[_token] -= _shares; totalDebtAmount[_token] -= amount; } } function _accrueDebt(address _token) internal returns(uint newDebt) { if (totalDebtAmount[_token] > 0) { uint blocksElapsed = block.number - lastBlockAccrued[_token]; uint pendingInterestRate = _interestRatePerBlock(_token) * blocksElapsed; newDebt = totalDebtAmount[_token] * pendingInterestRate / 100e18; totalDebtAmount[_token] += newDebt; } } function _withdrawShares(address _token, uint _shares) internal { uint amount = _burnSupplyShares(_token, msg.sender, _shares); checkAccountHealth(msg.sender); emit Withdraw(msg.sender, _token, amount); } function _borrow(address _token, uint _amount) internal { require(supplySharesOf[_token][msg.sender] == 0, "LendingPair: cannot borrow supplied token"); _checkBorrowEnabled(); _checkBorrowLimits(_token, msg.sender, _amount); _mintDebtAmount(_token, msg.sender, _amount); checkAccountHealth(msg.sender); emit Borrow(msg.sender, _token, _amount); } function _repayShares(address _account, address _token, uint _shares) internal returns(uint amount) { amount = _burnDebtShares(_token, _account, _shares); emit Repay(_account, _token, amount); } function _deposit(address _account, address _token, uint _amount) internal { require(debtSharesOf[_token][_account] == 0, "LendingPair: cannot deposit borrowed token"); _checkDepositsEnabled(); _checkDepositLimit(_token, _amount); _mintSupplyAmount(_token, _account, _amount); emit Deposit(_account, _token, _amount); } function _createLpToken(address _lpTokenMaster, address _underlying) internal returns(address) { ILPTokenMaster newLPToken = ILPTokenMaster(_lpTokenMaster.clone()); newLPToken.initialize(_underlying, address(lendingController)); return address(newLPToken); } function _amountToShares(uint _totalShares, uint _totalAmount, uint _inputSupply) internal view returns(uint) { if (_totalShares > 0 && _totalAmount > 0) { return _inputSupply * _totalShares / _totalAmount; } else { return _inputSupply; } } function _sharesToAmount(uint _totalShares, uint _totalAmount, uint _inputShares) internal view returns(uint) { if (_totalShares > 0 && _totalAmount > 0) { return _inputShares * _totalAmount / _totalShares; } else { return _inputShares; } } function _debtToShares(address _token, uint _amount) internal view returns(uint) { return _amountToShares(totalDebtShares[_token], totalDebtAmount[_token], _amount); } function _sharesToDebt(address _token, uint _shares) internal view returns(uint) { return _sharesToAmount(totalDebtShares[_token], totalDebtAmount[_token], _shares); } function _supplyToShares(address _token, uint _amount) internal view returns(uint) { return _amountToShares(totalSupplyShares[_token], totalSupplyAmount[_token], _amount); } function _sharesToSupply(address _token, uint _shares) internal view returns(uint) { return _sharesToAmount(totalSupplyShares[_token], totalSupplyAmount[_token], _shares); } function _debtOf(address _token, address _account) internal view returns(uint) { return _sharesToDebt(_token, debtSharesOf[_token][_account]); } function _supplyOf(address _token, address _account) internal view returns(uint) { return _sharesToSupply(_token, supplySharesOf[_token][_account]); } function _interestRatePerBlock(address _token) internal view returns(uint) { return _interestRateModel().interestRatePerBlock( address(this), _token, totalSupplyAmount[_token], totalDebtAmount[_token] ); } function _interestRateModel() internal view returns(IInterestRateModel) { return IInterestRateModel(lendingController.interestRateModel()); } // Get borrow balance converted to the units of _returnToken function _borrowBalanceConverted( address _account, address _borrowedToken, address _returnToken, uint _borrowPrice, uint _returnPrice ) internal view returns(uint) { return _convertTokenValues( _borrowedToken, _returnToken, _debtOf(_borrowedToken, _account), _borrowPrice, _returnPrice ); } // Get supply balance converted to the units of _returnToken function _supplyBalanceConverted( address _account, address _suppliedToken, address _returnToken, uint _supplyPrice, uint _returnPrice ) internal view returns(uint) { return _convertTokenValues( _suppliedToken, _returnToken, _supplyOf(_suppliedToken, _account), _supplyPrice, _returnPrice ); } function _convertedCreditAUni( address _account, uint _priceA, uint _priceB, uint _colFactorA, uint _colFactorB ) internal view returns(uint) { if (uniPosition[_account] > 0) { (uint amountA, uint amountB) = _positionAmounts(uniPosition[_account], _priceA, _priceB); uint creditA = amountA * _colFactorA / 100e18; uint creditB = _convertTokenValues(tokenB, tokenA, amountB, _priceB, _priceA) * _colFactorB / 100e18; return (creditA + creditB); } else { return 0; } } function _positionAmounts( uint _position, uint _priceA, uint _priceB ) internal view returns(uint, uint) { uint priceA = 1 * 10 ** decimals[tokenB]; uint priceB = _priceB * 10 ** decimals[tokenA] / _priceA; return uniV3Helper.positionAmounts(_position, priceA, priceB); } // Not calling priceOracle.convertTokenValues() to save gas by reusing already fetched prices function _convertTokenValues( address _fromToken, address _toToken, uint _inputAmount, uint _fromPrice, uint _toPrice ) internal view returns(uint) { uint fromPrice = _fromPrice * 1e18 / 10 ** decimals[_fromToken]; uint toPrice = _toPrice * 1e18 / 10 ** decimals[_toToken]; return _inputAmount * fromPrice / toPrice; } function _validateToken(address _token) internal view { require(_token == tokenA || _token == tokenB, "LendingPair: invalid token"); } function _validateUniPosition(uint _positionID) internal view { (, , address uniTokenA, address uniTokenB, , , , uint liquidity, , , ,) = positionManager.positions(_positionID); require(liquidity > 0, "LendingPair: liquidity > 0"); _validateToken(uniTokenA); _validateToken(uniTokenB); } function _checkDepositsEnabled() internal view { require(lendingController.depositsEnabled(), "LendingPair: deposits disabled"); } function _checkBorrowEnabled() internal view { require(lendingController.borrowingEnabled(), "LendingPair: borrowing disabled"); } function _checkDepositLimit(address _token, uint _amount) internal view { uint depositLimit = lendingController.depositLimit(address(this), _token); if (depositLimit > 0) { require( totalSupplyAmount[_token] + _amount <= depositLimit, "LendingPair: deposit limit reached" ); } } function _checkBorrowLimits(address _token, address _account, uint _amount) internal view { require( _debtOf(_token, _account) + _amount >= lendingController.minBorrow(_token), "LendingPair: borrow amount below minimum" ); uint borrowLimit = lendingController.borrowLimit(address(this), _token); if (borrowLimit > 0) { require(totalDebtAmount[_token] + _amount <= borrowLimit, "LendingPair: borrow limit reached"); } } function _lpRate(address _token) internal view returns(uint) { return _interestRateModel().lpRate(address(this), _token); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.7.0; interface IERC20 { function totalSupply() external view returns (uint); function balanceOf(address account) external view returns(uint); function transfer(address recipient, uint256 amount) external returns(bool); function allowance(address owner, address spender) external view returns(uint); function decimals() external view returns(uint8); function approve(address spender, uint amount) external returns(bool); function transferFrom(address sender, address recipient, uint amount) external returns(bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; interface IERC721 { function approve(address to, uint tokenId) external; function ownerOf(uint _tokenId) external view returns (address); function safeTransferFrom( address from, address to, uint tokenId ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; import "IOwnable.sol"; import "IERC20.sol"; interface ILPTokenMaster is IOwnable, IERC20 { function initialize(address _underlying, address _lendingController) external; function underlying() external view returns(address); function lendingPair() external view returns(address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; interface IOwnable { function owner() external view returns(address); function transferOwnership(address _newOwner) external; function acceptOwnership() external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; interface ILendingPair { function tokenA() external view returns(address); function tokenB() external view returns(address); function lpToken(address _token) external view returns(address); function deposit(address _account, address _token, uint _amount) external; function withdraw(address _token, uint _amount) external; function withdrawAll(address _token) external; function transferLp(address _token, address _from, address _to, uint _amount) external; function supplySharesOf(address _token, address _account) external view returns(uint); function totalSupplyShares(address _token) external view returns(uint); function totalSupplyAmount(address _token) external view returns(uint); function totalDebtShares(address _token) external view returns(uint); function totalDebtAmount(address _token) external view returns(uint); function supplyOf(address _token, address _account) external view returns(uint); function supplyBalanceConverted( address _account, address _suppliedToken, address _returnToken ) external view returns(uint); function initialize( address _lpTokenMaster, address _lendingController, address _uniV3Helper, address _feeRecipient, address _tokenA, address _tokenB ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; import "IOwnable.sol"; interface ILendingController is IOwnable { function interestRateModel() external view returns(address); function liqFeeSystem(address _token) external view returns(uint); function liqFeeCaller(address _token) external view returns(uint); function uniMinOutputPct() external view returns(uint); function colFactor(address _token) external view returns(uint); function depositLimit(address _lendingPair, address _token) external view returns(uint); function borrowLimit(address _lendingPair, address _token) external view returns(uint); function depositsEnabled() external view returns(bool); function borrowingEnabled() external view returns(bool); function tokenPrice(address _token) external view returns(uint); function minBorrow(address _token) external view returns(uint); function tokenPrices(address _tokenA, address _tokenB) external view returns (uint, uint); function tokenSupported(address _token) external view returns(bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; interface IInterestRateModel { function lpRate(address _pair, address _token) external view returns(uint); function interestRatePerBlock(address _pair, address _token, uint _totalSupply, uint _totalDebt) external view returns(uint); }
// SPDX-License-Identifier: UNLICENSED pragma solidity >0.7.0; interface IUniswapV3Helper { function removeLiquidity(uint _tokenId, uint _minOutput0, uint _minOutput1) external returns (uint, uint); function collectFees(uint _tokenId) external returns (uint amount0, uint amount1); function positionTokens(uint _tokenId) external view returns(address, address); function positionAmounts(uint _tokenId, uint _price0, uint _price1) external view returns(uint, uint); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; // We can't use full INonfungiblePositionManager as provided by Uniswap since it's on Solidity 0.7 interface INonfungiblePositionManagerSimple { function positions(uint256 tokenId) external view returns ( uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1 ); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.6; library Math { function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute. return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); } function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a / b + (a % b == 0 ? 0 : 1); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.6; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. * * _Available since v3.4._ */ library Clones { /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`. * * This function uses the create opcode, which should never revert. */ function clone(address master) internal returns (address instance) { // solhint-disable-next-line no-inline-assembly assembly { let ptr := mload(0x40) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(ptr, 0x14), shl(0x60, master)) mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) instance := create(0, ptr, 0x37) } require(instance != address(0), "ERC1167: create failed"); } /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `master`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `master` and `salt` multiple time will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address master, bytes32 salt) internal returns (address instance) { // solhint-disable-next-line no-inline-assembly assembly { let ptr := mload(0x40) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(ptr, 0x14), shl(0x60, master)) mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) instance := create2(0, ptr, 0x37, salt) } require(instance != address(0), "ERC1167: create2 failed"); } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress(address master, bytes32 salt, address deployer) internal pure returns (address predicted) { // solhint-disable-next-line no-inline-assembly assembly { let ptr := mload(0x40) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(ptr, 0x14), shl(0x60, master)) mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000) mstore(add(ptr, 0x38), shl(0x60, deployer)) mstore(add(ptr, 0x4c), salt) mstore(add(ptr, 0x6c), keccak256(ptr, 0x37)) predicted := keccak256(add(ptr, 0x37), 0x55) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress(address master, bytes32 salt) internal view returns (address predicted) { return predictDeterministicAddress(master, salt, address(this)); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; contract ReentrancyGuard { uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () { _status = _NOT_ENTERED; } modifier nonReentrant() { require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); _status = _ENTERED; _; _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /** * @dev Collection of functions related to the address type */ library AddressLibrary { /** * @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); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(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: UNLICENSED // Copyright (c) WildCredit - All rights reserved // https://twitter.com/WildCredit pragma solidity 0.8.6; import "ILPTokenMaster.sol"; import "ILendingPair.sol"; import "ILendingController.sol"; import "SafeOwnable.sol"; contract LPTokenMaster is ILPTokenMaster, SafeOwnable { event Transfer(address indexed from, address indexed to, uint value); event Approval(address indexed owner, address indexed spender, uint value); event NameChange(string _name, string _symbol); mapping (address => mapping (address => uint)) public override allowance; address public override underlying; address public lendingController; string public constant name = "WILD-LP"; string public constant symbol = "WILD-LP"; uint8 public constant override decimals = 18; bool private initialized; modifier onlyOperator() { require(msg.sender == ILendingController(lendingController).owner(), "LPToken: caller is not an operator"); _; } function initialize(address _underlying, address _lendingController) external override { require(initialized != true, "LPToken: already intialized"); owner = msg.sender; underlying = _underlying; lendingController = _lendingController; initialized = true; } function transfer(address _recipient, uint _amount) external override returns(bool) { _transfer(msg.sender, _recipient, _amount); return true; } function approve(address _spender, uint _amount) external override returns(bool) { _approve(msg.sender, _spender, _amount); return true; } function transferFrom(address _sender, address _recipient, uint _amount) external override returns(bool) { _approve(_sender, msg.sender, allowance[_sender][msg.sender] - _amount); _transfer(_sender, _recipient, _amount); return true; } function lendingPair() external view override returns(address) { return owner; } function balanceOf(address _account) external view override returns(uint) { return ILendingPair(owner).supplySharesOf(underlying, _account); } function totalSupply() external view override returns(uint) { return ILendingPair(owner).totalSupplyShares(underlying); } function _transfer(address _sender, address _recipient, uint _amount) internal { require(_sender != address(0), "ERC20: transfer from the zero address"); require(_recipient != address(0), "ERC20: transfer to the zero address"); ILendingPair(owner).transferLp(underlying, _sender, _recipient, _amount); emit Transfer(_sender, _recipient, _amount); } function _approve(address _owner, address _spender, uint _amount) internal { require(_owner != address(0), "ERC20: approve from the zero address"); require(_spender != address(0), "ERC20: approve to the zero address"); allowance[_owner][_spender] = _amount; emit Approval(_owner, _spender, _amount); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; import "IOwnable.sol"; contract SafeOwnable is IOwnable { uint public constant RENOUNCE_TIMEOUT = 1 hours; address public override owner; address public pendingOwner; uint public renouncedAt; event OwnershipTransferInitiated(address indexed previousOwner, address indexed newOwner); event OwnershipTransferConfirmed(address indexed previousOwner, address indexed newOwner); constructor() { owner = msg.sender; emit OwnershipTransferConfirmed(address(0), msg.sender); } modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } function isOwner() public view returns (bool) { return msg.sender == owner; } function transferOwnership(address _newOwner) external override onlyOwner { require(_newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferInitiated(owner, _newOwner); pendingOwner = _newOwner; } function acceptOwnership() external override { require(msg.sender == pendingOwner, "Ownable: caller is not pending owner"); emit OwnershipTransferConfirmed(msg.sender, pendingOwner); owner = pendingOwner; pendingOwner = address(0); } function initiateRenounceOwnership() external onlyOwner { require(renouncedAt == 0, "Ownable: already initiated"); renouncedAt = block.timestamp; } function acceptRenounceOwnership() external onlyOwner { require(renouncedAt > 0, "Ownable: not initiated"); require(block.timestamp - renouncedAt > RENOUNCE_TIMEOUT, "Ownable: too early"); owner = address(0); pendingOwner = address(0); renouncedAt = 0; } function cancelRenounceOwnership() external onlyOwner { require(renouncedAt > 0, "Ownable: not initiated"); renouncedAt = 0; } }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) WildCredit - All rights reserved // https://twitter.com/WildCredit pragma solidity >0.7.0; contract ERC721Receivable { function onERC721Received( address _operator, address _user, uint _tokenId, bytes memory _data ) public returns (bytes4) { return 0x150b7a02; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.6; import "IWETH.sol"; import "IERC20.sol"; import "SafeERC20.sol"; contract TransferHelper { using SafeERC20 for IERC20; // Mainnet IWETH internal constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); // Goerli // IWETH internal constant WETH = IWETH(0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6); function _safeTransferFrom(address _token, address _sender, uint _amount) internal { require(_amount > 0, "TransferHelper: amount must be > 0"); IERC20(_token).safeTransferFrom(_sender, address(this), _amount); } function _safeTransfer(address _token, address _recipient, uint _amount) internal { require(_amount > 0, "TransferHelper: amount must be > 0"); IERC20(_token).safeTransfer(_recipient, _amount); } function _wethWithdrawTo(address _to, uint _amount) internal { require(_amount > 0, "TransferHelper: amount must be > 0"); require(_to != address(0), "TransferHelper: invalid recipient"); WETH.withdraw(_amount); (bool success, ) = _to.call { value: _amount }(new bytes(0)); require(success, 'TransferHelper: ETH transfer failed'); } function _depositWeth() internal { require(msg.value > 0, "TransferHelper: amount must be > 0"); WETH.deposit { value: msg.value }(); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.6; import "IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint wad) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; import "IERC20.sol"; import "SafeMath.sol"; import "AddressLibrary.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using AddressLibrary for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // 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(IERC20 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(IERC20 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(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // 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; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @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) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @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) { 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, reverting 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) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting 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) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * 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); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * 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); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * 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; } }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CollectSystemFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"positionID","type":"uint256"}],"name":"DepositUniPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"repayToken","type":"address"},{"indexed":true,"internalType":"address","name":"supplyToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supplyAmount","type":"uint256"}],"name":"Liquidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Repay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"positionID","type":"uint256"}],"name":"WithdrawUniPosition","type":"event"},{"inputs":[],"name":"LIQ_MIN_HEALTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"accountHealth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"accrue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_borrowedToken","type":"address"},{"internalType":"address","name":"_returnToken","type":"address"}],"name":"borrowBalanceConverted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"borrowRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"checkAccountHealth","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"collectSystemFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fromToken","type":"address"},{"internalType":"address","name":"_toToken","type":"address"},{"internalType":"uint256","name":"_inputAmount","type":"uint256"}],"name":"convertTokenValues","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"debtOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"debtSharesOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositRepay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"depositRepayETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_positionID","type":"uint256"}],"name":"depositUniPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_lpTokenMaster","type":"address"},{"internalType":"address","name":"_lendingController","type":"address"},{"internalType":"address","name":"_uniV3Helper","type":"address"},{"internalType":"address","name":"_feeRecipient","type":"address"},{"internalType":"address","name":"_tokenA","type":"address"},{"internalType":"address","name":"_tokenB","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastBlockAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lendingController","outputs":[{"internalType":"contract ILendingController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_repayToken","type":"address"},{"internalType":"uint256","name":"_repayAmount","type":"uint256"},{"internalType":"uint256","name":"_minSupplyOutput","type":"uint256"}],"name":"liquidateAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lpToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingSystemFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_maxAmount","type":"uint256"}],"name":"repayAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"repayAllETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_suppliedToken","type":"address"},{"internalType":"address","name":"_returnToken","type":"address"}],"name":"supplyBalanceConverted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"supplyOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"supplyRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"supplySharesOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalDebtAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalDebtShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalSupplyAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalSupplyShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferLp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniClaimDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniClaimWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"uniPosition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAllETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawBorrowETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawUniPosition","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506001600055614b61806100256000396000f3fe60806040526004361061027d5760003560e01c80636af0a9ae1161014f57806391a50ee1116100c1578063cbaa354d1161007a578063cbaa354d1461082a578063cc2a9a5b1461084a578063ed5ab17c1461086a578063f3fef3a31461088a578063fa09e630146108aa578063fcccc83b146108ca57600080fd5b806391a50ee11461076c578063954755401461078c578063a790f7ab146107a8578063ac23cb21146107c8578063bd326bd0146107e8578063c9e2ed2b146107fd57600080fd5b806382e5ea361161011357806382e5ea36146106c45780638340f549146106e45780638800304e146107045780638b96b280146107175780638bf78f5a1461073757806390386bbf1461075757600080fd5b80636af0a9ae146105f45780636f16ca851461062157806376a562a41461064e5780637f9358a214610684578063808355bf146106a457600080fd5b8063360d6d57116101f35780634b8a3529116101ac5780634b8a35291461050f5780634c4ab1691461052f5780634d5553f41461054f5780635f64b55b1461058757806365a5b9cb146105a75780636680ac0b146105d457600080fd5b8063360d6d571461044f57806344b7cd5a14610464578063469048401461048457806347702768146104a45780634849d50e146104dc57806348632718146104ef57600080fd5b80631f7e8dd9116102455780631f7e8dd91461038057806325fd7bc814610395578063270eaa4d146103b55780632cff767e146103d55780632e977621146103f55780632f847fbe1461042257600080fd5b806307b298c51461028257806308c61c3c146102c25780630fc63d10146102e4578063150b7a021461031c5780631da649cf14610360575b600080fd5b34801561028e57600080fd5b506102af61029d3660046143c1565b60056020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156102ce57600080fd5b506102e26102dd3660046146b9565b6108ea565b005b3480156102f057600080fd5b50600f54610304906001600160a01b031681565b6040516001600160a01b0390911681526020016102b9565b34801561032857600080fd5b50610347610337366004614593565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016102b9565b34801561036c57600080fd5b506102e261037b366004614552565b610aba565b34801561038c57600080fd5b506102e2610b1e565b3480156103a157600080fd5b506102e26103b0366004614707565b610c93565b3480156103c157600080fd5b506102af6103d0366004614552565b610d13565b3480156103e157600080fd5b506102e26103f0366004614552565b610dca565b34801561040157600080fd5b506102af6104103660046143c1565b60096020526000908152604090205481565b34801561042e57600080fd5b506102af61043d3660046143c1565b60086020526000908152604090205481565b34801561045b57600080fd5b506102e2610e1a565b34801561047057600080fd5b506102e261047f366004614552565b610e8a565b34801561049057600080fd5b50600e54610304906001600160a01b031681565b3480156104b057600080fd5b506102af6104bf3660046143fb565b600260209081526000928352604080842090915290825290205481565b6102e26104ea3660046143c1565b610f6b565b3480156104fb57600080fd5b50600d54610304906001600160a01b031681565b34801561051b57600080fd5b506102e261052a3660046146b9565b6110a8565b34801561053b57600080fd5b506102af61054a3660046143fb565b6110f7565b34801561055b57600080fd5b506102af61056a3660046143fb565b600160209081526000928352604080842090915290825290205481565b34801561059357600080fd5b50601054610304906001600160a01b031681565b3480156105b357600080fd5b506102af6105c23660046143c1565b60076020526000908152604090205481565b3480156105e057600080fd5b506102e26105ef3660046143c1565b611115565b34801561060057600080fd5b506102af61060f3660046143c1565b60066020526000908152604090205481565b34801561062d57600080fd5b506102af61063c3660046143c1565b60036020526000908152604090205481565b34801561065a57600080fd5b506103046106693660046143c1565b600b602052600090815260409020546001600160a01b031681565b34801561069057600080fd5b506102e261069f366004614673565b6111f6565b3480156106b057600080fd5b506102e26106bf3660046143c1565b611680565b3480156106d057600080fd5b506102af6106df366004614434565b6116f9565b3480156106f057600080fd5b506102e26106ff366004614552565b6117a4565b6102e26107123660046143c1565b6117e9565b34801561072357600080fd5b506102af6107323660046143c1565b611860565b34801561074357600080fd5b506102af6107523660046143c1565b611b91565b34801561076357600080fd5b506102e2611c6d565b34801561077857600080fd5b506102e26107873660046146b9565b611d2f565b34801561079857600080fd5b506102af670de0b6b3a764000081565b3480156107b457600080fd5b506102af6107c3366004614434565b611d73565b3480156107d457600080fd5b506102af6107e33660046143c1565b611e1e565b3480156107f457600080fd5b506102e2611e32565b34801561080957600080fd5b506102af6108183660046143c1565b60046020526000908152604090205481565b34801561083657600080fd5b506102e26108453660046146b9565b611ec4565b34801561085657600080fd5b506102e261086536600461447f565b611f75565b34801561087657600080fd5b506102e2610885366004614501565b612280565b34801561089657600080fd5b506102e26108a53660046146b9565b612434565b3480156108b657600080fd5b506102e26108c53660046143c1565b612481565b3480156108d657600080fd5b506102af6108e53660046143fb565b612501565b600260005414156109165760405162461bcd60e51b815260040161090d9061490c565b60405180910390fd5b6002600055610923612516565b61092c816125ea565b6000811161097c5760405162461bcd60e51b815260206004820152601d60248201527f4c656e64696e67506169723a20696e76616c696420706f736974696f6e000000604482015260640161090d565b6001600160a01b038216600090815260096020526040902054156109f05760405162461bcd60e51b815260206004820152602560248201527f4c656e64696e67506169723a206f6e6520706f736974696f6e2070657220616360448201526418dbdd5b9d60da1b606482015260840161090d565b604051632142170760e11b81523360048201523060248201526044810182905273c36442b4a4522e871399cd717abdd847ab11fe88906342842e0e90606401600060405180830381600087803b158015610a4957600080fd5b505af1158015610a5d573d6000803e3d6000fd5b505050506001600160a01b03821660008181526009602090815260409182902084905590518381527fd29d3dde8502487866d88250c8ed8a2efc0d6b7f9d0838eedc045f1b428ac49091015b60405180910390a250506001600055565b60026000541415610add5760405162461bcd60e51b815260040161090d9061490c565b6002600055610aeb826126eb565b610af482611115565b610b088383610b038585612760565b61278f565b50610b148233836127f2565b5050600160005550565b60026000541415610b415760405162461bcd60e51b815260040161090d9061490c565b600260009081553381526009602052604090205480610ba25760405162461bcd60e51b815260206004820181905260248201527f4c656e64696e67506169723a206e6f7468696e6720746f207769746864726177604482015260640161090d565b604051632142170760e11b81523060048201523360248201526044810182905273c36442b4a4522e871399cd717abdd847ab11fe88906342842e0e90606401600060405180830381600087803b158015610bfb57600080fd5b505af1158015610c0f573d6000803e3d6000fd5b5050336000908152600960205260408120555050600f54610c38906001600160a01b0316611115565b601054610c4d906001600160a01b0316611115565b610c5633611680565b60405181815233907f903c747253c7c908432c053beee6f85a2d1cab2430f1f13ce07b8526805351789060200160405180910390a2506001600055565b60026000541415610cb65760405162461bcd60e51b815260040161090d9061490c565b6002600055610cd2600080516020614b0c8339815191526126eb565b610ce9600080516020614b0c833981519152611115565b610d01600080516020614b0c8339815191528261282c565b610d0b3382612886565b506001600055565b6000610d1e846126eb565b610d27836126eb565b600d5460405163877722bf60e01b815260009182916001600160a01b039091169063877722bf90610d5e908990899060040161487d565b604080518083038186803b158015610d7557600080fd5b505afa158015610d89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dad9190614739565b91509150610dbe8686868585612a2d565b925050505b9392505050565b60026000541415610ded5760405162461bcd60e51b815260040161090d9061490c565b6002600055610dfb826126eb565b610e0482611115565b610e0f838383612ada565b610b148233836127f2565b60026000541415610e3d5760405162461bcd60e51b815260040161090d9061490c565b6002600090815580610e4e33612b39565b600f549193509150610e6a906001600160a01b03163384612c60565b601054610e81906001600160a01b03163383612c60565b50506001600055565b60026000541415610ead5760405162461bcd60e51b815260040161090d9061490c565b6002600055610ebb826126eb565b610ec482611115565b6001600160a01b038083166000908152600260209081526040808320938716835292905290812054610ef9908590859061278f565b905081811115610f555760405162461bcd60e51b815260206004820152602160248201527f4c656e64696e67506169723a20616d6f756e74203c3d205f6d6178416d6f756e6044820152601d60fa1b606482015260840161090d565b610f608333836127f2565b505060016000555050565b60026000541415610f8e5760405162461bcd60e51b815260040161090d9061490c565b6002600055610faa600080516020614b0c8339815191526126eb565b610fc1600080516020614b0c833981519152611115565b6001600160a01b03811660009081527fde032e96a833a2191f55c5766e34554d9b07734477ea9cb69c40158c1078e7936020526040812054611014908390600080516020614b0c8339815191529061278f565b9050803410156110745760405162461bcd60e51b815260206004820152602560248201527f4c656e64696e67506169723a20696e73756666696369656e74204554482064656044820152641c1bdcda5d60da1b606482015260840161090d565b61107c612c94565b600081341161108c576000611096565b6110968234614a87565b90508015610b1457610b143382612886565b600260005414156110cb5760405162461bcd60e51b815260040161090d9061490c565b60026000556110d9826126eb565b6110e282611115565b6110ec8282612d11565b610e81823383612c60565b6000611102836126eb565b61110c8383612e00565b90505b92915050565b6001600160a01b0381166000908152600460205260409020544311156111f357600061114082612e33565b9050600068056bc75e2d6310000061115784612f02565b6111619084614a68565b61116b919061495b565b6001600160a01b038416600090815260066020526040812080549293508392909190611198908490614943565b909155506111a890508183614a87565b6001600160a01b038416600090815260036020526040812080549091906111d0908490614943565b9091555050506001600160a01b0382166000908152600460205260409020439055505b50565b600260005414156112195760405162461bcd60e51b815260040161090d9061490c565b6002600055611227836126eb565b600f546000906001600160a01b0385811691161461125057600f546001600160a01b031661125d565b6010546001600160a01b03165b905061126881611115565b61127184611115565b600061127c86611860565b9050670de0b6b3a764000081106112ea5760405162461bcd60e51b815260206004820152602c60248201527f4c656e64696e67506169723a206163636f756e74206865616c7468203c204c4960448201526b0a2be9a929cbe908a8298a8960a31b606482015260840161090d565b6112f386612f89565b611306846113018789612e00565b6132b5565b600d5460405163877722bf60e01b815291955060009182916001600160a01b03169063877722bf9061133e908a90889060040161487d565b604080518083038186803b15801561135557600080fd5b505afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d9190614739565b9150915060006113a08886898686612a2d565b600d54604051633d3fd19760e21b81526001600160a01b038b8116600483015292935060009268056bc75e2d6310000092169063f4ff465c9060240160206040518083038186803b1580156113f457600080fd5b505afa158015611408573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142c9190614720565b6114369084614a68565b611440919061495b565b600d54604051636c77410360e11b81526001600160a01b038c8116600483015292935060009268056bc75e2d6310000092169063d8ee82069060240160206040518083038186803b15801561149457600080fd5b505afa1580156114a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114cc9190614720565b6114d69085614a68565b6114e0919061495b565b90506000816114ef8486614943565b6114f99190614943565b905060006115078486614943565b90508981101561156f5760405162461bcd60e51b815260206004820152602d60248201527f4c656e64696e67506169723a20737570706c794f7574707574203e3d205f6d6960448201526c1b94dd5c1c1b1e53dd5d1c1d5d609a1b606482015260840161090d565b611583898e61157e8c866132cb565b6132fa565b506001600160a01b038916600090815260036020526040812080548592906115ac908490614943565b909155506115c690508c8e6115c1828f612760565b6133f5565b50600f546115de908e906001600160a01b03166134e4565b6010546115f5908e906001600160a01b03166134e4565b6116008c338d6127f2565b61160b893383613524565b50886001600160a01b03168c6001600160a01b03168e6001600160a01b03167fd58706648644be277f6999c826f65f98128c29c6846a892b929a304a7f19e3eb8e85604051611664929190918252602082015260400190565b60405180910390a4505060016000555050505050505050505050565b600061168b82611860565b9050670de0b6b3a76400008110156116f55760405162461bcd60e51b815260206004820152602760248201527f4c656e64696e67506169723a20696e73756666696369656e74206163636f756e6044820152660e890cac2d8e8d60cb1b606482015260840161090d565b5050565b6000611704836126eb565b61170d826126eb565b600d5460405163877722bf60e01b815260009182916001600160a01b039091169063877722bf90611744908890889060040161487d565b604080518083038186803b15801561175b57600080fd5b505afa15801561176f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117939190614739565b91509150610dbe86868685856135cc565b600260005414156117c75760405162461bcd60e51b815260040161090d9061490c565b60026000556117d5826126eb565b6117de82611115565b610e0f8383836135ee565b6002600054141561180c5760405162461bcd60e51b815260040161090d9061490c565b6002600055611828600080516020614b0c8339815191526126eb565b61183f600080516020614b0c833981519152611115565b61185881600080516020614b0c83398151915234612ada565b610d0b612c94565b600f546001600160a01b0390811660009081526002602090815260408083209385168352929052908120541580156118be57506010546001600160a01b03908116600090815260026020908152604080832093861683529290522054155b156118d25750670de0b6b3a7640000919050565b600d54600f5460105460405163877722bf60e01b815260009384936001600160a01b039182169363877722bf9361191393928316929091169060040161487d565b604080518083038186803b15801561192a57600080fd5b505afa15801561193e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119629190614739565b600d54600f54604051631d74844360e11b81526001600160a01b039182166004820152939550919350600092911690633ae908869060240160206040518083038186803b1580156119b257600080fd5b505afa1580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614720565b600d54601054604051631d74844360e11b81526001600160a01b039182166004820152929350600092911690633ae908869060240160206040518083038186803b158015611a3757600080fd5b505afa158015611a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6f9190614720565b600f5490915060009068056bc75e2d63100000908490611a98906001600160a01b03168a6136e4565b611aa29190614a68565b611aac919061495b565b601054600f5491925060009168056bc75e2d63100000918591611adf918c916001600160a01b0391821691168a8c6135cc565b611ae99190614a68565b611af3919061495b565b90506000611b048988888888613717565b9050600081611b138486614943565b611b1d9190614943565b601054600f54919250600091611b43918d916001600160a01b0391821691168b8d6137e5565b600f54611b59906001600160a01b03168d612e00565b611b639190614943565b905080611b7883670de0b6b3a7640000614a68565b611b82919061495b565b9b9a5050505050505050505050565b6000611b9c826126eb565b6001600160a01b0382166000908152600660205260409020541580611bd757506001600160a01b038216600090815260086020526040902054155b15611be457506000919050565b6001600160a01b0382166000908152600660209081526040808320546008909252822054611c1b9068056bc75e2d63100000614a68565b611c25919061495b565b905068056bc75e2d6310000080611c3b85612f02565b83611c45876137f6565b611c4f9190614a68565b611c599190614a68565b611c63919061495b565b610dc3919061495b565b60026000541415611c905760405162461bcd60e51b815260040161090d9061490c565b6002600055611cac600080516020614b0c8339815191526126eb565b611cc3600080516020614b0c833981519152611115565b3360009081527f49e349d4f386739afdf8e55db7675b584d46c3b2a603eef62554e21dc437b5db602052604081205490611d0b600080516020614b0c8339815191528361385c565b9050611d25600080516020614b0c8339815191528361388b565b610e813382612886565b60026000541415611d525760405162461bcd60e51b815260040161090d9061490c565b6002600055611d60826126eb565b611d6982611115565b6110ec828261282c565b6000611d7e836126eb565b611d87826126eb565b600d5460405163877722bf60e01b815260009182916001600160a01b039091169063877722bf90611dbe908890889060040161487d565b604080518083038186803b158015611dd557600080fd5b505afa158015611de9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e0d9190614739565b91509150610dbe86868685856137e5565b6000611e29826126eb565b61110f826137f6565b60026000541415611e555760405162461bcd60e51b815260040161090d9061490c565b6002600055600f54611e6f906001600160a01b0316611115565b601054611e84906001600160a01b0316611115565b600080611e9033612b39565b600f549193509150611eac906001600160a01b03163384613524565b50601054610b14906001600160a01b03163383613524565b60026000541415611ee75760405162461bcd60e51b815260040161090d9061490c565b6002600055611ef5826126eb565b6001600160a01b03821660009081526003602052604081208054839290611f1d908490614a87565b9091555050600e54611f3a9083906001600160a01b031683612c60565b816001600160a01b03167fb15db7a2f2927e329da6d3ed5b95a2e8984f3e0c21d525bc9ae5d3adf070df6e82604051610aa991815260200190565b600f546001600160a01b031615611fce5760405162461bcd60e51b815260206004820181905260248201527f4c656e64696e67506169723a20616c726561647920696e697469616c697a6564604482015260640161090d565b600d80546001600160a01b03199081166001600160a01b0388811691909117909255600c80548216878416179055600e80548216868416179055600f805482168584169081178255601080549093168585161783556000908152600460208181526040808420439081905595548716845292839020949094559154815163313ce56760e01b8152915194169363313ce56793828401939092829003018186803b15801561207a57600080fd5b505afa15801561208e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b2919061475d565b600f546001600160a01b039081166000908152600a602090815260409182902060ff94909416909355601054815163313ce56760e01b8152915192169263313ce56792600480840193829003018186803b15801561210f57600080fd5b505afa158015612123573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612147919061475d565b6010546001600160a01b039081166000908152600a602052604080822060ff94909416909355600f54909116815220546006118015906121a257506010546001600160a01b03166000908152600a6020526040902054600611155b6121ee5760405162461bcd60e51b815260206004820152601960248201527f4c656e64696e67506169723a204d494e5f444543494d414c5300000000000000604482015260640161090d565b600f546122059087906001600160a01b03166138e0565b600f546001600160a01b039081166000908152600b6020526040902080546001600160a01b03191692821692909217909155601054612246918891166138e0565b6010546001600160a01b039081166000908152600b6020526040902080546001600160a01b03191692909116919091179055505050505050565b600f546001600160a01b039081166000908152600b6020526040902054163314806122c757506010546001600160a01b039081166000908152600b60205260409020541633145b6123265760405162461bcd60e51b815260206004820152602a60248201527f4c656e64696e67436f6e74726f6c6c65723a2063616c6c6572206d757374206260448201526932902628103a37b5b2b760b11b606482015260840161090d565b6001600160a01b03808516600090815260026020908152604080832093861683529290522054156123ac5760405162461bcd60e51b815260206004820152602a60248201527f4c656e64696e67506169723a2063616e6e6f74207265636569766520626f727260448201526937bbb2b2103a37b5b2b760b11b606482015260840161090d565b6001600160a01b038085166000908152600160209081526040808320938716835292905290812080548392906123e3908490614a87565b90915550506001600160a01b0380851660009081526001602090815260408083209386168352929052908120805483929061241f908490614943565b9091555061242e905083611680565b50505050565b600260005414156124575760405162461bcd60e51b815260040161090d9061490c565b6002600055612465826126eb565b61246e82611115565b6110ec8261247c84846132cb565b61388b565b600260005414156124a45760405162461bcd60e51b815260040161090d9061490c565b60026000556124b2816126eb565b6124bb81611115565b6001600160a01b0381166000908152600160209081526040808320338452909152812054906124ea838361385c565b90506124f6838361388b565b610b14833383612c60565b600061250c836126eb565b61110c83836136e4565b600d60009054906101000a90046001600160a01b03166001600160a01b0316635392fd1c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561256457600080fd5b505afa158015612578573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061259c91906146e5565b6125e85760405162461bcd60e51b815260206004820152601e60248201527f4c656e64696e67506169723a206465706f736974732064697361626c65640000604482015260640161090d565b565b60405163133f757160e31b8152600481018290526000908190819073c36442b4a4522e871399cd717abdd847ab11fe88906399fbab88906024016101806040518083038186803b15801561263d57600080fd5b505afa158015612651573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126759190614780565b505050506001600160801b03169750505050945094505050600081116126dd5760405162461bcd60e51b815260206004820152601a60248201527f4c656e64696e67506169723a206c6971756964697479203e2030000000000000604482015260640161090d565b6126e6836126eb565b61242e825b600f546001600160a01b038281169116148061271457506010546001600160a01b038281169116145b6111f35760405162461bcd60e51b815260206004820152601a60248201527f4c656e64696e67506169723a20696e76616c696420746f6b656e000000000000604482015260640161090d565b6001600160a01b038216600090815260076020908152604080832054600890925282205461110c919084613965565b600061279c8385846133f5565b9050826001600160a01b0316846001600160a01b03167f05f2eeda0e08e4b437f487c8d7d29b14537d15e3488170dc3de5dbdf8dac4684836040516127e391815260200190565b60405180910390a39392505050565b600081116128125760405162461bcd60e51b815260040161090d906148ca565b6128276001600160a01b03841683308461399e565b505050565b600061283883336136e4565b90506000828211612849578161284b565b825b905060006128598285614a87565b9050811561286f5761286f8561247c87856132cb565b801561287f5761287f8582612d11565b5050505050565b600081116128a65760405162461bcd60e51b815260040161090d906148ca565b6001600160a01b0382166129065760405162461bcd60e51b815260206004820152602160248201527f5472616e7366657248656c7065723a20696e76616c696420726563697069656e6044820152601d60fa1b606482015260840161090d565b604051632e1a7d4d60e01b815260048101829052600080516020614b0c83398151915290632e1a7d4d90602401600060405180830381600087803b15801561294d57600080fd5b505af1158015612961573d6000803e3d6000fd5b5050604080516000808252602082019283905293506001600160a01b0386169250849161298e9190614861565b60006040518083038185875af1925050503d80600081146129cb576040519150601f19603f3d011682016040523d82523d6000602084013e6129d0565b606091505b50509050806128275760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a20455448207472616e73666572206661696044820152621b195960ea1b606482015260840161090d565b6001600160a01b0385166000908152600a602081905260408220548291612a5491906149c0565b612a6685670de0b6b3a7640000614a68565b612a70919061495b565b6001600160a01b0387166000908152600a602081905260408220549293509091612a99916149c0565b612aab85670de0b6b3a7640000614a68565b612ab5919061495b565b905080612ac28388614a68565b612acc919061495b565b925050505b95945050505050565b6000612ae68385612e00565b90506000828211612af75781612af9565b825b90506000612b078285614a87565b90508115612b2057612b1e8686610b038886612760565b505b8015612b3157612b318686836135ee565b505050505050565b600c546001600160a01b0382811660009081526009602052604080822054905163095ea7b360e01b81529290931660048301526024820192909252819073c36442b4a4522e871399cd717abdd847ab11fe889063095ea7b390604401600060405180830381600087803b158015612baf57600080fd5b505af1158015612bc3573d6000803e3d6000fd5b5050600c546001600160a01b038681166000908152600960205260409081902054905163b17acdcd60e01b815260048101919091529116925063b17acdcd91506024016040805180830381600087803b158015612c1f57600080fd5b505af1158015612c33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c579190614739565b91509150915091565b60008111612c805760405162461bcd60e51b815260040161090d906148ca565b6128276001600160a01b0384168383613a09565b60003411612cb45760405162461bcd60e51b815260040161090d906148ca565b600080516020614b0c8339815191526001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015612cfd57600080fd5b505af115801561287f573d6000803e3d6000fd5b6001600160a01b038216600090815260016020908152604080832033845290915290205415612d945760405162461bcd60e51b815260206004820152602960248201527f4c656e64696e67506169723a2063616e6e6f7420626f72726f7720737570706c60448201526834b2b2103a37b5b2b760b91b606482015260840161090d565b612d9c613a39565b612da7823383613b0b565b612db2823383613d05565b50612dbc33611680565b6040518181526001600160a01b0383169033907f312a5e5e1079f5dda4e95dbbd0b908b291fd5b992ef22073643ab691572c5b529060200160405180910390a35050565b6001600160a01b03808316600090815260026020908152604080832093851683529290529081205461110c908490613dad565b6001600160a01b03811660009081526008602052604081205415612efd576001600160a01b038216600090815260046020526040812054612e749043614a87565b9050600081612e82856137f6565b612e8c9190614a68565b6001600160a01b03851660009081526008602052604090205490915068056bc75e2d6310000090612ebe908390614a68565b612ec8919061495b565b6001600160a01b038516600090815260086020526040812080549295508592909190612ef5908490614943565b909155505050505b919050565b6000612f0c613ddc565b6001600160a01b0316638f32896030846040518363ffffffff1660e01b8152600401612f3992919061487d565b60206040518083038186803b158015612f5157600080fd5b505afa158015612f65573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110f9190614720565b6001600160a01b038116600090815260096020526040902054156111f357600d54600f5460105460405163877722bf60e01b815260009384936001600160a01b039182169363877722bf93612fe893928316929091169060040161487d565b604080518083038186803b158015612fff57600080fd5b505afa158015613013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130379190614739565b6001600160a01b038516600090815260096020526040812054929450909250908190613064908585613e5e565b915091506000600d60009054906101000a90046001600160a01b03166001600160a01b031663aa6a77816040518163ffffffff1660e01b815260040160206040518083038186803b1580156130b857600080fd5b505afa1580156130cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f09190614720565b600c546001600160a01b038881166000908152600960205260409081902054905163095ea7b360e01b8152919092166004820152602481019190915290915073c36442b4a4522e871399cd717abdd847ab11fe889063095ea7b390604401600060405180830381600087803b15801561316857600080fd5b505af115801561317c573d6000803e3d6000fd5b5050600c546001600160a01b0389811660009081526009602052604081205490945084935091169063857620e19068056bc75e2d631000006131be878a614a68565b6131c8919061495b565b68056bc75e2d631000006131dc888a614a68565b6131e6919061495b565b6040516001600160e01b031960e086901b1681526004810193909352602483019190915260448201526064016040805180830381600087803b15801561322b57600080fd5b505af115801561323f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132639190614739565b6001600160a01b03808b16600090815260096020526040812055600f5492945090925061329291168984613524565b506010546132aa906001600160a01b03168983613524565b505050505050505050565b60008183106132c4578161110c565b5090919050565b6001600160a01b038216600090815260056020908152604080832054600690925282205461110c919084613965565b60008115610dc3576001600160a01b03808516600090815260016020908152604080832093871683529290522054613333908390614a87565b6001141561334957613346600183614943565b91505b613353848361385c565b6001600160a01b03808616600090815260016020908152604080832093881683529290529081208054929350849290919061338f908490614a87565b90915550506001600160a01b038416600090815260056020526040812080548492906133bc908490614a87565b90915550506001600160a01b038416600090815260066020526040812080548392906133e9908490614a87565b90915550509392505050565b60008115610dc3576001600160a01b0380851660009081526002602090815260408083209387168352929052205461342e908390614a87565b6001141561344457613441600183614943565b91505b61344e8483613dad565b6001600160a01b03808616600090815260026020908152604080832093881683529290529081208054929350849290919061348a908490614a87565b90915550506001600160a01b038416600090815260076020526040812080548492906134b7908490614a87565b90915550506001600160a01b038416600090815260086020526040812080548392906133e9908490614a87565b60006134fd6134f38385612e00565b61130184866136e4565b905080156128275761351482846115c18585612760565b5061242e828461157e85856132cb565b60008115610dc35761353684836132cb565b6001600160a01b038086166000908152600160209081526040808320938816835292905290812080549293508392909190613572908490614943565b90915550506001600160a01b0384166000908152600560205260408120805483929061359f908490614943565b90915550506001600160a01b038416600090815260066020526040812080548492906133e9908490614943565b60006135e485856135dd888a6136e4565b8686612a2d565b9695505050505050565b6001600160a01b03808316600090815260026020908152604080832093871683529290522054156136745760405162461bcd60e51b815260206004820152602a60248201527f4c656e64696e67506169723a2063616e6e6f74206465706f73697420626f727260448201526937bbb2b2103a37b5b2b760b11b606482015260840161090d565b61367c612516565b6136868282613f6d565b613691828483613524565b50816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62836040516136d791815260200190565b60405180910390a3505050565b6001600160a01b03808316600090815260016020908152604080832093851683529290529081205461110c90849061385c565b6001600160a01b038516600090815260096020526040812054156137dd576001600160a01b038616600090815260096020526040812054819061375b908888613e5e565b9092509050600068056bc75e2d631000006137768785614a68565b613780919061495b565b601054600f5491925060009168056bc75e2d631000009188916137b2916001600160a01b039081169116878d8f612a2d565b6137bc9190614a68565b6137c6919061495b565b90506137d28183614943565b945050505050612ad1565b506000612ad1565b60006135e485856135dd888a612e00565b6000613800613ddc565b6001600160a01b03838116600081815260066020908152604080832054600890925291829020549151639b5b2e3560e01b8152306004820152602481019390935260448301526064820152911690639b5b2e3590608401612f39565b6001600160a01b038216600090815260056020908152604080832054600690925282205461110c919084614077565b60006138988333846132fa565b90506138a333611680565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020016136d7565b6000806138f5846001600160a01b0316614098565b600d5460405163485cc95560e01b81529192506001600160a01b038084169263485cc9559261392b92889291169060040161487d565b600060405180830381600087803b15801561394557600080fd5b505af1158015613959573d6000803e3d6000fd5b50929695505050505050565b600080841180156139765750600083115b1561399757826139868584614a68565b613990919061495b565b9050610dc3565b5080610dc3565b6040516001600160a01b038085166024830152831660448201526064810182905261242e9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614130565b6040516001600160a01b03831660248201526044810182905261282790849063a9059cbb60e01b906064016139d2565b600d60009054906101000a90046001600160a01b03166001600160a01b031663a35d13006040518163ffffffff1660e01b815260040160206040518083038186803b158015613a8757600080fd5b505afa158015613a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613abf91906146e5565b6125e85760405162461bcd60e51b815260206004820152601f60248201527f4c656e64696e67506169723a20626f72726f77696e672064697361626c656400604482015260640161090d565b600d5460405163f4b7f23d60e01b81526001600160a01b0385811660048301529091169063f4b7f23d9060240160206040518083038186803b158015613b5057600080fd5b505afa158015613b64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b889190614720565b81613b938585612e00565b613b9d9190614943565b1015613bfc5760405162461bcd60e51b815260206004820152602860248201527f4c656e64696e67506169723a20626f72726f7720616d6f756e742062656c6f77604482015267206d696e696d756d60c01b606482015260840161090d565b600d5460405163676573bf60e01b81526000916001600160a01b03169063676573bf90613c2f903090889060040161487d565b60206040518083038186803b158015613c4757600080fd5b505afa158015613c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c7f9190614720565b9050801561242e576001600160a01b0384166000908152600860205260409020548190613cad908490614943565b111561242e5760405162461bcd60e51b815260206004820152602160248201527f4c656e64696e67506169723a20626f72726f77206c696d6974207265616368656044820152601960fa1b606482015260840161090d565b60008115610dc357613d178483612760565b6001600160a01b038086166000908152600260209081526040808320938816835292905290812080549293508392909190613d53908490614943565b90915550506001600160a01b03841660009081526007602052604081208054839290613d80908490614943565b90915550506001600160a01b038416600090815260086020526040812080548492906133e9908490614943565b6001600160a01b038216600090815260076020908152604080832054600890925282205461110c919084614077565b600d54604080516379fed8ad60e11b815290516000926001600160a01b03169163f3fdb15a916004808301926020929190829003018186803b158015613e2157600080fd5b505afa158015613e35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e5991906143de565b905090565b6010546001600160a01b03166000908152600a6020819052604082205482918291613e88916149c0565b613e93906001614a68565b600f546001600160a01b03166000908152600a6020819052604082205492935090918791613ec191906149c0565b613ecb9087614a68565b613ed5919061495b565b600c54604051631c91d67160e01b8152600481018a905260248101859052604481018390529192506001600160a01b031690631c91d67190606401604080518083038186803b158015613f2757600080fd5b505afa158015613f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f5f9190614739565b935093505050935093915050565b600d546040516341f8a85b60e11b81526000916001600160a01b0316906383f150b690613fa0903090879060040161487d565b60206040518083038186803b158015613fb857600080fd5b505afa158015613fcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ff09190614720565b90508015612827576001600160a01b038316600090815260066020526040902054819061401e908490614943565b11156128275760405162461bcd60e51b815260206004820152602260248201527f4c656e64696e67506169723a206465706f736974206c696d6974207265616368604482015261195960f21b606482015260840161090d565b600080841180156140885750600083115b1561399757836139868484614a68565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116612efd5760405162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015260640161090d565b6000614185826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166142029092919063ffffffff16565b80519091501561282757808060200190518101906141a391906146e5565b6128275760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161090d565b60606142118484600085614219565b949350505050565b60608247101561427a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161090d565b843b6142c85760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161090d565b600080866001600160a01b031685876040516142e49190614861565b60006040518083038185875af1925050503d8060008114614321576040519150601f19603f3d011682016040523d82523d6000602084013e614326565b606091505b5091509150614336828286614341565b979650505050505050565b60608315614350575081610dc3565b8251156143605782518084602001fd5b8160405162461bcd60e51b815260040161090d9190614897565b8051612efd81614af6565b8051600281900b8114612efd57600080fd5b80516001600160801b0381168114612efd57600080fd5b805162ffffff81168114612efd57600080fd5b6000602082840312156143d357600080fd5b8135610dc381614af6565b6000602082840312156143f057600080fd5b8151610dc381614af6565b6000806040838503121561440e57600080fd5b823561441981614af6565b9150602083013561442981614af6565b809150509250929050565b60008060006060848603121561444957600080fd5b833561445481614af6565b9250602084013561446481614af6565b9150604084013561447481614af6565b809150509250925092565b60008060008060008060c0878903121561449857600080fd5b86356144a381614af6565b955060208701356144b381614af6565b945060408701356144c381614af6565b935060608701356144d381614af6565b925060808701356144e381614af6565b915060a08701356144f381614af6565b809150509295509295509295565b6000806000806080858703121561451757600080fd5b843561452281614af6565b9350602085013561453281614af6565b9250604085013561454281614af6565b9396929550929360600135925050565b60008060006060848603121561456757600080fd5b833561457281614af6565b9250602084013561458281614af6565b929592945050506040919091013590565b600080600080608085870312156145a957600080fd5b84356145b481614af6565b935060208501356145c481614af6565b925060408501359150606085013567ffffffffffffffff808211156145e857600080fd5b818701915087601f8301126145fc57600080fd5b81358181111561460e5761460e614ae0565b604051601f8201601f19908116603f0116810190838211818310171561463657614636614ae0565b816040528281528a602084870101111561464f57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806000806080858703121561468957600080fd5b843561469481614af6565b935060208501356146a481614af6565b93969395505050506040820135916060013590565b600080604083850312156146cc57600080fd5b82356146d781614af6565b946020939093013593505050565b6000602082840312156146f757600080fd5b81518015158114610dc357600080fd5b60006020828403121561471957600080fd5b5035919050565b60006020828403121561473257600080fd5b5051919050565b6000806040838503121561474c57600080fd5b505080516020909101519092909150565b60006020828403121561476f57600080fd5b815160ff81168114610dc357600080fd5b6000806000806000806000806000806000806101808d8f0312156147a357600080fd5b8c516bffffffffffffffffffffffff811681146147bf57600080fd5b9b506147cd60208e0161437a565b9a506147db60408e0161437a565b99506147e960608e0161437a565b98506147f760808e016143ae565b975061480560a08e01614385565b965061481360c08e01614385565b955061482160e08e01614397565b94506101008d015193506101208d015192506148406101408e01614397565b915061484f6101608e01614397565b90509295989b509295989b509295989b565b60008251614873818460208701614a9e565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b60208152600082518060208401526148b6816040850160208701614a9e565b601f01601f19169190910160400192915050565b60208082526022908201527f5472616e7366657248656c7065723a20616d6f756e74206d757374206265203e604082015261020360f41b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6000821982111561495657614956614aca565b500190565b60008261497857634e487b7160e01b600052601260045260246000fd5b500490565b600181815b808511156149b857816000190482111561499e5761499e614aca565b808516156149ab57918102915b93841c9390800290614982565b509250929050565b600061110c83836000826149d65750600161110f565b816149e35750600061110f565b81600181146149f95760028114614a0357614a1f565b600191505061110f565b60ff841115614a1457614a14614aca565b50506001821b61110f565b5060208310610133831016604e8410600b8410161715614a42575081810a61110f565b614a4c838361497d565b8060001904821115614a6057614a60614aca565b029392505050565b6000816000190483118215151615614a8257614a82614aca565b500290565b600082821015614a9957614a99614aca565b500390565b60005b83811015614ab9578181015183820152602001614aa1565b8381111561242e5750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146111f357600080fdfe000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a26469706673582212204a17f876c4df2a80474b685b6c1903385cd253b56a9ca258f1eacdb33b332ec664736f6c63430008060033
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.