![ads](/images/gen/moonpay_20.png)
20M+ users trust MoonPay worldwide. Checkout with your preferred payment method.
![ads](/images/gen/cons_20.png)
Ready to onboard to Ethereum? With MetaMask Portfolio, you're in control.
![ads](/images/gen/nexo.png)
Get up to 0.5% cashback per purchase and receive daily interest.
![ads](/images/gen/cons_20.png)
Ready to simplify your web3 experience? Try the all-in-one web3 app trusted by millions worldwide.
Opt-in, make your first trade on Exchange Plus & receive random crypto rewards from 10,000 SHIB, to 0.01 BTC.
![ads](/images/gen/coinsgame_20a.png)
Everyday giveaways up to 100 ETH, Lucky Spins. Deposit BONUS 300% and Cashbacks!
![ads](/images/gen/celsiuscasino_20.png)
9 years old Licensed Crypto Casino, Instant Withdraw 24/7, 6000+ Slots available, Paypal Deposit, Instant Live Support 24/7, 30% Rakeback.
![ads](/images/gen/bcgames_20.png)
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
![ads](/images/gen/bcgames_20.png)
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
![ads](/images/gen/cw_20.png)
Play 100s of games anonymously with all major cryptos. Join CryptoWins & start winning!
![ads](/images/gen/cryptoslots.png)
Anonymous play on awesome games - sign up now for 25 free jackpot spins - worth $100s!
Overview
ETH Balance
Eth Value
$0.00Token Holdings
Could not find any matches!
- ERC-20 Tokens (13)2,238.05844651 stkAAVEStaked Aave (stkAAV...)$304,487.85@136.0528,286,446,274.0681 PAIRSHOT PAIRS (PAIRS)200 TokenERC-20 TOKEN*[Suspicious]8,271 TokenERC-20 TOKEN*[Suspicious]30 TokenERC-20 TOKEN*[Suspicious]8,271 TokenERC-20 TOKEN*[Suspicious]8,271 TokenERC-20 TOKEN*[Suspicious]9,283 TokenERC-20 TOKEN*[Suspicious]98,127 TokenERC-20 TOKEN*[Suspicious]30 TokenERC-20 TOKEN*[Spam]9,283 TokenERC-20 TOKEN*[Spam]100 TokenERC-20 TOKEN*[Spam]100 TokenERC-20 TOKEN*[Spam]NFT Tokens (12)aavevault.comaavevault.comERC-1155
ERC-1155 TOKEN*
[Suspicious]ERC-1155 TOKEN*
[Suspicious]ERC-1155 TOKEN*
[Suspicious]More Info
Private Name Tags
ContractCreator
- Transactions
- Internal Transactions
- Token Transfers (ERC-20)
- NFT Transfers
- Contract
- Events
- Analytics
- Multichain Portfolio
Advanced Filter- Filter by Tx Type:
- Tx
- Internal Tx
- ERC-20
- NFTs
Latest 25 from a total of 830 transactions
Transaction Hash MethodBlockFromToWithdraw 20547233 2024-08-17 8:44:59 4 days ago 1723884299 IN 0 ETH$0.00 0.00028579 0.89036912 Withdraw 20533291 2024-08-15 9:59:35 6 days ago 1723715975 IN 0 ETH$0.00 0.0044761 13.73242035 Withdraw 20532752 2024-08-15 8:11:23 6 days ago 1723709483 IN 0 ETH$0.00 0.00088318 2.75159384 Withdraw 20504706 2024-08-11 10:14:35 9 days ago 1723371275 IN 0 ETH$0.00 0.00030271 0.9431109 Withdraw 20263760 2024-07-08 19:05:11 43 days ago 1720465511 IN 0 ETH$0.00 0.00137286 4.2770403 Withdraw 20056750 2024-06-09 20:47:47 72 days ago 1717966067 IN 0 ETH$0.00 0.0030282 9.80509305 Withdraw 20052841 2024-06-09 7:41:23 73 days ago 1717918883 IN 0 ETH$0.00 0.00135229 4 Withdraw 19884133 2024-05-16 17:49:35 96 days ago 1715881775 IN 0 ETH$0.00 0.00260237 8.42695872 Withdraw 19883066 2024-05-16 14:14:59 96 days ago 1715868899 IN 0 ETH$0.00 0.00186245 5.80253827 Withdraw 19853007 2024-05-12 9:20:23 101 days ago 1715505623 IN 0 ETH$0.00 0.00113185 3.66472897 Withdraw 19745288 2024-04-27 7:49:23 116 days ago 1714204163 IN 0 ETH$0.00 0.00171409 5.55010874 Withdraw 19704823 2024-04-21 15:57:59 121 days ago 1713715079 IN 0 ETH$0.00 0.003179 9.90427344 Withdraw 19703316 2024-04-21 10:54:59 121 days ago 1713696899 IN 0 ETH$0.00 0.00200524 6.43527665 Withdraw 19703237 2024-04-21 10:39:11 121 days ago 1713695951 IN 0 ETH$0.00 0.00196402 6.11897578 Withdraw 19637710 2024-04-12 6:23:11 131 days ago 1712902991 IN 0 ETH$0.00 0.00354609 11.4815365 Withdraw 19637677 2024-04-12 6:16:35 131 days ago 1712902595 IN 0 ETH$0.00 0.00391053 12.0038747 Withdraw 19633263 2024-04-11 15:26:47 131 days ago 1712849207 IN 0 ETH$0.00 0.00861917 27.90712913 Withdraw 19553484 2024-03-31 11:08:47 142 days ago 1711883327 IN 0 ETH$0.00 0.00535113 16.67097003 Withdraw 19543403 2024-03-30 1:06:47 144 days ago 1711760807 IN 0 ETH$0.00 0.00552565 16.95298237 Withdraw 19483646 2024-03-21 14:31:35 152 days ago 1711031495 IN 0 ETH$0.00 0.00969922 30.21820548 Withdraw 19475708 2024-03-20 11:47:59 153 days ago 1710935279 IN 0 ETH$0.00 0.01003958 31.27860078 Withdraw 19397864 2024-03-09 13:33:47 164 days ago 1709991227 IN 0 ETH$0.00 0.01709215 53.24908354 Withdraw 19389180 2024-03-08 8:13:23 166 days ago 1709885603 IN 0 ETH$0.00 0.01637023 51 Withdraw 19382170 2024-03-07 8:42:47 167 days ago 1709800967 IN 0 ETH$0.00 0.01573998 49.03649715 Withdraw 19340521 2024-03-01 13:07:59 172 days ago 1709298479 IN 0 ETH$0.00 0.01626349 52.65992154 Latest 11 internal transactions
Advanced mode:Parent Transaction Hash Block From To 17161995 2023-04-30 23:00:47 478 days ago 1682895647 0 ETH$0.00 17157299 2023-04-30 7:12:23 479 days ago 1682838743 Contract Creation 0 ETH$0.00 15854803 2022-10-29 16:08:11 661 days ago 1667059691 0 ETH$0.00 15854777 2022-10-29 16:02:59 661 days ago 1667059379 Contract Creation 0 ETH$0.00 14340765 2022-03-07 16:23:44 897 days ago 1646670224 0 ETH$0.00 14269250 2022-02-24 14:12:51 908 days ago 1645711971 Contract Creation 0 ETH$0.00 13679837 2021-11-24 22:28:08 1000 days ago 1637792888 0 ETH$0.00 13676021 2021-11-24 7:53:09 1001 days ago 1637740389 Contract Creation 0 ETH$0.00 13396339 2021-10-11 8:51:13 1045 days ago 1633942273 0 ETH$0.00 13396335 2021-10-11 8:50:32 1045 days ago 1633942232 Contract Creation 0 ETH$0.00 13329190 2021-09-30 20:24:31 1055 days ago 1633033471 Contract Creation 0 ETH$0.00 Loading...LoadingThis 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:PalPoolStkAave
Compiler Versionv0.7.6+commit.7338295f
Optimization Enabled:Yes with 25000 runs
Other Settings:default evmVersionContract Source Code (Solidity Standard Json-Input format)
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; pragma abicoder v2; //SPDX-License-Identifier: MIT import "../PalPool.sol"; import "../utils/SafeMath.sol"; import "../utils/SafeERC20.sol"; import "../utils/IERC20.sol"; import "../tokens/AAVE/IStakedAave.sol"; import {Errors} from "../utils/Errors.sol"; /** @title PalPoolStkAave Pool contract */ /// @author Paladin contract PalPoolStkAave is PalPool { using SafeMath for uint; using SafeERC20 for IERC20; /** @dev stkAAVE token address */ address private immutable stkAaveAddress; /** @dev AAVE token address */ address private immutable aaveAddress; /** @dev Block number of the last reward claim */ uint public claimBlockNumber = 0; constructor( address _palToken, address _controller, address _underlying, address _interestModule, address _delegator, address _palLoanToken, address _aaveAddress ) PalPool( _palToken, _controller, _underlying, _interestModule, _delegator, _palLoanToken ) { stkAaveAddress = _underlying; aaveAddress = _aaveAddress; } /** * @dev Claim AAVE tokens from the AAVE Safety Module and stake them back in the Module * @return bool : Success */ function claimFromAave() internal returns(bool) { //Load contracts IERC20 _aave = IERC20(aaveAddress); IStakedAave _stkAave = IStakedAave(stkAaveAddress); //Get pending rewards amount uint _pendingRewards = _stkAave.getTotalRewardsBalance(address(this)); //If there is reward to claim if(_pendingRewards > 0 && claimBlockNumber != block.number){ //claim the AAVE tokens _stkAave.claimRewards(address(this), _pendingRewards); //Stake the AAVE tokens to get stkAAVE tokens uint _toStakeAmount = _aave.balanceOf(address(this)); _aave.safeApprove(stkAaveAddress, _toStakeAmount); _stkAave.stake(address(this), _toStakeAmount); //update the block number claimBlockNumber = block.number; return true; } return true; } /** * @notice Deposit underlying in the Pool * @dev Deposit underlying, and mints palToken for the user * @param _amount Amount of underlying to deposit * @return bool : amount of minted palTokens */ function deposit(uint _amount) public override(PalPool) returns(uint){ require(claimFromAave()); return super.deposit(_amount); } /** * @notice Withdraw underliyng token from the Pool * @dev Transfer underlying token to the user, and burn the corresponding palToken amount * @param _amount Amount of palToken to return * @return uint : amount of underlying returned */ function withdraw(uint _amount) public override(PalPool) returns(uint){ require(claimFromAave()); return super.withdraw(_amount); } /** * @dev Create a Borrow, deploy a Loan Pool and delegate voting power * @param _delegatee Address to delegate the voting power to * @param _amount Amount of underlying to borrow * @param _feeAmount Amount of fee to pay to start the loan * @return uint : amount of paid fees */ function borrow(address _delegatee, uint _amount, uint _feeAmount) public override(PalPool) returns(uint){ require(claimFromAave()); return super.borrow(_delegatee, _amount, _feeAmount); } /** * @notice Transfer the new fees to the Loan, and expand the Loan * @param _loan Address of the Loan * @param _feeAmount New amount of fees to pay * @return bool : Amount of fees paid */ function expandBorrow(address _loan, uint _feeAmount) public override(PalPool) returns(uint){ require(claimFromAave()); return super.expandBorrow(_loan, _feeAmount); } /** * @notice Close a Loan, and return the non-used fees to the Borrower. * If closed before the minimum required length, penalty fees are taken to the non-used fees * @dev Close a Loan, and return the non-used fees to the Borrower * @param _loan Address of the Loan */ function closeBorrow(address _loan) public override(PalPool) { require(claimFromAave()); super.closeBorrow(_loan); } /** * @notice Kill a non-healthy Loan to collect rewards * @dev Kill a non-healthy Loan to collect rewards * @param _loan Address of the Loan */ function killBorrow(address _loan) public override(PalPool) { require(claimFromAave()); super.killBorrow(_loan); } function changeBorrowDelegatee(address _loan, address _newDelegatee) public override(PalPool) { require(claimFromAave()); super.changeBorrowDelegatee(_loan, _newDelegatee); } }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; pragma abicoder v2; //SPDX-License-Identifier: MIT import "./utils/SafeMath.sol"; import "./utils/SafeERC20.sol"; import "./utils/Clones.sol"; import "./IPalPool.sol"; import "./PalPoolStorage.sol"; import "./IPalLoan.sol"; //import "./PalLoan.sol"; import "./IPalToken.sol"; import "./IPaladinController.sol"; import "./IPalLoanToken.sol"; import "./interests/InterestInterface.sol"; import "./utils/IERC20.sol"; import "./utils/Admin.sol"; import "./utils/ReentrancyGuard.sol"; import {Errors} from "./utils/Errors.sol"; /** @title PalPool contract */ /// @author Paladin contract PalPool is IPalPool, PalPoolStorage, Admin, ReentrancyGuard { using SafeMath for uint; using SafeERC20 for IERC20; modifier controllerOnly() { //allows only the Controller and the admin to call the function require(msg.sender == admin || msg.sender == address(controller), Errors.CALLER_NOT_CONTROLLER); _; } //Functions constructor( address _palToken, address _controller, address _underlying, address _interestModule, address _delegator, address _palLoanToken ){ //Set admin admin = msg.sender; //Set inital values & modules palToken = IPalToken(_palToken); controller = IPaladinController(_controller); underlying = IERC20(_underlying); accrualBlockNumber = block.number; interestModule = InterestInterface(_interestModule); borrowIndex = 1e36; delegator = _delegator; palLoanToken = IPalLoanToken(_palLoanToken); } /** * @notice Get the underlying balance for this Pool * @dev Get the underlying balance of this Pool * @return uint : balance of this pool in the underlying token */ function underlyingBalance() public view returns(uint){ //Return the balance of this contract for the underlying asset return underlying.balanceOf(address(this)); } /** * @notice Deposit underlying in the Pool * @dev Deposit underlying, and mints palToken for the user * @param _amount Amount of underlying to deposit * @return bool : amount of minted palTokens */ function deposit(uint _amount) public virtual override nonReentrant returns(uint){ require(_updateInterest()); //Retrieve the current exchange rate palToken:underlying uint _exchRate = _exchangeRate(); //Find the amount to mint depending on the amount to transfer uint _num = _amount.mul(mantissaScale); uint _toMint = _num.div(_exchRate); //Transfer the underlying to this contract //The amount of underlying needs to be approved before underlying.safeTransferFrom(msg.sender, address(this), _amount); //Mint the palToken require(palToken.mint(msg.sender, _toMint), Errors.FAIL_MINT); //Emit the Deposit event emit Deposit(msg.sender, _amount, address(this)); //Use the controller to check if the minting was successfull require(controller.depositVerify(address(this), msg.sender, _toMint), Errors.FAIL_DEPOSIT); return _toMint; } /** * @notice Withdraw underliyng token from the Pool * @dev Transfer underlying token to the user, and burn the corresponding palToken amount * @param _amount Amount of palToken to return * @return uint : amount of underlying returned */ function withdraw(uint _amount) public virtual override nonReentrant returns(uint){ require(_updateInterest()); require(balanceOf(msg.sender) >= _amount, Errors.INSUFFICIENT_BALANCE); //Retrieve the current exchange rate palToken:underlying uint _exchRate = _exchangeRate(); //Find the amount to return depending on the amount of palToken to burn uint _num = _amount.mul(_exchRate); uint _toReturn = _num.div(mantissaScale); //Check if the pool has enough underlying to return require(_toReturn <= underlyingBalance(), Errors.INSUFFICIENT_CASH); //Burn the corresponding palToken amount require(palToken.burn(msg.sender, _amount), Errors.FAIL_BURN); //Make the underlying transfer underlying.safeTransfer(msg.sender, _toReturn); //Use the controller to check if the burning was successfull require(controller.withdrawVerify(address(this), msg.sender, _toReturn), Errors.FAIL_WITHDRAW); //Emit the Withdraw event emit Withdraw(msg.sender, _amount, address(this)); return _toReturn; } /** * @dev Create a Borrow, deploy a Loan Pool and delegate voting power * @param _delegatee Address to delegate the voting power to * @param _amount Amount of underlying to borrow * @param _feeAmount Amount of fee to pay to start the loan * @return uint : new PalLoanToken Id */ function borrow(address _delegatee, uint _amount, uint _feeAmount) public virtual override nonReentrant returns(uint){ //Need the pool to have enough liquidity, and the interests to be up to date require(_amount < underlyingBalance(), Errors.INSUFFICIENT_CASH); require(_delegatee != address(0), Errors.ZERO_ADDRESS); require(_amount > 0, Errors.ZERO_BORROW); require(_feeAmount >= minBorrowFees(_amount), Errors.BORROW_INSUFFICIENT_FEES); require(_updateInterest()); address _borrower = msg.sender; //Update Total Borrowed totalBorrowed = totalBorrowed.add(_amount); IPalLoan _newLoan = IPalLoan(Clones.clone(delegator)); //Send the borrowed amount of underlying tokens to the Loan underlying.safeTransfer(address(_newLoan), _amount); //And transfer the fees from the Borrower to the Loan underlying.safeTransferFrom(_borrower, address(_newLoan), _feeAmount); //Start the Loan (and delegate voting power) require(_newLoan.initiate( address(this), _borrower, address(underlying), _delegatee, _amount, _feeAmount ), Errors.FAIL_LOAN_INITIATE); //Add the new Loan to mappings loans.push(address(_newLoan)); //Mint the palLoanToken linked to this new Loan uint256 _newTokenId = palLoanToken.mint(_borrower, address(this), address(_newLoan)); //New Borrow struct for this Loan loanToBorrow[address(_newLoan)] = Borrow( _newTokenId, _delegatee, address(_newLoan), _amount, address(underlying), _feeAmount, 0, borrowIndex, block.number, 0, false, false ); //Check the borrow succeeded require( controller.borrowVerify(address(this), _borrower, _delegatee, _amount, _feeAmount, address(_newLoan)), Errors.FAIL_BORROW ); //Emit the NewLoan Event emit NewLoan( _borrower, _delegatee, address(underlying), _amount, address(this), address(_newLoan), _newTokenId, block.number ); //Return the PalLoanToken Id return _newTokenId; } /** * @notice Transfer the new fees to the Loan, and expand the Loan * @param _loan Address of the Loan * @param _feeAmount New amount of fees to pay * @return bool : Amount of fees paid */ function expandBorrow(address _loan, uint _feeAmount) public virtual override nonReentrant returns(uint){ //Fetch the corresponding Borrow //And check that the caller is the Borrower, and the Loan is still active Borrow storage _borrow = loanToBorrow[_loan]; require(!_borrow.closed, Errors.LOAN_CLOSED); require(isLoanOwner(_loan, msg.sender), Errors.NOT_LOAN_OWNER); require(_feeAmount > 0); require(_updateInterest()); //Load the Loan Pool contract & get Loan owner IPalLoan _palLoan = IPalLoan(_borrow.loan); address _loanOwner = palLoanToken.ownerOf(_borrow.tokenId); _borrow.feesAmount = _borrow.feesAmount.add(_feeAmount); //Transfer the new fees to the Loan //If success, call the expand function of the Loan underlying.safeTransferFrom(_loanOwner, _borrow.loan, _feeAmount); require(_palLoan.expand(_feeAmount), Errors.FAIL_LOAN_EXPAND); emit ExpandLoan( _loanOwner, _borrow.delegatee, address(underlying), address(this), _borrow.feesAmount, _borrow.loan, _borrow.tokenId ); return _feeAmount; } /** * @notice Close a Loan, and return the non-used fees to the Borrower. * If closed before the minimum required length, penalty fees are taken to the non-used fees * @dev Close a Loan, and return the non-used fees to the Borrower * @param _loan Address of the Loan */ function closeBorrow(address _loan) public virtual override nonReentrant { //Fetch the corresponding Borrow //And check that the caller is the Borrower, and the Loan is still active Borrow storage _borrow = loanToBorrow[_loan]; require(!_borrow.closed, Errors.LOAN_CLOSED); require(isLoanOwner(_loan, msg.sender), Errors.NOT_LOAN_OWNER); require(_updateInterest()); //Get Loan owner from the ERC721 contract address _loanOwner = palLoanToken.ownerOf(_borrow.tokenId); //Load the Loan contract IPalLoan _palLoan = IPalLoan(_borrow.loan); //Calculates the amount of fees used uint _feesUsed = (_borrow.amount.mul(borrowIndex).div(_borrow.borrowIndex)).sub(_borrow.amount); uint _penaltyFees = 0; uint _totalFees = _feesUsed; //If the Borrow is closed before the minimum length, calculates the penalty fees to pay // -> Number of block remaining to complete the minimum length * current Borrow Rate if(block.number < (_borrow.startBlock.add(minBorrowLength))){ uint _currentBorrowRate = interestModule.getBorrowRate(address(this), underlyingBalance(), totalBorrowed, totalReserve); uint _missingBlocks = (_borrow.startBlock.add(minBorrowLength)).sub(block.number); _penaltyFees = _missingBlocks.mul(_borrow.amount.mul(_currentBorrowRate)).div(mantissaScale); _totalFees = _totalFees.add(_penaltyFees); } //Security so the Borrow can be closed if there are no more fees //(if the Borrow wasn't Killed yet, or the loan is closed before minimum time, and already paid fees aren't enough) if(_totalFees > _borrow.feesAmount){ _totalFees = _borrow.feesAmount; } //Set the Borrow as closed _borrow.closed = true; _borrow.feesUsed = _totalFees; _borrow.closeBlock = block.number; //Remove the borrowed tokens + fees from the TotalBorrowed //Add to the Reserve the reserveFactor of Penalty Fees (if there is Penalty Fees) //And add the fees counted as potential Killer Fees to the Accrued Fees, since no killing was necessary totalBorrowed = totalBorrowed.sub((_borrow.amount).add(_feesUsed)); uint _realPenaltyFees = _totalFees.sub(_feesUsed); uint _killerFees = _feesUsed.mul(killerRatio).div(mantissaScale); totalReserve = totalReserve.add(reserveFactor.mul(_realPenaltyFees).div(mantissaScale)); accruedFees = accruedFees.add(_killerFees).add(reserveFactor.mul(_realPenaltyFees).div(mantissaScale)); //Close and destroy the loan _palLoan.closeLoan(_totalFees); //Burn the palLoanToken for this Loan require(palLoanToken.burn(_borrow.tokenId), Errors.FAIL_LOAN_TOKEN_BURN); require(controller.closeBorrowVerify(address(this), _loanOwner, _borrow.loan), Errors.FAIL_CLOSE_BORROW); //Emit the CloseLoan Event emit CloseLoan( _loanOwner, _borrow.delegatee, address(underlying), _borrow.amount, address(this), _totalFees, _loan, _borrow.tokenId, false ); } /** * @notice Kill a non-healthy Loan to collect rewards * @dev Kill a non-healthy Loan to collect rewards * @param _loan Address of the Loan */ function killBorrow(address _loan) public virtual override nonReentrant { address killer = msg.sender; //Fetch the corresponding Borrow //And check that the killer is not the Borrower, and the Loan is still active Borrow storage _borrow = loanToBorrow[_loan]; require(!_borrow.closed, Errors.LOAN_CLOSED); require(!isLoanOwner(_loan, killer), Errors.LOAN_OWNER); require(_updateInterest()); //Get the owner of the Loan through the ERC721 contract address _loanOwner = palLoanToken.ownerOf(_borrow.tokenId); //Calculate the amount of fee used, and check if the Loan is killable uint _feesUsed = (_borrow.amount.mul(borrowIndex).div(_borrow.borrowIndex)).sub(_borrow.amount); uint _loanHealthFactor = _feesUsed.mul(uint(1e18)).div(_borrow.feesAmount); require(_loanHealthFactor >= killFactor, Errors.NOT_KILLABLE); //Load the Loan IPalLoan _palLoan = IPalLoan(_borrow.loan); //Close the Loan, and update storage variables _borrow.closed = true; _borrow.killed = true; _borrow.feesUsed = _borrow.feesAmount; _borrow.closeBlock = block.number; //Remove the borrowed tokens + fees from the TotalBorrowed //Remove the amount paid as killer fees from the Reserve, and any over accrued interest in the Reserve & AccruedFees uint _overAccruedInterest = _loanHealthFactor <= mantissaScale ? 0 : _feesUsed.sub(_borrow.feesAmount); uint _killerFees = (_borrow.feesAmount).mul(killerRatio).div(mantissaScale); totalBorrowed = totalBorrowed.sub((_borrow.amount).add(_feesUsed)); totalReserve = totalReserve.sub(_killerFees).sub(_overAccruedInterest.mul(reserveFactor).div(mantissaScale)); accruedFees = accruedFees.sub(_overAccruedInterest.mul(reserveFactor.sub(killerRatio)).div(mantissaScale)); //Kill the Loan _palLoan.killLoan(killer, killerRatio); //Burn the palLoanToken for this Loan require(palLoanToken.burn(_borrow.tokenId), Errors.FAIL_LOAN_TOKEN_BURN); require(controller.killBorrowVerify(address(this), killer, _borrow.loan), Errors.FAIL_KILL_BORROW); //Emit the CloseLoan Event emit CloseLoan( _loanOwner, _borrow.delegatee, address(underlying), _borrow.amount, address(this), _borrow.feesAmount, _loan, _borrow.tokenId, true ); } /** * @notice Change the delegatee of a Loan, and delegate him the voting power * @dev Change the delegatee in the Borrow struct and in the palLoan, then change the voting power delegation recipient * @param _loan Address of the Loan * @param _newDelegatee Address of the new voting power recipient */ function changeBorrowDelegatee(address _loan, address _newDelegatee) public virtual override nonReentrant { //Fetch the corresponding Borrow //And check that the caller is the Borrower, and the Loan is still active Borrow storage _borrow = loanToBorrow[_loan]; require(!_borrow.closed, Errors.LOAN_CLOSED); require(_newDelegatee != address(0), Errors.ZERO_ADDRESS); require(isLoanOwner(_loan, msg.sender), Errors.NOT_LOAN_OWNER); require(_updateInterest()); //Load the Loan Pool contract IPalLoan _palLoan = IPalLoan(_borrow.loan); //Update storage data _borrow.delegatee = _newDelegatee; //Call the delegation logic in the palLoan to change the votong power recipient require(_palLoan.changeDelegatee(_newDelegatee), Errors.FAIL_LOAN_DELEGATEE_CHANGE); //Emit the Event emit ChangeLoanDelegatee( palLoanToken.ownerOf(_borrow.tokenId), _newDelegatee, address(underlying), address(this), _borrow.loan, _borrow.tokenId ); } /** * @notice Return the user's palToken balance * @dev Links the PalToken balanceOf() method * @param _account User address * @return uint256 : user palToken balance (in wei) */ function balanceOf(address _account) public view override returns(uint){ return palToken.balanceOf(_account); } /** * @notice Return the corresponding balance of the pool underlying token depending on the user's palToken balance * @param _account User address * @return uint256 : corresponding balance in the underlying token (in wei) */ function underlyingBalanceOf(address _account) external view override returns(uint){ uint _balance = palToken.balanceOf(_account); if(_balance == 0){ return 0; } uint _exchRate = _exchangeRate(); uint _num = _balance.mul(_exchRate); return _num.div(mantissaScale); } /** * @notice Return true is the given address is the owner of the palLoanToken for the given palLoan * @param _loanAddress Address of the Loan * @param _user User address * @return bool : true if owner */ function isLoanOwner(address _loanAddress, address _user) public view override returns(bool){ return palLoanToken.allOwnerOf(idOfLoan(_loanAddress)) == _user; } /** * @notice Return the token Id of the palLoanToken linked to this palLoan * @param _loanAddress Address of the Loan * @return uint256 : palLoanToken token Id */ function idOfLoan(address _loanAddress) public view override returns(uint256){ return loanToBorrow[_loanAddress].tokenId; } /** * @notice Return the list of all Loans for this Pool (closed and active) * @return address[] : list of Loans */ function getLoansPools() external view override returns(address [] memory){ //Return the addresses of all loans (old ones and active ones) return loans; } /** * @notice Return all the Loans for a given address * @param _borrower Address of the user * @return address : list of Loans */ function getLoansByBorrower(address _borrower) external view override returns(address [] memory){ return palLoanToken.allLoansOfForPool(_borrower, address(this)); } /** * @notice Return the stored Borrow data for a given Loan * @dev Return the Borrow data for a given Loan * @param _loanAddress Address of the palLoan * Composants of a Borrow struct */ function getBorrowData(address _loanAddress) external view override returns( address _borrower, address _delegatee, address _loan, uint256 _palLoanTokenId, uint _amount, address _underlying, uint _feesAmount, uint _feesUsed, uint _startBlock, uint _closeBlock, bool _closed, bool _killed ){ //Return the data inside a Borrow struct Borrow memory _borrow = loanToBorrow[_loanAddress]; return ( //Get the Loan owner through the ERC721 contract palLoanToken.allOwnerOf(_borrow.tokenId), _borrow.delegatee, _borrow.loan, _borrow.tokenId, _borrow.amount, _borrow.underlying, _borrow.feesAmount, //Calculate amount of fees used _borrow.closed ? _borrow.feesUsed : (_borrow.amount.mul(borrowIndex).div(_borrow.borrowIndex)).sub(_borrow.amount), _borrow.startBlock, _borrow.closeBlock, _borrow.closed, _borrow.killed ); } /** * @notice Get the Borrow Rate for this Pool * @dev Get the Borrow Rate from the Interest Module * @return uint : Borrow Rate (scale 1e18) */ function borrowRatePerBlock() external view override returns (uint){ return interestModule.getBorrowRate(address(this), underlyingBalance(), totalBorrowed, totalReserve); } /** * @notice Get the Supply Rate for this Pool * @dev Get the Supply Rate from the Interest Module * @return uint : Supply Rate (scale 1e18) */ function supplyRatePerBlock() external view override returns (uint){ return interestModule.getSupplyRate(address(this), underlyingBalance(), totalBorrowed, totalReserve, reserveFactor); } /** * @dev Calculates the current exchange rate * @return uint : current exchange rate (scale 1e18) */ function _exchangeRate() internal view returns (uint){ uint _totalSupply = palToken.totalSupply(); //If no palTokens where minted, use the initial exchange rate if(_totalSupply == 0){ return initialExchangeRate; } else{ // Exchange Rate = (Cash + Borrows - Reserve) / Supply uint _cash = underlyingBalance(); uint _availableCash = _cash.add(totalBorrowed).sub(totalReserve); return _availableCash.mul(1e18).div(_totalSupply); } } /** * @notice Get the current exchange rate for the palToken * @dev Updates interest & Calls internal function _exchangeRate * @return uint : current exchange rate (scale 1e18) */ function exchangeRateCurrent() external override returns (uint){ _updateInterest(); return _exchangeRate(); } /** * @notice Get the stored exchange rate for the palToken * @dev Calls internal function _exchangeRate * @return uint : current exchange rate (scale 1e18) */ function exchangeRateStored() external view override returns (uint){ return _exchangeRate(); } /** * @notice Return the minimum of fees to pay to borrow * @dev Fees to pay for a Borrow (for the minimum borrow length) * @return uint : minimum amount (in wei) */ function minBorrowFees(uint _amount) public view override returns (uint){ require(_amount < underlyingBalance(), Errors.INSUFFICIENT_CASH); //Future Borrow Rate with the amount to borrow counted as already borrowed uint _borrowRate = interestModule.getBorrowRate(address(this), underlyingBalance().sub(_amount), totalBorrowed.add(_amount), totalReserve); uint _minFees = minBorrowLength.mul(_amount.mul(_borrowRate)).div(mantissaScale); return _minFees > 0 ? _minFees : 1; } function isKillable(address _loan) external view override returns(bool){ Borrow memory __borrow = loanToBorrow[_loan]; if(__borrow.closed){ return false; } //Calculate the amount of fee used, and check if the Loan is killable uint _feesUsed = (__borrow.amount.mul(borrowIndex).div(__borrow.borrowIndex)).sub(__borrow.amount); uint _loanHealthFactor = _feesUsed.mul(uint(1e18)).div(__borrow.feesAmount); return _loanHealthFactor >= killFactor; } /** * @dev Updates Inetrest and variables for this Pool * @return bool : Update success */ function _updateInterest() public returns (bool){ //Get the current block //Check if the Pool has already been updated this block uint _currentBlock = block.number; if(_currentBlock == accrualBlockNumber){ return true; } //Get Pool variables from Storage uint _cash = underlyingBalance(); uint _borrows = totalBorrowed; uint _reserves = totalReserve; uint _accruedFees = accruedFees; uint _oldBorrowIndex = borrowIndex; //Get the Borrow Rate from the Interest Module uint _borrowRate = interestModule.getBorrowRate(address(this), _cash, _borrows, _reserves); //Delta of blocks since the last update uint _ellapsedBlocks = _currentBlock.sub(accrualBlockNumber); /* Interest Factor = Borrow Rate * Ellapsed Blocks Accumulated Interests = Interest Factor * Borrows Total Borrows = Borrows + Accumulated Interests Total Reserve = Reserve + Accumulated Interests * Reserve Factor Accrued Fees = Accrued Fees + Accumulated Interests * (Reserve Factor - Killer Ratio) -> (available fees should not count potential fees to send to killers) Borrow Index = old Borrow Index + old Borrow Index * Interest Factor */ uint _interestFactor = _borrowRate.mul(_ellapsedBlocks); uint _accumulatedInterest = _interestFactor.mul(_borrows).div(mantissaScale); uint _newBorrows = _borrows.add(_accumulatedInterest); uint _newReserve = _reserves.add(reserveFactor.mul(_accumulatedInterest).div(mantissaScale)); uint _newAccruedFees = _accruedFees.add((reserveFactor.sub(killerRatio)).mul(_accumulatedInterest).div(mantissaScale)); uint _newBorrowIndex = _oldBorrowIndex.add(_interestFactor.mul(_oldBorrowIndex).div(1e18)); //Update storage totalBorrowed = _newBorrows; totalReserve = _newReserve; accruedFees = _newAccruedFees; borrowIndex = _newBorrowIndex; accrualBlockNumber = _currentBlock; return true; } // Admin Functions /** * @notice Set a new Controller * @dev Loads the new Controller for the Pool * @param _newController address of the new Controller */ function setNewController(address _newController) external override controllerOnly { controller = IPaladinController(_newController); } /** * @notice Set a new Interest Module * @dev Load a new Interest Module * @param _interestModule address of the new Interest Module */ function setNewInterestModule(address _interestModule) external override adminOnly { interestModule = InterestInterface(_interestModule); } /** * @notice Set a new Delegator * @dev Change Delegator address * @param _delegator address of the new Delegator */ function setNewDelegator(address _delegator) external override adminOnly { delegator = _delegator; } /** * @notice Set a new Minimum Borrow Length * @dev Change Minimum Borrow Length value * @param _length new Minimum Borrow Length */ function updateMinBorrowLength(uint _length) external override adminOnly { require(_length > 0, Errors.INVALID_PARAMETERS); minBorrowLength = _length; } /** * @notice Update the Pool Reserve Factor & Killer Ratio * @dev Change Reserve Factor value & Killer Ratio value * @param _reserveFactor new % of fees to set as Reserve * @param _killerRatio new Ratio of Fees to pay the killer */ function updatePoolFactors(uint _reserveFactor, uint _killerRatio) external override adminOnly { require(_reserveFactor > 0 && _killerRatio > 0 && _reserveFactor >= _killerRatio, Errors.INVALID_PARAMETERS ); reserveFactor = _reserveFactor; killerRatio = _killerRatio; } /** * @notice Add underlying in the Pool Reserve * @dev Transfer underlying token from the admin to the Pool * @param _amount Amount of underlying to transfer */ function addReserve(uint _amount) external override adminOnly { require(_updateInterest()); totalReserve = totalReserve.add(_amount); //Transfer from the admin to the Pool underlying.safeTransferFrom(admin, address(this), _amount); emit AddReserve(_amount); } /** * @notice Remove underlying from the Pool Reserve * @dev Transfer underlying token from the Pool to the admin * @param _amount Amount of underlying to transfer */ function removeReserve(uint _amount) external override adminOnly { //Check if there is enough in the reserve require(_updateInterest()); require(_amount <= underlyingBalance() && _amount <= totalReserve, Errors.RESERVE_FUNDS_INSUFFICIENT); totalReserve = totalReserve.sub(_amount); //Transfer underlying to the admin underlying.safeTransfer(admin, _amount); emit RemoveReserve(_amount); } /** * @notice Method to allow the Controller (or admin) to withdraw protocol fees * @dev Transfer underlying token from the Pool to the controller (or admin) * @param _amount Amount of underlying to transfer * @param _recipient Address to receive the token */ function withdrawFees(uint _amount, address _recipient) external override controllerOnly { //Check if there is enough in the reserve require(_updateInterest()); require(_amount<= accruedFees && _amount <= totalReserve, Errors.FEES_ACCRUED_INSUFFICIENT); //Substract from accruedFees (to track how much fees the Controller can withdraw since last time) //And also from the REserve, since the fees are part of the Reserve accruedFees = accruedFees.sub(_amount); totalReserve = totalReserve.sub(_amount); //Transfer fees to the recipient underlying.safeTransfer(_recipient, _amount); emit WithdrawFees(_amount); } }
pragma solidity ^0.7.6; //SPDX-License-Identifier: MIT // From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol // Subject to the MIT license. /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, errorMessage); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot underflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction underflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot underflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, errorMessage); return c; } /** * @dev Returns the integer division of two unsigned integers. * Reverts on division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. * Reverts with custom message on division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import "./IERC20.sol"; import "./SafeMath.sol"; import "./Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // 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: agpl-3.0 pragma solidity ^0.7.6; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.7.5; interface IStakedAave { function stake(address to, uint256 amount) external; function redeem(address to, uint256 amount) external; function cooldown() external; function claimRewards(address to, uint256 amount) external; function getTotalRewardsBalance(address staker) external view returns (uint256); }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; //SPDX-License-Identifier: MIT library Errors { // Admin error string public constant CALLER_NOT_ADMIN = '1'; // 'The caller must be the admin' string public constant CALLER_NOT_CONTROLLER = '29'; // 'The caller must be the admin or the controller' string public constant CALLER_NOT_ALLOWED_POOL = '30'; // 'The caller must be a palPool listed in the controller' string public constant CALLER_NOT_MINTER = '31'; // ERC20 type errors string public constant FAIL_TRANSFER = '2'; string public constant FAIL_TRANSFER_FROM = '3'; string public constant BALANCE_TOO_LOW = '4'; string public constant ALLOWANCE_TOO_LOW = '5'; string public constant SELF_TRANSFER = '6'; // PalPool errors string public constant INSUFFICIENT_CASH = '9'; string public constant INSUFFICIENT_BALANCE = '10'; string public constant FAIL_DEPOSIT = '11'; string public constant FAIL_LOAN_INITIATE = '12'; string public constant FAIL_BORROW = '13'; string public constant ZERO_BORROW = '27'; string public constant BORROW_INSUFFICIENT_FEES = '23'; string public constant LOAN_CLOSED = '14'; string public constant NOT_LOAN_OWNER = '15'; string public constant LOAN_OWNER = '16'; string public constant FAIL_LOAN_EXPAND = '17'; string public constant NOT_KILLABLE = '18'; string public constant RESERVE_FUNDS_INSUFFICIENT = '19'; string public constant FAIL_MINT = '20'; string public constant FAIL_BURN = '21'; string public constant FAIL_WITHDRAW = '24'; string public constant FAIL_CLOSE_BORROW = '25'; string public constant FAIL_KILL_BORROW = '26'; string public constant ZERO_ADDRESS = '22'; string public constant INVALID_PARAMETERS = '28'; string public constant FAIL_LOAN_DELEGATEE_CHANGE = '32'; string public constant FAIL_LOAN_TOKEN_BURN = '33'; string public constant FEES_ACCRUED_INSUFFICIENT = '34'; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @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)); } }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; pragma abicoder v2; //SPDX-License-Identifier: MIT /** @title palPool Interface */ /// @author Paladin interface IPalPool { //Events /** @notice Event when an user deposit tokens in the pool */ event Deposit(address user, uint amount, address palPool); /** @notice Event when an user withdraw tokens from the pool */ event Withdraw(address user, uint amount, address palPool); /** @notice Event when a loan is started */ event NewLoan( address borrower, address delegatee, address underlying, uint amount, address palPool, address loanAddress, uint256 palLoanTokenId, uint startBlock); /** @notice Event when the fee amount in the loan is updated */ event ExpandLoan( address borrower, address delegatee, address underlying, address palPool, uint newFeesAmount, address loanAddress, uint256 palLoanTokenId ); /** @notice Event when the delegatee of the loan is updated */ event ChangeLoanDelegatee( address borrower, address newDelegatee, address underlying, address palPool, address loanAddress, uint256 palLoanTokenId ); /** @notice Event when a loan is ended */ event CloseLoan( address borrower, address delegatee, address underlying, uint amount, address palPool, uint usedFees, address loanAddress, uint256 palLoanTokenId, bool wasKilled ); /** @notice Reserve Events */ event AddReserve(uint amount); event RemoveReserve(uint amount); event WithdrawFees(uint amount); //Functions function deposit(uint _amount) external returns(uint); function withdraw(uint _amount) external returns(uint); function borrow(address _delegatee, uint _amount, uint _feeAmount) external returns(uint); function expandBorrow(address _loanPool, uint _feeAmount) external returns(uint); function closeBorrow(address _loanPool) external; function killBorrow(address _loanPool) external; function changeBorrowDelegatee(address _loanPool, address _newDelegatee) external; function balanceOf(address _account) external view returns(uint); function underlyingBalanceOf(address _account) external view returns(uint); function isLoanOwner(address _loanAddress, address _user) external view returns(bool); function idOfLoan(address _loanAddress) external view returns(uint256); function getLoansPools() external view returns(address [] memory); function getLoansByBorrower(address _borrower) external view returns(address [] memory); function getBorrowData(address _loanAddress) external view returns( address _borrower, address _delegatee, address _loanPool, uint256 _palLoanTokenId, uint _amount, address _underlying, uint _feesAmount, uint _feesUsed, uint _startBlock, uint _closeBlock, bool _closed, bool _killed ); function borrowRatePerBlock() external view returns (uint); function supplyRatePerBlock() external view returns (uint); function exchangeRateCurrent() external returns (uint); function exchangeRateStored() external view returns (uint); function minBorrowFees(uint _amount) external view returns (uint); function isKillable(address _loan) external view returns(bool); //Admin functions : function setNewController(address _newController) external; function setNewInterestModule(address _interestModule) external; function setNewDelegator(address _delegator) external; function updateMinBorrowLength(uint _length) external; function updatePoolFactors(uint _reserveFactor, uint _killerRatio) external; function addReserve(uint _amount) external; function removeReserve(uint _amount) external; function withdrawFees(uint _amount, address _recipient) external; }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; //SPDX-License-Identifier: MIT import "./IPaladinController.sol"; import "./IPalLoanToken.sol"; import "./interests/InterestInterface.sol"; import "./IPalPool.sol"; import "./IPalToken.sol"; import "./utils/IERC20.sol"; /** @title palPool Storage contract */ /// @author Paladin contract PalPoolStorage { /** @notice Struct of a Borrow */ struct Borrow { //id of the palLoanToken uint256 tokenId; //address of the delegatee address delegatee; //address of the Loan Pool contract holding the loan address loan; //amount of the loan uint amount; //address of the underlying for this loan address underlying; //amount of fees (in the underlying token) paid by the borrower uint feesAmount; //amount of fees (in the underlying token) already used uint feesUsed; //borrow index at the loan creation uint borrowIndex; //start block for the Borrow uint startBlock; //block where the Borrow was closed uint closeBlock; //false if the loan is active, true if loan was closed or killed bool closed; //false when the loan is active, true if the loan was killed bool killed; } //palPool variables & Mappings /** @notice ERC721 palLoanToken */ IPalLoanToken public palLoanToken; /** @notice Underlying ERC20 token of this Pool */ IERC20 public underlying; /** @notice ERC20 palToken for this Pool */ IPalToken public palToken; /** @dev Boolean to prevent reentry in some functions */ bool internal entered = false; /** @notice Total of the current Reserve */ uint public totalReserve; /** @notice Total of underlying tokens "borrowed" (in Loan Pool contracts) */ uint public totalBorrowed; /** @notice Total fees accrued since last withdraw */ /** (this amount id part of the Reserve : we should always have totalReserve >= accruedFees) */ uint public accruedFees; /** @notice Minimum duration of a Borrow (in blocks) */ uint public minBorrowLength = 45290; /** @dev Health Factor to kill a loan */ uint public constant killFactor = 0.95e18; /** @dev Ratio of the borrow fees to pay the killer of a loan */ uint public killerRatio = 0.1e18; /** @dev Base value to mint palTokens */ uint internal constant initialExchangeRate = 1e18; /** @notice Part of the borrows interest to set as Reserves */ uint public reserveFactor = 0.2e18; /** @notice Last block where the interest where updated for this pool */ uint public accrualBlockNumber; /** @notice Borrow Index : increase at each interest update to represent borrows interests increasing (scaled 1e36) */ uint public borrowIndex; /** @dev Scale used to represent decimal values */ uint constant internal mantissaScale = 1e18; /** @dev Mapping of Loan Pool contract address to Borrow struct */ mapping (address => Borrow) internal loanToBorrow; /** @dev List of all loans (current & closed) */ address[] internal loans; //Modules /** @notice Paladin Controller contract */ IPaladinController public controller; /** @dev Current Inetrest Module */ InterestInterface internal interestModule; /** @dev Delegator for the underlying governance token */ address internal delegator; }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; //SPDX-License-Identifier: MIT /** @title Interface for PalLoan contract */ /// @author Paladin interface IPalLoan { // Variables function underlying() external view returns(address); function amount() external view returns(uint); function borrower() external view returns(address); function delegatee() external view returns(address); function motherPool() external view returns(address); function feesAmount() external view returns(uint); // Functions function initiate( address _motherPool, address _borrower, address _underlying, address _delegatee, uint _amount, uint _feesAmount ) external returns(bool); function expand(uint _newFeesAmount) external returns(bool); function closeLoan(uint _usedAmount) external; function killLoan(address _killer, uint _killerRatio) external; function changeDelegatee(address _delegatee) external returns(bool); }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; //SPDX-License-Identifier: MIT /** @title simple PalToken Interface to be used inside the PalPool contract */ /// @author Paladin interface IPalToken { function mint(address _user, uint _toMint) external returns(bool); function burn(address _user, uint _toBurn) external returns(bool); function balanceOf(address owner) external view returns(uint); function totalSupply() external view returns (uint256); }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; //SPDX-License-Identifier: MIT /** @title Paladin Controller Interface */ /// @author Paladin interface IPaladinController { //Events /** @notice Event emitted when a new token & pool are added to the list */ event NewPalPool(address palPool, address palToken); /** @notice Event emitted when a token & pool are removed from the list */ event RemovePalPool(address palPool, address palToken); //Functions function isPalPool(address pool) external view returns(bool); function getPalTokens() external view returns(address[] memory); function getPalPools() external view returns(address[] memory); function setInitialPools(address[] memory palTokens, address[] memory palPools) external returns(bool); function addNewPool(address palToken, address palPool) external returns(bool); function removePool(address _palPool) external returns(bool); function withdrawPossible(address palPool, uint amount) external view returns(bool); function borrowPossible(address palPool, uint amount) external view returns(bool); function depositVerify(address palPool, address dest, uint amount) external view returns(bool); function withdrawVerify(address palPool, address dest, uint amount) external view returns(bool); function borrowVerify(address palPool, address borrower, address delegatee, uint amount, uint feesAmount, address loanAddress) external view returns(bool); function expandBorrowVerify(address palPool, address loanAddress, uint newFeesAmount) external view returns(bool); function closeBorrowVerify(address palPool, address borrower, address loanAddress) external view returns(bool); function killBorrowVerify(address palPool, address killer, address loanAddress) external view returns(bool); //Admin functions function setPoolsNewController(address _newController) external returns(bool); function withdrawFromPool(address _pool, uint _amount, address _recipient) external returns(bool); }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; pragma abicoder v2; //SPDX-License-Identifier: MIT import "./utils/IERC721.sol"; /** @title palLoanToken Interface */ /// @author Paladin interface IPalLoanToken is IERC721 { //Events /** @notice Event when a new Loan Token is minted */ event NewLoanToken(address palPool, address indexed owner, address indexed palLoan, uint256 indexed tokenId); /** @notice Event when a Loan Token is burned */ event BurnLoanToken(address palPool, address indexed owner, address indexed palLoan, uint256 indexed tokenId); //Functions function mint(address to, address palPool, address palLoan) external returns(uint256); function burn(uint256 tokenId) external returns(bool); function tokenURI(uint256 tokenId) external view returns (string memory); function tokenOfByIndex(address owner, uint256 tokenIdex) external view returns (uint256); function loanOf(uint256 tokenId) external view returns(address); function poolOf(uint256 tokenId) external view returns(address); function loansOf(address owner) external view returns(address[] memory); function tokensOf(address owner) external view returns(uint256[] memory); function loansOfForPool(address owner, address palPool) external view returns(address[] memory); function allTokensOf(address owner) external view returns(uint256[] memory); function allLoansOf(address owner) external view returns(address[] memory); function allLoansOfForPool(address owner, address palPool) external view returns(address[] memory); function allOwnerOf(uint256 tokenId) external view returns(address); function isBurned(uint256 tokenId) external view returns(bool); //Admin functions function setNewController(address _newController) external; function setNewBaseURI(string memory _newBaseURI) external; }
//██████╗ █████╗ ██╗ █████╗ ██████╗ ██╗███╗ ██╗ //██╔══██╗██╔══██╗██║ ██╔══██╗██╔══██╗██║████╗ ██║ //██████╔╝███████║██║ ███████║██║ ██║██║██╔██╗ ██║ //██╔═══╝ ██╔══██║██║ ██╔══██║██║ ██║██║██║╚██╗██║ //██║ ██║ ██║███████╗██║ ██║██████╔╝██║██║ ╚████║ //╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ pragma solidity ^0.7.6; //SPDX-License-Identifier: MIT /** @title Interest Module Interface */ /// @author Paladin interface InterestInterface { function getSupplyRate(address palPool, uint cash, uint borrows, uint reserves, uint reserveFactor) external view returns(uint); function getBorrowRate(address palPool, uint cash, uint borrows, uint reserves) external view returns(uint); }
pragma solidity ^0.7.6; //SPDX-License-Identifier: MIT /** @title Admin contract */ /// @author Paladin contract Admin { /** @notice (Admin) Event when the contract admin is updated */ event NewAdmin(address oldAdmin, address newAdmin); /** @dev Admin address for this contract */ address payable internal admin; modifier adminOnly() { //allows only the admin of this contract to call the function require(msg.sender == admin, '1'); _; } /** * @notice Set a new Admin * @dev Changes the address for the admin parameter * @param _newAdmin address of the new Controller Admin */ function setNewAdmin(address payable _newAdmin) external adminOnly { address _oldAdmin = admin; admin = _newAdmin; emit NewAdmin(_oldAdmin, _newAdmin); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ 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: MIT pragma solidity ^0.7.6; import "./IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "optimizer": { "enabled": true, "runs": 25000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
[{"inputs":[{"internalType":"address","name":"_palToken","type":"address"},{"internalType":"address","name":"_controller","type":"address"},{"internalType":"address","name":"_underlying","type":"address"},{"internalType":"address","name":"_interestModule","type":"address"},{"internalType":"address","name":"_delegator","type":"address"},{"internalType":"address","name":"_palLoanToken","type":"address"},{"internalType":"address","name":"_aaveAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AddReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"newDelegatee","type":"address"},{"indexed":false,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"address","name":"palPool","type":"address"},{"indexed":false,"internalType":"address","name":"loanAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"palLoanTokenId","type":"uint256"}],"name":"ChangeLoanDelegatee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"delegatee","type":"address"},{"indexed":false,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"palPool","type":"address"},{"indexed":false,"internalType":"uint256","name":"usedFees","type":"uint256"},{"indexed":false,"internalType":"address","name":"loanAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"palLoanTokenId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"wasKilled","type":"bool"}],"name":"CloseLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"palPool","type":"address"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"delegatee","type":"address"},{"indexed":false,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"address","name":"palPool","type":"address"},{"indexed":false,"internalType":"uint256","name":"newFeesAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"loanAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"palLoanTokenId","type":"uint256"}],"name":"ExpandLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"delegatee","type":"address"},{"indexed":false,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"palPool","type":"address"},{"indexed":false,"internalType":"address","name":"loanAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"palLoanTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"}],"name":"NewLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RemoveReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"palPool","type":"address"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawFees","type":"event"},{"inputs":[],"name":"_updateInterest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accrualBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accruedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_delegatee","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_feeAmount","type":"uint256"}],"name":"borrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrowIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_loan","type":"address"},{"internalType":"address","name":"_newDelegatee","type":"address"}],"name":"changeBorrowDelegatee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_loan","type":"address"}],"name":"closeBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IPaladinController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeRateCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeRateStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_loan","type":"address"},{"internalType":"uint256","name":"_feeAmount","type":"uint256"}],"name":"expandBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_loanAddress","type":"address"}],"name":"getBorrowData","outputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address","name":"_delegatee","type":"address"},{"internalType":"address","name":"_loan","type":"address"},{"internalType":"uint256","name":"_palLoanTokenId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_underlying","type":"address"},{"internalType":"uint256","name":"_feesAmount","type":"uint256"},{"internalType":"uint256","name":"_feesUsed","type":"uint256"},{"internalType":"uint256","name":"_startBlock","type":"uint256"},{"internalType":"uint256","name":"_closeBlock","type":"uint256"},{"internalType":"bool","name":"_closed","type":"bool"},{"internalType":"bool","name":"_killed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"}],"name":"getLoansByBorrower","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLoansPools","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_loanAddress","type":"address"}],"name":"idOfLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_loan","type":"address"}],"name":"isKillable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_loanAddress","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"isLoanOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_loan","type":"address"}],"name":"killBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"killFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"killerRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"minBorrowFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minBorrowLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"palLoanToken","outputs":[{"internalType":"contract IPalLoanToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"palToken","outputs":[{"internalType":"contract IPalToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"removeReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newAdmin","type":"address"}],"name":"setNewAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newController","type":"address"}],"name":"setNewController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegator","type":"address"}],"name":"setNewDelegator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_interestModule","type":"address"}],"name":"setNewInterestModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBorrowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"underlyingBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"updateMinBorrowLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reserveFactor","type":"uint256"},{"internalType":"uint256","name":"_killerRatio","type":"uint256"}],"name":"updatePoolFactors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040526002805460ff60a01b1916905561b0ea60065567016345785d8a00006007556702c68af0bb14000060085560006012553480156200004157600080fd5b506040516200514738038062005147833981016040819052620000649162000133565b6001601181905560108054336001600160a01b0319918216179091556002805482166001600160a01b039a8b16179055600d80548216988a16989098179097558054871686891617905543600955600e80548716948816949094179093556ec097ce7bc90715b34b9f1000000000600a55600f805486169287169290921790915560008054909416941693909317909155606090811b6001600160601b031990811660805291901b1660a052620001c7565b80516001600160a01b03811681146200012e57600080fd5b919050565b600080600080600080600060e0888a0312156200014e578283fd5b620001598862000116565b9650620001696020890162000116565b9550620001796040890162000116565b9450620001896060890162000116565b9350620001996080890162000116565b9250620001a960a0890162000116565b9150620001b960c0890162000116565b905092959891949750929550565b60805160601c60a05160601c614f51620001f660003980611a2b525080611a4d5280611c195250614f516000f3fe608060405234801561001057600080fd5b50600436106102ff5760003560e01c806371bfbd4e1161019c578063b6331d46116100ee578063c7f3b6b111610097578063dd2cc3f311610071578063dd2cc3f3146105a8578063f77c4791146105bb578063f8f9da28146105c3576102ff565b8063c7f3b6b11461056f578063d4a3109d14610582578063d5c4a11714610595576102ff565b8063c1bce0b7116100c8578063c1bce0b71461051e578063c1c55d0c14610531578063c5d40b8a14610544576102ff565b8063b6331d46146104fb578063b6b55f2514610503578063bd6d894d14610516576102ff565b806393610b8d11610150578063a764804f1161012a578063a764804f146104d8578063aa5af0fd146104eb578063ae9d70b0146104f3576102ff565b806393610b8d146104aa5780639bdaa5e6146104bd578063a0187e8a146104d0576102ff565b806386a2a4381161018157806386a2a438146104715780638eec99c814610484578063935a8b8414610497576102ff565b806371bfbd4e146104565780637312520214610469576102ff565b8063516e2f2a11610255578063622d2efc116102095780636c540baf116101e35780636c540baf146104335780636f307dc31461043b57806370a0823114610443576102ff565b8063622d2efc146104035780636558d7b114610423578063682c20581461042b576102ff565b806357d1bc961161023a57806357d1bc96146103d557806359356c5c146103e857806359baef40146103f0576102ff565b8063516e2f2a146103af578063560acbc2146103c2576102ff565b8063304d5f07116102b75780634b8243c9116102915780634b8243c91461038a5780634c19386c1461039f5780634c68df67146103a7576102ff565b8063304d5f07146103655780634322b7141461036d5780634754990314610375576102ff565b80631e348629116102e85780631e348629146103355780632d66da9f1461033d5780632e1a7d4d14610352576102ff565b8063130cbe5c14610304578063182df0f51461032d575b600080fd5b61031761031236600461490c565b6105cb565b6040516103249190614e7c565b60405180910390f35b6103176105f1565b610317610601565b610345610607565b6040516103249190614db3565b610317610360366004614a40565b610669565b61031761068d565b610317610693565b61037d610699565b6040516103249190614ab5565b61039d610398366004614a40565b6106a8565b005b610317610780565b610317610786565b61039d6103bd36600461489c565b61078c565b61039d6103d0366004614a40565b610825565b61039d6103e3366004614a40565b610968565b610317610a1f565b61039d6103fe36600461489c565b610ab9565b6104166104113660046148d4565b610b6b565b6040516103249190614e00565b610317610c07565b610317610c0d565b610317610c13565b61037d610c19565b61031761045136600461489c565b610c28565b61039d61046436600461489c565b610cc2565b610416610cdf565b61034561047f36600461489c565b610eb8565b61039d61049236600461489c565b610f76565b6103176104a536600461489c565b611050565b61039d6104b8366004614a94565b611134565b6103176104cb36600461489c565b61120f565b61037d61122a565b61039d6104e636600461489c565b611239565b6103176112d2565b6103176112d8565b610317611337565b610317610511366004614a40565b611343565b61031761135f565b61031761052c366004614937565b611372565b61041661053f36600461489c565b61139a565b61055761055236600461489c565b6114cb565b6040516103249c9b9a99989796959493929190614cf1565b61039d61057d36600461489c565b6116b6565b61039d6105903660046148d4565b6116d0565b6103176105a3366004614a40565b6116ef565b61039d6105b6366004614a70565b611831565b61037d611995565b6103176119a4565b60006105d5611a00565b6105de57600080fd5b6105e88383611cd3565b90505b92915050565b60006105fb612063565b90505b90565b60125481565b6060600c80548060200260200160405190810160405280929190818152602001828054801561065f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610641575b5050505050905090565b6000610673611a00565b61067c57600080fd5b6106858261214f565b90505b919050565b60075481565b60085481565b6002546001600160a01b031681565b6010546001600160a01b03163314610707576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b61070f610cdf565b61071857600080fd5b60035461072590826124f3565b600355601054600154610746916001600160a01b039182169116308461254d565b7fa3e421ddc9810d39cc90c4a3998578420d1c1ebc5b67a3c133c4044a1114de99816040516107759190614e7c565b60405180910390a150565b60045481565b60035481565b6010546001600160a01b031633146107eb576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6010546001600160a01b03163314610884576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b61088c610cdf565b61089557600080fd5b61089d610a1f565b81111580156108ae57506003548111155b6040518060400160405280600281526020017f31390000000000000000000000000000000000000000000000000000000000008152509061090b5760405162461bcd60e51b81526004016109029190614e0b565b60405180910390fd5b5060035461091990826125db565b600355601054600154610939916001600160a01b0391821691168361261d565b7ff78dc30da85b5e9540c710154f60a2e296f1461551b7995ef2c7112e3c2be9c3816040516107759190614e7c565b6010546001600160a01b031633146109c7576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60408051808201909152600281527f3238000000000000000000000000000000000000000000000000000000000000602082015281610a195760405162461bcd60e51b81526004016109029190614e0b565b50600655565b6001546040517f70a082310000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906370a0823190610a69903090600401614ab5565b60206040518083038186803b158015610a8157600080fd5b505afa158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fb9190614a58565b6010546001600160a01b0316331480610adc5750600d546001600160a01b031633145b6040518060400160405280600281526020017f323900000000000000000000000000000000000000000000000000000000000081525090610b305760405162461bcd60e51b81526004016109029190614e0b565b50600d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080546001600160a01b038084169116632d7254e5610b8a8661120f565b6040518263ffffffff1660e01b8152600401610ba69190614e7c565b60206040518083038186803b158015610bbe57600080fd5b505afa158015610bd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf691906148b8565b6001600160a01b0316149392505050565b60065481565b60055481565b60095481565b6001546001600160a01b031681565b6002546040517f70a082310000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906370a0823190610c72908590600401614ab5565b60206040518083038186803b158015610c8a57600080fd5b505afa158015610c9e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106859190614a58565b610cca611a00565b610cd357600080fd5b610cdc816126a2565b50565b6009546000904390811415610cf85760019150506105fe565b6000610d02610a1f565b60048054600354600554600a54600e546040517f200d16aa00000000000000000000000000000000000000000000000000000000815296975093959294919390926000926001600160a01b039092169163200d16aa91610d6a9130918b918b918b9101614d5f565b60206040518083038186803b158015610d8257600080fd5b505afa158015610d96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dba9190614a58565b90506000610dd3600954896125db90919063ffffffff16565b90506000610de18383612dd7565b90506000610e01670de0b6b3a7640000610dfb848b612dd7565b90612e30565b90506000610e0f89836124f3565b90506000610e3e610e37670de0b6b3a7640000610dfb86600854612dd790919063ffffffff16565b8a906124f3565b90506000610e72610e37670de0b6b3a7640000610dfb87610e6c6007546008546125db90919063ffffffff16565b90612dd7565b90506000610e8f610e37670de0b6b3a7640000610dfb898d612dd7565b60049490945550600391909155600555600a555050506009969096555060019550505050505090565b6000546040517f6a2291650000000000000000000000000000000000000000000000000000000081526060916001600160a01b031690636a22916590610f049085903090600401614b05565b60006040518083038186803b158015610f1c57600080fd5b505afa158015610f30573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610685919081019061496b565b6010546001600160a01b03163314610fd5576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b601080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040805191909216808252602082019390935281517ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc929181900390910190a15050565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815260009182916001600160a01b03909116906370a082319061109e908690600401614ab5565b60206040518083038186803b1580156110b657600080fd5b505afa1580156110ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ee9190614a58565b9050806110ff576000915050610688565b6000611109612063565b905060006111178383612dd7565b905061112b81670de0b6b3a7640000612e30565b95945050505050565b6010546001600160a01b03163314611193576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000821180156111a35750600081115b80156111af5750808210155b6040518060400160405280600281526020017f3238000000000000000000000000000000000000000000000000000000000000815250906112035760405162461bcd60e51b81526004016109029190614e0b565b50600891909155600755565b6001600160a01b03166000908152600b602052604090205490565b6000546001600160a01b031681565b6010546001600160a01b03163314611298576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600a5481565b600e546000906001600160a01b031663e4ef277a306112f5610a1f565b600480546003546008546040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b168152610a6996959401614d85565b670d2f13f7789f000081565b600061134d611a00565b61135657600080fd5b61068582612e72565b6000611369610cdf565b506105fb612063565b600061137c611a00565b61138557600080fd5b611390848484613157565b90505b9392505050565b6001600160a01b038082166000908152600b6020908152604080832081516101808101835281548152600182015486169381019390935260028101548516918301919091526003810154606083015260048101549093166080820152600583015460a0820152600683015460c0820152600783015460e08201526008830154610100808301919091526009840154610120830152600a9093015460ff80821615801561014085015294909104161515610160820152909161145f576000915050610688565b6000611490826060015161148a8460e00151610dfb600a548760600151612dd790919063ffffffff16565b906125db565b905060006114b78360a00151610dfb670de0b6b3a764000085612dd790919063ffffffff16565b670d2f13f7789f0000111595945050505050565b6001600160a01b038082166000908152600b602090815260408083208151610180810183528154808252600183015487169482019490945260028201548616818401526003820154606082015260048083015487166080830152600583015460a0830152600683015460c0830152600783015460e08301526008830154610100808401919091526009840154610120840152600a9093015460ff80821615156101408501529390049092161515610160820152845492517f2d7254e5000000000000000000000000000000000000000000000000000000008152949586958695869586958695869586958695869586958695949190911692632d7254e5926115d592909101614e7c565b60206040518083038186803b1580156115ed57600080fd5b505afa158015611601573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162591906148b8565b6020820151604083015183516060850151608086015160a087015161014088015161167057606088015160e0890151600a5461166b929161148a91610dfb908490612dd7565b611676565b8760c001515b8861010001518961012001518a61014001518b61016001519c509c509c509c509c509c509c509c509c509c509c509c505091939597999b5091939597999b565b6116be611a00565b6116c757600080fd5b610cdc816138a2565b6116d8611a00565b6116e157600080fd5b6116eb8282613f64565b5050565b60006116f9610a1f565b82106040518060400160405280600181526020017f39000000000000000000000000000000000000000000000000000000000000008152509061174f5760405162461bcd60e51b81526004016109029190614e0b565b50600e546000906001600160a01b031663200d16aa306117718661148a610a1f565b60045461177e90886124f3565b6003546040518563ffffffff1660e01b81526004016117a09493929190614d5f565b60206040518083038186803b1580156117b857600080fd5b505afa1580156117cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f09190614a58565b90506000611816670de0b6b3a7640000610dfb61180d8786612dd7565b60065490612dd7565b905060008111611827576001611829565b805b949350505050565b6010546001600160a01b03163314806118545750600d546001600160a01b031633145b6040518060400160405280600281526020017f3239000000000000000000000000000000000000000000000000000000000000815250906118a85760405162461bcd60e51b81526004016109029190614e0b565b506118b1610cdf565b6118ba57600080fd5b60055482111580156118ce57506003548211155b6040518060400160405280600281526020017f3334000000000000000000000000000000000000000000000000000000000000815250906119225760405162461bcd60e51b81526004016109029190614e0b565b5060055461193090836125db565b60055560035461194090836125db565b60035560015461195a906001600160a01b0316828461261d565b7f835862a12039ab712842887f732f62f9ba4e46c8a157b8f2ece290bb03cb6229826040516119899190614e7c565b60405180910390a15050565b600d546001600160a01b031681565b600e546000906001600160a01b031663200d16aa306119c1610a1f565b600480546003546040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b168152610a6995949301614d5f565b6040517f8dbefee20000000000000000000000000000000000000000000000000000000081526000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009083906001600160a01b03831690638dbefee290611a8e903090600401614ab5565b60206040518083038186803b158015611aa657600080fd5b505afa158015611aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ade9190614a58565b9050600081118015611af257504360125414155b15611cc9576040517f9a99b4f00000000000000000000000000000000000000000000000000000000081526001600160a01b03831690639a99b4f090611b3e9030908590600401614ac9565b600060405180830381600087803b158015611b5857600080fd5b505af1158015611b6c573d6000803e3d6000fd5b50506040517f70a08231000000000000000000000000000000000000000000000000000000008152600092506001600160a01b03861691506370a0823190611bb8903090600401614ab5565b60206040518083038186803b158015611bd057600080fd5b505afa158015611be4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c089190614a58565b9050611c3e6001600160a01b0385167f000000000000000000000000000000000000000000000000000000000000000083614324565b6040517fadc9772e0000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063adc9772e90611c859030908590600401614ac9565b600060405180830381600087803b158015611c9f57600080fd5b505af1158015611cb3573d6000803e3d6000fd5b50504360125550600195506105fe945050505050565b6001935050505090565b600060026011541415611d2d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260118190556001600160a01b0384166000908152600b6020908152604091829020600a81015483518085019094529383527f3134000000000000000000000000000000000000000000000000000000000000918301919091529160ff1615611daa5760405162461bcd60e51b81526004016109029190614e0b565b50611db58433610b6b565b6040518060400160405280600281526020017f313500000000000000000000000000000000000000000000000000000000000081525090611e095760405162461bcd60e51b81526004016109029190614e0b565b5060008311611e1757600080fd5b611e1f610cdf565b611e2857600080fd5b60028101546000805483546040517f6352211e0000000000000000000000000000000000000000000000000000000081526001600160a01b039485169490921691636352211e91611e7b91600401614e7c565b60206040518083038186803b158015611e9357600080fd5b505afa158015611ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ecb91906148b8565b6005840154909150611edd90866124f3565b60058401556002830154600154611f03916001600160a01b03918216918491168861254d565b6040517f682904a50000000000000000000000000000000000000000000000000000000081526001600160a01b0383169063682904a590611f48908890600401614e7c565b602060405180830381600087803b158015611f6257600080fd5b505af1158015611f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9a9190614a20565b6040518060400160405280600281526020017f313700000000000000000000000000000000000000000000000000000000000081525090611fee5760405162461bcd60e51b81526004016109029190614e0b565b5060018381015490546005850154600286015486546040517f23d5462a0f15711328244c2dee4e7c32ae4c4f8f74faad197b67566f38b021e79561204c9588956001600160a01b039283169591831694309491939092169190614ba1565b60405180910390a150506001601155509092915050565b600080600260009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120b457600080fd5b505afa1580156120c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ec9190614a58565b90508061210457670de0b6b3a76400009150506105fe565b600061210e610a1f565b9050600061212d60035461148a600454856124f390919063ffffffff16565b905061214583610dfb83670de0b6b3a7640000612dd7565b93505050506105fe565b6000600260115414156121a9576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026011556121b6610cdf565b6121bf57600080fd5b816121c933610c28565b10156040518060400160405280600281526020017f31300000000000000000000000000000000000000000000000000000000000008152509061221f5760405162461bcd60e51b81526004016109029190614e0b565b50600061222a612063565b905060006122388483612dd7565b9050600061224e82670de0b6b3a7640000612e30565b9050612258610a1f565b8111156040518060400160405280600181526020017f3900000000000000000000000000000000000000000000000000000000000000815250906122af5760405162461bcd60e51b81526004016109029190614e0b565b506002546040517f9dc29fac0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690639dc29fac906122fb9033908990600401614ac9565b602060405180830381600087803b15801561231557600080fd5b505af1158015612329573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234d9190614a20565b6040518060400160405280600281526020017f3231000000000000000000000000000000000000000000000000000000000000815250906123a15760405162461bcd60e51b81526004016109029190614e0b565b506001546123b9906001600160a01b0316338361261d565b600d546040517f5c0d1b0d0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690635c0d1b0d9061240690309033908690600401614b1f565b60206040518083038186803b15801561241e57600080fd5b505afa158015612432573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124569190614a20565b6040518060400160405280600281526020017f3234000000000000000000000000000000000000000000000000000000000000815250906124aa5760405162461bcd60e51b81526004016109029190614e0b565b507f56c54ba9bd38d8fd62012e42c7ee564519b09763c426d331b3661b537ead19b23386306040516124de93929190614ae2565b60405180910390a16001601155949350505050565b6000828201838110156105e8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526125d590859061447a565b50505050565b60006105e883836040518060400160405280601f81526020017f536166654d6174683a207375627472616374696f6e20756e646572666c6f770081525061452b565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261269d90849061447a565b505050565b600260115414156126fa576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260118190556001600160a01b0382166000908152600b6020908152604091829020600a81015483518085019094529383527f3134000000000000000000000000000000000000000000000000000000000000918301919091529160ff16156127775760405162461bcd60e51b81526004016109029190614e0b565b506127828233610b6b565b6040518060400160405280600281526020017f3135000000000000000000000000000000000000000000000000000000000000815250906127d65760405162461bcd60e51b81526004016109029190614e0b565b506127df610cdf565b6127e857600080fd5b6000805482546040517f6352211e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691636352211e9161283291600401614e7c565b60206040518083038186803b15801561284a57600080fd5b505afa15801561285e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288291906148b8565b600283015460038401546007850154600a549394506001600160a01b03909216926000926128bb929161148a9190610dfb908490612dd7565b600654600886015491925060009183916128d591906124f3565b4310156129e957600e546000906001600160a01b031663200d16aa306128f9610a1f565b600480546003546040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b16815261293895949301614d5f565b60206040518083038186803b15801561295057600080fd5b505afa158015612964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129889190614a58565b905060006129a94361148a6006548b600801546124f390919063ffffffff16565b90506129d8670de0b6b3a7640000610dfb6129d1858c60030154612dd790919063ffffffff16565b8490612dd7565b93506129e483856124f3565b925050505b85600501548111156129fc575060058501545b600a860180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600686018190554360098701556003860154612a5290612a4990856124f3565b600454906125db565b6004556000612a6182856125db565b90506000612a86670de0b6b3a7640000610dfb60075488612dd790919063ffffffff16565b9050612ab5612aac670de0b6b3a7640000610dfb85600854612dd790919063ffffffff16565b600354906124f3565b600355600854612aea90612ad790670de0b6b3a764000090610dfb9086612dd7565b600554612ae490846124f3565b906124f3565b6005556040517fd05951a00000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063d05951a090612b32908690600401614e7c565b600060405180830381600087803b158015612b4c57600080fd5b505af1158015612b60573d6000803e3d6000fd5b50506000548a546040517f42966c680000000000000000000000000000000000000000000000000000000081526001600160a01b0390921693506342966c689250612bad91600401614e7c565b602060405180830381600087803b158015612bc757600080fd5b505af1158015612bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bff9190614a20565b6040518060400160405280600281526020017f333300000000000000000000000000000000000000000000000000000000000081525090612c535760405162461bcd60e51b81526004016109029190614e0b565b50600d5460028901546040517f08bc016e0000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926308bc016e92612ca69230928d921690600401614b43565b60206040518083038186803b158015612cbe57600080fd5b505afa158015612cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf69190614a20565b6040518060400160405280600281526020017f323500000000000000000000000000000000000000000000000000000000000081525090612d4a5760405162461bcd60e51b81526004016109029190614e0b565b507f976725bed73d37e8b46d0d5694646bfa4d33c5b84bae26b3194570f3ad53befb878960010160009054906101000a90046001600160a01b0316600160009054906101000a90046001600160a01b03168b6003015430888f8f600001546000604051612dbf99989796959493929190614c67565b60405180910390a15050600160115550505050505050565b600082612de6575060006105eb565b82820282848281612df357fe5b04146105e85760405162461bcd60e51b8152600401808060200182810382526021815260200180614e9b6021913960400191505060405180910390fd5b60006105e883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506145c2565b600060026011541415612ecc576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002601155612ed9610cdf565b612ee257600080fd5b6000612eec612063565b90506000612f0284670de0b6b3a7640000612dd7565b90506000612f108284612e30565b600154909150612f2b906001600160a01b031633308861254d565b6002546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906340c10f1990612f769033908590600401614ac9565b602060405180830381600087803b158015612f9057600080fd5b505af1158015612fa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fc89190614a20565b6040518060400160405280600281526020017f32300000000000000000000000000000000000000000000000000000000000008152509061301c5760405162461bcd60e51b81526004016109029190614e0b565b507fe31c7b8d08ee7db0afa68782e1028ef92305caeea8626633ad44d413e30f6b2f33863060405161305093929190614ae2565b60405180910390a1600d546040517f806f8ab20000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063806f8ab2906130a590309033908690600401614b1f565b60206040518083038186803b1580156130bd57600080fd5b505afa1580156130d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f59190614a20565b6040518060400160405280600281526020017f3131000000000000000000000000000000000000000000000000000000000000815250906131495760405162461bcd60e51b81526004016109029190614e0b565b506001601155949350505050565b6000600260115414156131b1576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026011556131be610a1f565b83106040518060400160405280600181526020017f3900000000000000000000000000000000000000000000000000000000000000815250906132145760405162461bcd60e51b81526004016109029190614e0b565b5060408051808201909152600281527f323200000000000000000000000000000000000000000000000000000000000060208201526001600160a01b0385166132705760405162461bcd60e51b81526004016109029190614e0b565b5060408051808201909152600281527f32370000000000000000000000000000000000000000000000000000000000006020820152836132c35760405162461bcd60e51b81526004016109029190614e0b565b506132cd836116ef565b8210156040518060400160405280600281526020017f3233000000000000000000000000000000000000000000000000000000000000815250906133245760405162461bcd60e51b81526004016109029190614e0b565b5061332d610cdf565b61333657600080fd5b600454339061334590856124f3565b600455600f54600090613360906001600160a01b0316614627565b60015490915061337a906001600160a01b0316828761261d565b600154613392906001600160a01b031683838761254d565b6001546040517f890dcf540000000000000000000000000000000000000000000000000000000081526001600160a01b038084169263890dcf54926133e692309288929116908c908c908c90600401614be1565b602060405180830381600087803b15801561340057600080fd5b505af1158015613414573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134389190614a20565b6040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152509061348c5760405162461bcd60e51b81526004016109029190614e0b565b50600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038481169190911790915581546040517f63185c420000000000000000000000000000000000000000000000000000000081529116906363185c429061353790869030908790600401614b43565b602060405180830381600087803b15801561355157600080fd5b505af1158015613565573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135899190614a58565b9050604051806101800160405280828152602001886001600160a01b03168152602001836001600160a01b03168152602001878152602001600160009054906101000a90046001600160a01b03166001600160a01b0316815260200186815260200160008152602001600a5481526020014381526020016000815260200160001515815260200160001515815250600b6000846001600160a01b03166001600160a01b031681526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506060820151816003015560808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a0160006101000a81548160ff02191690831515021790555061016082015181600a0160016101000a81548160ff021916908315150217905550905050600d60009054906101000a90046001600160a01b03166001600160a01b031663f5565ddf30858a8a8a886040518763ffffffff1660e01b815260040161379b96959493929190614cb9565b60206040518083038186803b1580156137b357600080fd5b505afa1580156137c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137eb9190614a20565b6040518060400160405280600281526020017f31330000000000000000000000000000000000000000000000000000000000008152509061383f5760405162461bcd60e51b81526004016109029190614e0b565b506001546040517f8f11691cf96727f419bd99b50853d8351f147118e4778f62bdaa8528ab3e50bb9161388b9186918b916001600160a01b03909116908b903090899089904390614c1b565b60405180910390a160016011559695505050505050565b600260115414156138fa576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260118190556001600160a01b0382166000908152600b6020908152604091829020600a81015483518085019094529383527f313400000000000000000000000000000000000000000000000000000000000091830191909152339290919060ff161561397b5760405162461bcd60e51b81526004016109029190614e0b565b506139868383610b6b565b156040518060400160405280600281526020017f3136000000000000000000000000000000000000000000000000000000000000815250906139db5760405162461bcd60e51b81526004016109029190614e0b565b506139e4610cdf565b6139ed57600080fd5b6000805482546040517f6352211e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691636352211e91613a3791600401614e7c565b60206040518083038186803b158015613a4f57600080fd5b505afa158015613a63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8791906148b8565b90506000613ab4836003015461148a8560070154610dfb600a548860030154612dd790919063ffffffff16565b90506000613adb8460050154610dfb670de0b6b3a764000085612dd790919063ffffffff16565b9050670d2f13f7789f00008110156040518060400160405280600281526020017f313800000000000000000000000000000000000000000000000000000000000081525090613b3d5760405162461bcd60e51b81526004016109029190614e0b565b506002840154600a850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911660011716610100179055600585015460068601554360098601556001600160a01b03166000670de0b6b3a7640000831115613bd8576005860154613bd39085906125db565b613bdb565b60005b90506000613c04670de0b6b3a7640000610dfb6007548a60050154612dd790919063ffffffff16565b9050613c20612a498689600301546124f390919063ffffffff16565b600455600854613c5090613c4390670de0b6b3a764000090610dfb908690612dd7565b60035461148a90846125db565b600355600754600854613c8891613c7f91670de0b6b3a764000091610dfb91613c78916125db565b8690612dd7565b600554906125db565b6005556007546040517ff8cfe49d0000000000000000000000000000000000000000000000000000000081526001600160a01b0385169163f8cfe49d91613cd3918c91600401614ac9565b600060405180830381600087803b158015613ced57600080fd5b505af1158015613d01573d6000803e3d6000fd5b505060005489546040517f42966c680000000000000000000000000000000000000000000000000000000081526001600160a01b0390921693506342966c689250613d4e91600401614e7c565b602060405180830381600087803b158015613d6857600080fd5b505af1158015613d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613da09190614a20565b6040518060400160405280600281526020017f333300000000000000000000000000000000000000000000000000000000000081525090613df45760405162461bcd60e51b81526004016109029190614e0b565b50600d5460028801546040517f716e257f0000000000000000000000000000000000000000000000000000000081526001600160a01b039283169263716e257f92613e479230928e921690600401614b43565b60206040518083038186803b158015613e5f57600080fd5b505afa158015613e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e979190614a20565b6040518060400160405280600281526020017f323600000000000000000000000000000000000000000000000000000000000081525090613eeb5760405162461bcd60e51b81526004016109029190614e0b565b507f976725bed73d37e8b46d0d5694646bfa4d33c5b84bae26b3194570f3ad53befb868860010160009054906101000a90046001600160a01b0316600160009054906101000a90046001600160a01b03168a60030154308c600501548f8e600001546001604051612dbf99989796959493929190614c67565b60026011541415613fbc576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260118190556001600160a01b0383166000908152600b6020908152604091829020600a81015483518085019094529383527f3134000000000000000000000000000000000000000000000000000000000000918301919091529160ff16156140395760405162461bcd60e51b81526004016109029190614e0b565b5060408051808201909152600281527f323200000000000000000000000000000000000000000000000000000000000060208201526001600160a01b0383166140955760405162461bcd60e51b81526004016109029190614e0b565b506140a08333610b6b565b6040518060400160405280600281526020017f3135000000000000000000000000000000000000000000000000000000000000815250906140f45760405162461bcd60e51b81526004016109029190614e0b565b506140fd610cdf565b61410657600080fd5b60028101546001820180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03858116919091179091556040517f10187c7500000000000000000000000000000000000000000000000000000000815291169081906310187c7590614184908690600401614ab5565b602060405180830381600087803b15801561419e57600080fd5b505af11580156141b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d69190614a20565b6040518060400160405280600281526020017f33320000000000000000000000000000000000000000000000000000000000008152509061422a5760405162461bcd60e51b81526004016109029190614e0b565b5060005482546040517f6352211e0000000000000000000000000000000000000000000000000000000081527f0495d9ab17c89a5018a45652488d3006feedcac9a14e348e939ffdab14705724926001600160a01b031691636352211e916142959190600401614e7c565b60206040518083038186803b1580156142ad57600080fd5b505afa1580156142c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142e591906148b8565b60015460028501548554604051614311949389936001600160a01b039182169330939290911691614b66565b60405180910390a1505060016011555050565b8015806143c35750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b15801561439557600080fd5b505afa1580156143a9573d6000803e3d6000fd5b505050506040513d60208110156143bf57600080fd5b5051155b6143fe5760405162461bcd60e51b8152600401808060200182810382526036815260200180614ee66036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261269d9084905b60006144cf826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166146e29092919063ffffffff16565b80519091501561269d578080602001905160208110156144ee57600080fd5b505161269d5760405162461bcd60e51b815260040180806020018281038252602a815260200180614ebc602a913960400191505060405180910390fd5b600081848411156145ba5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561457f578181015183820152602001614567565b50505050905090810190601f1680156145ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836146115760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561457f578181015183820152602001614567565b50600083858161461d57fe5b0495945050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f09150506001600160a01b038116610688576040805162461bcd60e51b815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015290519081900360640190fd5b60606113908484600085856146f685614825565b614747576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b602083106147a357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614766565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614805576040519150601f19603f3d011682016040523d82523d6000602084013e61480a565b606091505b509150915061481a82828661482b565b979650505050505050565b3b151590565b6060831561483a575081611393565b82511561484a5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561457f578181015183820152602001614567565b805161068881614e85565b6000602082840312156148ad578081fd5b81356105e881614e85565b6000602082840312156148c9578081fd5b81516105e881614e85565b600080604083850312156148e6578081fd5b82356148f181614e85565b9150602083013561490181614e85565b809150509250929050565b6000806040838503121561491e578182fd5b823561492981614e85565b946020939093013593505050565b60008060006060848603121561494b578081fd5b833561495681614e85565b95602085013595506040909401359392505050565b6000602080838503121561497d578182fd5b825167ffffffffffffffff80821115614994578384fd5b818501915085601f8301126149a7578384fd5b8151818111156149b357fe5b838102604051858282010181811085821117156149cc57fe5b604052828152858101935084860182860187018a10156149ea578788fd5b8795505b83861015614a13576149ff81614891565b8552600195909501949386019386016149ee565b5098975050505050505050565b600060208284031215614a31578081fd5b815180151581146105e8578182fd5b600060208284031215614a51578081fd5b5035919050565b600060208284031215614a69578081fd5b5051919050565b60008060408385031215614a82578182fd5b82359150602083013561490181614e85565b60008060408385031215614aa6578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b039687168152948616602086015292851660408501529084166060840152909216608082015260a081019190915260c00190565b6001600160a01b039788168152958716602087015293861660408601529185166060850152608084015290921660a082015260c081019190915260e00190565b6001600160a01b0396871681529486166020860152928516604085015293166060830152608082019290925260a081019190915260c00190565b6001600160a01b039889168152968816602088015294871660408701526060860193909352908516608085015290931660a083015260c082019290925260e08101919091526101000190565b6001600160a01b03998a168152978916602089015295881660408801526060870194909452918616608086015260a085015290931660c083015260e08201929092529015156101008201526101200190565b6001600160a01b039687168152948616602086015292851660408501526060840191909152608083015290911660a082015260c00190565b6001600160a01b039c8d1681529a8c1660208c0152988b1660408b015260608a019790975260808901959095529290971660a087015260c086015260e08501959095526101008401949094526101208301939093529115156101408201529015156101608201526101800190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03959095168552602085019390935260408401919091526060830152608082015260a00190565b6020808252825182820181905260009190848201906040850190845b81811015614df45783516001600160a01b031683529284019291840191600101614dcf565b50909695505050505050565b901515815260200190565b6000602080835283518082850152825b81811015614e3757858101830151858201604001528201614e1b565b81811115614e485783604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b90815260200190565b6001600160a01b0381168114610cdc57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220be08c056d801186983217449e435e2d3b835fb2e672440a1d5a63b03a552b59064736f6c6343000706003300000000000000000000000024e79e946dea5482212c38aab2d0782f04cdb0e0000000000000000000000000bbfa3b05b2dae65fb4c05ec7f1598793a4bc06230000000000000000000000004da27a545c0c5b758a6ba100e3a049001de870f5000000000000000000000000076d4cf37e48b9265e05d57f280eff562b177476000000000000000000000000a35c7681655811ad3befd76b45c3b2920f0c613c00000000000000000000000055da1cbd77b1c3b2d8bfe0f5fdf63d684b49f8a50000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102ff5760003560e01c806371bfbd4e1161019c578063b6331d46116100ee578063c7f3b6b111610097578063dd2cc3f311610071578063dd2cc3f3146105a8578063f77c4791146105bb578063f8f9da28146105c3576102ff565b8063c7f3b6b11461056f578063d4a3109d14610582578063d5c4a11714610595576102ff565b8063c1bce0b7116100c8578063c1bce0b71461051e578063c1c55d0c14610531578063c5d40b8a14610544576102ff565b8063b6331d46146104fb578063b6b55f2514610503578063bd6d894d14610516576102ff565b806393610b8d11610150578063a764804f1161012a578063a764804f146104d8578063aa5af0fd146104eb578063ae9d70b0146104f3576102ff565b806393610b8d146104aa5780639bdaa5e6146104bd578063a0187e8a146104d0576102ff565b806386a2a4381161018157806386a2a438146104715780638eec99c814610484578063935a8b8414610497576102ff565b806371bfbd4e146104565780637312520214610469576102ff565b8063516e2f2a11610255578063622d2efc116102095780636c540baf116101e35780636c540baf146104335780636f307dc31461043b57806370a0823114610443576102ff565b8063622d2efc146104035780636558d7b114610423578063682c20581461042b576102ff565b806357d1bc961161023a57806357d1bc96146103d557806359356c5c146103e857806359baef40146103f0576102ff565b8063516e2f2a146103af578063560acbc2146103c2576102ff565b8063304d5f07116102b75780634b8243c9116102915780634b8243c91461038a5780634c19386c1461039f5780634c68df67146103a7576102ff565b8063304d5f07146103655780634322b7141461036d5780634754990314610375576102ff565b80631e348629116102e85780631e348629146103355780632d66da9f1461033d5780632e1a7d4d14610352576102ff565b8063130cbe5c14610304578063182df0f51461032d575b600080fd5b61031761031236600461490c565b6105cb565b6040516103249190614e7c565b60405180910390f35b6103176105f1565b610317610601565b610345610607565b6040516103249190614db3565b610317610360366004614a40565b610669565b61031761068d565b610317610693565b61037d610699565b6040516103249190614ab5565b61039d610398366004614a40565b6106a8565b005b610317610780565b610317610786565b61039d6103bd36600461489c565b61078c565b61039d6103d0366004614a40565b610825565b61039d6103e3366004614a40565b610968565b610317610a1f565b61039d6103fe36600461489c565b610ab9565b6104166104113660046148d4565b610b6b565b6040516103249190614e00565b610317610c07565b610317610c0d565b610317610c13565b61037d610c19565b61031761045136600461489c565b610c28565b61039d61046436600461489c565b610cc2565b610416610cdf565b61034561047f36600461489c565b610eb8565b61039d61049236600461489c565b610f76565b6103176104a536600461489c565b611050565b61039d6104b8366004614a94565b611134565b6103176104cb36600461489c565b61120f565b61037d61122a565b61039d6104e636600461489c565b611239565b6103176112d2565b6103176112d8565b610317611337565b610317610511366004614a40565b611343565b61031761135f565b61031761052c366004614937565b611372565b61041661053f36600461489c565b61139a565b61055761055236600461489c565b6114cb565b6040516103249c9b9a99989796959493929190614cf1565b61039d61057d36600461489c565b6116b6565b61039d6105903660046148d4565b6116d0565b6103176105a3366004614a40565b6116ef565b61039d6105b6366004614a70565b611831565b61037d611995565b6103176119a4565b60006105d5611a00565b6105de57600080fd5b6105e88383611cd3565b90505b92915050565b60006105fb612063565b90505b90565b60125481565b6060600c80548060200260200160405190810160405280929190818152602001828054801561065f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610641575b5050505050905090565b6000610673611a00565b61067c57600080fd5b6106858261214f565b90505b919050565b60075481565b60085481565b6002546001600160a01b031681565b6010546001600160a01b03163314610707576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b61070f610cdf565b61071857600080fd5b60035461072590826124f3565b600355601054600154610746916001600160a01b039182169116308461254d565b7fa3e421ddc9810d39cc90c4a3998578420d1c1ebc5b67a3c133c4044a1114de99816040516107759190614e7c565b60405180910390a150565b60045481565b60035481565b6010546001600160a01b031633146107eb576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6010546001600160a01b03163314610884576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b61088c610cdf565b61089557600080fd5b61089d610a1f565b81111580156108ae57506003548111155b6040518060400160405280600281526020017f31390000000000000000000000000000000000000000000000000000000000008152509061090b5760405162461bcd60e51b81526004016109029190614e0b565b60405180910390fd5b5060035461091990826125db565b600355601054600154610939916001600160a01b0391821691168361261d565b7ff78dc30da85b5e9540c710154f60a2e296f1461551b7995ef2c7112e3c2be9c3816040516107759190614e7c565b6010546001600160a01b031633146109c7576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60408051808201909152600281527f3238000000000000000000000000000000000000000000000000000000000000602082015281610a195760405162461bcd60e51b81526004016109029190614e0b565b50600655565b6001546040517f70a082310000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906370a0823190610a69903090600401614ab5565b60206040518083038186803b158015610a8157600080fd5b505afa158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fb9190614a58565b6010546001600160a01b0316331480610adc5750600d546001600160a01b031633145b6040518060400160405280600281526020017f323900000000000000000000000000000000000000000000000000000000000081525090610b305760405162461bcd60e51b81526004016109029190614e0b565b50600d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600080546001600160a01b038084169116632d7254e5610b8a8661120f565b6040518263ffffffff1660e01b8152600401610ba69190614e7c565b60206040518083038186803b158015610bbe57600080fd5b505afa158015610bd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf691906148b8565b6001600160a01b0316149392505050565b60065481565b60055481565b60095481565b6001546001600160a01b031681565b6002546040517f70a082310000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906370a0823190610c72908590600401614ab5565b60206040518083038186803b158015610c8a57600080fd5b505afa158015610c9e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106859190614a58565b610cca611a00565b610cd357600080fd5b610cdc816126a2565b50565b6009546000904390811415610cf85760019150506105fe565b6000610d02610a1f565b60048054600354600554600a54600e546040517f200d16aa00000000000000000000000000000000000000000000000000000000815296975093959294919390926000926001600160a01b039092169163200d16aa91610d6a9130918b918b918b9101614d5f565b60206040518083038186803b158015610d8257600080fd5b505afa158015610d96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dba9190614a58565b90506000610dd3600954896125db90919063ffffffff16565b90506000610de18383612dd7565b90506000610e01670de0b6b3a7640000610dfb848b612dd7565b90612e30565b90506000610e0f89836124f3565b90506000610e3e610e37670de0b6b3a7640000610dfb86600854612dd790919063ffffffff16565b8a906124f3565b90506000610e72610e37670de0b6b3a7640000610dfb87610e6c6007546008546125db90919063ffffffff16565b90612dd7565b90506000610e8f610e37670de0b6b3a7640000610dfb898d612dd7565b60049490945550600391909155600555600a555050506009969096555060019550505050505090565b6000546040517f6a2291650000000000000000000000000000000000000000000000000000000081526060916001600160a01b031690636a22916590610f049085903090600401614b05565b60006040518083038186803b158015610f1c57600080fd5b505afa158015610f30573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610685919081019061496b565b6010546001600160a01b03163314610fd5576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b601080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040805191909216808252602082019390935281517ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc929181900390910190a15050565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815260009182916001600160a01b03909116906370a082319061109e908690600401614ab5565b60206040518083038186803b1580156110b657600080fd5b505afa1580156110ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ee9190614a58565b9050806110ff576000915050610688565b6000611109612063565b905060006111178383612dd7565b905061112b81670de0b6b3a7640000612e30565b95945050505050565b6010546001600160a01b03163314611193576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000821180156111a35750600081115b80156111af5750808210155b6040518060400160405280600281526020017f3238000000000000000000000000000000000000000000000000000000000000815250906112035760405162461bcd60e51b81526004016109029190614e0b565b50600891909155600755565b6001600160a01b03166000908152600b602052604090205490565b6000546001600160a01b031681565b6010546001600160a01b03163314611298576040805162461bcd60e51b815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600a5481565b600e546000906001600160a01b031663e4ef277a306112f5610a1f565b600480546003546008546040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b168152610a6996959401614d85565b670d2f13f7789f000081565b600061134d611a00565b61135657600080fd5b61068582612e72565b6000611369610cdf565b506105fb612063565b600061137c611a00565b61138557600080fd5b611390848484613157565b90505b9392505050565b6001600160a01b038082166000908152600b6020908152604080832081516101808101835281548152600182015486169381019390935260028101548516918301919091526003810154606083015260048101549093166080820152600583015460a0820152600683015460c0820152600783015460e08201526008830154610100808301919091526009840154610120830152600a9093015460ff80821615801561014085015294909104161515610160820152909161145f576000915050610688565b6000611490826060015161148a8460e00151610dfb600a548760600151612dd790919063ffffffff16565b906125db565b905060006114b78360a00151610dfb670de0b6b3a764000085612dd790919063ffffffff16565b670d2f13f7789f0000111595945050505050565b6001600160a01b038082166000908152600b602090815260408083208151610180810183528154808252600183015487169482019490945260028201548616818401526003820154606082015260048083015487166080830152600583015460a0830152600683015460c0830152600783015460e08301526008830154610100808401919091526009840154610120840152600a9093015460ff80821615156101408501529390049092161515610160820152845492517f2d7254e5000000000000000000000000000000000000000000000000000000008152949586958695869586958695869586958695869586958695949190911692632d7254e5926115d592909101614e7c565b60206040518083038186803b1580156115ed57600080fd5b505afa158015611601573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162591906148b8565b6020820151604083015183516060850151608086015160a087015161014088015161167057606088015160e0890151600a5461166b929161148a91610dfb908490612dd7565b611676565b8760c001515b8861010001518961012001518a61014001518b61016001519c509c509c509c509c509c509c509c509c509c509c509c505091939597999b5091939597999b565b6116be611a00565b6116c757600080fd5b610cdc816138a2565b6116d8611a00565b6116e157600080fd5b6116eb8282613f64565b5050565b60006116f9610a1f565b82106040518060400160405280600181526020017f39000000000000000000000000000000000000000000000000000000000000008152509061174f5760405162461bcd60e51b81526004016109029190614e0b565b50600e546000906001600160a01b031663200d16aa306117718661148a610a1f565b60045461177e90886124f3565b6003546040518563ffffffff1660e01b81526004016117a09493929190614d5f565b60206040518083038186803b1580156117b857600080fd5b505afa1580156117cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f09190614a58565b90506000611816670de0b6b3a7640000610dfb61180d8786612dd7565b60065490612dd7565b905060008111611827576001611829565b805b949350505050565b6010546001600160a01b03163314806118545750600d546001600160a01b031633145b6040518060400160405280600281526020017f3239000000000000000000000000000000000000000000000000000000000000815250906118a85760405162461bcd60e51b81526004016109029190614e0b565b506118b1610cdf565b6118ba57600080fd5b60055482111580156118ce57506003548211155b6040518060400160405280600281526020017f3334000000000000000000000000000000000000000000000000000000000000815250906119225760405162461bcd60e51b81526004016109029190614e0b565b5060055461193090836125db565b60055560035461194090836125db565b60035560015461195a906001600160a01b0316828461261d565b7f835862a12039ab712842887f732f62f9ba4e46c8a157b8f2ece290bb03cb6229826040516119899190614e7c565b60405180910390a15050565b600d546001600160a01b031681565b600e546000906001600160a01b031663200d16aa306119c1610a1f565b600480546003546040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b168152610a6995949301614d5f565b6040517f8dbefee20000000000000000000000000000000000000000000000000000000081526000907f0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9907f0000000000000000000000004da27a545c0c5b758a6ba100e3a049001de870f59083906001600160a01b03831690638dbefee290611a8e903090600401614ab5565b60206040518083038186803b158015611aa657600080fd5b505afa158015611aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ade9190614a58565b9050600081118015611af257504360125414155b15611cc9576040517f9a99b4f00000000000000000000000000000000000000000000000000000000081526001600160a01b03831690639a99b4f090611b3e9030908590600401614ac9565b600060405180830381600087803b158015611b5857600080fd5b505af1158015611b6c573d6000803e3d6000fd5b50506040517f70a08231000000000000000000000000000000000000000000000000000000008152600092506001600160a01b03861691506370a0823190611bb8903090600401614ab5565b60206040518083038186803b158015611bd057600080fd5b505afa158015611be4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c089190614a58565b9050611c3e6001600160a01b0385167f0000000000000000000000004da27a545c0c5b758a6ba100e3a049001de870f583614324565b6040517fadc9772e0000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063adc9772e90611c859030908590600401614ac9565b600060405180830381600087803b158015611c9f57600080fd5b505af1158015611cb3573d6000803e3d6000fd5b50504360125550600195506105fe945050505050565b6001935050505090565b600060026011541415611d2d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260118190556001600160a01b0384166000908152600b6020908152604091829020600a81015483518085019094529383527f3134000000000000000000000000000000000000000000000000000000000000918301919091529160ff1615611daa5760405162461bcd60e51b81526004016109029190614e0b565b50611db58433610b6b565b6040518060400160405280600281526020017f313500000000000000000000000000000000000000000000000000000000000081525090611e095760405162461bcd60e51b81526004016109029190614e0b565b5060008311611e1757600080fd5b611e1f610cdf565b611e2857600080fd5b60028101546000805483546040517f6352211e0000000000000000000000000000000000000000000000000000000081526001600160a01b039485169490921691636352211e91611e7b91600401614e7c565b60206040518083038186803b158015611e9357600080fd5b505afa158015611ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ecb91906148b8565b6005840154909150611edd90866124f3565b60058401556002830154600154611f03916001600160a01b03918216918491168861254d565b6040517f682904a50000000000000000000000000000000000000000000000000000000081526001600160a01b0383169063682904a590611f48908890600401614e7c565b602060405180830381600087803b158015611f6257600080fd5b505af1158015611f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9a9190614a20565b6040518060400160405280600281526020017f313700000000000000000000000000000000000000000000000000000000000081525090611fee5760405162461bcd60e51b81526004016109029190614e0b565b5060018381015490546005850154600286015486546040517f23d5462a0f15711328244c2dee4e7c32ae4c4f8f74faad197b67566f38b021e79561204c9588956001600160a01b039283169591831694309491939092169190614ba1565b60405180910390a150506001601155509092915050565b600080600260009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120b457600080fd5b505afa1580156120c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ec9190614a58565b90508061210457670de0b6b3a76400009150506105fe565b600061210e610a1f565b9050600061212d60035461148a600454856124f390919063ffffffff16565b905061214583610dfb83670de0b6b3a7640000612dd7565b93505050506105fe565b6000600260115414156121a9576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026011556121b6610cdf565b6121bf57600080fd5b816121c933610c28565b10156040518060400160405280600281526020017f31300000000000000000000000000000000000000000000000000000000000008152509061221f5760405162461bcd60e51b81526004016109029190614e0b565b50600061222a612063565b905060006122388483612dd7565b9050600061224e82670de0b6b3a7640000612e30565b9050612258610a1f565b8111156040518060400160405280600181526020017f3900000000000000000000000000000000000000000000000000000000000000815250906122af5760405162461bcd60e51b81526004016109029190614e0b565b506002546040517f9dc29fac0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690639dc29fac906122fb9033908990600401614ac9565b602060405180830381600087803b15801561231557600080fd5b505af1158015612329573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234d9190614a20565b6040518060400160405280600281526020017f3231000000000000000000000000000000000000000000000000000000000000815250906123a15760405162461bcd60e51b81526004016109029190614e0b565b506001546123b9906001600160a01b0316338361261d565b600d546040517f5c0d1b0d0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690635c0d1b0d9061240690309033908690600401614b1f565b60206040518083038186803b15801561241e57600080fd5b505afa158015612432573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124569190614a20565b6040518060400160405280600281526020017f3234000000000000000000000000000000000000000000000000000000000000815250906124aa5760405162461bcd60e51b81526004016109029190614e0b565b507f56c54ba9bd38d8fd62012e42c7ee564519b09763c426d331b3661b537ead19b23386306040516124de93929190614ae2565b60405180910390a16001601155949350505050565b6000828201838110156105e8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526125d590859061447a565b50505050565b60006105e883836040518060400160405280601f81526020017f536166654d6174683a207375627472616374696f6e20756e646572666c6f770081525061452b565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261269d90849061447a565b505050565b600260115414156126fa576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260118190556001600160a01b0382166000908152600b6020908152604091829020600a81015483518085019094529383527f3134000000000000000000000000000000000000000000000000000000000000918301919091529160ff16156127775760405162461bcd60e51b81526004016109029190614e0b565b506127828233610b6b565b6040518060400160405280600281526020017f3135000000000000000000000000000000000000000000000000000000000000815250906127d65760405162461bcd60e51b81526004016109029190614e0b565b506127df610cdf565b6127e857600080fd5b6000805482546040517f6352211e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691636352211e9161283291600401614e7c565b60206040518083038186803b15801561284a57600080fd5b505afa15801561285e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288291906148b8565b600283015460038401546007850154600a549394506001600160a01b03909216926000926128bb929161148a9190610dfb908490612dd7565b600654600886015491925060009183916128d591906124f3565b4310156129e957600e546000906001600160a01b031663200d16aa306128f9610a1f565b600480546003546040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b16815261293895949301614d5f565b60206040518083038186803b15801561295057600080fd5b505afa158015612964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129889190614a58565b905060006129a94361148a6006548b600801546124f390919063ffffffff16565b90506129d8670de0b6b3a7640000610dfb6129d1858c60030154612dd790919063ffffffff16565b8490612dd7565b93506129e483856124f3565b925050505b85600501548111156129fc575060058501545b600a860180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600686018190554360098701556003860154612a5290612a4990856124f3565b600454906125db565b6004556000612a6182856125db565b90506000612a86670de0b6b3a7640000610dfb60075488612dd790919063ffffffff16565b9050612ab5612aac670de0b6b3a7640000610dfb85600854612dd790919063ffffffff16565b600354906124f3565b600355600854612aea90612ad790670de0b6b3a764000090610dfb9086612dd7565b600554612ae490846124f3565b906124f3565b6005556040517fd05951a00000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063d05951a090612b32908690600401614e7c565b600060405180830381600087803b158015612b4c57600080fd5b505af1158015612b60573d6000803e3d6000fd5b50506000548a546040517f42966c680000000000000000000000000000000000000000000000000000000081526001600160a01b0390921693506342966c689250612bad91600401614e7c565b602060405180830381600087803b158015612bc757600080fd5b505af1158015612bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bff9190614a20565b6040518060400160405280600281526020017f333300000000000000000000000000000000000000000000000000000000000081525090612c535760405162461bcd60e51b81526004016109029190614e0b565b50600d5460028901546040517f08bc016e0000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926308bc016e92612ca69230928d921690600401614b43565b60206040518083038186803b158015612cbe57600080fd5b505afa158015612cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf69190614a20565b6040518060400160405280600281526020017f323500000000000000000000000000000000000000000000000000000000000081525090612d4a5760405162461bcd60e51b81526004016109029190614e0b565b507f976725bed73d37e8b46d0d5694646bfa4d33c5b84bae26b3194570f3ad53befb878960010160009054906101000a90046001600160a01b0316600160009054906101000a90046001600160a01b03168b6003015430888f8f600001546000604051612dbf99989796959493929190614c67565b60405180910390a15050600160115550505050505050565b600082612de6575060006105eb565b82820282848281612df357fe5b04146105e85760405162461bcd60e51b8152600401808060200182810382526021815260200180614e9b6021913960400191505060405180910390fd5b60006105e883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506145c2565b600060026011541415612ecc576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002601155612ed9610cdf565b612ee257600080fd5b6000612eec612063565b90506000612f0284670de0b6b3a7640000612dd7565b90506000612f108284612e30565b600154909150612f2b906001600160a01b031633308861254d565b6002546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906340c10f1990612f769033908590600401614ac9565b602060405180830381600087803b158015612f9057600080fd5b505af1158015612fa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fc89190614a20565b6040518060400160405280600281526020017f32300000000000000000000000000000000000000000000000000000000000008152509061301c5760405162461bcd60e51b81526004016109029190614e0b565b507fe31c7b8d08ee7db0afa68782e1028ef92305caeea8626633ad44d413e30f6b2f33863060405161305093929190614ae2565b60405180910390a1600d546040517f806f8ab20000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063806f8ab2906130a590309033908690600401614b1f565b60206040518083038186803b1580156130bd57600080fd5b505afa1580156130d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f59190614a20565b6040518060400160405280600281526020017f3131000000000000000000000000000000000000000000000000000000000000815250906131495760405162461bcd60e51b81526004016109029190614e0b565b506001601155949350505050565b6000600260115414156131b1576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026011556131be610a1f565b83106040518060400160405280600181526020017f3900000000000000000000000000000000000000000000000000000000000000815250906132145760405162461bcd60e51b81526004016109029190614e0b565b5060408051808201909152600281527f323200000000000000000000000000000000000000000000000000000000000060208201526001600160a01b0385166132705760405162461bcd60e51b81526004016109029190614e0b565b5060408051808201909152600281527f32370000000000000000000000000000000000000000000000000000000000006020820152836132c35760405162461bcd60e51b81526004016109029190614e0b565b506132cd836116ef565b8210156040518060400160405280600281526020017f3233000000000000000000000000000000000000000000000000000000000000815250906133245760405162461bcd60e51b81526004016109029190614e0b565b5061332d610cdf565b61333657600080fd5b600454339061334590856124f3565b600455600f54600090613360906001600160a01b0316614627565b60015490915061337a906001600160a01b0316828761261d565b600154613392906001600160a01b031683838761254d565b6001546040517f890dcf540000000000000000000000000000000000000000000000000000000081526001600160a01b038084169263890dcf54926133e692309288929116908c908c908c90600401614be1565b602060405180830381600087803b15801561340057600080fd5b505af1158015613414573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134389190614a20565b6040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152509061348c5760405162461bcd60e51b81526004016109029190614e0b565b50600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038481169190911790915581546040517f63185c420000000000000000000000000000000000000000000000000000000081529116906363185c429061353790869030908790600401614b43565b602060405180830381600087803b15801561355157600080fd5b505af1158015613565573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135899190614a58565b9050604051806101800160405280828152602001886001600160a01b03168152602001836001600160a01b03168152602001878152602001600160009054906101000a90046001600160a01b03166001600160a01b0316815260200186815260200160008152602001600a5481526020014381526020016000815260200160001515815260200160001515815250600b6000846001600160a01b03166001600160a01b031681526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506060820151816003015560808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a0160006101000a81548160ff02191690831515021790555061016082015181600a0160016101000a81548160ff021916908315150217905550905050600d60009054906101000a90046001600160a01b03166001600160a01b031663f5565ddf30858a8a8a886040518763ffffffff1660e01b815260040161379b96959493929190614cb9565b60206040518083038186803b1580156137b357600080fd5b505afa1580156137c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137eb9190614a20565b6040518060400160405280600281526020017f31330000000000000000000000000000000000000000000000000000000000008152509061383f5760405162461bcd60e51b81526004016109029190614e0b565b506001546040517f8f11691cf96727f419bd99b50853d8351f147118e4778f62bdaa8528ab3e50bb9161388b9186918b916001600160a01b03909116908b903090899089904390614c1b565b60405180910390a160016011559695505050505050565b600260115414156138fa576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260118190556001600160a01b0382166000908152600b6020908152604091829020600a81015483518085019094529383527f313400000000000000000000000000000000000000000000000000000000000091830191909152339290919060ff161561397b5760405162461bcd60e51b81526004016109029190614e0b565b506139868383610b6b565b156040518060400160405280600281526020017f3136000000000000000000000000000000000000000000000000000000000000815250906139db5760405162461bcd60e51b81526004016109029190614e0b565b506139e4610cdf565b6139ed57600080fd5b6000805482546040517f6352211e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691636352211e91613a3791600401614e7c565b60206040518083038186803b158015613a4f57600080fd5b505afa158015613a63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8791906148b8565b90506000613ab4836003015461148a8560070154610dfb600a548860030154612dd790919063ffffffff16565b90506000613adb8460050154610dfb670de0b6b3a764000085612dd790919063ffffffff16565b9050670d2f13f7789f00008110156040518060400160405280600281526020017f313800000000000000000000000000000000000000000000000000000000000081525090613b3d5760405162461bcd60e51b81526004016109029190614e0b565b506002840154600a850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911660011716610100179055600585015460068601554360098601556001600160a01b03166000670de0b6b3a7640000831115613bd8576005860154613bd39085906125db565b613bdb565b60005b90506000613c04670de0b6b3a7640000610dfb6007548a60050154612dd790919063ffffffff16565b9050613c20612a498689600301546124f390919063ffffffff16565b600455600854613c5090613c4390670de0b6b3a764000090610dfb908690612dd7565b60035461148a90846125db565b600355600754600854613c8891613c7f91670de0b6b3a764000091610dfb91613c78916125db565b8690612dd7565b600554906125db565b6005556007546040517ff8cfe49d0000000000000000000000000000000000000000000000000000000081526001600160a01b0385169163f8cfe49d91613cd3918c91600401614ac9565b600060405180830381600087803b158015613ced57600080fd5b505af1158015613d01573d6000803e3d6000fd5b505060005489546040517f42966c680000000000000000000000000000000000000000000000000000000081526001600160a01b0390921693506342966c689250613d4e91600401614e7c565b602060405180830381600087803b158015613d6857600080fd5b505af1158015613d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613da09190614a20565b6040518060400160405280600281526020017f333300000000000000000000000000000000000000000000000000000000000081525090613df45760405162461bcd60e51b81526004016109029190614e0b565b50600d5460028801546040517f716e257f0000000000000000000000000000000000000000000000000000000081526001600160a01b039283169263716e257f92613e479230928e921690600401614b43565b60206040518083038186803b158015613e5f57600080fd5b505afa158015613e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e979190614a20565b6040518060400160405280600281526020017f323600000000000000000000000000000000000000000000000000000000000081525090613eeb5760405162461bcd60e51b81526004016109029190614e0b565b507f976725bed73d37e8b46d0d5694646bfa4d33c5b84bae26b3194570f3ad53befb868860010160009054906101000a90046001600160a01b0316600160009054906101000a90046001600160a01b03168a60030154308c600501548f8e600001546001604051612dbf99989796959493929190614c67565b60026011541415613fbc576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260118190556001600160a01b0383166000908152600b6020908152604091829020600a81015483518085019094529383527f3134000000000000000000000000000000000000000000000000000000000000918301919091529160ff16156140395760405162461bcd60e51b81526004016109029190614e0b565b5060408051808201909152600281527f323200000000000000000000000000000000000000000000000000000000000060208201526001600160a01b0383166140955760405162461bcd60e51b81526004016109029190614e0b565b506140a08333610b6b565b6040518060400160405280600281526020017f3135000000000000000000000000000000000000000000000000000000000000815250906140f45760405162461bcd60e51b81526004016109029190614e0b565b506140fd610cdf565b61410657600080fd5b60028101546001820180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03858116919091179091556040517f10187c7500000000000000000000000000000000000000000000000000000000815291169081906310187c7590614184908690600401614ab5565b602060405180830381600087803b15801561419e57600080fd5b505af11580156141b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d69190614a20565b6040518060400160405280600281526020017f33320000000000000000000000000000000000000000000000000000000000008152509061422a5760405162461bcd60e51b81526004016109029190614e0b565b5060005482546040517f6352211e0000000000000000000000000000000000000000000000000000000081527f0495d9ab17c89a5018a45652488d3006feedcac9a14e348e939ffdab14705724926001600160a01b031691636352211e916142959190600401614e7c565b60206040518083038186803b1580156142ad57600080fd5b505afa1580156142c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142e591906148b8565b60015460028501548554604051614311949389936001600160a01b039182169330939290911691614b66565b60405180910390a1505060016011555050565b8015806143c35750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b15801561439557600080fd5b505afa1580156143a9573d6000803e3d6000fd5b505050506040513d60208110156143bf57600080fd5b5051155b6143fe5760405162461bcd60e51b8152600401808060200182810382526036815260200180614ee66036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261269d9084905b60006144cf826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166146e29092919063ffffffff16565b80519091501561269d578080602001905160208110156144ee57600080fd5b505161269d5760405162461bcd60e51b815260040180806020018281038252602a815260200180614ebc602a913960400191505060405180910390fd5b600081848411156145ba5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561457f578181015183820152602001614567565b50505050905090810190601f1680156145ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836146115760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561457f578181015183820152602001614567565b50600083858161461d57fe5b0495945050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f09150506001600160a01b038116610688576040805162461bcd60e51b815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015290519081900360640190fd5b60606113908484600085856146f685614825565b614747576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b602083106147a357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614766565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614805576040519150601f19603f3d011682016040523d82523d6000602084013e61480a565b606091505b509150915061481a82828661482b565b979650505050505050565b3b151590565b6060831561483a575081611393565b82511561484a5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561457f578181015183820152602001614567565b805161068881614e85565b6000602082840312156148ad578081fd5b81356105e881614e85565b6000602082840312156148c9578081fd5b81516105e881614e85565b600080604083850312156148e6578081fd5b82356148f181614e85565b9150602083013561490181614e85565b809150509250929050565b6000806040838503121561491e578182fd5b823561492981614e85565b946020939093013593505050565b60008060006060848603121561494b578081fd5b833561495681614e85565b95602085013595506040909401359392505050565b6000602080838503121561497d578182fd5b825167ffffffffffffffff80821115614994578384fd5b818501915085601f8301126149a7578384fd5b8151818111156149b357fe5b838102604051858282010181811085821117156149cc57fe5b604052828152858101935084860182860187018a10156149ea578788fd5b8795505b83861015614a13576149ff81614891565b8552600195909501949386019386016149ee565b5098975050505050505050565b600060208284031215614a31578081fd5b815180151581146105e8578182fd5b600060208284031215614a51578081fd5b5035919050565b600060208284031215614a69578081fd5b5051919050565b60008060408385031215614a82578182fd5b82359150602083013561490181614e85565b60008060408385031215614aa6578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b039687168152948616602086015292851660408501529084166060840152909216608082015260a081019190915260c00190565b6001600160a01b039788168152958716602087015293861660408601529185166060850152608084015290921660a082015260c081019190915260e00190565b6001600160a01b0396871681529486166020860152928516604085015293166060830152608082019290925260a081019190915260c00190565b6001600160a01b039889168152968816602088015294871660408701526060860193909352908516608085015290931660a083015260c082019290925260e08101919091526101000190565b6001600160a01b03998a168152978916602089015295881660408801526060870194909452918616608086015260a085015290931660c083015260e08201929092529015156101008201526101200190565b6001600160a01b039687168152948616602086015292851660408501526060840191909152608083015290911660a082015260c00190565b6001600160a01b039c8d1681529a8c1660208c0152988b1660408b015260608a019790975260808901959095529290971660a087015260c086015260e08501959095526101008401949094526101208301939093529115156101408201529015156101608201526101800190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03959095168552602085019390935260408401919091526060830152608082015260a00190565b6020808252825182820181905260009190848201906040850190845b81811015614df45783516001600160a01b031683529284019291840191600101614dcf565b50909695505050505050565b901515815260200190565b6000602080835283518082850152825b81811015614e3757858101830151858201604001528201614e1b565b81811115614e485783604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b90815260200190565b6001600160a01b0381168114610cdc57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220be08c056d801186983217449e435e2d3b835fb2e672440a1d5a63b03a552b59064736f6c63430007060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000024e79e946dea5482212c38aab2d0782f04cdb0e0000000000000000000000000bbfa3b05b2dae65fb4c05ec7f1598793a4bc06230000000000000000000000004da27a545c0c5b758a6ba100e3a049001de870f5000000000000000000000000076d4cf37e48b9265e05d57f280eff562b177476000000000000000000000000a35c7681655811ad3befd76b45c3b2920f0c613c00000000000000000000000055da1cbd77b1c3b2d8bfe0f5fdf63d684b49f8a50000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9
-----Decoded View---------------
Arg [0] : _palToken (address): 0x24E79e946dEa5482212c38aaB2D0782F04cdB0E0
Arg [1] : _controller (address): 0xbBFA3b05b2dAe65Fb4C05Ec7F1598793a4Bc0623
Arg [2] : _underlying (address): 0x4da27a545c0c5B758a6BA100e3a049001de870f5
Arg [3] : _interestModule (address): 0x076D4cf37E48B9265E05D57f280EfF562b177476
Arg [4] : _delegator (address): 0xA35C7681655811Ad3BefD76B45c3B2920F0C613C
Arg [5] : _palLoanToken (address): 0x55DA1CBD77B1c3b2d8Bfe0F5fDF63d684b49F8A5
Arg [6] : _aaveAddress (address): 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000024e79e946dea5482212c38aab2d0782f04cdb0e0
Arg [1] : 000000000000000000000000bbfa3b05b2dae65fb4c05ec7f1598793a4bc0623
Arg [2] : 0000000000000000000000004da27a545c0c5b758a6ba100e3a049001de870f5
Arg [3] : 000000000000000000000000076d4cf37e48b9265e05d57f280eff562b177476
Arg [4] : 000000000000000000000000a35c7681655811ad3befd76b45c3b2920f0c613c
Arg [5] : 00000000000000000000000055da1cbd77b1c3b2d8bfe0f5fdf63d684b49f8a5
Arg [6] : 0000000000000000000000007fc66500c84a76ad7e9c93437bfc5ac33e2ddae9Loading...LoadingLoading...Loading
Loading...Loading
Loading...LoadingLoading...LoadingLoading...LoadingLoading...LoadingLoading...LoadingMultichain Portfolio | 26 Chains
Chain Token Portfolio % Price Amount Value ETH 100.00% $136.05 2,238.0584 $304,487.85 Loading...Loading[ Download: CSV Export ][ Download: CSV Export ]A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.
Address QR Code
My Address - Private Name Tag or Note
My Name Tag:
Private Name Tags (up to 35 characters) can be used for easy identification of addressesPrivate Note:
A private note (up to 500 characters) can be attached to this address.
Please DO NOT store any passwords or private keys here.Compiler specific version warnings:
The compiled contract might be susceptible to FullInlinerNonExpressionSplitArgumentEvaluationOrder (low-severity), MissingSideEffectsOnSelectorAccess (low-severity), AbiReencodingHeadOverflowWithStaticArrayCleanup (medium-severity), DirtyBytesArrayToStorage (low-severity), DataLocationChangeInInternalOverride (very low-severity), NestedCalldataArrayAbiReencodingSizeValidation (very low-severity), SignedImmutables (very low-severity), ABIDecodeTwoDimensionalArrayMemory (very low-severity), KeccakCaching (medium-severity) Solidity Compiler Bugs.
Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.Address Cards
To use this feature, please login to your Etherscan account and return to this page.Before You Copy
This website uses cookies to improve your experience. By continuing to use this website, you agree to its Terms and Privacy Policy.