Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 17909825 | 383 days ago | IN | 0 ETH | 0.04787659 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ERC721LendingPool02
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.8.9; import "openzeppelin-contracts-upgradeable/access/OwnableUpgradeable.sol"; import "openzeppelin-contracts-upgradeable/security/PausableUpgradeable.sol"; import "openzeppelin-contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "openzeppelin-contracts/token/ERC1155/utils/ERC1155Holder.sol"; import "openzeppelin-contracts/token/ERC721/IERC721Receiver.sol"; import "openzeppelin-contracts/token/ERC721/IERC721.sol"; import "openzeppelin-contracts/token/ERC20/IERC20.sol"; import "openzeppelin-contracts/token/ERC1155/IERC1155.sol"; import "../libraries/FeeStructure.sol"; import "../libraries/PineLendingLibrary.sol"; import "../libraries/VerifySignaturePool02.sol"; import "../interfaces/IControlPlane01.sol"; import "../interfaces/IFlashloanReceiver.sol"; contract ERC721LendingPool02 is OwnableUpgradeable, IERC721Receiver, PausableUpgradeable, ReentrancyGuardUpgradeable, ERC1155Holder { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) public pure override returns (bytes4) { return bytes4( keccak256("onERC721Received(address,address,uint256,bytes)") ); } /** * Pool Constants */ address public _valuationSigner; address public _supportedCollection; address public _controlPlane; address public _fundSource; address public _supportedCurrency; FeeStructure public _feeStructure; uint256 public _maxLoanLimit; uint256 public _currentLoanAmount; struct PoolParams { uint32 interestBPS1000000XBlock; uint32 collateralFactorBPS; } mapping(uint256 => PoolParams) public durationSeconds_poolParam; mapping(uint256 => uint256) public blockLoanAmount; uint256 public blockLoanLimit; uint256[] public supportedSlots; /** * Pool Setup */ constructor () { _disableInitializers(); } function initialize( address supportedCollection, address valuationSigner, address controlPlane, address supportedCurrency, address fundSource, address feeStructure, uint256 maxLoanLimit ) public initializer { __Ownable_init(); __Pausable_init(); __ReentrancyGuard_init(); _supportedCollection = supportedCollection; _valuationSigner = valuationSigner; _controlPlane = controlPlane; _supportedCurrency = supportedCurrency; _fundSource = fundSource; blockLoanLimit = 200000000000000000000; _feeStructure = FeeStructure(feeStructure); _maxLoanLimit = maxLoanLimit; } function changeValuationSigner(address _newValuationSigner) external { require(msg.sender == owner() || msg.sender == _controlPlane); _valuationSigner = _newValuationSigner; } function addSupportedSlot(uint256 slot) external onlyOwner { supportedSlots.push(slot); } function setBlockLoanLimit(uint256 bll) public onlyOwner { blockLoanLimit = bll; } function setMaxLoanLimit(uint256 bll) public onlyOwner { _maxLoanLimit = bll; } function setDurationParam(uint256 duration, PoolParams calldata ppm) public onlyOwner { require(ppm.interestBPS1000000XBlock < _feeStructure.maxLenderRateBpsPerBlock()); durationSeconds_poolParam[duration] = ppm; require(durationSeconds_poolParam[0].collateralFactorBPS == 0); } function pause() public onlyOwner { _pause(); } function unpause() public onlyOwner { _unpause(); } function updateBlockLoanAmount(uint256 loanAmount) internal { blockLoanAmount[block.number] += loanAmount; require( blockLoanAmount[block.number] < blockLoanLimit, "Amount exceed block limit" ); } function updateMaxLoanAmount(uint256 loanAmount) internal { _currentLoanAmount += loanAmount; require( _currentLoanAmount <= _maxLoanLimit, "Amount exceed total limit" ); } /** * Storage and Events */ mapping(uint256 => PineLendingLibrary.LoanTerms) public _loans; /** * Loan origination */ function flashLoan( address payable _receiver, address _reserve, uint256 _amount, bytes memory _params ) external nonReentrant { require(IControlPlane01(_controlPlane).whitelistedIntermediaries( msg.sender ), "Router not whitelisted"); require(IControlPlane01(_controlPlane).whitelistedIntermediaries( _receiver ), "Executer not whitelisted"); //check that the reserve has enough available liquidity uint256 availableLiquidityBefore = _reserve == address(0) ? address(this).balance : IERC20(_reserve).balanceOf(_fundSource); require( availableLiquidityBefore >= _amount, "There is not enough liquidity available to borrow" ); // uint256 lenderFeeBips = durationSeconds_poolParam[0] // .interestBPS1000000XBlock; //calculate amount fee uint256 amountFee = 0; //get the FlashLoanReceiver instance IFlashLoanReceiver receiver = IFlashLoanReceiver(_receiver); //transfer funds to the receiver if (_reserve == address(0)) { (bool success, ) = _receiver.call{value: _amount}(""); require(success, "Flash loan: cannot send ether"); } else { require(IERC20(_reserve).transferFrom(_fundSource, _receiver, _amount)); } //execute action of the receiver receiver.executeOperation(_reserve, _amount, amountFee, _params); //check that the actual balance of the core contract includes the returned amount uint256 availableLiquidityAfter = _reserve == address(0) ? address(this).balance : IERC20(_reserve).balanceOf(_fundSource); require( availableLiquidityAfter == availableLiquidityBefore + (amountFee), "The actual balance of the protocol is inconsistent" ); } function borrow( uint256[5] calldata x, bytes memory signature, address borrowFor, address pineWallet ) external nonReentrant whenNotPaused returns (bool) { //valuation = x[0] //nftID = x[1] //uint256 loanDurationSeconds = x[2]; //uint256 expireAtBlock = x[3]; //uint256 borrowedAmount = x[4]; require( VerifySignaturePool02.verify( _supportedCollection, x[1], x[0], x[3], _valuationSigner, signature ), "SignatureVerifier: fake valuation provided!" ); require( IControlPlane01(_controlPlane).whitelistedIntermediaries( msg.sender ) || msg.sender == tx.origin, "Phishing!" ); address contextUser = msg.sender; require( !PineLendingLibrary.nftHasLoan(_loans[x[1]]), "NFT already has loan!" ); uint32 maxLTVBPS = durationSeconds_poolParam[x[2]].collateralFactorBPS; require(maxLTVBPS > 0, "Duration not supported"); require( IERC721(_supportedCollection).ownerOf(x[1]) == contextUser, "Stealer1!" ); require(block.number < x[3], "Valuation expired"); require( x[4] <= (x[0] * maxLTVBPS) / 10_000, "Can't borrow more than max LTV" ); require( x[4] < IERC20(_supportedCurrency).balanceOf(_fundSource), "not enough money" ); updateBlockLoanAmount(x[4]); updateMaxLoanAmount(x[4]); require(IERC20(_supportedCurrency).transferFrom( _fundSource, msg.sender, x[4] )); _loans[x[1]] = PineLendingLibrary.LoanTerms( block.number, block.timestamp + x[2], durationSeconds_poolParam[x[2]].interestBPS1000000XBlock, maxLTVBPS, x[4], 0, 0, 0, borrowFor != address(0) ? borrowFor : contextUser ); IERC721(_supportedCollection).transferFrom( contextUser, address(this), x[1] ); emit PineLendingLibrary.LoanInitiated( contextUser, _supportedCollection, x[1], _loans[x[1]] ); return true; } /** * Repay */ // repay change loan terms, renew loan start, fix interest to borrowed amount, dont renew loan expiry function repay( uint256 nftID, uint256 repayAmount, address pineWallet ) external nonReentrant returns (bool) { // uint256 pineMirrorID = uint256( // keccak256(abi.encodePacked(_supportedCollection, nftID)) // ); require(tx.origin == _loans[nftID].borrower, "Repay by 3rd party is disabled"); require(!IERC721(_supportedCollection).isApprovedForAll(_loans[nftID].borrower, 0x5284d97a1462A767F385aE6Ae89BA9065ecE193c), "PSA: please revoke the NFT collection's approvals to 0x5284d97a1462A767F385aE6Ae89BA9065ecE193c using revoke.cash before repaying this loan. Please reach out to support in discord if in doubt."); uint256 repaidInterest; PineLendingLibrary.LoanTerms memory termsWithRealRate = _loans[nftID]; termsWithRealRate.interestBPS1000000XBlock = _feeStructure.getClientRateByLenderRatePerBlock(_loans[nftID].interestBPS1000000XBlock); require( PineLendingLibrary.nftHasLoan(_loans[nftID]), "NFT does not have active loan" ); require( IERC20(_supportedCurrency).transferFrom( msg.sender, address(this), repayAmount ), "fund transfer unsuccessful" ); if (repayAmount >= PineLendingLibrary.outstanding(termsWithRealRate)) { require( IERC20(_supportedCurrency).transfer( msg.sender, repayAmount - PineLendingLibrary.outstanding(termsWithRealRate) ), "exceed amount transfer unsuccessful" ); repayAmount = PineLendingLibrary.outstanding(termsWithRealRate); _currentLoanAmount -= (_loans[nftID].borrowedWei - _loans[nftID].returnedWei); repaidInterest = repayAmount - (_loans[nftID].borrowedWei - _loans[nftID].returnedWei); _loans[nftID].returnedWei = _loans[nftID].borrowedWei; IERC721(_supportedCollection).transferFrom( address(this), _loans[nftID].borrower, nftID ); } else { // lump in interest _loans[nftID].accuredInterestWei += ((block.number - _loans[nftID].loanStartBlock) * (_loans[nftID].borrowedWei - _loans[nftID].returnedWei) * (_feeStructure.getClientRateByLenderRatePerBlock(_loans[nftID].interestBPS1000000XBlock))) / 10000000000; uint256 outstandingInterest = _loans[nftID].accuredInterestWei - _loans[nftID].repaidInterestWei; if (repayAmount > outstandingInterest) { _loans[nftID].repaidInterestWei = _loans[nftID] .accuredInterestWei; _loans[nftID].returnedWei += (repayAmount - outstandingInterest); // reduce limit _currentLoanAmount -= (repayAmount - outstandingInterest); repaidInterest = outstandingInterest; } else { _loans[nftID].repaidInterestWei += repayAmount; repaidInterest = repayAmount; } // restart interest calculation _loans[nftID].loanStartBlock = block.number; } require( IERC20(_supportedCurrency).transferFrom( address(this), _fundSource, IERC20(_supportedCurrency).balanceOf(address(this)) - (repaidInterest * _feeStructure.getFeeCutBpsByLenderRatePerBlock(_loans[nftID].interestBPS1000000XBlock) / 10_000) ), "fund transfer unsuccessful (payload)" ); require(IERC20(_supportedCurrency).transferFrom( address(this), _controlPlane, repaidInterest * _feeStructure.getFeeCutBpsByLenderRatePerBlock(_loans[nftID].interestBPS1000000XBlock) / 10_000 ), "fund transfer unsuccessful (fee)" ); //termsWithRealRate switch back to lender rate termsWithRealRate.interestBPS1000000XBlock = _loans[nftID].interestBPS1000000XBlock; if (IERC721(_supportedCollection).ownerOf(nftID) != address(this)) { clearLoanTerms(nftID); } emit PineLendingLibrary.LoanTermsChanged( _loans[nftID].borrower, _supportedCollection, nftID, termsWithRealRate, _loans[nftID] ); return true; } /** * Admin functions */ function withdraw(uint256 amount) external onlyOwner { (bool success, ) = owner().call{value: amount}(""); require(success, "cannot send ether"); } function withdrawERC20(address currency, uint256 amount) external onlyOwner { IERC20(currency).transfer(owner(), amount); } function withdrawERC1155(address currency, uint256 id, uint256 amount) external onlyOwner { IERC1155(currency).safeTransferFrom(address(this), owner(), id, amount, ""); } function withdrawERC721( address collection, uint256 nftID, address target, bool liquidation ) external { require(msg.sender == _controlPlane, "not control plane"); if ((collection == _supportedCollection) && liquidation) { PineLendingLibrary.LoanTerms memory lt = _loans[nftID]; emit PineLendingLibrary.Liquidation( lt.borrower, _supportedCollection, nftID, block.timestamp, tx.origin ); clearLoanTerms(nftID); } IERC721(collection).transferFrom(address(this), target, nftID); } function clearLoanTerms(uint256 nftID) internal { _loans[nftID] = PineLendingLibrary.LoanTerms( 0, 0, 0, 0, 0, 0, 0, 0, address(0) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ReentrancyGuardUpgradeable is Initializable { // 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; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.0; import "./ERC1155Receiver.sol"; /** * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. * * @dev _Available since v3.1._ */ contract ERC1155Holder is ERC1155Receiver { function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/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`. * * 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; /** * @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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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 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 the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; contract FeeStructure { uint256 constant log_10_2 = 301029995663981195213738; uint256 constant log_10_2_base_7prec = 100000000000000000; uint256 constant two_64 = 18446744073709551616; uint256 constant blocksPerYear = 2628000; uint256 constant baseFeeBps = 200; uint256 constant public maxLenderRateBpsPerBlock = 178000000; function log_2 (int128 x) internal pure returns (int128) { unchecked { require (x > 0); int256 msb = 0; int256 xc = x; if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; } if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore int256 result = msb - 64 << 64; uint256 ux = uint256 (int256 (x)) << uint256 (127 - msb); for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) { ux *= ux; uint256 b = ux >> 255; ux >>= 127 + b; result += bit * int256 (b); } return int128 (result); } } // function getFeeCutBpsByLenderRate(uint256 lenderRateBps) external pure returns (uint256) { // uint256 clientRate = getClientRateByLenderRate(lenderRateBps); // return (clientRate - lenderRateBps) * 10000 / clientRate; // } function getFeeCutBpsByLenderRatePerBlock(uint32 lenderRateBpsPerBlock) external pure returns (uint256) { if (lenderRateBpsPerBlock > maxLenderRateBpsPerBlock) return 0; if (lenderRateBpsPerBlock == 0) return 10000; uint256 lenderRateBps = lenderRateBpsPerBlock * blocksPerYear / 1000000; uint256 clientRate = getClientRateByLenderRate(lenderRateBps); return (clientRate - lenderRateBps) * 10000 / clientRate; } function getClientRateByLenderRatePerBlock(uint32 lenderRateBpsPerBlock) external pure returns (uint32) { if (lenderRateBpsPerBlock > maxLenderRateBpsPerBlock) return uint32(lenderRateBpsPerBlock); if (lenderRateBpsPerBlock == 0) return uint32(baseFeeBps*1000000/blocksPerYear); uint256 lenderRateBps = lenderRateBpsPerBlock * blocksPerYear / 1000000; uint256 clientRate = getClientRateByLenderRate(lenderRateBps); return uint32(clientRate*1000000/blocksPerYear); } function getClientRateByLenderRate(uint256 lenderRateBps) internal pure returns (uint256) { uint extraFee = (uint256(uint128(log_2(int128(int256(10000 + lenderRateBps))*int128(int256(two_64))))) * log_10_2 / two_64 / log_10_2_base_7prec - 40000000) *10000 / 10000000 ; return lenderRateBps + extraFee + baseFeeBps; } // function getFeeCutBpsByClientRate(uint256 clientRateBps) external pure returns (uint256) { // require(clientRateBps >= baseFeeBps); // // log 1+lR = cR // uint lenderRate = 10**(clientRateBps - baseFeeBps) - 10000; // return (clientRateBps - lenderRate) / clientRateBps; // //uint extraFee = (uint256(uint128(log_2(int128(int256(10000 + lenderRateBps))*int128(int256(two_64))))) * log_10_2 / two_64 / log_10_2_base_7prec - 40000000) *10000 / 10000000 ; // //return (extraFee + baseFeeBps) * 10000 / (lenderRateBps + extraFee + baseFeeBps); // } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; library PineLendingLibrary { struct LoanTerms { uint256 loanStartBlock; uint256 loanExpireTimestamp; uint32 interestBPS1000000XBlock; uint32 maxLTVBPS; uint256 borrowedWei; uint256 returnedWei; uint256 accuredInterestWei; uint256 repaidInterestWei; address borrower; } function outstanding(LoanTerms calldata loanTerms, uint txSpeedBlocks) public view returns (uint256) { // do not lump the interest if (loanTerms.borrowedWei <= loanTerms.returnedWei) return 0; uint256 newAccuredInterestWei = ((block.number + txSpeedBlocks - loanTerms.loanStartBlock) * (loanTerms.borrowedWei - loanTerms.returnedWei) * loanTerms.interestBPS1000000XBlock) / 10000000000; return (loanTerms.borrowedWei - loanTerms.returnedWei) + (loanTerms.accuredInterestWei - loanTerms.repaidInterestWei) + newAccuredInterestWei; } function outstanding(LoanTerms calldata loanTerms) public view returns (uint256) { return outstanding(loanTerms, 0); } function nftHasLoan(LoanTerms memory loanTerms) public pure returns (bool) { return loanTerms.borrowedWei > loanTerms.returnedWei; } function isUnHealthyLoan(LoanTerms calldata loanTerms) public view returns (bool, uint32) { require(nftHasLoan(loanTerms), "nft does not have active loan"); bool isExpired = block.timestamp > loanTerms.loanExpireTimestamp && outstanding(loanTerms) > 0; return (isExpired, 0); } event LoanInitiated( address indexed user, address indexed erc721, uint256 indexed nftID, LoanTerms loan ); event LoanTermsChanged( address indexed user, address indexed erc721, uint256 indexed nftID, LoanTerms oldTerms, LoanTerms newTerms ); event Liquidation( address indexed user, address indexed erc721, uint256 indexed nftID, uint256 liquidated_at, address liquidator ); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; /* Signature Verification How to Sign and Verify # Signing 1. Create message to sign 2. Hash the message 3. Sign the hash (off chain, keep your private key secret) # Verify 1. Recreate hash from the original message 2. Recover signer from signature and hash 3. Compare recovered signer to claimed signer */ library VerifySignaturePool02 { /* 1. Unlock MetaMask account ethereum.enable() */ /* 2. Get message hash to sign getMessageHash( 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C, 123, "coffee and donuts", 1 ) hash = "0xcf36ac4f97dc10d91fc2cbb20d718e94a8cbfe0f82eaedc6a4aa38946fb797cd" */ function getMessageHash( address nft, uint tokenID, uint valuation, uint expireAtBlock ) public pure returns (bytes32) { return keccak256(abi.encodePacked(nft, tokenID, valuation, expireAtBlock)); } /* 3. Sign message hash # using browser account = "copy paste account of signer here" ethereum.request({ method: "personal_sign", params: [account, hash]}).then(console.log) # using web3 web3.personal.sign(hash, web3.eth.defaultAccount, console.log) Signature will be different for different accounts 0x993dab3dd91f5c6dc28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063e8f3f781b */ function getEthSignedMessageHash(bytes32 _messageHash) public pure returns (bytes32) { /* Signature is produced by signing a keccak256 hash with the following format: "\x19Ethereum Signed Message\n" + len(msg) + msg */ return keccak256( abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash) ); } /* 4. Verify signature signer = 0xB273216C05A8c0D4F0a4Dd0d7Bae1D2EfFE636dd to = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C amount = 123 message = "coffee and donuts" nonce = 1 signature = 0x993dab3dd91f5c6dc28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063e8f3f781b */ function verify( address nft, uint tokenID, uint valuation, uint expireAtBlock, address _signer, bytes memory signature ) public pure returns (bool) { bytes32 messageHash = getMessageHash(nft, tokenID, valuation, expireAtBlock); bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash); return recoverSigner(ethSignedMessageHash, signature) == _signer; } function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) internal pure returns (address) { (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature); return ecrecover(_ethSignedMessageHash, v, r, s); } function splitSignature(bytes memory sig) internal pure returns ( bytes32 r, bytes32 s, uint8 v ) { require(sig.length == 65, "invalid signature length"); assembly { /* First 32 bytes stores the length of the signature add(sig, 32) = pointer of sig + 32 effectively, skips first 32 bytes of signature mload(p) loads next 32 bytes starting at the memory address p into memory */ // first 32 bytes, after the length prefix r := mload(add(sig, 32)) // second 32 bytes s := mload(add(sig, 64)) // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } // implicitly return (r, s, v) } }
/** * ControlPlane01.sol * Registers the current global params */ pragma solidity 0.8.9; interface IControlPlane01 { function whitelistedIntermediaries(address target) external returns (bool result); function whitelistedFactory() external returns (address result); function feeBps() external returns (uint32 result); }
pragma solidity 0.8.9; /** * @title IFlashLoanReceiver interface * @notice Interface for the Aave fee IFlashLoanReceiver. * @author Aave * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract **/ interface IFlashLoanReceiver { function executeOperation(address _reserve, uint256 _amount, uint256 _fee, bytes calldata _params) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol) pragma solidity ^0.8.0; import "../IERC1155Receiver.sol"; import "../../../utils/introspection/ERC165.sol"; /** * @dev _Available since v3.1._ */ abstract contract ERC1155Receiver is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": { "src/libraries/PineLendingLibrary.sol": { "PineLendingLibrary": "0x510263ecbc928c8b78df68420a5955f6c9cc59a1" }, "src/libraries/VerifySignaturePool02.sol": { "VerifySignaturePool02": "0x830f14a360ce394f3d5b6b0daa1140e577e4a488" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"_controlPlane","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_currentLoanAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_feeStructure","outputs":[{"internalType":"contract FeeStructure","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_fundSource","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_loans","outputs":[{"internalType":"uint256","name":"loanStartBlock","type":"uint256"},{"internalType":"uint256","name":"loanExpireTimestamp","type":"uint256"},{"internalType":"uint32","name":"interestBPS1000000XBlock","type":"uint32"},{"internalType":"uint32","name":"maxLTVBPS","type":"uint32"},{"internalType":"uint256","name":"borrowedWei","type":"uint256"},{"internalType":"uint256","name":"returnedWei","type":"uint256"},{"internalType":"uint256","name":"accuredInterestWei","type":"uint256"},{"internalType":"uint256","name":"repaidInterestWei","type":"uint256"},{"internalType":"address","name":"borrower","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_maxLoanLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_supportedCollection","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_supportedCurrency","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_valuationSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot","type":"uint256"}],"name":"addSupportedSlot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"blockLoanAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockLoanLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"x","type":"uint256[5]"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"borrowFor","type":"address"},{"internalType":"address","name":"pineWallet","type":"address"}],"name":"borrow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newValuationSigner","type":"address"}],"name":"changeValuationSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"durationSeconds_poolParam","outputs":[{"internalType":"uint32","name":"interestBPS1000000XBlock","type":"uint32"},{"internalType":"uint32","name":"collateralFactorBPS","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_receiver","type":"address"},{"internalType":"address","name":"_reserve","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_params","type":"bytes"}],"name":"flashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"supportedCollection","type":"address"},{"internalType":"address","name":"valuationSigner","type":"address"},{"internalType":"address","name":"controlPlane","type":"address"},{"internalType":"address","name":"supportedCurrency","type":"address"},{"internalType":"address","name":"fundSource","type":"address"},{"internalType":"address","name":"feeStructure","type":"address"},{"internalType":"uint256","name":"maxLoanLimit","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftID","type":"uint256"},{"internalType":"uint256","name":"repayAmount","type":"uint256"},{"internalType":"address","name":"pineWallet","type":"address"}],"name":"repay","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bll","type":"uint256"}],"name":"setBlockLoanLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"},{"components":[{"internalType":"uint32","name":"interestBPS1000000XBlock","type":"uint32"},{"internalType":"uint32","name":"collateralFactorBPS","type":"uint32"}],"internalType":"struct ERC721LendingPool02.PoolParams","name":"ppm","type":"tuple"}],"name":"setDurationParam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bll","type":"uint256"}],"name":"setMaxLoanLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportedSlots","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"nftID","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"liquidation","type":"bool"}],"name":"withdrawERC721","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6139fb80620000f36000396000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c806378d4c57a11610125578063bc197c81116100ad578063d7087bc11161007c578063d7087bc11461059d578063f1a8cf85146105b0578063f23a6e61146105c3578063f2fde38b146105e2578063fd9147ae146105f557600080fd5b8063bc197c811461049c578063bd5c569b146104bb578063c6600e9a14610577578063ca45f7731461058a57600080fd5b806394bfd7b0116100f457806394bfd7b014610447578063960d86d51461045a578063a1db978214610463578063a6c81f5614610476578063b1e8f8ef1461048957600080fd5b806378d4c57a146104125780637e7f291b146104255780638456cb591461042e5780638da5cb5b1461043657600080fd5b80633ba7517c116101a85780634fa22448116101775780634fa224481461038b5780635c975abb146103d95780635cffe9de146103e4578063715018a6146103f7578063781cc8e5146103ff57600080fd5b80633ba7517c146103255780633e22c008146103385780633f4ba83a146103635780634f647a661461036b57600080fd5b80631b3d1f3b116101ef5780631b3d1f3b146102c25780631c39fe56146102d5578063297dc6b8146102ec5780632e1a7d4d146102ff57806339ead7201461031257600080fd5b806301ffc9a7146102215780631460e390146102495780631477f02d1461025e578063150b7a0214610271575b600080fd5b61023461022f366004612fdc565b610608565b60405190151581526020015b60405180910390f35b61025c61025736600461301b565b61063f565b005b61025c61026c3660046130a8565b6107e0565b6102a961027f3660046130c1565b7f150b7a023d4804d13e8c85fb27262cb750cf6ba9f9dd3bb30d90f482ceeb4b1f95945050505050565b6040516001600160e01b03199091168152602001610240565b61025c6102d03660046130a8565b6107ed565b6102de60d05481565b604051908152602001610240565b61025c6102fa366004613160565b61082a565b61025c61030d3660046130a8565b610878565b61025c61032036600461317d565b61092c565b6102de6103333660046130a8565b6109d7565b60c95461034b906001600160a01b031681565b6040516001600160a01b039091168152602001610240565b61025c6109f8565b6102de6103793660046130a8565b60d26020526000908152604090205481565b6103bc6103993660046130a8565b60d16020526000908152604090205463ffffffff80821691600160201b90041682565b6040805163ffffffff938416815292909116602083015201610240565b60655460ff16610234565b61025c6103f2366004613269565b610a0a565b61025c610f6e565b60cc5461034b906001600160a01b031681565b6102346104203660046132d5565b610f80565b6102de60cf5481565b61025c6117bc565b6033546001600160a01b031661034b565b60ca5461034b906001600160a01b031681565b6102de60d35481565b61025c61047136600461334e565b6117cc565b61025c6104843660046130a8565b61187a565b61023461049736600461337a565b611887565b6102a96104aa366004613433565b63bc197c8160e01b95945050505050565b6105216104c93660046130a8565b60d560205260009081526040902080546001820154600283015460038401546004850154600586015460068701546007909701549596949563ffffffff80861696600160201b9096041694906001600160a01b031689565b60408051998a5260208a019890985263ffffffff96871697890197909752949093166060870152608086019190915260a085015260c084015260e08301526001600160a01b031661010082015261012001610240565b61025c6105853660046134e1565b6127b1565b60cb5461034b906001600160a01b031681565b61025c6105ab366004613527565b6128b9565b60ce5461034b906001600160a01b031681565b6102a96105d136600461356f565b63f23a6e6160e01b95945050505050565b61025c6105f0366004613160565b612a5d565b60cd5461034b906001600160a01b031681565b60006001600160e01b03198216630271189760e51b148061063957506301ffc9a760e01b6001600160e01b03198316145b92915050565b600054610100900460ff161580801561065f5750600054600160ff909116105b806106795750303b158015610679575060005460ff166001145b6106e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610704576000805461ff0019166101001790555b61070c612ad6565b610714612b05565b61071c612b34565b60ca80546001600160a01b03199081166001600160a01b038b81169190911790925560c9805482168a841617905560cb8054821689841617905560cd8054821688841617905560cc80548216878416179055680ad78ebc5ac620000060d35560ce805490911691851691909117905560cf82905580156107d6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6107e8612b63565b60cf55565b6107f5612b63565b60d480546001810182556000919091527f9780e26d96b1f2a9a18ef8fc72d589dbf03ef788137b64f43897e83a91e7feec0155565b6033546001600160a01b031633148061084d575060cb546001600160a01b031633145b61085657600080fd5b60c980546001600160a01b0319166001600160a01b0392909216919091179055565b610880612b63565b60006108946033546001600160a01b031690565b6001600160a01b03168260405160006040518083038185875af1925050503d80600081146108de576040519150601f19603f3d011682016040523d82523d6000602084013e6108e3565b606091505b50509050806109285760405162461bcd60e51b815260206004820152601160248201527031b0b73737ba1039b2b7321032ba3432b960791b60448201526064016106d8565b5050565b610934612b63565b826001600160a01b031663f242432a306109566033546001600160a01b031690565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018590526064810184905260a06084820152600060a482015260c401600060405180830381600087803b1580156109ba57600080fd5b505af11580156109ce573d6000803e3d6000fd5b50505050505050565b60d481815481106109e757600080fd5b600091825260209091200154905081565b610a00612b63565b610a08612bbd565b565b610a12612c0f565b60cb5460405163ee5ea74b60e01b81523360048201526001600160a01b039091169063ee5ea74b90602401602060405180830381600087803b158015610a5757600080fd5b505af1158015610a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8f91906135d8565b610ad45760405162461bcd60e51b8152602060048201526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b60448201526064016106d8565b60cb5460405163ee5ea74b60e01b81526001600160a01b0386811660048301529091169063ee5ea74b90602401602060405180830381600087803b158015610b1b57600080fd5b505af1158015610b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5391906135d8565b610b9f5760405162461bcd60e51b815260206004820152601860248201527f4578656375746572206e6f742077686974656c6973746564000000000000000060448201526064016106d8565b60006001600160a01b03841615610c325760cc546040516370a0823160e01b81526001600160a01b039182166004820152908516906370a082319060240160206040518083038186803b158015610bf557600080fd5b505afa158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d91906135f5565b610c34565b475b905082811015610ca05760405162461bcd60e51b815260206004820152603160248201527f5468657265206973206e6f7420656e6f756768206c697175696469747920617660448201527061696c61626c6520746f20626f72726f7760781b60648201526084016106d8565b6000856001600160a01b038616610d5a576000876001600160a01b03168660405160006040518083038185875af1925050503d8060008114610cfe576040519150601f19603f3d011682016040523d82523d6000602084013e610d03565b606091505b5050905080610d545760405162461bcd60e51b815260206004820152601d60248201527f466c617368206c6f616e3a2063616e6e6f742073656e6420657468657200000060448201526064016106d8565b50610deb565b60cc546040516323b872dd60e01b81526001600160a01b03888116926323b872dd92610d9092909116908b908a9060040161360e565b602060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de291906135d8565b610deb57600080fd5b604051631dd0e4ab60e31b81526001600160a01b0382169063ee87255890610e1d908990899087908a9060040161367f565b600060405180830381600087803b158015610e3757600080fd5b505af1158015610e4b573d6000803e3d6000fd5b506000925050506001600160a01b03871615610ee35760cc546040516370a0823160e01b81526001600160a01b039182166004820152908816906370a082319060240160206040518083038186803b158015610ea657600080fd5b505afa158015610eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ede91906135f5565b610ee5565b475b9050610ef183856136cc565b8114610f5a5760405162461bcd60e51b815260206004820152603260248201527f5468652061637475616c2062616c616e6365206f66207468652070726f746f636044820152711bdb081a5cc81a5b98dbdb9cda5cdd195b9d60721b60648201526084016106d8565b50505050610f686001609755565b50505050565b610f76612b63565b610a086000612c70565b6000610f8a612c0f565b610f92612cc2565b60ca5460c954604051630f3f9bbf60e01b815273830f14a360ce394f3d5b6b0daa1140e577e4a48892630f3f9bbf92610fee926001600160a01b039283169260208c0135928c359260608e013592909116908c906004016136fa565b60206040518083038186803b15801561100657600080fd5b505af415801561101a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103e91906135d8565b61109e5760405162461bcd60e51b815260206004820152602b60248201527f5369676e617475726556657269666965723a2066616b652076616c756174696f60448201526a6e2070726f76696465642160a81b60648201526084016106d8565b60cb5460405163ee5ea74b60e01b81523360048201526001600160a01b039091169063ee5ea74b90602401602060405180830381600087803b1580156110e357600080fd5b505af11580156110f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111b91906135d8565b8061112557503332145b61115d5760405162461bcd60e51b81526020600482015260096024820152685068697368696e672160b81b60448201526064016106d8565b602080860135600090815260d5909152604090819020905163d4d3006360e01b8152339173510263ecbc928c8b78df68420a5955f6c9cc59a19163d4d30063916111a9916004016137ba565b60206040518083038186803b1580156111c157600080fd5b505af41580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f991906135d8565b1561123e5760405162461bcd60e51b81526020600482015260156024820152744e465420616c726561647920686173206c6f616e2160581b60448201526064016106d8565b604086810135600090815260d16020522054600160201b900463ffffffff16806112a35760405162461bcd60e51b8152602060048201526016602482015275111d5c985d1a5bdb881b9bdd081cdd5c1c1bdc9d195960521b60448201526064016106d8565b60ca546040516331a9108f60e11b8152602089013560048201526001600160a01b03848116921690636352211e9060240160206040518083038186803b1580156112ec57600080fd5b505afa158015611300573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132491906137c9565b6001600160a01b0316146113665760405162461bcd60e51b8152602060048201526009602482015268537465616c6572312160b81b60448201526064016106d8565b606087013543106113ad5760405162461bcd60e51b815260206004820152601160248201527015985b1d585d1a5bdb88195e1c1a5c9959607a1b60448201526064016106d8565b6127106113c163ffffffff831689356137e6565b6113cb9190613805565b6080880135111561141e5760405162461bcd60e51b815260206004820152601e60248201527f43616e277420626f72726f77206d6f7265207468616e206d6178204c5456000060448201526064016106d8565b60cd5460cc546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a082319060240160206040518083038186803b15801561146557600080fd5b505afa158015611479573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149d91906135f5565b6080880135106114e25760405162461bcd60e51b815260206004820152601060248201526f6e6f7420656e6f756768206d6f6e657960801b60448201526064016106d8565b6114ef6080880135612d08565b6114fc6080880135612d8c565b60cd5460cc546040516323b872dd60e01b81526001600160a01b03928316926323b872dd9261153892911690339060808d01359060040161360e565b602060405180830381600087803b15801561155257600080fd5b505af1158015611566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158a91906135d8565b61159357600080fd5b60408051610120810182524381529060208201906115b4908a0135426136cc565b81526040808a0135600090815260d160209081528282205463ffffffff908116918501919091528516918301919091526080808b01356060840152820181905260a0820181905260c082015260e0016001600160a01b0387166116175783611619565b865b6001600160a01b03908116909152602089810135600081815260d583526040908190208551815592850151600184015584810151600284018054606088015163ffffffff908116600160201b0267ffffffffffffffff199092169316929092179190911790556080850151600384015560a085015160048085019190915560c0860151600585015560e0860151600685015561010090950151600790930180549385166001600160a01b03199094169390931790925560ca5491516323b872dd60e01b815291909216926323b872dd926116f89287923092910161360e565b600060405180830381600087803b15801561171257600080fd5b505af1158015611726573d6000803e3d6000fd5b505050508660016005811061173d5761173d6136e4565b60ca5460208a810135600090815260d582526040908190209051939091029390930135926001600160a01b0391821692918616917f872dc93aead2083e073cc885fd9a73e19b414626890d68c6251f12ba51f8a3bd9161179c916137ba565b60405180910390a46001925050506117b46001609755565b949350505050565b6117c4612b63565b610a08612df7565b6117d4612b63565b816001600160a01b031663a9059cbb6117f56033546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b15801561183d57600080fd5b505af1158015611851573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187591906135d8565b505050565b611882612b63565b60d355565b6000611891612c0f565b600084815260d560205260409020600701546001600160a01b031632146118fa5760405162461bcd60e51b815260206004820152601e60248201527f5265706179206279203372642070617274792069732064697361626c6564000060448201526064016106d8565b60ca54600085815260d560205260409081902060070154905163e985e9c560e01b81526001600160a01b039182166004820152735284d97a1462a767f385ae6ae89ba9065ece193c602482015291169063e985e9c59060440160206040518083038186803b15801561196b57600080fd5b505afa15801561197f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a391906135d8565b15611aaf5760405162461bcd60e51b81526020600482015260c060248201527f5053413a20706c65617365207265766f6b6520746865204e465420636f6c6c6560448201527f6374696f6e277320617070726f76616c7320746f20307835323834643937613160648201527f343632413736374633383561453641653839424139303635656345313933632060848201527f7573696e67207265766f6b652e63617368206265666f7265207265706179696e60a48201527f672074686973206c6f616e2e20506c65617365207265616368206f757420746f60c48201527f20737570706f727420696e20646973636f726420696620696e20646f7562742e60e4820152610104016106d8565b600084815260d56020818152604080842081516101208101835281548152600182015481850152600282015463ffffffff808216838601819052600160201b9092041660608301526003830154608083015260048084015460a0840152600584015460c0840152600684015460e08401526007909301546001600160a01b0390811661010084015260ce548c895296909552925162b95dd160e21b8152918201929092529092909116906302e577449060240160206040518083038186803b158015611b7a57600080fd5b505afa158015611b8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb29190613839565b63ffffffff16604080830191909152600087815260d5602052819020905163d4d3006360e01b815273510263ecbc928c8b78df68420a5955f6c9cc59a19163d4d3006391611c0391906004016137ba565b60206040518083038186803b158015611c1b57600080fd5b505af4158015611c2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5391906135d8565b611c9f5760405162461bcd60e51b815260206004820152601d60248201527f4e465420646f6573206e6f74206861766520616374697665206c6f616e00000060448201526064016106d8565b60cd546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611cd390339030908a9060040161360e565b602060405180830381600087803b158015611ced57600080fd5b505af1158015611d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2591906135d8565b611d715760405162461bcd60e51b815260206004820152601a60248201527f66756e64207472616e7366657220756e7375636365737366756c00000000000060448201526064016106d8565b60405163df9a33b760e01b815273510263ecbc928c8b78df68420a5955f6c9cc59a19063df9a33b790611da89084906004016138c4565b60206040518083038186803b158015611dc057600080fd5b505af4158015611dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df891906135f5565b85106120fb5760cd5460405163df9a33b760e01b81526001600160a01b039091169063a9059cbb90339073510263ecbc928c8b78df68420a5955f6c9cc59a19063df9a33b790611e4c9087906004016138c4565b60206040518083038186803b158015611e6457600080fd5b505af4158015611e78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9c91906135f5565b611ea690896138d3565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b158015611eec57600080fd5b505af1158015611f00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2491906135d8565b611f7c5760405162461bcd60e51b815260206004820152602360248201527f65786365656420616d6f756e74207472616e7366657220756e73756363657373604482015262199d5b60ea1b60648201526084016106d8565b60405163df9a33b760e01b815273510263ecbc928c8b78df68420a5955f6c9cc59a19063df9a33b790611fb39084906004016138c4565b60206040518083038186803b158015611fcb57600080fd5b505af4158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200391906135f5565b600087815260d5602052604090206004810154600390910154919650612028916138d3565b60d0600082825461203991906138d3565b9091555050600086815260d560205260409020600481015460039091015461206191906138d3565b61206b90866138d3565b600087815260d5602052604090819020600381015460048083019190915560ca5460079092015492516323b872dd60e01b81529395506001600160a01b03918216936323b872dd936120c49330939116918c910161360e565b600060405180830381600087803b1580156120de57600080fd5b505af11580156120f2573d6000803e3d6000fd5b505050506122fc565b60ce54600087815260d560205260409081902060020154905162b95dd160e21b815263ffffffff90911660048201526402540be400916001600160a01b0316906302e577449060240160206040518083038186803b15801561215c57600080fd5b505afa158015612170573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121949190613839565b600088815260d560205260409020600481015460039091015463ffffffff92909216916121c191906138d3565b600089815260d560205260409020546121da90436138d3565b6121e491906137e6565b6121ee91906137e6565b6121f89190613805565b600087815260d56020526040812060050180549091906122199084906136cc565b9091555050600086815260d560205260408120600681015460059091015461224191906138d3565b9050808611156122bf57600087815260d560205260409020600581015460069091015561226e81876138d3565b600088815260d560205260408120600401805490919061228f9084906136cc565b9091555061229f905081876138d3565b60d060008282546122b091906138d3565b925050819055508092506122e9565b600087815260d56020526040812060060180548892906122e09084906136cc565b90915550869350505b50600086815260d5602052604090204390555b60cd5460cc5460ce54600089815260d56020526040908190206002015490516305c3aced60e31b815263ffffffff90911660048201526001600160a01b03938416936323b872dd933093908216926127109290911690632e1d67689060240160206040518083038186803b15801561237357600080fd5b505afa158015612387573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ab91906135f5565b6123b590886137e6565b6123bf9190613805565b60cd546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561240257600080fd5b505afa158015612416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243a91906135f5565b61244491906138d3565b6040518463ffffffff1660e01b81526004016124629392919061360e565b602060405180830381600087803b15801561247c57600080fd5b505af1158015612490573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b491906135d8565b61250c5760405162461bcd60e51b8152602060048201526024808201527f66756e64207472616e7366657220756e7375636365737366756c20287061796c6044820152636f61642960e01b60648201526084016106d8565b60cd5460cb5460ce54600089815260d56020526040908190206002015490516305c3aced60e31b815263ffffffff90911660048201526001600160a01b03938416936323b872dd933093908216926127109290911690632e1d67689060240160206040518083038186803b15801561258357600080fd5b505afa158015612597573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125bb91906135f5565b6125c590886137e6565b6125cf9190613805565b6040518463ffffffff1660e01b81526004016125ed9392919061360e565b602060405180830381600087803b15801561260757600080fd5b505af115801561261b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263f91906135d8565b61268b5760405162461bcd60e51b815260206004820181905260248201527f66756e64207472616e7366657220756e7375636365737366756c20286665652960448201526064016106d8565b600086815260d56020526040908190206002015463ffffffff168282015260ca5490516331a9108f60e11b81526004810188905230916001600160a01b031690636352211e9060240160206040518083038186803b1580156126ec57600080fd5b505afa158015612700573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272491906137c9565b6001600160a01b03161461273b5761273b86612e34565b60ca54600087815260d56020526040908190206007810154915189936001600160a01b039081169316917fb7faaf58a53a3a4bdfdd90dff44b713036c882f23772663c180bf72866f44c1c916127929187916138ea565b60405180910390a46001925050506127aa6001609755565b9392505050565b6127b9612b63565b60ce60009054906101000a90046001600160a01b03166001600160a01b031663f81c4bcd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561280757600080fd5b505afa15801561281b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283f91906135f5565b61284c6020830183613907565b63ffffffff161061285c57600080fd5b600082815260d16020526040902081906128768282613924565b50506000805260d16020527efa5413e7b01fc543d01f0911de573ace463b956369df4472f39030e8d98b7754600160201b900463ffffffff161561092857600080fd5b60cb546001600160a01b031633146129075760405162461bcd60e51b81526020600482015260116024820152706e6f7420636f6e74726f6c20706c616e6560781b60448201526064016106d8565b60ca546001600160a01b0385811691161480156129215750805b156129ff57600083815260d5602090815260409182902082516101208101845281548152600182015481840152600282015463ffffffff80821683870152600160201b90910416606082015260038201546080820152600482015460a0820152600582015460c0820152600682015460e08201526007909101546001600160a01b03908116610100830181905260ca548551428152329581019590955292948894939092169290917f23182fd5cfdcab25dcc2d3cd0edc29844ff4a8b180fd6ea161f6d935ae0f51c1910160405180910390a46129fd84612e34565b505b6040516323b872dd60e01b81526001600160a01b038516906323b872dd90612a2f9030908690889060040161360e565b600060405180830381600087803b158015612a4957600080fd5b505af11580156107d6573d6000803e3d6000fd5b612a65612b63565b6001600160a01b038116612aca5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106d8565b612ad381612c70565b50565b600054610100900460ff16612afd5760405162461bcd60e51b81526004016106d89061397a565b610a08612f09565b600054610100900460ff16612b2c5760405162461bcd60e51b81526004016106d89061397a565b610a08612f39565b600054610100900460ff16612b5b5760405162461bcd60e51b81526004016106d89061397a565b610a08612f6c565b6033546001600160a01b03163314610a085760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106d8565b612bc5612f93565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60026097541415612c625760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106d8565b6002609755565b6001609755565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60655460ff1615610a085760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106d8565b43600090815260d2602052604081208054839290612d279084906136cc565b909155505060d35443600090815260d2602052604090205410612ad35760405162461bcd60e51b815260206004820152601960248201527f416d6f756e742065786365656420626c6f636b206c696d69740000000000000060448201526064016106d8565b8060d06000828254612d9e91906136cc565b909155505060cf5460d0541115612ad35760405162461bcd60e51b815260206004820152601960248201527f416d6f756e742065786365656420746f74616c206c696d69740000000000000060448201526064016106d8565b612dff612cc2565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612bf23390565b604080516101208101825260008082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815260e089018881526101008a018981529b895260d59097529890962096518755925160018701559051600286018054925163ffffffff908116600160201b0267ffffffffffffffff199094169216919091179190911790555160038401559051600483015591516005820155905160068201559051600790910180546001600160a01b03929092166001600160a01b0319909216919091179055565b600054610100900460ff16612f305760405162461bcd60e51b81526004016106d89061397a565b610a0833612c70565b600054610100900460ff16612f605760405162461bcd60e51b81526004016106d89061397a565b6065805460ff19169055565b600054610100900460ff16612c695760405162461bcd60e51b81526004016106d89061397a565b60655460ff16610a085760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106d8565b600060208284031215612fee57600080fd5b81356001600160e01b0319811681146127aa57600080fd5b6001600160a01b0381168114612ad357600080fd5b600080600080600080600060e0888a03121561303657600080fd5b873561304181613006565b9650602088013561305181613006565b9550604088013561306181613006565b9450606088013561307181613006565b9350608088013561308181613006565b925060a088013561309181613006565b8092505060c0880135905092959891949750929550565b6000602082840312156130ba57600080fd5b5035919050565b6000806000806000608086880312156130d957600080fd5b85356130e481613006565b945060208601356130f481613006565b935060408601359250606086013567ffffffffffffffff8082111561311857600080fd5b818801915088601f83011261312c57600080fd5b81358181111561313b57600080fd5b89602082850101111561314d57600080fd5b9699959850939650602001949392505050565b60006020828403121561317257600080fd5b81356127aa81613006565b60008060006060848603121561319257600080fd5b833561319d81613006565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156131f1576131f16131b2565b604052919050565b600082601f83011261320a57600080fd5b813567ffffffffffffffff811115613224576132246131b2565b613237601f8201601f19166020016131c8565b81815284602083860101111561324c57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561327f57600080fd5b843561328a81613006565b9350602085013561329a81613006565b925060408501359150606085013567ffffffffffffffff8111156132bd57600080fd5b6132c9878288016131f9565b91505092959194509250565b60008060008061010085870312156132ec57600080fd5b60a08501868111156132fd57600080fd5b8594503567ffffffffffffffff81111561331657600080fd5b613322878288016131f9565b93505060c085013561333381613006565b915060e085013561334381613006565b939692955090935050565b6000806040838503121561336157600080fd5b823561336c81613006565b946020939093013593505050565b60008060006060848603121561338f57600080fd5b833592506020840135915060408401356133a881613006565b809150509250925092565b600082601f8301126133c457600080fd5b8135602067ffffffffffffffff8211156133e0576133e06131b2565b8160051b6133ef8282016131c8565b928352848101820192828101908785111561340957600080fd5b83870192505b848310156134285782358252918301919083019061340f565b979650505050505050565b600080600080600060a0868803121561344b57600080fd5b853561345681613006565b9450602086013561346681613006565b9350604086013567ffffffffffffffff8082111561348357600080fd5b61348f89838a016133b3565b945060608801359150808211156134a557600080fd5b6134b189838a016133b3565b935060808801359150808211156134c757600080fd5b506134d4888289016131f9565b9150509295509295909350565b60008082840360608112156134f557600080fd5b833592506040601f198201121561350b57600080fd5b506020830190509250929050565b8015158114612ad357600080fd5b6000806000806080858703121561353d57600080fd5b843561354881613006565b935060208501359250604085013561355f81613006565b9150606085013561334381613519565b600080600080600060a0868803121561358757600080fd5b853561359281613006565b945060208601356135a281613006565b93506040860135925060608601359150608086013567ffffffffffffffff8111156135cc57600080fd5b6134d4888289016131f9565b6000602082840312156135ea57600080fd5b81516127aa81613519565b60006020828403121561360757600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000815180845260005b818110156136585760208185018101518683018201520161363c565b8181111561366a576000602083870101525b50601f01601f19169290920160200192915050565b60018060a01b03851681528360208201528260408201526080606082015260006136ac6080830184613632565b9695505050505050565b634e487b7160e01b600052601160045260246000fd5b600082198211156136df576136df6136b6565b500190565b634e487b7160e01b600052603260045260246000fd5b600060018060a01b03808916835287602084015286604084015285606084015280851660808401525060c060a083015261373760c0830184613632565b98975050505050505050565b8054825260018101546020830152600281015463ffffffff808216604085015261377a60608501828460201c1663ffffffff169052565b505060038101546080830152600481015460a0830152600581015460c0830152600681015460e0830152600701546001600160a01b031661010090910152565b61012081016106398284613743565b6000602082840312156137db57600080fd5b81516127aa81613006565b6000816000190483118215151615613800576138006136b6565b500290565b60008261382257634e487b7160e01b600052601260045260246000fd5b500490565b63ffffffff81168114612ad357600080fd5b60006020828403121561384b57600080fd5b81516127aa81613827565b8051825260208101516020830152604081015163ffffffff808216604085015280606084015116606085015250506080810151608083015260a081015160a083015260c081015160c083015260e081015160e083015261010060018060a01b03818301511681840152505050565b61012081016106398284613856565b6000828210156138e5576138e56136b6565b500390565b61024081016138f98285613856565b6127aa610120830184613743565b60006020828403121561391957600080fd5b81356127aa81613827565b813561392f81613827565b63ffffffff8116905081548163ffffffff198216178355602084013561395481613827565b67ffffffff000000008160201b168367ffffffffffffffff198416171784555050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea264697066735822122010c3890b2badd00929624d688806c58757bcc793f3c7b54978b66a4884bc02f964736f6c63430008090033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061021c5760003560e01c806378d4c57a11610125578063bc197c81116100ad578063d7087bc11161007c578063d7087bc11461059d578063f1a8cf85146105b0578063f23a6e61146105c3578063f2fde38b146105e2578063fd9147ae146105f557600080fd5b8063bc197c811461049c578063bd5c569b146104bb578063c6600e9a14610577578063ca45f7731461058a57600080fd5b806394bfd7b0116100f457806394bfd7b014610447578063960d86d51461045a578063a1db978214610463578063a6c81f5614610476578063b1e8f8ef1461048957600080fd5b806378d4c57a146104125780637e7f291b146104255780638456cb591461042e5780638da5cb5b1461043657600080fd5b80633ba7517c116101a85780634fa22448116101775780634fa224481461038b5780635c975abb146103d95780635cffe9de146103e4578063715018a6146103f7578063781cc8e5146103ff57600080fd5b80633ba7517c146103255780633e22c008146103385780633f4ba83a146103635780634f647a661461036b57600080fd5b80631b3d1f3b116101ef5780631b3d1f3b146102c25780631c39fe56146102d5578063297dc6b8146102ec5780632e1a7d4d146102ff57806339ead7201461031257600080fd5b806301ffc9a7146102215780631460e390146102495780631477f02d1461025e578063150b7a0214610271575b600080fd5b61023461022f366004612fdc565b610608565b60405190151581526020015b60405180910390f35b61025c61025736600461301b565b61063f565b005b61025c61026c3660046130a8565b6107e0565b6102a961027f3660046130c1565b7f150b7a023d4804d13e8c85fb27262cb750cf6ba9f9dd3bb30d90f482ceeb4b1f95945050505050565b6040516001600160e01b03199091168152602001610240565b61025c6102d03660046130a8565b6107ed565b6102de60d05481565b604051908152602001610240565b61025c6102fa366004613160565b61082a565b61025c61030d3660046130a8565b610878565b61025c61032036600461317d565b61092c565b6102de6103333660046130a8565b6109d7565b60c95461034b906001600160a01b031681565b6040516001600160a01b039091168152602001610240565b61025c6109f8565b6102de6103793660046130a8565b60d26020526000908152604090205481565b6103bc6103993660046130a8565b60d16020526000908152604090205463ffffffff80821691600160201b90041682565b6040805163ffffffff938416815292909116602083015201610240565b60655460ff16610234565b61025c6103f2366004613269565b610a0a565b61025c610f6e565b60cc5461034b906001600160a01b031681565b6102346104203660046132d5565b610f80565b6102de60cf5481565b61025c6117bc565b6033546001600160a01b031661034b565b60ca5461034b906001600160a01b031681565b6102de60d35481565b61025c61047136600461334e565b6117cc565b61025c6104843660046130a8565b61187a565b61023461049736600461337a565b611887565b6102a96104aa366004613433565b63bc197c8160e01b95945050505050565b6105216104c93660046130a8565b60d560205260009081526040902080546001820154600283015460038401546004850154600586015460068701546007909701549596949563ffffffff80861696600160201b9096041694906001600160a01b031689565b60408051998a5260208a019890985263ffffffff96871697890197909752949093166060870152608086019190915260a085015260c084015260e08301526001600160a01b031661010082015261012001610240565b61025c6105853660046134e1565b6127b1565b60cb5461034b906001600160a01b031681565b61025c6105ab366004613527565b6128b9565b60ce5461034b906001600160a01b031681565b6102a96105d136600461356f565b63f23a6e6160e01b95945050505050565b61025c6105f0366004613160565b612a5d565b60cd5461034b906001600160a01b031681565b60006001600160e01b03198216630271189760e51b148061063957506301ffc9a760e01b6001600160e01b03198316145b92915050565b600054610100900460ff161580801561065f5750600054600160ff909116105b806106795750303b158015610679575060005460ff166001145b6106e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610704576000805461ff0019166101001790555b61070c612ad6565b610714612b05565b61071c612b34565b60ca80546001600160a01b03199081166001600160a01b038b81169190911790925560c9805482168a841617905560cb8054821689841617905560cd8054821688841617905560cc80548216878416179055680ad78ebc5ac620000060d35560ce805490911691851691909117905560cf82905580156107d6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6107e8612b63565b60cf55565b6107f5612b63565b60d480546001810182556000919091527f9780e26d96b1f2a9a18ef8fc72d589dbf03ef788137b64f43897e83a91e7feec0155565b6033546001600160a01b031633148061084d575060cb546001600160a01b031633145b61085657600080fd5b60c980546001600160a01b0319166001600160a01b0392909216919091179055565b610880612b63565b60006108946033546001600160a01b031690565b6001600160a01b03168260405160006040518083038185875af1925050503d80600081146108de576040519150601f19603f3d011682016040523d82523d6000602084013e6108e3565b606091505b50509050806109285760405162461bcd60e51b815260206004820152601160248201527031b0b73737ba1039b2b7321032ba3432b960791b60448201526064016106d8565b5050565b610934612b63565b826001600160a01b031663f242432a306109566033546001600160a01b031690565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018590526064810184905260a06084820152600060a482015260c401600060405180830381600087803b1580156109ba57600080fd5b505af11580156109ce573d6000803e3d6000fd5b50505050505050565b60d481815481106109e757600080fd5b600091825260209091200154905081565b610a00612b63565b610a08612bbd565b565b610a12612c0f565b60cb5460405163ee5ea74b60e01b81523360048201526001600160a01b039091169063ee5ea74b90602401602060405180830381600087803b158015610a5757600080fd5b505af1158015610a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8f91906135d8565b610ad45760405162461bcd60e51b8152602060048201526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b60448201526064016106d8565b60cb5460405163ee5ea74b60e01b81526001600160a01b0386811660048301529091169063ee5ea74b90602401602060405180830381600087803b158015610b1b57600080fd5b505af1158015610b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5391906135d8565b610b9f5760405162461bcd60e51b815260206004820152601860248201527f4578656375746572206e6f742077686974656c6973746564000000000000000060448201526064016106d8565b60006001600160a01b03841615610c325760cc546040516370a0823160e01b81526001600160a01b039182166004820152908516906370a082319060240160206040518083038186803b158015610bf557600080fd5b505afa158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d91906135f5565b610c34565b475b905082811015610ca05760405162461bcd60e51b815260206004820152603160248201527f5468657265206973206e6f7420656e6f756768206c697175696469747920617660448201527061696c61626c6520746f20626f72726f7760781b60648201526084016106d8565b6000856001600160a01b038616610d5a576000876001600160a01b03168660405160006040518083038185875af1925050503d8060008114610cfe576040519150601f19603f3d011682016040523d82523d6000602084013e610d03565b606091505b5050905080610d545760405162461bcd60e51b815260206004820152601d60248201527f466c617368206c6f616e3a2063616e6e6f742073656e6420657468657200000060448201526064016106d8565b50610deb565b60cc546040516323b872dd60e01b81526001600160a01b03888116926323b872dd92610d9092909116908b908a9060040161360e565b602060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de291906135d8565b610deb57600080fd5b604051631dd0e4ab60e31b81526001600160a01b0382169063ee87255890610e1d908990899087908a9060040161367f565b600060405180830381600087803b158015610e3757600080fd5b505af1158015610e4b573d6000803e3d6000fd5b506000925050506001600160a01b03871615610ee35760cc546040516370a0823160e01b81526001600160a01b039182166004820152908816906370a082319060240160206040518083038186803b158015610ea657600080fd5b505afa158015610eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ede91906135f5565b610ee5565b475b9050610ef183856136cc565b8114610f5a5760405162461bcd60e51b815260206004820152603260248201527f5468652061637475616c2062616c616e6365206f66207468652070726f746f636044820152711bdb081a5cc81a5b98dbdb9cda5cdd195b9d60721b60648201526084016106d8565b50505050610f686001609755565b50505050565b610f76612b63565b610a086000612c70565b6000610f8a612c0f565b610f92612cc2565b60ca5460c954604051630f3f9bbf60e01b815273830f14a360ce394f3d5b6b0daa1140e577e4a48892630f3f9bbf92610fee926001600160a01b039283169260208c0135928c359260608e013592909116908c906004016136fa565b60206040518083038186803b15801561100657600080fd5b505af415801561101a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103e91906135d8565b61109e5760405162461bcd60e51b815260206004820152602b60248201527f5369676e617475726556657269666965723a2066616b652076616c756174696f60448201526a6e2070726f76696465642160a81b60648201526084016106d8565b60cb5460405163ee5ea74b60e01b81523360048201526001600160a01b039091169063ee5ea74b90602401602060405180830381600087803b1580156110e357600080fd5b505af11580156110f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111b91906135d8565b8061112557503332145b61115d5760405162461bcd60e51b81526020600482015260096024820152685068697368696e672160b81b60448201526064016106d8565b602080860135600090815260d5909152604090819020905163d4d3006360e01b8152339173510263ecbc928c8b78df68420a5955f6c9cc59a19163d4d30063916111a9916004016137ba565b60206040518083038186803b1580156111c157600080fd5b505af41580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f991906135d8565b1561123e5760405162461bcd60e51b81526020600482015260156024820152744e465420616c726561647920686173206c6f616e2160581b60448201526064016106d8565b604086810135600090815260d16020522054600160201b900463ffffffff16806112a35760405162461bcd60e51b8152602060048201526016602482015275111d5c985d1a5bdb881b9bdd081cdd5c1c1bdc9d195960521b60448201526064016106d8565b60ca546040516331a9108f60e11b8152602089013560048201526001600160a01b03848116921690636352211e9060240160206040518083038186803b1580156112ec57600080fd5b505afa158015611300573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132491906137c9565b6001600160a01b0316146113665760405162461bcd60e51b8152602060048201526009602482015268537465616c6572312160b81b60448201526064016106d8565b606087013543106113ad5760405162461bcd60e51b815260206004820152601160248201527015985b1d585d1a5bdb88195e1c1a5c9959607a1b60448201526064016106d8565b6127106113c163ffffffff831689356137e6565b6113cb9190613805565b6080880135111561141e5760405162461bcd60e51b815260206004820152601e60248201527f43616e277420626f72726f77206d6f7265207468616e206d6178204c5456000060448201526064016106d8565b60cd5460cc546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a082319060240160206040518083038186803b15801561146557600080fd5b505afa158015611479573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149d91906135f5565b6080880135106114e25760405162461bcd60e51b815260206004820152601060248201526f6e6f7420656e6f756768206d6f6e657960801b60448201526064016106d8565b6114ef6080880135612d08565b6114fc6080880135612d8c565b60cd5460cc546040516323b872dd60e01b81526001600160a01b03928316926323b872dd9261153892911690339060808d01359060040161360e565b602060405180830381600087803b15801561155257600080fd5b505af1158015611566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158a91906135d8565b61159357600080fd5b60408051610120810182524381529060208201906115b4908a0135426136cc565b81526040808a0135600090815260d160209081528282205463ffffffff908116918501919091528516918301919091526080808b01356060840152820181905260a0820181905260c082015260e0016001600160a01b0387166116175783611619565b865b6001600160a01b03908116909152602089810135600081815260d583526040908190208551815592850151600184015584810151600284018054606088015163ffffffff908116600160201b0267ffffffffffffffff199092169316929092179190911790556080850151600384015560a085015160048085019190915560c0860151600585015560e0860151600685015561010090950151600790930180549385166001600160a01b03199094169390931790925560ca5491516323b872dd60e01b815291909216926323b872dd926116f89287923092910161360e565b600060405180830381600087803b15801561171257600080fd5b505af1158015611726573d6000803e3d6000fd5b505050508660016005811061173d5761173d6136e4565b60ca5460208a810135600090815260d582526040908190209051939091029390930135926001600160a01b0391821692918616917f872dc93aead2083e073cc885fd9a73e19b414626890d68c6251f12ba51f8a3bd9161179c916137ba565b60405180910390a46001925050506117b46001609755565b949350505050565b6117c4612b63565b610a08612df7565b6117d4612b63565b816001600160a01b031663a9059cbb6117f56033546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b15801561183d57600080fd5b505af1158015611851573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187591906135d8565b505050565b611882612b63565b60d355565b6000611891612c0f565b600084815260d560205260409020600701546001600160a01b031632146118fa5760405162461bcd60e51b815260206004820152601e60248201527f5265706179206279203372642070617274792069732064697361626c6564000060448201526064016106d8565b60ca54600085815260d560205260409081902060070154905163e985e9c560e01b81526001600160a01b039182166004820152735284d97a1462a767f385ae6ae89ba9065ece193c602482015291169063e985e9c59060440160206040518083038186803b15801561196b57600080fd5b505afa15801561197f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a391906135d8565b15611aaf5760405162461bcd60e51b81526020600482015260c060248201527f5053413a20706c65617365207265766f6b6520746865204e465420636f6c6c6560448201527f6374696f6e277320617070726f76616c7320746f20307835323834643937613160648201527f343632413736374633383561453641653839424139303635656345313933632060848201527f7573696e67207265766f6b652e63617368206265666f7265207265706179696e60a48201527f672074686973206c6f616e2e20506c65617365207265616368206f757420746f60c48201527f20737570706f727420696e20646973636f726420696620696e20646f7562742e60e4820152610104016106d8565b600084815260d56020818152604080842081516101208101835281548152600182015481850152600282015463ffffffff808216838601819052600160201b9092041660608301526003830154608083015260048084015460a0840152600584015460c0840152600684015460e08401526007909301546001600160a01b0390811661010084015260ce548c895296909552925162b95dd160e21b8152918201929092529092909116906302e577449060240160206040518083038186803b158015611b7a57600080fd5b505afa158015611b8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb29190613839565b63ffffffff16604080830191909152600087815260d5602052819020905163d4d3006360e01b815273510263ecbc928c8b78df68420a5955f6c9cc59a19163d4d3006391611c0391906004016137ba565b60206040518083038186803b158015611c1b57600080fd5b505af4158015611c2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5391906135d8565b611c9f5760405162461bcd60e51b815260206004820152601d60248201527f4e465420646f6573206e6f74206861766520616374697665206c6f616e00000060448201526064016106d8565b60cd546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611cd390339030908a9060040161360e565b602060405180830381600087803b158015611ced57600080fd5b505af1158015611d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2591906135d8565b611d715760405162461bcd60e51b815260206004820152601a60248201527f66756e64207472616e7366657220756e7375636365737366756c00000000000060448201526064016106d8565b60405163df9a33b760e01b815273510263ecbc928c8b78df68420a5955f6c9cc59a19063df9a33b790611da89084906004016138c4565b60206040518083038186803b158015611dc057600080fd5b505af4158015611dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df891906135f5565b85106120fb5760cd5460405163df9a33b760e01b81526001600160a01b039091169063a9059cbb90339073510263ecbc928c8b78df68420a5955f6c9cc59a19063df9a33b790611e4c9087906004016138c4565b60206040518083038186803b158015611e6457600080fd5b505af4158015611e78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9c91906135f5565b611ea690896138d3565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b158015611eec57600080fd5b505af1158015611f00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2491906135d8565b611f7c5760405162461bcd60e51b815260206004820152602360248201527f65786365656420616d6f756e74207472616e7366657220756e73756363657373604482015262199d5b60ea1b60648201526084016106d8565b60405163df9a33b760e01b815273510263ecbc928c8b78df68420a5955f6c9cc59a19063df9a33b790611fb39084906004016138c4565b60206040518083038186803b158015611fcb57600080fd5b505af4158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200391906135f5565b600087815260d5602052604090206004810154600390910154919650612028916138d3565b60d0600082825461203991906138d3565b9091555050600086815260d560205260409020600481015460039091015461206191906138d3565b61206b90866138d3565b600087815260d5602052604090819020600381015460048083019190915560ca5460079092015492516323b872dd60e01b81529395506001600160a01b03918216936323b872dd936120c49330939116918c910161360e565b600060405180830381600087803b1580156120de57600080fd5b505af11580156120f2573d6000803e3d6000fd5b505050506122fc565b60ce54600087815260d560205260409081902060020154905162b95dd160e21b815263ffffffff90911660048201526402540be400916001600160a01b0316906302e577449060240160206040518083038186803b15801561215c57600080fd5b505afa158015612170573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121949190613839565b600088815260d560205260409020600481015460039091015463ffffffff92909216916121c191906138d3565b600089815260d560205260409020546121da90436138d3565b6121e491906137e6565b6121ee91906137e6565b6121f89190613805565b600087815260d56020526040812060050180549091906122199084906136cc565b9091555050600086815260d560205260408120600681015460059091015461224191906138d3565b9050808611156122bf57600087815260d560205260409020600581015460069091015561226e81876138d3565b600088815260d560205260408120600401805490919061228f9084906136cc565b9091555061229f905081876138d3565b60d060008282546122b091906138d3565b925050819055508092506122e9565b600087815260d56020526040812060060180548892906122e09084906136cc565b90915550869350505b50600086815260d5602052604090204390555b60cd5460cc5460ce54600089815260d56020526040908190206002015490516305c3aced60e31b815263ffffffff90911660048201526001600160a01b03938416936323b872dd933093908216926127109290911690632e1d67689060240160206040518083038186803b15801561237357600080fd5b505afa158015612387573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ab91906135f5565b6123b590886137e6565b6123bf9190613805565b60cd546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561240257600080fd5b505afa158015612416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243a91906135f5565b61244491906138d3565b6040518463ffffffff1660e01b81526004016124629392919061360e565b602060405180830381600087803b15801561247c57600080fd5b505af1158015612490573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b491906135d8565b61250c5760405162461bcd60e51b8152602060048201526024808201527f66756e64207472616e7366657220756e7375636365737366756c20287061796c6044820152636f61642960e01b60648201526084016106d8565b60cd5460cb5460ce54600089815260d56020526040908190206002015490516305c3aced60e31b815263ffffffff90911660048201526001600160a01b03938416936323b872dd933093908216926127109290911690632e1d67689060240160206040518083038186803b15801561258357600080fd5b505afa158015612597573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125bb91906135f5565b6125c590886137e6565b6125cf9190613805565b6040518463ffffffff1660e01b81526004016125ed9392919061360e565b602060405180830381600087803b15801561260757600080fd5b505af115801561261b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263f91906135d8565b61268b5760405162461bcd60e51b815260206004820181905260248201527f66756e64207472616e7366657220756e7375636365737366756c20286665652960448201526064016106d8565b600086815260d56020526040908190206002015463ffffffff168282015260ca5490516331a9108f60e11b81526004810188905230916001600160a01b031690636352211e9060240160206040518083038186803b1580156126ec57600080fd5b505afa158015612700573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272491906137c9565b6001600160a01b03161461273b5761273b86612e34565b60ca54600087815260d56020526040908190206007810154915189936001600160a01b039081169316917fb7faaf58a53a3a4bdfdd90dff44b713036c882f23772663c180bf72866f44c1c916127929187916138ea565b60405180910390a46001925050506127aa6001609755565b9392505050565b6127b9612b63565b60ce60009054906101000a90046001600160a01b03166001600160a01b031663f81c4bcd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561280757600080fd5b505afa15801561281b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283f91906135f5565b61284c6020830183613907565b63ffffffff161061285c57600080fd5b600082815260d16020526040902081906128768282613924565b50506000805260d16020527efa5413e7b01fc543d01f0911de573ace463b956369df4472f39030e8d98b7754600160201b900463ffffffff161561092857600080fd5b60cb546001600160a01b031633146129075760405162461bcd60e51b81526020600482015260116024820152706e6f7420636f6e74726f6c20706c616e6560781b60448201526064016106d8565b60ca546001600160a01b0385811691161480156129215750805b156129ff57600083815260d5602090815260409182902082516101208101845281548152600182015481840152600282015463ffffffff80821683870152600160201b90910416606082015260038201546080820152600482015460a0820152600582015460c0820152600682015460e08201526007909101546001600160a01b03908116610100830181905260ca548551428152329581019590955292948894939092169290917f23182fd5cfdcab25dcc2d3cd0edc29844ff4a8b180fd6ea161f6d935ae0f51c1910160405180910390a46129fd84612e34565b505b6040516323b872dd60e01b81526001600160a01b038516906323b872dd90612a2f9030908690889060040161360e565b600060405180830381600087803b158015612a4957600080fd5b505af11580156107d6573d6000803e3d6000fd5b612a65612b63565b6001600160a01b038116612aca5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106d8565b612ad381612c70565b50565b600054610100900460ff16612afd5760405162461bcd60e51b81526004016106d89061397a565b610a08612f09565b600054610100900460ff16612b2c5760405162461bcd60e51b81526004016106d89061397a565b610a08612f39565b600054610100900460ff16612b5b5760405162461bcd60e51b81526004016106d89061397a565b610a08612f6c565b6033546001600160a01b03163314610a085760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106d8565b612bc5612f93565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60026097541415612c625760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106d8565b6002609755565b6001609755565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60655460ff1615610a085760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106d8565b43600090815260d2602052604081208054839290612d279084906136cc565b909155505060d35443600090815260d2602052604090205410612ad35760405162461bcd60e51b815260206004820152601960248201527f416d6f756e742065786365656420626c6f636b206c696d69740000000000000060448201526064016106d8565b8060d06000828254612d9e91906136cc565b909155505060cf5460d0541115612ad35760405162461bcd60e51b815260206004820152601960248201527f416d6f756e742065786365656420746f74616c206c696d69740000000000000060448201526064016106d8565b612dff612cc2565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612bf23390565b604080516101208101825260008082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815260e089018881526101008a018981529b895260d59097529890962096518755925160018701559051600286018054925163ffffffff908116600160201b0267ffffffffffffffff199094169216919091179190911790555160038401559051600483015591516005820155905160068201559051600790910180546001600160a01b03929092166001600160a01b0319909216919091179055565b600054610100900460ff16612f305760405162461bcd60e51b81526004016106d89061397a565b610a0833612c70565b600054610100900460ff16612f605760405162461bcd60e51b81526004016106d89061397a565b6065805460ff19169055565b600054610100900460ff16612c695760405162461bcd60e51b81526004016106d89061397a565b60655460ff16610a085760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106d8565b600060208284031215612fee57600080fd5b81356001600160e01b0319811681146127aa57600080fd5b6001600160a01b0381168114612ad357600080fd5b600080600080600080600060e0888a03121561303657600080fd5b873561304181613006565b9650602088013561305181613006565b9550604088013561306181613006565b9450606088013561307181613006565b9350608088013561308181613006565b925060a088013561309181613006565b8092505060c0880135905092959891949750929550565b6000602082840312156130ba57600080fd5b5035919050565b6000806000806000608086880312156130d957600080fd5b85356130e481613006565b945060208601356130f481613006565b935060408601359250606086013567ffffffffffffffff8082111561311857600080fd5b818801915088601f83011261312c57600080fd5b81358181111561313b57600080fd5b89602082850101111561314d57600080fd5b9699959850939650602001949392505050565b60006020828403121561317257600080fd5b81356127aa81613006565b60008060006060848603121561319257600080fd5b833561319d81613006565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156131f1576131f16131b2565b604052919050565b600082601f83011261320a57600080fd5b813567ffffffffffffffff811115613224576132246131b2565b613237601f8201601f19166020016131c8565b81815284602083860101111561324c57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561327f57600080fd5b843561328a81613006565b9350602085013561329a81613006565b925060408501359150606085013567ffffffffffffffff8111156132bd57600080fd5b6132c9878288016131f9565b91505092959194509250565b60008060008061010085870312156132ec57600080fd5b60a08501868111156132fd57600080fd5b8594503567ffffffffffffffff81111561331657600080fd5b613322878288016131f9565b93505060c085013561333381613006565b915060e085013561334381613006565b939692955090935050565b6000806040838503121561336157600080fd5b823561336c81613006565b946020939093013593505050565b60008060006060848603121561338f57600080fd5b833592506020840135915060408401356133a881613006565b809150509250925092565b600082601f8301126133c457600080fd5b8135602067ffffffffffffffff8211156133e0576133e06131b2565b8160051b6133ef8282016131c8565b928352848101820192828101908785111561340957600080fd5b83870192505b848310156134285782358252918301919083019061340f565b979650505050505050565b600080600080600060a0868803121561344b57600080fd5b853561345681613006565b9450602086013561346681613006565b9350604086013567ffffffffffffffff8082111561348357600080fd5b61348f89838a016133b3565b945060608801359150808211156134a557600080fd5b6134b189838a016133b3565b935060808801359150808211156134c757600080fd5b506134d4888289016131f9565b9150509295509295909350565b60008082840360608112156134f557600080fd5b833592506040601f198201121561350b57600080fd5b506020830190509250929050565b8015158114612ad357600080fd5b6000806000806080858703121561353d57600080fd5b843561354881613006565b935060208501359250604085013561355f81613006565b9150606085013561334381613519565b600080600080600060a0868803121561358757600080fd5b853561359281613006565b945060208601356135a281613006565b93506040860135925060608601359150608086013567ffffffffffffffff8111156135cc57600080fd5b6134d4888289016131f9565b6000602082840312156135ea57600080fd5b81516127aa81613519565b60006020828403121561360757600080fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000815180845260005b818110156136585760208185018101518683018201520161363c565b8181111561366a576000602083870101525b50601f01601f19169290920160200192915050565b60018060a01b03851681528360208201528260408201526080606082015260006136ac6080830184613632565b9695505050505050565b634e487b7160e01b600052601160045260246000fd5b600082198211156136df576136df6136b6565b500190565b634e487b7160e01b600052603260045260246000fd5b600060018060a01b03808916835287602084015286604084015285606084015280851660808401525060c060a083015261373760c0830184613632565b98975050505050505050565b8054825260018101546020830152600281015463ffffffff808216604085015261377a60608501828460201c1663ffffffff169052565b505060038101546080830152600481015460a0830152600581015460c0830152600681015460e0830152600701546001600160a01b031661010090910152565b61012081016106398284613743565b6000602082840312156137db57600080fd5b81516127aa81613006565b6000816000190483118215151615613800576138006136b6565b500290565b60008261382257634e487b7160e01b600052601260045260246000fd5b500490565b63ffffffff81168114612ad357600080fd5b60006020828403121561384b57600080fd5b81516127aa81613827565b8051825260208101516020830152604081015163ffffffff808216604085015280606084015116606085015250506080810151608083015260a081015160a083015260c081015160c083015260e081015160e083015261010060018060a01b03818301511681840152505050565b61012081016106398284613856565b6000828210156138e5576138e56136b6565b500390565b61024081016138f98285613856565b6127aa610120830184613743565b60006020828403121561391957600080fd5b81356127aa81613827565b813561392f81613827565b63ffffffff8116905081548163ffffffff198216178355602084013561395481613827565b67ffffffff000000008160201b168367ffffffffffffffff198416171784555050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea264697066735822122010c3890b2badd00929624d688806c58757bcc793f3c7b54978b66a4884bc02f964736f6c63430008090033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.