Source Code
Latest 8 from a total of 8 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Repay Loan | 22718457 | 21 days ago | IN | 0 ETH | 0.00083251 | ||||
Accept Loan | 22718448 | 21 days ago | IN | 0 ETH | 0.0003069 | ||||
Place Bid | 22718441 | 21 days ago | IN | 0 ETH | 0.00049129 | ||||
List Loan | 22718372 | 21 days ago | IN | 0 ETH | 0.00125233 | ||||
Delist Loan | 22714407 | 22 days ago | IN | 0 ETH | 0.00009862 | ||||
List Loan | 22698678 | 24 days ago | IN | 0 ETH | 0.00044092 | ||||
Update Allowed N... | 22624439 | 35 days ago | IN | 0 ETH | 0.00026903 | ||||
Update Allowed E... | 22624438 | 35 days ago | IN | 0 ETH | 0.00025235 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
NFTLendMarket
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; // For ERC‑20 principal token import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; /** * @title NFTLendMarket * @notice A decentralized NFT lending platform where borrowers list NFTs as collateral, * and loans are funded using one of a list of allowed ERC‑20 tokens as the principal. * Lenders can either bid by transferring tokens on the fly or use their deposited funds. * * SECURITY NOTE: * This version follows the checks‑effects‑interactions pattern. */ contract NFTLendMarket is ReentrancyGuard, AccessControl { // Roles bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE"); bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); // Enum for loan status enum LoanStatus { Listed, // Newly listed, awaiting bids Accepted, // A bid has been accepted Repaid, // Loan repaid Defaulted, // Loan defaulted and NFT claimed by lender Delisted, // Loan canceled by borrower before acceptance Expired // Loan listing expired (admin action) } // Enum for loan type remains unchanged enum LoanType { FIXED, APR } struct Loan { address borrower; // Borrower's address address lender; // Current lender (lowest bid) address nftAddress; // NFT contract address uint256 tokenId; // NFT token ID used as collateral uint256 loanAmount; // Loan principal amount (in ERC20 token smallest units) uint256 maxInterestRate; // Maximum acceptable interest rate (in basis points) uint256 currentInterestRate;// Current best bid interest rate (in basis points) uint256 duration; // Loan duration (in seconds) uint256 startTime; // Start time once accepted (0 if not started) LoanType loanType; // FIXED or APR LoanStatus status; // Current status of the loan address principalToken; // The ERC20 token used as the loan principal uint256 listingTime; // Timestamp when the loan was listed } uint256 public loanCounter; mapping(uint256 => Loan) public loans; // Escrowed lender funds per loan (in ERC20 token units) mapping(uint256 => uint256) public escrowedFunds; // Allowed NFT and ERC20 contracts mapping(address => bool) public allowedNFTContracts; mapping(address => bool) public allowedERC20Contracts; // Tracking which NFTs are currently collateralized mapping(address => mapping(uint256 => bool)) public isCollateralized; /// @notice maps an NFT to its current active loanId+1 (0 means “no active loan”) mapping(address => mapping(uint256 => uint256)) private _nftLoanPlusOne; /// @notice true if this NFT has ever defaulted (borrower failed to repay on time) mapping(address => mapping(uint256 => bool)) public everDefaultedLoan; // User balances held in the contract (available funds for bids or withdrawal) mapping(address => mapping(address => uint256)) public userBalances; // Global tracking of user funds per token mapping(address => uint256) public totalUserBalances; // Protocol fees collected per ERC20 token mapping(address => uint256) public protocolFeeBalance; // Active loan tracking uint256 public maxActiveLoans = 1000; uint256[] public activeLoanIds; mapping(uint256 => bool) public activeLoans; // Expiration time for listed loans (e.g., 7 days) uint256 public loanListExpiration = 7 days; uint256 public protocolFeeRate = 200; // In basis points (e.g., 200 = 2%) // Timestamp of the last bid for each loan mapping(uint256 => uint256) public bidTimestamps; uint256 public bidCancelPeriod = 1 days; // EVENTS event LoanListed( uint256 indexed loanId, address indexed borrower, address nftAddress, uint256 tokenId, uint256 loanAmount, uint256 maxInterestRate, uint256 duration, LoanType loanType, address principalToken ); event LoanDelisted(uint256 indexed loanId, address indexed borrower); event LoanBidPlaced(uint256 indexed loanId, address indexed lender, uint256 currentInterestRate); event LoanBidCancelled(uint256 indexed loanId, address indexed lender); event LoanAccepted( uint256 indexed loanId, address indexed borrower, address indexed lender, uint256 startTime, address principalToken ); event LoanRepaid(uint256 indexed loanId, address indexed borrower, uint256 repaymentAmount); event LoanDefaulted(uint256 indexed loanId, address indexed lender); event AllowedNFTUpdated(address indexed nftAddress, bool allowed); event AllowedERC20Updated(address indexed token, bool allowed); event ProtocolFeeRateUpdated(uint256 newFeeRate); event ProtocolFeesWithdrawn(address to, uint256 amount, address token); event MaxActiveLoansUpdated(uint256 newMaxActiveLoans); event BidCancelPeriodUpdated(uint256 newBidCancelPeriod); event UserBalanceUpdated(address indexed user, uint256 amount, address token); event FundsWithdrawn(address indexed user, uint256 amount, address indexed to, address token); event FundsDeposited(address indexed user, uint256 amount, address token); event LoanListExpirationUpdated(uint256 newExpiration); // MODIFIERS modifier onlyBorrower(uint256 loanId) { require(msg.sender == loans[loanId].borrower, "Not loan borrower"); _; } modifier onlyLender(uint256 loanId) { require(msg.sender == loans[loanId].lender, "Not loan lender"); _; } modifier onlyNftOwner(address nftAddress, uint256 tokenId) { require(IERC721(nftAddress).ownerOf(tokenId) == msg.sender, "Not NFT owner"); _; } // Instead of isNotAccepted, we now require the loan be in Listed status. modifier isListed(uint256 loanId) { require(loans[loanId].status == LoanStatus.Listed, "Loan not in Listed status"); _; } modifier loanExists(uint256 loanId) { require(loans[loanId].borrower != address(0), "Loan does not exist"); _; } modifier isAllowedNFT(address nftAddress) { require(allowedNFTContracts[nftAddress], "NFT contract not allowed"); _; } modifier isAllowedERC20(address token) { require(allowedERC20Contracts[token], "ERC20 token not allowed"); _; } // CONSTRUCTOR constructor(address _govAddress, address _manager) { _grantRole(DEFAULT_ADMIN_ROLE, _govAddress); _grantRole(OWNER_ROLE, _govAddress); _grantRole(MANAGER_ROLE, _manager); } // SETTER: Update default loan expiration function setLoanListExpiration(uint256 newExpiration) external onlyRole(OWNER_ROLE) { loanListExpiration = newExpiration; emit LoanListExpirationUpdated(newExpiration); } // Getter for active loan IDs function getActiveLoans() external view returns (uint256[] memory) { return activeLoanIds; } // ADMIN FUNCTIONS function grantManagerRole(address account) external onlyRole(DEFAULT_ADMIN_ROLE) { grantRole(MANAGER_ROLE, account); } function setMaxActiveLoans(uint256 newMax) external onlyRole(OWNER_ROLE) { maxActiveLoans = newMax; emit MaxActiveLoansUpdated(newMax); } function updateAllowedNFT(address nftAddress, bool allowed) external onlyRole(MANAGER_ROLE) { require(nftAddress != address(0), "Invalid NFT address"); require(nftAddress.code.length > 0, "Address is not a contract"); try IERC721(nftAddress).supportsInterface(0x80ac58cd) returns (bool isERC721) { require(isERC721, "Contract not ERC721"); } catch { revert("Failed to verify ERC721"); } allowedNFTContracts[nftAddress] = allowed; emit AllowedNFTUpdated(nftAddress, allowed); } function updateAllowedERC20(address token, bool allowed) external onlyRole(MANAGER_ROLE) { require(token != address(0), "Invalid token address"); allowedERC20Contracts[token] = allowed; emit AllowedERC20Updated(token, allowed); } function revokeManagerRole(address account) external onlyRole(DEFAULT_ADMIN_ROLE) { revokeRole(MANAGER_ROLE, account); } function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(OWNER_ROLE) { require(newFeeRate <= 1000, "Fee rate too high"); protocolFeeRate = newFeeRate; emit ProtocolFeeRateUpdated(newFeeRate); } function setBidCancelPeriod(uint256 newBidCancelPeriod) external onlyRole(OWNER_ROLE) { require(newBidCancelPeriod > 1 hours, "BidCancelPeriod too short"); bidCancelPeriod = newBidCancelPeriod; emit BidCancelPeriodUpdated(newBidCancelPeriod); } // INTERNAL: Update user balance (for deposits, refunds, etc.) function _addUserBalance(address user, uint256 amount, address token) internal { userBalances[user][token] += amount; totalUserBalances[token] += amount; emit UserBalanceUpdated(user, userBalances[user][token], token); } // INTERNAL: Deduct user balance function _deductUserBalance(address user, uint256 amount, address token) internal { require(userBalances[user][token] >= amount, "Insufficient balance"); userBalances[user][token] -= amount; totalUserBalances[token] -= amount; emit UserBalanceUpdated(user, userBalances[user][token], token); } // INTERNAL: Update active loans list (removes loanId from activeLoanIds) function _removeActiveLoan(uint256 loanId) private { delete activeLoans[loanId]; for (uint256 i = 0; i < activeLoanIds.length; ) { if (activeLoanIds[i] == loanId) { activeLoanIds[i] = activeLoanIds[activeLoanIds.length - 1]; activeLoanIds.pop(); break; } unchecked { i++; } } } // LOAN FUNCTIONS /** * @notice Lists a new loan by depositing an NFT as collateral. */ function listLoan( address nftAddress, uint256 tokenId, uint256 loanAmount, uint256 maxInterestRate, uint256 duration, LoanType loanType, address principalToken ) external nonReentrant isAllowedNFT(nftAddress) isAllowedERC20(principalToken) onlyNftOwner(nftAddress, tokenId) { require(activeLoanIds.length < maxActiveLoans, "Active loan limit reached"); require(!isCollateralized[nftAddress][tokenId], "NFT already collateralized"); require(loanAmount > 0, "Loan amount must be > 0"); require(maxInterestRate > 0, "Interest rate must be > 0"); require(duration > 0, "Duration must be > 0"); require(uint256(loanType) <= uint256(type(LoanType).max), "Invalid loan type"); uint256 loanId = loanCounter; loans[loanId] = Loan({ borrower: msg.sender, lender: address(0), nftAddress: nftAddress, tokenId: tokenId, loanAmount: loanAmount, maxInterestRate: maxInterestRate, currentInterestRate: maxInterestRate, duration: duration, startTime: 0, loanType: loanType, status: LoanStatus.Listed, principalToken: principalToken, listingTime: block.timestamp }); activeLoans[loanId] = true; activeLoanIds.push(loanId); _nftLoanPlusOne[nftAddress][tokenId] = loanId + 1; loanCounter++; isCollateralized[nftAddress][tokenId] = true; try IERC721(nftAddress).transferFrom(msg.sender, address(this), tokenId) { emit LoanListed(loanId, msg.sender, nftAddress, tokenId, loanAmount, maxInterestRate, duration, loanType, principalToken); } catch { revert("NFT transfer failed"); } } /** * @notice Allows a user to deposit ERC20 tokens into their balance. */ function depositFunds(address token, uint256 amount) external nonReentrant isAllowedERC20(token) { require(amount > 0, "Amount must be > 0"); _addUserBalance(msg.sender, amount, token); require(IERC20(token).transferFrom(msg.sender, address(this), amount), "Token transfer failed"); emit FundsDeposited(msg.sender, amount, token); } /** * @notice Withdraw funds from the user's balance. */ function withdrawFunds(address token, address to) external nonReentrant { require(to != address(0), "Invalid address"); uint256 amount = userBalances[msg.sender][token]; require(amount > 0, "No funds to withdraw"); userBalances[msg.sender][token] = 0; totalUserBalances[token] -= amount; require(IERC20(token).transfer(to, amount), "Transfer failed"); emit FundsWithdrawn(msg.sender, amount, to, token); } /** * @notice Places a bid by transferring ERC20 tokens directly. */ function placeBid(uint256 loanId, uint256 interestRate) external nonReentrant loanExists(loanId) isListed(loanId) { Loan storage loan = loans[loanId]; require(interestRate < loan.currentInterestRate && interestRate <= loan.maxInterestRate, "Bid interest rate invalid"); address previousBidder = loan.lender; uint256 escrowRefund = escrowedFunds[loanId]; loan.lender = msg.sender; loan.currentInterestRate = interestRate; escrowedFunds[loanId] = loan.loanAmount; bidTimestamps[loanId] = block.timestamp; if (previousBidder != address(0) && escrowRefund > 0) { _addUserBalance(previousBidder, escrowRefund, loan.principalToken); } require(IERC20(loan.principalToken).transferFrom(msg.sender, address(this), loan.loanAmount), "Token transfer failed"); emit LoanBidPlaced(loanId, msg.sender, interestRate); } /** * @notice Alternative bid function that uses the lender's deposited balance. */ function placeBidUsingBalance(uint256 loanId, uint256 interestRate) external nonReentrant loanExists(loanId) isListed(loanId) { Loan storage loan = loans[loanId]; require(interestRate < loan.currentInterestRate && interestRate <= loan.maxInterestRate, "Bid interest rate invalid"); _deductUserBalance(msg.sender, loan.loanAmount, loan.principalToken); address previousBidder = loan.lender; uint256 escrowRefund = escrowedFunds[loanId]; loan.lender = msg.sender; loan.currentInterestRate = interestRate; escrowedFunds[loanId] = loan.loanAmount; bidTimestamps[loanId] = block.timestamp; if (previousBidder != address(0) && escrowRefund > 0) { _addUserBalance(previousBidder, escrowRefund, loan.principalToken); } emit LoanBidPlaced(loanId, msg.sender, interestRate); } /** * @notice Delists a loan that hasn't been accepted. */ function delistLoan(uint256 loanId) external nonReentrant loanExists(loanId) isListed(loanId) onlyBorrower(loanId) { Loan memory loan = loans[loanId]; address previousBidder = loan.lender; uint256 escrowRefund = 0; if (previousBidder != address(0)) { escrowRefund = escrowedFunds[loanId]; escrowedFunds[loanId] = 0; if (escrowRefund > 0) { _addUserBalance(previousBidder, escrowRefund, loan.principalToken); } } loans[loanId].status = LoanStatus.Delisted; _nftLoanPlusOne[loan.nftAddress][loan.tokenId] = 0; // Reset the loan ID for this NFT delete loans[loanId]; _removeActiveLoan(loanId); isCollateralized[loan.nftAddress][loan.tokenId] = false; try IERC721(loan.nftAddress).safeTransferFrom(address(this), loan.borrower, loan.tokenId) { emit LoanDelisted(loanId, loan.borrower); } catch { revert("NFT transfer failed"); } } /** * @notice delist an expired loan (not accepted within loanListExpiration). */ function delistExpiredLoan(uint256 loanId) external nonReentrant loanExists(loanId) isListed(loanId) { Loan memory loan = loans[loanId]; require(block.timestamp >= loan.listingTime + loanListExpiration, "Loan not expired yet"); address previousBidder = loan.lender; uint256 escrowRefund = escrowedFunds[loanId]; if (previousBidder != address(0) && escrowRefund > 0) { _addUserBalance(previousBidder, escrowRefund, loan.principalToken); } loans[loanId].status = LoanStatus.Expired; _nftLoanPlusOne[loan.nftAddress][loan.tokenId] = 0; // Reset the loan ID for this NFT delete loans[loanId]; _removeActiveLoan(loanId); isCollateralized[loan.nftAddress][loan.tokenId] = false; try IERC721(loan.nftAddress).safeTransferFrom(address(this), loan.borrower, loan.tokenId) { emit LoanDelisted(loanId, loan.borrower); } catch { revert("NFT transfer failed"); } } /** * @notice Accepts a lender’s bid to start the loan. */ function acceptLoan(uint256 loanId) external nonReentrant loanExists(loanId) isListed(loanId) onlyBorrower(loanId) { Loan storage loan = loans[loanId]; require(loan.lender != address(0), "No lender bid"); require(escrowedFunds[loanId] == loan.loanAmount, "Escrowed funds mismatch"); require(loan.startTime == 0, "Loan already started"); loan.startTime = block.timestamp; loan.status = LoanStatus.Accepted; uint256 amount = escrowedFunds[loanId]; escrowedFunds[loanId] = 0; require(IERC20(loan.principalToken).transfer(loan.borrower, amount), "Transfer failed"); emit LoanAccepted(loanId, loan.borrower, loan.lender, loan.startTime, loan.principalToken); } /** * @notice Computes the total repayment (principal + interest) for a loan. */ function getTotalRepayment(uint256 loanId) public view loanExists(loanId) returns (uint256) { Loan storage loan = loans[loanId]; uint256 interestAmount; if (loan.loanType == LoanType.FIXED) { interestAmount = (loan.loanAmount * loan.currentInterestRate) / 10000; } else if (loan.loanType == LoanType.APR) { uint256 annualizedInterest = (loan.loanAmount * loan.currentInterestRate) / 10000; if (loan.status == LoanStatus.Accepted) { uint256 elapsedDays = (block.timestamp - loan.startTime) / 1 days; interestAmount = (annualizedInterest * (elapsedDays > 0 ? elapsedDays : 1)) / 365; } else { uint256 durationDays = loan.duration / 1 days; interestAmount = (annualizedInterest * (durationDays > 0 ? durationDays : 1)) / 365; } } return loan.loanAmount + interestAmount; } /** * @notice Repays an active loan, returning the NFT collateral and crediting the lender. */ function repayLoan(uint256 loanId) external nonReentrant loanExists(loanId) onlyBorrower(loanId) { Loan storage loan = loans[loanId]; require(loan.status == LoanStatus.Accepted, "Loan not active"); require(block.timestamp >= loan.startTime, "Repayment before start"); require(block.timestamp <= loan.startTime + loan.duration, "Loan duration expired"); uint256 totalRepayment = getTotalRepayment(loanId); uint256 borrowerFee = (totalRepayment * protocolFeeRate) / 10000; uint256 lenderFee = (totalRepayment * protocolFeeRate) / 10000; uint256 requiredRepayment = totalRepayment + borrowerFee; uint256 lenderPayout = totalRepayment - lenderFee; protocolFeeBalance[loan.principalToken] += (lenderFee + borrowerFee); loan.status = LoanStatus.Repaid; _nftLoanPlusOne[loan.nftAddress][loan.tokenId] = 0; // Reset the loan ID for this NFT _removeActiveLoan(loanId); isCollateralized[loan.nftAddress][loan.tokenId] = false; _addUserBalance(loan.lender, lenderPayout, loan.principalToken); require(IERC20(loan.principalToken).transferFrom(msg.sender, address(this), requiredRepayment), "Token transfer failed"); try IERC721(loan.nftAddress).safeTransferFrom(address(this), loan.borrower, loan.tokenId) { emit LoanRepaid(loanId, loan.borrower, requiredRepayment); } catch { revert("NFT transfer failed"); } } /** * @notice Cancels a lender's bid if the loan is still listed. */ function cancelBid(uint256 loanId) external nonReentrant loanExists(loanId) isListed(loanId) onlyLender(loanId) { Loan storage loan = loans[loanId]; require(block.timestamp >= bidTimestamps[loanId] + bidCancelPeriod, "Bid cancel period not met"); address bidder = loan.lender; uint256 refundAmount = escrowedFunds[loanId]; escrowedFunds[loanId] = 0; loan.lender = address(0); loan.currentInterestRate = loan.maxInterestRate; require(IERC20(loan.principalToken).transfer(bidder, refundAmount), "Refund failed"); emit LoanBidCancelled(loanId, bidder); } /** * @notice Claims the NFT collateral after a defaulted loan. */ function claimDefaultedLoan(uint256 loanId) external nonReentrant loanExists(loanId) { Loan storage loan = loans[loanId]; require(loan.status == LoanStatus.Accepted, "Loan not active"); require(block.timestamp > loan.startTime + loan.duration, "Loan not expired"); uint256 totalRepayment = getTotalRepayment(loanId); uint256 lenderFee = (totalRepayment * protocolFeeRate) / 10000; require(IERC20(loan.principalToken).transferFrom(msg.sender, address(this), lenderFee), "Protocol fee transfer failed"); protocolFeeBalance[loan.principalToken] += lenderFee; loan.status = LoanStatus.Defaulted; _nftLoanPlusOne[loan.nftAddress][loan.tokenId] = 0; // Reset the loan ID for this NFT _removeActiveLoan(loanId); isCollateralized[loan.nftAddress][loan.tokenId] = false; // —— Mark NFT as having defaulted —— everDefaultedLoan[loan.nftAddress][loan.tokenId] = true; try IERC721(loan.nftAddress).safeTransferFrom(address(this), loan.lender, loan.tokenId) { emit LoanDefaulted(loanId, loan.lender); } catch { revert("NFT transfer failed"); } } /** * @notice Returns the active loanId for a given NFT, or reverts if none. * @dev we store loanId+1 so that a 0 mapping means “no active loan”. */ function getLoanIdForNFT(address nftAddress, uint256 tokenId) external view returns (uint256) { uint256 plusOne = _nftLoanPlusOne[nftAddress][tokenId]; require(plusOne != 0, "No active loan for this NFT"); return plusOne - 1; } /** * @notice Returns true if the NFT: * - is not currently collateralized, AND * - has never defaulted on a loan. * In other words, it’s valid as new collateral. */ function isValidCollateral(address nftAddress, uint256 tokenId) external view returns (bool) { return !isCollateralized[nftAddress][tokenId] && !everDefaultedLoan[nftAddress][tokenId]; } /** * @notice Withdraws protocol fees (in a given ERC20) to a specified address. */ function withdrawProtocolFees(address token, address to) external nonReentrant onlyRole(OWNER_ROLE) { require(to != address(0), "Invalid address"); uint256 tokenBalance = IERC20(token).balanceOf(address(this)); uint256 totalEscrowed = 0; for (uint256 i = 0; i < activeLoanIds.length; i++) { uint256 loanId = activeLoanIds[i]; if (loans[loanId].principalToken == token) { totalEscrowed += escrowedFunds[loanId]; } } uint256 withdrawable = tokenBalance - totalEscrowed - totalUserBalances[token]; require(withdrawable > 0, "No funds to withdraw"); protocolFeeBalance[token] = 0; require(IERC20(token).transfer(to, withdrawable), "Transfer failed"); emit ProtocolFeesWithdrawn(to, withdrawable, token); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC-721 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 ERC-721 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 ERC-721 * 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 address zero. * * 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 v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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 Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 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); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * 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[ERC 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 v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @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 EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and 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 if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // 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; } }
{ "evmVersion": "cancun", "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_govAddress","type":"address"},{"internalType":"address","name":"_manager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"AllowedERC20Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"AllowedNFTUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newBidCancelPeriod","type":"uint256"}],"name":"BidCancelPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"FundsDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"address","name":"principalToken","type":"address"}],"name":"LoanAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":true,"internalType":"address","name":"lender","type":"address"}],"name":"LoanBidCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"currentInterestRate","type":"uint256"}],"name":"LoanBidPlaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":true,"internalType":"address","name":"lender","type":"address"}],"name":"LoanDefaulted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"}],"name":"LoanDelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newExpiration","type":"uint256"}],"name":"LoanListExpirationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxInterestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"enum NFTLendMarket.LoanType","name":"loanType","type":"uint8"},{"indexed":false,"internalType":"address","name":"principalToken","type":"address"}],"name":"LoanListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"loanId","type":"uint256"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"repaymentAmount","type":"uint256"}],"name":"LoanRepaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxActiveLoans","type":"uint256"}],"name":"MaxActiveLoansUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"ProtocolFeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"ProtocolFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"UserBalanceUpdated","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OWNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"acceptLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"activeLoanIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"activeLoans","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedERC20Contracts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedNFTContracts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bidCancelPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bidTimestamps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"cancelBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"claimDefaultedLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"delistExpiredLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"delistLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"escrowedFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"everDefaultedLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getActiveLoans","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getLoanIdForNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"getTotalRepayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"grantManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"isCollateralized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isValidCollateral","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"loanAmount","type":"uint256"},{"internalType":"uint256","name":"maxInterestRate","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"enum NFTLendMarket.LoanType","name":"loanType","type":"uint8"},{"internalType":"address","name":"principalToken","type":"address"}],"name":"listLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"loanCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"loanListExpiration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"loans","outputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"loanAmount","type":"uint256"},{"internalType":"uint256","name":"maxInterestRate","type":"uint256"},{"internalType":"uint256","name":"currentInterestRate","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"enum NFTLendMarket.LoanType","name":"loanType","type":"uint8"},{"internalType":"enum NFTLendMarket.LoanStatus","name":"status","type":"uint8"},{"internalType":"address","name":"principalToken","type":"address"},{"internalType":"uint256","name":"listingTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxActiveLoans","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"},{"internalType":"uint256","name":"interestRate","type":"uint256"}],"name":"placeBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"},{"internalType":"uint256","name":"interestRate","type":"uint256"}],"name":"placeBidUsingBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFeeBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"repayLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"revokeManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newBidCancelPeriod","type":"uint256"}],"name":"setBidCancelPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newExpiration","type":"uint256"}],"name":"setLoanListExpiration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMax","type":"uint256"}],"name":"setMaxActiveLoans","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","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":"","type":"address"}],"name":"totalUserBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"updateAllowedERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"updateAllowedNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526103e8600d5562093a8060105560c860115562015180601355348015610028575f5ffd5b5060405161413c38038061413c83398101604081905261004791610162565b60015f90815561005790836100b5565b506100827fb19546dff01e856fb3f010c267a7b1c60363cf8a4664e21cc89c26224620214e836100b5565b506100ad7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08826100b5565b505050610193565b5f8281526001602090815260408083206001600160a01b038516845290915281205460ff1661013e575f8381526001602081815260408084206001600160a01b0387168086529252808420805460ff19169093179092559051339286917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a4506001610141565b505f5b92915050565b80516001600160a01b038116811461015d575f5ffd5b919050565b5f5f60408385031215610173575f5ffd5b61017c83610147565b915061018a60208401610147565b90509250929050565b613f9c806101a05f395ff3fe608060405234801561000f575f5ffd5b50600436106102ca575f3560e01c8063921b004b1161017b578063c153a234116100e4578063e1ec3c681161009e578063e58378bb11610079578063e58378bb14610748578063e5a7bfd01461075c578063e5e05bd714610789578063ec87621c146107a8575f5ffd5b8063e1ec3c681461067a578063e2cb0e4d14610722578063e505d0c514610735575f5ffd5b8063c153a234146105f8578063c9a759cb14610625578063cf7b287f1461062e578063d547741f14610641578063deb0ef4014610654578063deb298c314610667575f5ffd5b8063adfbe22f11610135578063adfbe22f1461056b578063b13aa2d61461057e578063b489e14714610591578063b93186ba146105b0578063be4dc94f146105c3578063c0f6ae97146105d6575f5ffd5b8063921b004b146104e25780639703ef35146104f55780639b087af414610508578063a217fddf14610527578063ab7b1c891461052e578063adb5198014610541575f5ffd5b80633360874c116102375780635d54f5c1116101f157806374a3f8fc116101cc57806374a3f8fc146104965780638f112248146104a95780638fd4f224146104bc57806391d14854146104cf575f5ffd5b80635d54f5c1146104585780636729629f1461046b5780636f504fd714610474575f5ffd5b80633360874c146103eb57806334d9289e146103fe57806336568abe1461040757806347126f621461041a57806357c90de51461043c57806358f858801461044f575f5ffd5b8063248a9ca311610288578063248a9ca31461037357806326e885e31461039657806327f8dce3146103a95780632f010b43146103bc5780632f2ff15d146103cf57806332b814ba146103e2575f5ffd5b80620fa9fb146102ce57806301ffc9a7146102e3578063079712b61461030b578063121ed2a714610338578063158c6bdb1461034d5780631e837ef314610360575b5f5ffd5b6102e16102dc3660046139eb565b6107bc565b005b6102f66102f1366004613a22565b61099a565b60405190151581526020015b60405180910390f35b61032a610319366004613a49565b600b6020525f908152604090205481565b604051908152602001610302565b6103406109d0565b6040516103029190613a64565b6102e161035b366004613aa6565b610a26565b6102e161036e366004613ac6565b610bff565b61032a610381366004613ac6565b5f908152600160208190526040909120015490565b6102e16103a4366004613a49565b610c53565b6102e16103b7366004613ac6565b610c74565b6102f66103ca366004613add565b610ffc565b6102e16103dd366004613b07565b611059565b61032a60135481565b6102e16103f9366004613b37565b611084565b61032a60025481565b6102e1610415366004613b07565b611297565b6102f6610428366004613ac6565b600f6020525f908152604090205460ff1681565b6102e161044a366004613aa6565b6112cf565b61032a60115481565b6102e1610466366004613ac6565b6114d8565b61032a60105481565b6102f6610482366004613a49565b60066020525f908152604090205460ff1681565b6102e16104a4366004613ac6565b6118ab565b6102e16104b7366004613ac6565b6118f7565b6102e16104ca366004613b37565b611994565b6102f66104dd366004613b07565b611a50565b6102e16104f0366004613add565b611a7a565b6102e1610503366004613ac6565b611c0d565b61032a610516366004613ac6565b60126020525f908152604090205481565b61032a5f81565b6102e161053c366004613ac6565b611e98565b61032a61054f3660046139eb565b600a60209081525f928352604080842090915290825290205481565b6102e1610579366004613ac6565b6122c8565b6102e161058c366004613ac6565b6125c2565b61032a61059f366004613ac6565b60046020525f908152604090205481565b61032a6105be366004613ac6565b612654565b6102e16105d1366004613a49565b612673565b6102f66105e4366004613a49565b60056020525f908152604090205460ff1681565b6102f6610606366004613add565b600960209081525f928352604080842090915290825290205460ff1681565b61032a600d5481565b6102e161063c3660046139eb565b612694565b6102e161064f366004613b07565b61294c565b6102e1610662366004613b63565b612971565b6102e1610675366004613ac6565b61306a565b610709610688366004613ac6565b600360208190525f918252604090912080546001820154600283015493830154600484015460058501546006860154600787015460088801546009890154600a909901546001600160a01b039889169a978916999789169896979596949593949293919260ff8084169361010081049091169262010000909104909116908d565b6040516103029d9c9b9a99989796959493929190613bfb565b61032a610730366004613add565b61341b565b61032a610743366004613ac6565b6134a0565b61032a5f516020613f275f395f51905f5281565b6102f661076a366004613add565b600760209081525f928352604080842090915290825290205460ff1681565b61032a610797366004613a49565b600c6020525f908152604090205481565b61032a5f516020613f475f395f51905f5281565b6107c461363f565b6001600160a01b0381166108115760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b60448201526064015b60405180910390fd5b335f908152600a602090815260408083206001600160a01b0386168452909152902054806108785760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610808565b335f908152600a602090815260408083206001600160a01b03871684528252808320839055600b909152812080548392906108b4908490613caf565b909155505060405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303815f875af1158015610905573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109299190613cc2565b6109455760405162461bcd60e51b815260040161080890613cdd565b604080518281526001600160a01b03858116602083015284169133917fc6d7522ade22416d5f000975be266c973d54b87b3bd997daeba6258d2de358d1910160405180910390a35061099660015f55565b5050565b5f6001600160e01b03198216637965db0b60e01b14806109ca57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600e805480602002602001604051908101604052809291908181526020018280548015610a1c57602002820191905f5260205f20905b815481526020019060010190808311610a08575b5050505050905090565b610a2e61363f565b5f8281526003602052604090205482906001600160a01b0316610a635760405162461bcd60e51b815260040161080890613d06565b825f5f82815260036020526040902060090154610100900460ff166005811115610a8f57610a8f613bd3565b14610aac5760405162461bcd60e51b815260040161080890613d33565b5f848152600360205260409020600681015484108015610ad0575080600501548411155b610b185760405162461bcd60e51b8152602060048201526019602482015278109a59081a5b9d195c995cdd081c985d19481a5b9d985b1a59603a1b6044820152606401610808565b60048101546009820154610b3c9133916201000090046001600160a01b0316613667565b6001810180545f87815260046020818152604080842080546001600160a01b031987163317909755600688018b9055928701549092556012905290204290556001600160a01b0316908115801590610b9357505f81115b15610bba57610bba82828560090160029054906101000a90046001600160a01b0316613798565b604051868152339088907fd1b9c752eb85783f53e7669e993e44d05db062782a8dcd72a7757746cc981f1d9060200160405180910390a3505050505061099660015f55565b5f516020613f275f395f51905f52610c16816137fa565b600d8290556040518281527fc59dcd6979a73a87266c1f2a5d4c4108daee42034d779ef00e960a510c789625906020015b60405180910390a15050565b5f610c5d816137fa565b6109965f516020613f475f395f51905f5283611059565b610c7c61363f565b5f8181526003602052604090205481906001600160a01b0316610cb15760405162461bcd60e51b815260040161080890613d06565b5f82815260036020526040902060016009820154610100900460ff166005811115610cde57610cde613bd3565b14610d1d5760405162461bcd60e51b815260206004820152600f60248201526e4c6f616e206e6f742061637469766560881b6044820152606401610808565b80600701548160080154610d319190613d6a565b4211610d725760405162461bcd60e51b815260206004820152601060248201526f131bd85b881b9bdd08195e1c1a5c995960821b6044820152606401610808565b5f610d7c846134a0565b90505f61271060115483610d909190613d7d565b610d9a9190613d94565b60098401546040516323b872dd60e01b81529192506201000090046001600160a01b0316906323b872dd90610dd790339030908690600401613db3565b6020604051808303815f875af1158015610df3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e179190613cc2565b610e635760405162461bcd60e51b815260206004820152601c60248201527f50726f746f636f6c20666565207472616e73666572206661696c6564000000006044820152606401610808565b60098301546201000090046001600160a01b03165f908152600c602052604081208054839290610e94908490613d6a565b909155505060098301805461ff00191661030017905560028301546001600160a01b03165f90815260086020908152604080832060038701548452909152812055610ede85613804565b6002830180546001600160a01b039081165f9081526007602090815260408083206003890180548552908352818420805460ff199081169091558654861685526009845282852082548652909352928190208054909216600190811790925593549087015491549351632142170760e11b8152908316936342842e0e93610f6d93309391169190600401613db3565b5f604051808303815f87803b158015610f84575f5ffd5b505af1925050508015610f95575060015b610fb15760405162461bcd60e51b815260040161080890613dd7565b60018301546040516001600160a01b039091169086907f13b88e6866f0156d706fecfa22b678de5fc2b749c1d2307f6f47eb541385f1ec905f90a350505050610ff960015f55565b50565b6001600160a01b0382165f90815260076020908152604080832084845290915281205460ff1615801561105257506001600160a01b0383165f90815260096020908152604080832085845290915290205460ff16155b9392505050565b5f8281526001602081905260409091200154611074816137fa565b61107e83836138bd565b50505050565b5f516020613f475f395f51905f5261109b816137fa565b6001600160a01b0383166110e75760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964204e4654206164647265737360681b6044820152606401610808565b5f836001600160a01b03163b116111405760405162461bcd60e51b815260206004820152601960248201527f41646472657373206973206e6f74206120636f6e7472616374000000000000006044820152606401610808565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa9250505080156111a7575060408051601f3d908101601f191682019092526111a491810190613cc2565b60015b6111f35760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f20766572696679204552433732310000000000000000006044820152606401610808565b806112365760405162461bcd60e51b8152602060048201526013602482015272436f6e7472616374206e6f742045524337323160681b6044820152606401610808565b506001600160a01b0383165f81815260056020908152604091829020805460ff191686151590811790915591519182527f7fe996db267f9f17db8865f67d54879fc39a38a2a37afa158a9ea52357e794ac91015b60405180910390a2505050565b6001600160a01b03811633146112c05760405163334bd91960e11b815260040160405180910390fd5b6112ca8282613933565b505050565b6112d761363f565b5f8281526003602052604090205482906001600160a01b031661130c5760405162461bcd60e51b815260040161080890613d06565b825f5f82815260036020526040902060090154610100900460ff16600581111561133857611338613bd3565b146113555760405162461bcd60e51b815260040161080890613d33565b5f848152600360205260409020600681015484108015611379575080600501548411155b6113c15760405162461bcd60e51b8152602060048201526019602482015278109a59081a5b9d195c995cdd081c985d19481a5b9d985b1a59603a1b6044820152606401610808565b6001810180545f87815260046020818152604080842080546001600160a01b031987163317909755600688018b9055928701549092556012905290204290556001600160a01b031690811580159061141857505f81115b1561143f5761143f82828560090160029054906101000a90046001600160a01b0316613798565b60098301546004808501546040516323b872dd60e01b8152620100009093046001600160a01b0316926323b872dd9261147c923392309201613db3565b6020604051808303815f875af1158015611498573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114bc9190613cc2565b610bba5760405162461bcd60e51b815260040161080890613e04565b6114e061363f565b5f8181526003602052604090205481906001600160a01b03166115155760405162461bcd60e51b815260040161080890613d06565b815f5f82815260036020526040902060090154610100900460ff16600581111561154157611541613bd3565b1461155e5760405162461bcd60e51b815260040161080890613d33565b5f83815260036020818152604080842081516101a08101835281546001600160a01b0390811682526001808401548216958301959095526002830154169281019290925292830154606082015260048301546080820152600583015460a0820152600683015460c0820152600783015460e08201526008830154610100820152600983015490929161012084019160ff16908111156115ff576115ff613bd3565b600181111561161057611610613bd3565b81526020016009820160019054906101000a900460ff16600581111561163857611638613bd3565b600581111561164957611649613bd3565b815260098201546201000090046001600160a01b03166020820152600a9091015460409091015260105461018082015191925061168591613d6a565b4210156116cb5760405162461bcd60e51b8152602060048201526014602482015273131bd85b881b9bdd08195e1c1a5c9959081e595d60621b6044820152606401610808565b6020808201515f86815260049092526040909120546001600160a01b038216158015906116f757505f81115b1561170c5761170c8282856101600151613798565b5f86815260036020818152604080842060098101805461ff001916610500178155888301516001600160a01b03168652600880855283872060608b0151885285529286208690558b86529284905280546001600160a01b0319908116825560018201805482169055600282018054909116905592830184905560048301849055600583018490556006830184905560078301849055820183905580546001600160b01b0319169055600a01556117c186613804565b604080840180516001600160a01b039081165f908152600760209081528482206060890180518452915290849020805460ff191690559151865192519351632142170760e11b81529116926342842e0e9261182192309290600401613db3565b5f604051808303815f87803b158015611838575f5ffd5b505af1925050508015611849575060015b6118655760405162461bcd60e51b815260040161080890613dd7565b82516040516001600160a01b039091169087907f94140863d1b77b2db4c5904c78e4343ab9c2a51a27e3e6beef9f21109162d93e905f90a35050505050610ff960015f55565b5f516020613f275f395f51905f526118c2816137fa565b60108290556040518281527f67d1057b745e2dfa75389ae5cc1305e8e8cad2ae31b991160a93762ab679af5990602001610c47565b5f516020613f275f395f51905f5261190e816137fa565b610e10821161195f5760405162461bcd60e51b815260206004820152601960248201527f42696443616e63656c506572696f6420746f6f2073686f7274000000000000006044820152606401610808565b60138290556040518281527f1d44ca6a9e035c33fe61047920d46da987cf827176af06973df6ff23a92f9d8890602001610c47565b5f516020613f475f395f51905f526119ab816137fa565b6001600160a01b0383166119f95760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420746f6b656e206164647265737360581b6044820152606401610808565b6001600160a01b0383165f81815260066020908152604091829020805460ff191686151590811790915591519182527f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a910161128a565b5f9182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b611a8261363f565b6001600160a01b0382165f90815260066020526040902054829060ff16611ae55760405162461bcd60e51b8152602060048201526017602482015276115490cc8c081d1bdad95b881b9bdd08185b1b1bddd959604a1b6044820152606401610808565b5f8211611b295760405162461bcd60e51b81526020600482015260126024820152710416d6f756e74206d757374206265203e20360741b6044820152606401610808565b611b34338385613798565b6040516323b872dd60e01b81526001600160a01b038416906323b872dd90611b6490339030908790600401613db3565b6020604051808303815f875af1158015611b80573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ba49190613cc2565b611bc05760405162461bcd60e51b815260040161080890613e04565b604080518381526001600160a01b038516602082015233917fdf4dcf17030d087ed1d90ed3c90719c7260706c1c4a88505dd2d0a982887cf43910160405180910390a25061099660015f55565b611c1561363f565b5f8181526003602052604090205481906001600160a01b0316611c4a5760405162461bcd60e51b815260040161080890613d06565b815f5f82815260036020526040902060090154610100900460ff166005811115611c7657611c76613bd3565b14611c935760405162461bcd60e51b815260040161080890613d33565b5f8381526003602052604090206001015483906001600160a01b03163314611cef5760405162461bcd60e51b815260206004820152600f60248201526e2737ba103637b0b7103632b73232b960891b6044820152606401610808565b5f8481526003602090815260408083206013546012909352922054611d149190613d6a565b421015611d635760405162461bcd60e51b815260206004820152601960248201527f4269642063616e63656c20706572696f64206e6f74206d6574000000000000006044820152606401610808565b6001810180545f878152600460208190526040808320805493905584546001600160a01b031916909455600585015460068601556009850154935163a9059cbb60e01b81526001600160a01b039384169181018290526024810183905290939192620100009092049091169063a9059cbb906044016020604051808303815f875af1158015611df4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e189190613cc2565b611e545760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606401610808565b6040516001600160a01b0383169088907f5677b1e812c0884dd700a8657ca2619da856a4940cb378aa593b217849a21a8a905f90a3505050505050610ff960015f55565b611ea061363f565b5f8181526003602052604090205481906001600160a01b0316611ed55760405162461bcd60e51b815260040161080890613d06565b5f8281526003602052604090205482906001600160a01b03163314611f0c5760405162461bcd60e51b815260040161080890613e33565b5f83815260036020526040902060016009820154610100900460ff166005811115611f3957611f39613bd3565b14611f785760405162461bcd60e51b815260206004820152600f60248201526e4c6f616e206e6f742061637469766560881b6044820152606401610808565b8060080154421015611fc55760405162461bcd60e51b815260206004820152601660248201527514995c185e5b595b9d081899599bdc99481cdd185c9d60521b6044820152606401610808565b80600701548160080154611fd99190613d6a565b4211156120205760405162461bcd60e51b8152602060048201526015602482015274131bd85b88191d5c985d1a5bdb88195e1c1a5c9959605a1b6044820152606401610808565b5f61202a856134a0565b90505f6127106011548361203e9190613d7d565b6120489190613d94565b90505f6127106011548461205c9190613d7d565b6120669190613d94565b90505f6120738385613d6a565b90505f6120808386613caf565b905061208c8484613d6a565b60098701546201000090046001600160a01b03165f908152600c6020526040812080549091906120bd908490613d6a565b909155505060098601805461ff00191661020017905560028601546001600160a01b03165f90815260086020908152604080832060038a0154845290915281205561210789613804565b60028601546001600160a01b039081165f90815260076020908152604080832060038b015484529091529020805460ff191690556001870154600988015461215b9291821691849162010000900416613798565b60098601546040516323b872dd60e01b8152620100009091046001600160a01b0316906323b872dd9061219690339030908790600401613db3565b6020604051808303815f875af11580156121b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121d69190613cc2565b6121f25760405162461bcd60e51b815260040161080890613e04565b600286015486546003880154604051632142170760e11b81526001600160a01b03938416936342842e0e936122309330939290911691600401613db3565b5f604051808303815f87803b158015612247575f5ffd5b505af1925050508015612258575060015b6122745760405162461bcd60e51b815260040161080890613dd7565b85546040518381526001600160a01b03909116908a907f512d3e65b3e58c2187bb1872aa435dba5bd09c1c03823ba56ab70aac411e4a219060200160405180910390a35050505050505050610ff960015f55565b6122d061363f565b5f8181526003602052604090205481906001600160a01b03166123055760405162461bcd60e51b815260040161080890613d06565b815f5f82815260036020526040902060090154610100900460ff16600581111561233157612331613bd3565b1461234e5760405162461bcd60e51b815260040161080890613d33565b5f8381526003602052604090205483906001600160a01b031633146123855760405162461bcd60e51b815260040161080890613e33565b5f84815260036020526040902060018101546001600160a01b03166123dc5760405162461bcd60e51b815260206004820152600d60248201526c139bc81b195b99195c88189a59609a1b6044820152606401610808565b806004015460045f8781526020019081526020015f2054146124405760405162461bcd60e51b815260206004820152601760248201527f457363726f7765642066756e6473206d69736d617463680000000000000000006044820152606401610808565b6008810154156124895760405162461bcd60e51b8152602060048201526014602482015273131bd85b88185b1c9958591e481cdd185c9d195960621b6044820152606401610808565b42600882015560098101805461010061ff00199091161781555f868152600460208190526040808320805493905592548454935163a9059cbb60e01b81526001600160a01b0394851692810192909252602482018390529192620100009092049091169063a9059cbb906044016020604051808303815f875af1158015612512573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125369190613cc2565b6125525760405162461bcd60e51b815260040161080890613cdd565b6001820154825460088401546009850154604080519283526001600160a01b0362010000909204821660208401529381169392169189917f520af44c0202f573865f02f53109b8768072746c32dc4eb57c89c27067d8644c910160405180910390a45050505050610ff960015f55565b5f516020613f275f395f51905f526125d9816137fa565b6103e882111561261f5760405162461bcd60e51b815260206004820152601160248201527008ccaca40e4c2e8ca40e8dede40d0d2ced607b1b6044820152606401610808565b60118290556040518281527f9d2a5010795914ccbdd5a4cdee6a9aa2addac5e44443b519897523b67ddfe9fc90602001610c47565b600e8181548110612663575f80fd5b5f91825260209091200154905081565b5f61267d816137fa565b6109965f516020613f475f395f51905f528361294c565b61269c61363f565b5f516020613f275f395f51905f526126b3816137fa565b6001600160a01b0382166126fb5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610808565b6040516370a0823160e01b81523060048201525f906001600160a01b038516906370a0823190602401602060405180830381865afa15801561273f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127639190613e5e565b90505f805b600e548110156127e3575f600e828154811061278657612786613e75565b5f91825260208083209091015480835260039091526040909120600901549091506001600160a01b038089166201000090920416036127da575f818152600460205260409020546127d79084613d6a565b92505b50600101612768565b506001600160a01b0385165f908152600b60205260408120546128068385613caf565b6128109190613caf565b90505f81116128585760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610808565b6001600160a01b038681165f818152600c6020526040808220919091555163a9059cbb60e01b81529187166004830152602482018390529063a9059cbb906044016020604051808303815f875af11580156128b5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128d99190613cc2565b6128f55760405162461bcd60e51b815260040161080890613cdd565b604080516001600160a01b0387811682526020820184905288168183015290517f66e1599cb4e6f8b24e2216b3ba87495e0bb4b22a948c322997a50b692ebe32329181900360600190a15050505061099660015f55565b5f8281526001602081905260409091200154612967816137fa565b61107e8383613933565b61297961363f565b6001600160a01b0387165f90815260056020526040902054879060ff166129e25760405162461bcd60e51b815260206004820152601860248201527f4e465420636f6e7472616374206e6f7420616c6c6f77656400000000000000006044820152606401610808565b6001600160a01b0382165f90815260066020526040902054829060ff16612a455760405162461bcd60e51b8152602060048201526017602482015276115490cc8c081d1bdad95b881b9bdd08185b1b1bddd959604a1b6044820152606401610808565b6040516331a9108f60e11b8152600481018990528990899033906001600160a01b03841690636352211e90602401602060405180830381865afa158015612a8e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ab29190613e89565b6001600160a01b031614612af85760405162461bcd60e51b815260206004820152600d60248201526c2737ba1027232a1037bbb732b960991b6044820152606401610808565b600d54600e5410612b4b5760405162461bcd60e51b815260206004820152601960248201527f416374697665206c6f616e206c696d69742072656163686564000000000000006044820152606401610808565b6001600160a01b038b165f9081526007602090815260408083208d845290915290205460ff1615612bbe5760405162461bcd60e51b815260206004820152601a60248201527f4e465420616c726561647920636f6c6c61746572616c697a65640000000000006044820152606401610808565b5f8911612c0d5760405162461bcd60e51b815260206004820152601760248201527f4c6f616e20616d6f756e74206d757374206265203e20300000000000000000006044820152606401610808565b5f8811612c5c5760405162461bcd60e51b815260206004820152601960248201527f496e7465726573742072617465206d757374206265203e2030000000000000006044820152606401610808565b5f8711612ca25760405162461bcd60e51b815260206004820152601460248201527304475726174696f6e206d757374206265203e20360641b6044820152606401610808565b6001866001811115612cb657612cb6613bd3565b1115612cf85760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964206c6f616e207479706560781b6044820152606401610808565b5f6002549050604051806101a00160405280336001600160a01b031681526020015f6001600160a01b031681526020018d6001600160a01b031681526020018c81526020018b81526020018a81526020018a81526020018981526020015f8152602001886001811115612d6d57612d6d613bd3565b81526020015f81526001600160a01b03888116602080840191909152426040938401525f858152600380835290849020855181546001600160a01b03199081169186169190911782559286015160018083018054861692871692909217909155948601516002820180549094169416939093179091556060840151908201556080830151600482015560a0830151600582015560c0830151600682015560e08301516007820155610100830151600882015561012083015160098201805492939192909160ff19909116908381811115612e4957612e49613bd3565b021790555061014082015160098201805461ff001916610100836005811115612e7457612e74613bd3565b02179055506101608201516009820180546001600160a01b03909216620100000262010000600160b01b031990921691909117905561018090910151600a909101555f818152600f60205260408120805460ff19166001908117909155600e8054808301825592527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd909101829055612f0e908290613d6a565b6001600160a01b038d165f9081526008602090815260408083208f84529091528120919091556002805491612f4283613ea4565b9190505550600160075f8e6001600160a01b03166001600160a01b031681526020019081526020015f205f8d81526020019081526020015f205f6101000a81548160ff0219169083151502179055508b6001600160a01b03166323b872dd33308e6040518463ffffffff1660e01b8152600401612fc193929190613db3565b5f604051808303815f87803b158015612fd8575f5ffd5b505af1925050508015612fe9575060015b6130055760405162461bcd60e51b815260040161080890613dd7565b336001600160a01b0316817ff7d0570a1cc7150abafdd7f18056e9d7696c7c4cd65d4e6e45b3ff0d1f7cf6fc8e8e8e8e8e8e8e60405161304b9796959493929190613ebc565b60405180910390a3505050505061306160015f55565b50505050505050565b61307261363f565b5f8181526003602052604090205481906001600160a01b03166130a75760405162461bcd60e51b815260040161080890613d06565b815f5f82815260036020526040902060090154610100900460ff1660058111156130d3576130d3613bd3565b146130f05760405162461bcd60e51b815260040161080890613d33565b5f8381526003602052604090205483906001600160a01b031633146131275760405162461bcd60e51b815260040161080890613e33565b5f84815260036020818152604080842081516101a08101835281546001600160a01b0390811682526001808401548216958301959095526002830154169281019290925292830154606082015260048301546080820152600583015460a0820152600683015460c0820152600783015460e08201526008830154610100820152600983015490929161012084019160ff16908111156131c8576131c8613bd3565b60018111156131d9576131d9613bd3565b81526020016009820160019054906101000a900460ff16600581111561320157613201613bd3565b600581111561321257613212613bd3565b815260098201546001600160a01b03620100009091048116602080840191909152600a90930154604090920191909152908201519192505f9082161561327b57505f8681526004602052604081208054919055801561327b5761327b8282856101600151613798565b5f87815260036020818152604080842060098101805461ff001916610400178155888301516001600160a01b03168652600880855283872060608b0151885285529286208690558c86529284905280546001600160a01b0319908116825560018201805482169055600282018054909116905592830184905560048301849055600583018490556006830184905560078301849055820183905580546001600160b01b0319169055600a015561333087613804565b604080840180516001600160a01b039081165f908152600760209081528482206060890180518452915290849020805460ff191690559151865192519351632142170760e11b81529116926342842e0e9261339092309290600401613db3565b5f604051808303815f87803b1580156133a7575f5ffd5b505af19250505080156133b8575060015b6133d45760405162461bcd60e51b815260040161080890613dd7565b82516040516001600160a01b039091169088907f94140863d1b77b2db4c5904c78e4343ab9c2a51a27e3e6beef9f21109162d93e905f90a3505050505050610ff960015f55565b6001600160a01b0382165f90815260086020908152604080832084845290915281205480820361348d5760405162461bcd60e51b815260206004820152601b60248201527f4e6f20616374697665206c6f616e20666f722074686973204e465400000000006044820152606401610808565b613498600182613caf565b949350505050565b5f8181526003602052604081205482906001600160a01b03166134d55760405162461bcd60e51b815260040161080890613d06565b5f8381526003602052604081209080600983015460ff1660018111156134fd576134fd613bd3565b0361352a57612710826006015483600401546135199190613d7d565b6135239190613d94565b9050613626565b6001600983015460ff16600181111561354557613545613bd3565b03613626575f612710836006015484600401546135629190613d7d565b61356c9190613d94565b905060016009840154610100900460ff16600581111561358e5761358e613bd3565b036135e3575f620151808460080154426135a89190613caf565b6135b29190613d94565b905061016d5f82116135c55760016135c7565b815b6135d19084613d7d565b6135db9190613d94565b925050613624565b5f6201518084600701546135f79190613d94565b905061016d5f821161360a57600161360c565b815b6136169084613d7d565b6136209190613d94565b9250505b505b8082600401546136369190613d6a565b95945050505050565b60025f540361366157604051633ee5aeb560e01b815260040160405180910390fd5b60025f55565b6001600160a01b038084165f908152600a60209081526040808320938516835292905220548211156136d25760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610808565b6001600160a01b038084165f908152600a6020908152604080832093851683529290529081208054849290613708908490613caf565b90915550506001600160a01b0381165f908152600b602052604081208054849290613734908490613caf565b90915550506001600160a01b038381165f818152600a60209081526040808320948616808452948252918290205482519081529081019390935290917f8b45c1c793e9a443eda263a15f880b1367ef5e2fb442a38fdd8f813b05e32c9b910161128a565b6001600160a01b038084165f908152600a60209081526040808320938516835292905290812080548492906137ce908490613d6a565b90915550506001600160a01b0381165f908152600b602052604081208054849290613734908490613d6a565b610ff9813361399e565b5f818152600f60205260408120805460ff191690555b600e548110156109965781600e828154811061383857613838613e75565b905f5260205f200154036138b557600e805461385690600190613caf565b8154811061386657613866613e75565b905f5260205f200154600e828154811061388257613882613e75565b5f91825260209091200155600e80548061389e5761389e613f12565b600190038181905f5260205f20015f905590555050565b60010161381a565b5f6138c88383611a50565b61392c575f8381526001602081815260408084206001600160a01b0387168086529252808420805460ff19169093179092559051339286917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45060016109ca565b505f6109ca565b5f61393e8383611a50565b1561392c575f8381526001602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016109ca565b6139a88282611a50565b6109965760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610808565b6001600160a01b0381168114610ff9575f5ffd5b5f5f604083850312156139fc575f5ffd5b8235613a07816139d7565b91506020830135613a17816139d7565b809150509250929050565b5f60208284031215613a32575f5ffd5b81356001600160e01b031981168114611052575f5ffd5b5f60208284031215613a59575f5ffd5b8135611052816139d7565b602080825282518282018190525f918401906040840190835b81811015613a9b578351835260209384019390920191600101613a7d565b509095945050505050565b5f5f60408385031215613ab7575f5ffd5b50508035926020909101359150565b5f60208284031215613ad6575f5ffd5b5035919050565b5f5f60408385031215613aee575f5ffd5b8235613af9816139d7565b946020939093013593505050565b5f5f60408385031215613b18575f5ffd5b823591506020830135613a17816139d7565b8015158114610ff9575f5ffd5b5f5f60408385031215613b48575f5ffd5b8235613b53816139d7565b91506020830135613a1781613b2a565b5f5f5f5f5f5f5f60e0888a031215613b79575f5ffd5b8735613b84816139d7565b96506020880135955060408801359450606088013593506080880135925060a088013560028110613bb3575f5ffd5b915060c0880135613bc3816139d7565b8091505092959891949750929550565b634e487b7160e01b5f52602160045260245ffd5b60028110613bf757613bf7613bd3565b9052565b6001600160a01b038e811682528d811660208301528c166040820152606081018b9052608081018a905260a0810189905260c0810188905260e0810187905261010081018690526101a08101613c55610120830187613be7565b60068510613c6557613c65613bd3565b84610140830152613c826101608301856001600160a01b03169052565b826101808301529e9d5050505050505050505050505050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156109ca576109ca613c9b565b5f60208284031215613cd2575f5ffd5b815161105281613b2a565b6020808252600f908201526e151c985b9cd9995c8819985a5b1959608a1b604082015260600190565b602080825260139082015272131bd85b88191bd95cc81b9bdd08195e1a5cdd606a1b604082015260600190565b60208082526019908201527f4c6f616e206e6f7420696e204c69737465642073746174757300000000000000604082015260600190565b808201808211156109ca576109ca613c9b565b80820281158282048414176109ca576109ca613c9b565b5f82613dae57634e487b7160e01b5f52601260045260245ffd5b500490565b6001600160a01b039384168152919092166020820152604081019190915260600190565b602080825260139082015272139195081d1c985b9cd9995c8819985a5b1959606a1b604082015260600190565b602080825260159082015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b6020808252601190820152702737ba103637b0b7103137b93937bbb2b960791b604082015260600190565b5f60208284031215613e6e575f5ffd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215613e99575f5ffd5b8151611052816139d7565b5f60018201613eb557613eb5613c9b565b5060010190565b6001600160a01b03881681526020810187905260408101869052606081018590526080810184905260e08101613ef560a0830185613be7565b6001600160a01b039290921660c091909101529695505050505050565b634e487b7160e01b5f52603160045260245ffdfeb19546dff01e856fb3f010c267a7b1c60363cf8a4664e21cc89c26224620214e241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08a2646970667358221220453c1b00b692d14815345b06344c033036ccec610be965dd7275d35dbc1d393b64736f6c634300081c00330000000000000000000000002190a1dba3e0a9f7216efc929e6faead44ad6131000000000000000000000000d9d96fb150136798861363d8ad9fe4033cfc32b3
Deployed Bytecode
0x608060405234801561000f575f5ffd5b50600436106102ca575f3560e01c8063921b004b1161017b578063c153a234116100e4578063e1ec3c681161009e578063e58378bb11610079578063e58378bb14610748578063e5a7bfd01461075c578063e5e05bd714610789578063ec87621c146107a8575f5ffd5b8063e1ec3c681461067a578063e2cb0e4d14610722578063e505d0c514610735575f5ffd5b8063c153a234146105f8578063c9a759cb14610625578063cf7b287f1461062e578063d547741f14610641578063deb0ef4014610654578063deb298c314610667575f5ffd5b8063adfbe22f11610135578063adfbe22f1461056b578063b13aa2d61461057e578063b489e14714610591578063b93186ba146105b0578063be4dc94f146105c3578063c0f6ae97146105d6575f5ffd5b8063921b004b146104e25780639703ef35146104f55780639b087af414610508578063a217fddf14610527578063ab7b1c891461052e578063adb5198014610541575f5ffd5b80633360874c116102375780635d54f5c1116101f157806374a3f8fc116101cc57806374a3f8fc146104965780638f112248146104a95780638fd4f224146104bc57806391d14854146104cf575f5ffd5b80635d54f5c1146104585780636729629f1461046b5780636f504fd714610474575f5ffd5b80633360874c146103eb57806334d9289e146103fe57806336568abe1461040757806347126f621461041a57806357c90de51461043c57806358f858801461044f575f5ffd5b8063248a9ca311610288578063248a9ca31461037357806326e885e31461039657806327f8dce3146103a95780632f010b43146103bc5780632f2ff15d146103cf57806332b814ba146103e2575f5ffd5b80620fa9fb146102ce57806301ffc9a7146102e3578063079712b61461030b578063121ed2a714610338578063158c6bdb1461034d5780631e837ef314610360575b5f5ffd5b6102e16102dc3660046139eb565b6107bc565b005b6102f66102f1366004613a22565b61099a565b60405190151581526020015b60405180910390f35b61032a610319366004613a49565b600b6020525f908152604090205481565b604051908152602001610302565b6103406109d0565b6040516103029190613a64565b6102e161035b366004613aa6565b610a26565b6102e161036e366004613ac6565b610bff565b61032a610381366004613ac6565b5f908152600160208190526040909120015490565b6102e16103a4366004613a49565b610c53565b6102e16103b7366004613ac6565b610c74565b6102f66103ca366004613add565b610ffc565b6102e16103dd366004613b07565b611059565b61032a60135481565b6102e16103f9366004613b37565b611084565b61032a60025481565b6102e1610415366004613b07565b611297565b6102f6610428366004613ac6565b600f6020525f908152604090205460ff1681565b6102e161044a366004613aa6565b6112cf565b61032a60115481565b6102e1610466366004613ac6565b6114d8565b61032a60105481565b6102f6610482366004613a49565b60066020525f908152604090205460ff1681565b6102e16104a4366004613ac6565b6118ab565b6102e16104b7366004613ac6565b6118f7565b6102e16104ca366004613b37565b611994565b6102f66104dd366004613b07565b611a50565b6102e16104f0366004613add565b611a7a565b6102e1610503366004613ac6565b611c0d565b61032a610516366004613ac6565b60126020525f908152604090205481565b61032a5f81565b6102e161053c366004613ac6565b611e98565b61032a61054f3660046139eb565b600a60209081525f928352604080842090915290825290205481565b6102e1610579366004613ac6565b6122c8565b6102e161058c366004613ac6565b6125c2565b61032a61059f366004613ac6565b60046020525f908152604090205481565b61032a6105be366004613ac6565b612654565b6102e16105d1366004613a49565b612673565b6102f66105e4366004613a49565b60056020525f908152604090205460ff1681565b6102f6610606366004613add565b600960209081525f928352604080842090915290825290205460ff1681565b61032a600d5481565b6102e161063c3660046139eb565b612694565b6102e161064f366004613b07565b61294c565b6102e1610662366004613b63565b612971565b6102e1610675366004613ac6565b61306a565b610709610688366004613ac6565b600360208190525f918252604090912080546001820154600283015493830154600484015460058501546006860154600787015460088801546009890154600a909901546001600160a01b039889169a978916999789169896979596949593949293919260ff8084169361010081049091169262010000909104909116908d565b6040516103029d9c9b9a99989796959493929190613bfb565b61032a610730366004613add565b61341b565b61032a610743366004613ac6565b6134a0565b61032a5f516020613f275f395f51905f5281565b6102f661076a366004613add565b600760209081525f928352604080842090915290825290205460ff1681565b61032a610797366004613a49565b600c6020525f908152604090205481565b61032a5f516020613f475f395f51905f5281565b6107c461363f565b6001600160a01b0381166108115760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b60448201526064015b60405180910390fd5b335f908152600a602090815260408083206001600160a01b0386168452909152902054806108785760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610808565b335f908152600a602090815260408083206001600160a01b03871684528252808320839055600b909152812080548392906108b4908490613caf565b909155505060405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303815f875af1158015610905573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109299190613cc2565b6109455760405162461bcd60e51b815260040161080890613cdd565b604080518281526001600160a01b03858116602083015284169133917fc6d7522ade22416d5f000975be266c973d54b87b3bd997daeba6258d2de358d1910160405180910390a35061099660015f55565b5050565b5f6001600160e01b03198216637965db0b60e01b14806109ca57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600e805480602002602001604051908101604052809291908181526020018280548015610a1c57602002820191905f5260205f20905b815481526020019060010190808311610a08575b5050505050905090565b610a2e61363f565b5f8281526003602052604090205482906001600160a01b0316610a635760405162461bcd60e51b815260040161080890613d06565b825f5f82815260036020526040902060090154610100900460ff166005811115610a8f57610a8f613bd3565b14610aac5760405162461bcd60e51b815260040161080890613d33565b5f848152600360205260409020600681015484108015610ad0575080600501548411155b610b185760405162461bcd60e51b8152602060048201526019602482015278109a59081a5b9d195c995cdd081c985d19481a5b9d985b1a59603a1b6044820152606401610808565b60048101546009820154610b3c9133916201000090046001600160a01b0316613667565b6001810180545f87815260046020818152604080842080546001600160a01b031987163317909755600688018b9055928701549092556012905290204290556001600160a01b0316908115801590610b9357505f81115b15610bba57610bba82828560090160029054906101000a90046001600160a01b0316613798565b604051868152339088907fd1b9c752eb85783f53e7669e993e44d05db062782a8dcd72a7757746cc981f1d9060200160405180910390a3505050505061099660015f55565b5f516020613f275f395f51905f52610c16816137fa565b600d8290556040518281527fc59dcd6979a73a87266c1f2a5d4c4108daee42034d779ef00e960a510c789625906020015b60405180910390a15050565b5f610c5d816137fa565b6109965f516020613f475f395f51905f5283611059565b610c7c61363f565b5f8181526003602052604090205481906001600160a01b0316610cb15760405162461bcd60e51b815260040161080890613d06565b5f82815260036020526040902060016009820154610100900460ff166005811115610cde57610cde613bd3565b14610d1d5760405162461bcd60e51b815260206004820152600f60248201526e4c6f616e206e6f742061637469766560881b6044820152606401610808565b80600701548160080154610d319190613d6a565b4211610d725760405162461bcd60e51b815260206004820152601060248201526f131bd85b881b9bdd08195e1c1a5c995960821b6044820152606401610808565b5f610d7c846134a0565b90505f61271060115483610d909190613d7d565b610d9a9190613d94565b60098401546040516323b872dd60e01b81529192506201000090046001600160a01b0316906323b872dd90610dd790339030908690600401613db3565b6020604051808303815f875af1158015610df3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e179190613cc2565b610e635760405162461bcd60e51b815260206004820152601c60248201527f50726f746f636f6c20666565207472616e73666572206661696c6564000000006044820152606401610808565b60098301546201000090046001600160a01b03165f908152600c602052604081208054839290610e94908490613d6a565b909155505060098301805461ff00191661030017905560028301546001600160a01b03165f90815260086020908152604080832060038701548452909152812055610ede85613804565b6002830180546001600160a01b039081165f9081526007602090815260408083206003890180548552908352818420805460ff199081169091558654861685526009845282852082548652909352928190208054909216600190811790925593549087015491549351632142170760e11b8152908316936342842e0e93610f6d93309391169190600401613db3565b5f604051808303815f87803b158015610f84575f5ffd5b505af1925050508015610f95575060015b610fb15760405162461bcd60e51b815260040161080890613dd7565b60018301546040516001600160a01b039091169086907f13b88e6866f0156d706fecfa22b678de5fc2b749c1d2307f6f47eb541385f1ec905f90a350505050610ff960015f55565b50565b6001600160a01b0382165f90815260076020908152604080832084845290915281205460ff1615801561105257506001600160a01b0383165f90815260096020908152604080832085845290915290205460ff16155b9392505050565b5f8281526001602081905260409091200154611074816137fa565b61107e83836138bd565b50505050565b5f516020613f475f395f51905f5261109b816137fa565b6001600160a01b0383166110e75760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964204e4654206164647265737360681b6044820152606401610808565b5f836001600160a01b03163b116111405760405162461bcd60e51b815260206004820152601960248201527f41646472657373206973206e6f74206120636f6e7472616374000000000000006044820152606401610808565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa9250505080156111a7575060408051601f3d908101601f191682019092526111a491810190613cc2565b60015b6111f35760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f20766572696679204552433732310000000000000000006044820152606401610808565b806112365760405162461bcd60e51b8152602060048201526013602482015272436f6e7472616374206e6f742045524337323160681b6044820152606401610808565b506001600160a01b0383165f81815260056020908152604091829020805460ff191686151590811790915591519182527f7fe996db267f9f17db8865f67d54879fc39a38a2a37afa158a9ea52357e794ac91015b60405180910390a2505050565b6001600160a01b03811633146112c05760405163334bd91960e11b815260040160405180910390fd5b6112ca8282613933565b505050565b6112d761363f565b5f8281526003602052604090205482906001600160a01b031661130c5760405162461bcd60e51b815260040161080890613d06565b825f5f82815260036020526040902060090154610100900460ff16600581111561133857611338613bd3565b146113555760405162461bcd60e51b815260040161080890613d33565b5f848152600360205260409020600681015484108015611379575080600501548411155b6113c15760405162461bcd60e51b8152602060048201526019602482015278109a59081a5b9d195c995cdd081c985d19481a5b9d985b1a59603a1b6044820152606401610808565b6001810180545f87815260046020818152604080842080546001600160a01b031987163317909755600688018b9055928701549092556012905290204290556001600160a01b031690811580159061141857505f81115b1561143f5761143f82828560090160029054906101000a90046001600160a01b0316613798565b60098301546004808501546040516323b872dd60e01b8152620100009093046001600160a01b0316926323b872dd9261147c923392309201613db3565b6020604051808303815f875af1158015611498573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114bc9190613cc2565b610bba5760405162461bcd60e51b815260040161080890613e04565b6114e061363f565b5f8181526003602052604090205481906001600160a01b03166115155760405162461bcd60e51b815260040161080890613d06565b815f5f82815260036020526040902060090154610100900460ff16600581111561154157611541613bd3565b1461155e5760405162461bcd60e51b815260040161080890613d33565b5f83815260036020818152604080842081516101a08101835281546001600160a01b0390811682526001808401548216958301959095526002830154169281019290925292830154606082015260048301546080820152600583015460a0820152600683015460c0820152600783015460e08201526008830154610100820152600983015490929161012084019160ff16908111156115ff576115ff613bd3565b600181111561161057611610613bd3565b81526020016009820160019054906101000a900460ff16600581111561163857611638613bd3565b600581111561164957611649613bd3565b815260098201546201000090046001600160a01b03166020820152600a9091015460409091015260105461018082015191925061168591613d6a565b4210156116cb5760405162461bcd60e51b8152602060048201526014602482015273131bd85b881b9bdd08195e1c1a5c9959081e595d60621b6044820152606401610808565b6020808201515f86815260049092526040909120546001600160a01b038216158015906116f757505f81115b1561170c5761170c8282856101600151613798565b5f86815260036020818152604080842060098101805461ff001916610500178155888301516001600160a01b03168652600880855283872060608b0151885285529286208690558b86529284905280546001600160a01b0319908116825560018201805482169055600282018054909116905592830184905560048301849055600583018490556006830184905560078301849055820183905580546001600160b01b0319169055600a01556117c186613804565b604080840180516001600160a01b039081165f908152600760209081528482206060890180518452915290849020805460ff191690559151865192519351632142170760e11b81529116926342842e0e9261182192309290600401613db3565b5f604051808303815f87803b158015611838575f5ffd5b505af1925050508015611849575060015b6118655760405162461bcd60e51b815260040161080890613dd7565b82516040516001600160a01b039091169087907f94140863d1b77b2db4c5904c78e4343ab9c2a51a27e3e6beef9f21109162d93e905f90a35050505050610ff960015f55565b5f516020613f275f395f51905f526118c2816137fa565b60108290556040518281527f67d1057b745e2dfa75389ae5cc1305e8e8cad2ae31b991160a93762ab679af5990602001610c47565b5f516020613f275f395f51905f5261190e816137fa565b610e10821161195f5760405162461bcd60e51b815260206004820152601960248201527f42696443616e63656c506572696f6420746f6f2073686f7274000000000000006044820152606401610808565b60138290556040518281527f1d44ca6a9e035c33fe61047920d46da987cf827176af06973df6ff23a92f9d8890602001610c47565b5f516020613f475f395f51905f526119ab816137fa565b6001600160a01b0383166119f95760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420746f6b656e206164647265737360581b6044820152606401610808565b6001600160a01b0383165f81815260066020908152604091829020805460ff191686151590811790915591519182527f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a910161128a565b5f9182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b611a8261363f565b6001600160a01b0382165f90815260066020526040902054829060ff16611ae55760405162461bcd60e51b8152602060048201526017602482015276115490cc8c081d1bdad95b881b9bdd08185b1b1bddd959604a1b6044820152606401610808565b5f8211611b295760405162461bcd60e51b81526020600482015260126024820152710416d6f756e74206d757374206265203e20360741b6044820152606401610808565b611b34338385613798565b6040516323b872dd60e01b81526001600160a01b038416906323b872dd90611b6490339030908790600401613db3565b6020604051808303815f875af1158015611b80573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ba49190613cc2565b611bc05760405162461bcd60e51b815260040161080890613e04565b604080518381526001600160a01b038516602082015233917fdf4dcf17030d087ed1d90ed3c90719c7260706c1c4a88505dd2d0a982887cf43910160405180910390a25061099660015f55565b611c1561363f565b5f8181526003602052604090205481906001600160a01b0316611c4a5760405162461bcd60e51b815260040161080890613d06565b815f5f82815260036020526040902060090154610100900460ff166005811115611c7657611c76613bd3565b14611c935760405162461bcd60e51b815260040161080890613d33565b5f8381526003602052604090206001015483906001600160a01b03163314611cef5760405162461bcd60e51b815260206004820152600f60248201526e2737ba103637b0b7103632b73232b960891b6044820152606401610808565b5f8481526003602090815260408083206013546012909352922054611d149190613d6a565b421015611d635760405162461bcd60e51b815260206004820152601960248201527f4269642063616e63656c20706572696f64206e6f74206d6574000000000000006044820152606401610808565b6001810180545f878152600460208190526040808320805493905584546001600160a01b031916909455600585015460068601556009850154935163a9059cbb60e01b81526001600160a01b039384169181018290526024810183905290939192620100009092049091169063a9059cbb906044016020604051808303815f875af1158015611df4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e189190613cc2565b611e545760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606401610808565b6040516001600160a01b0383169088907f5677b1e812c0884dd700a8657ca2619da856a4940cb378aa593b217849a21a8a905f90a3505050505050610ff960015f55565b611ea061363f565b5f8181526003602052604090205481906001600160a01b0316611ed55760405162461bcd60e51b815260040161080890613d06565b5f8281526003602052604090205482906001600160a01b03163314611f0c5760405162461bcd60e51b815260040161080890613e33565b5f83815260036020526040902060016009820154610100900460ff166005811115611f3957611f39613bd3565b14611f785760405162461bcd60e51b815260206004820152600f60248201526e4c6f616e206e6f742061637469766560881b6044820152606401610808565b8060080154421015611fc55760405162461bcd60e51b815260206004820152601660248201527514995c185e5b595b9d081899599bdc99481cdd185c9d60521b6044820152606401610808565b80600701548160080154611fd99190613d6a565b4211156120205760405162461bcd60e51b8152602060048201526015602482015274131bd85b88191d5c985d1a5bdb88195e1c1a5c9959605a1b6044820152606401610808565b5f61202a856134a0565b90505f6127106011548361203e9190613d7d565b6120489190613d94565b90505f6127106011548461205c9190613d7d565b6120669190613d94565b90505f6120738385613d6a565b90505f6120808386613caf565b905061208c8484613d6a565b60098701546201000090046001600160a01b03165f908152600c6020526040812080549091906120bd908490613d6a565b909155505060098601805461ff00191661020017905560028601546001600160a01b03165f90815260086020908152604080832060038a0154845290915281205561210789613804565b60028601546001600160a01b039081165f90815260076020908152604080832060038b015484529091529020805460ff191690556001870154600988015461215b9291821691849162010000900416613798565b60098601546040516323b872dd60e01b8152620100009091046001600160a01b0316906323b872dd9061219690339030908790600401613db3565b6020604051808303815f875af11580156121b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121d69190613cc2565b6121f25760405162461bcd60e51b815260040161080890613e04565b600286015486546003880154604051632142170760e11b81526001600160a01b03938416936342842e0e936122309330939290911691600401613db3565b5f604051808303815f87803b158015612247575f5ffd5b505af1925050508015612258575060015b6122745760405162461bcd60e51b815260040161080890613dd7565b85546040518381526001600160a01b03909116908a907f512d3e65b3e58c2187bb1872aa435dba5bd09c1c03823ba56ab70aac411e4a219060200160405180910390a35050505050505050610ff960015f55565b6122d061363f565b5f8181526003602052604090205481906001600160a01b03166123055760405162461bcd60e51b815260040161080890613d06565b815f5f82815260036020526040902060090154610100900460ff16600581111561233157612331613bd3565b1461234e5760405162461bcd60e51b815260040161080890613d33565b5f8381526003602052604090205483906001600160a01b031633146123855760405162461bcd60e51b815260040161080890613e33565b5f84815260036020526040902060018101546001600160a01b03166123dc5760405162461bcd60e51b815260206004820152600d60248201526c139bc81b195b99195c88189a59609a1b6044820152606401610808565b806004015460045f8781526020019081526020015f2054146124405760405162461bcd60e51b815260206004820152601760248201527f457363726f7765642066756e6473206d69736d617463680000000000000000006044820152606401610808565b6008810154156124895760405162461bcd60e51b8152602060048201526014602482015273131bd85b88185b1c9958591e481cdd185c9d195960621b6044820152606401610808565b42600882015560098101805461010061ff00199091161781555f868152600460208190526040808320805493905592548454935163a9059cbb60e01b81526001600160a01b0394851692810192909252602482018390529192620100009092049091169063a9059cbb906044016020604051808303815f875af1158015612512573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125369190613cc2565b6125525760405162461bcd60e51b815260040161080890613cdd565b6001820154825460088401546009850154604080519283526001600160a01b0362010000909204821660208401529381169392169189917f520af44c0202f573865f02f53109b8768072746c32dc4eb57c89c27067d8644c910160405180910390a45050505050610ff960015f55565b5f516020613f275f395f51905f526125d9816137fa565b6103e882111561261f5760405162461bcd60e51b815260206004820152601160248201527008ccaca40e4c2e8ca40e8dede40d0d2ced607b1b6044820152606401610808565b60118290556040518281527f9d2a5010795914ccbdd5a4cdee6a9aa2addac5e44443b519897523b67ddfe9fc90602001610c47565b600e8181548110612663575f80fd5b5f91825260209091200154905081565b5f61267d816137fa565b6109965f516020613f475f395f51905f528361294c565b61269c61363f565b5f516020613f275f395f51905f526126b3816137fa565b6001600160a01b0382166126fb5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610808565b6040516370a0823160e01b81523060048201525f906001600160a01b038516906370a0823190602401602060405180830381865afa15801561273f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127639190613e5e565b90505f805b600e548110156127e3575f600e828154811061278657612786613e75565b5f91825260208083209091015480835260039091526040909120600901549091506001600160a01b038089166201000090920416036127da575f818152600460205260409020546127d79084613d6a565b92505b50600101612768565b506001600160a01b0385165f908152600b60205260408120546128068385613caf565b6128109190613caf565b90505f81116128585760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610808565b6001600160a01b038681165f818152600c6020526040808220919091555163a9059cbb60e01b81529187166004830152602482018390529063a9059cbb906044016020604051808303815f875af11580156128b5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128d99190613cc2565b6128f55760405162461bcd60e51b815260040161080890613cdd565b604080516001600160a01b0387811682526020820184905288168183015290517f66e1599cb4e6f8b24e2216b3ba87495e0bb4b22a948c322997a50b692ebe32329181900360600190a15050505061099660015f55565b5f8281526001602081905260409091200154612967816137fa565b61107e8383613933565b61297961363f565b6001600160a01b0387165f90815260056020526040902054879060ff166129e25760405162461bcd60e51b815260206004820152601860248201527f4e465420636f6e7472616374206e6f7420616c6c6f77656400000000000000006044820152606401610808565b6001600160a01b0382165f90815260066020526040902054829060ff16612a455760405162461bcd60e51b8152602060048201526017602482015276115490cc8c081d1bdad95b881b9bdd08185b1b1bddd959604a1b6044820152606401610808565b6040516331a9108f60e11b8152600481018990528990899033906001600160a01b03841690636352211e90602401602060405180830381865afa158015612a8e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ab29190613e89565b6001600160a01b031614612af85760405162461bcd60e51b815260206004820152600d60248201526c2737ba1027232a1037bbb732b960991b6044820152606401610808565b600d54600e5410612b4b5760405162461bcd60e51b815260206004820152601960248201527f416374697665206c6f616e206c696d69742072656163686564000000000000006044820152606401610808565b6001600160a01b038b165f9081526007602090815260408083208d845290915290205460ff1615612bbe5760405162461bcd60e51b815260206004820152601a60248201527f4e465420616c726561647920636f6c6c61746572616c697a65640000000000006044820152606401610808565b5f8911612c0d5760405162461bcd60e51b815260206004820152601760248201527f4c6f616e20616d6f756e74206d757374206265203e20300000000000000000006044820152606401610808565b5f8811612c5c5760405162461bcd60e51b815260206004820152601960248201527f496e7465726573742072617465206d757374206265203e2030000000000000006044820152606401610808565b5f8711612ca25760405162461bcd60e51b815260206004820152601460248201527304475726174696f6e206d757374206265203e20360641b6044820152606401610808565b6001866001811115612cb657612cb6613bd3565b1115612cf85760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964206c6f616e207479706560781b6044820152606401610808565b5f6002549050604051806101a00160405280336001600160a01b031681526020015f6001600160a01b031681526020018d6001600160a01b031681526020018c81526020018b81526020018a81526020018a81526020018981526020015f8152602001886001811115612d6d57612d6d613bd3565b81526020015f81526001600160a01b03888116602080840191909152426040938401525f858152600380835290849020855181546001600160a01b03199081169186169190911782559286015160018083018054861692871692909217909155948601516002820180549094169416939093179091556060840151908201556080830151600482015560a0830151600582015560c0830151600682015560e08301516007820155610100830151600882015561012083015160098201805492939192909160ff19909116908381811115612e4957612e49613bd3565b021790555061014082015160098201805461ff001916610100836005811115612e7457612e74613bd3565b02179055506101608201516009820180546001600160a01b03909216620100000262010000600160b01b031990921691909117905561018090910151600a909101555f818152600f60205260408120805460ff19166001908117909155600e8054808301825592527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd909101829055612f0e908290613d6a565b6001600160a01b038d165f9081526008602090815260408083208f84529091528120919091556002805491612f4283613ea4565b9190505550600160075f8e6001600160a01b03166001600160a01b031681526020019081526020015f205f8d81526020019081526020015f205f6101000a81548160ff0219169083151502179055508b6001600160a01b03166323b872dd33308e6040518463ffffffff1660e01b8152600401612fc193929190613db3565b5f604051808303815f87803b158015612fd8575f5ffd5b505af1925050508015612fe9575060015b6130055760405162461bcd60e51b815260040161080890613dd7565b336001600160a01b0316817ff7d0570a1cc7150abafdd7f18056e9d7696c7c4cd65d4e6e45b3ff0d1f7cf6fc8e8e8e8e8e8e8e60405161304b9796959493929190613ebc565b60405180910390a3505050505061306160015f55565b50505050505050565b61307261363f565b5f8181526003602052604090205481906001600160a01b03166130a75760405162461bcd60e51b815260040161080890613d06565b815f5f82815260036020526040902060090154610100900460ff1660058111156130d3576130d3613bd3565b146130f05760405162461bcd60e51b815260040161080890613d33565b5f8381526003602052604090205483906001600160a01b031633146131275760405162461bcd60e51b815260040161080890613e33565b5f84815260036020818152604080842081516101a08101835281546001600160a01b0390811682526001808401548216958301959095526002830154169281019290925292830154606082015260048301546080820152600583015460a0820152600683015460c0820152600783015460e08201526008830154610100820152600983015490929161012084019160ff16908111156131c8576131c8613bd3565b60018111156131d9576131d9613bd3565b81526020016009820160019054906101000a900460ff16600581111561320157613201613bd3565b600581111561321257613212613bd3565b815260098201546001600160a01b03620100009091048116602080840191909152600a90930154604090920191909152908201519192505f9082161561327b57505f8681526004602052604081208054919055801561327b5761327b8282856101600151613798565b5f87815260036020818152604080842060098101805461ff001916610400178155888301516001600160a01b03168652600880855283872060608b0151885285529286208690558c86529284905280546001600160a01b0319908116825560018201805482169055600282018054909116905592830184905560048301849055600583018490556006830184905560078301849055820183905580546001600160b01b0319169055600a015561333087613804565b604080840180516001600160a01b039081165f908152600760209081528482206060890180518452915290849020805460ff191690559151865192519351632142170760e11b81529116926342842e0e9261339092309290600401613db3565b5f604051808303815f87803b1580156133a7575f5ffd5b505af19250505080156133b8575060015b6133d45760405162461bcd60e51b815260040161080890613dd7565b82516040516001600160a01b039091169088907f94140863d1b77b2db4c5904c78e4343ab9c2a51a27e3e6beef9f21109162d93e905f90a3505050505050610ff960015f55565b6001600160a01b0382165f90815260086020908152604080832084845290915281205480820361348d5760405162461bcd60e51b815260206004820152601b60248201527f4e6f20616374697665206c6f616e20666f722074686973204e465400000000006044820152606401610808565b613498600182613caf565b949350505050565b5f8181526003602052604081205482906001600160a01b03166134d55760405162461bcd60e51b815260040161080890613d06565b5f8381526003602052604081209080600983015460ff1660018111156134fd576134fd613bd3565b0361352a57612710826006015483600401546135199190613d7d565b6135239190613d94565b9050613626565b6001600983015460ff16600181111561354557613545613bd3565b03613626575f612710836006015484600401546135629190613d7d565b61356c9190613d94565b905060016009840154610100900460ff16600581111561358e5761358e613bd3565b036135e3575f620151808460080154426135a89190613caf565b6135b29190613d94565b905061016d5f82116135c55760016135c7565b815b6135d19084613d7d565b6135db9190613d94565b925050613624565b5f6201518084600701546135f79190613d94565b905061016d5f821161360a57600161360c565b815b6136169084613d7d565b6136209190613d94565b9250505b505b8082600401546136369190613d6a565b95945050505050565b60025f540361366157604051633ee5aeb560e01b815260040160405180910390fd5b60025f55565b6001600160a01b038084165f908152600a60209081526040808320938516835292905220548211156136d25760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610808565b6001600160a01b038084165f908152600a6020908152604080832093851683529290529081208054849290613708908490613caf565b90915550506001600160a01b0381165f908152600b602052604081208054849290613734908490613caf565b90915550506001600160a01b038381165f818152600a60209081526040808320948616808452948252918290205482519081529081019390935290917f8b45c1c793e9a443eda263a15f880b1367ef5e2fb442a38fdd8f813b05e32c9b910161128a565b6001600160a01b038084165f908152600a60209081526040808320938516835292905290812080548492906137ce908490613d6a565b90915550506001600160a01b0381165f908152600b602052604081208054849290613734908490613d6a565b610ff9813361399e565b5f818152600f60205260408120805460ff191690555b600e548110156109965781600e828154811061383857613838613e75565b905f5260205f200154036138b557600e805461385690600190613caf565b8154811061386657613866613e75565b905f5260205f200154600e828154811061388257613882613e75565b5f91825260209091200155600e80548061389e5761389e613f12565b600190038181905f5260205f20015f905590555050565b60010161381a565b5f6138c88383611a50565b61392c575f8381526001602081815260408084206001600160a01b0387168086529252808420805460ff19169093179092559051339286917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45060016109ca565b505f6109ca565b5f61393e8383611a50565b1561392c575f8381526001602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016109ca565b6139a88282611a50565b6109965760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610808565b6001600160a01b0381168114610ff9575f5ffd5b5f5f604083850312156139fc575f5ffd5b8235613a07816139d7565b91506020830135613a17816139d7565b809150509250929050565b5f60208284031215613a32575f5ffd5b81356001600160e01b031981168114611052575f5ffd5b5f60208284031215613a59575f5ffd5b8135611052816139d7565b602080825282518282018190525f918401906040840190835b81811015613a9b578351835260209384019390920191600101613a7d565b509095945050505050565b5f5f60408385031215613ab7575f5ffd5b50508035926020909101359150565b5f60208284031215613ad6575f5ffd5b5035919050565b5f5f60408385031215613aee575f5ffd5b8235613af9816139d7565b946020939093013593505050565b5f5f60408385031215613b18575f5ffd5b823591506020830135613a17816139d7565b8015158114610ff9575f5ffd5b5f5f60408385031215613b48575f5ffd5b8235613b53816139d7565b91506020830135613a1781613b2a565b5f5f5f5f5f5f5f60e0888a031215613b79575f5ffd5b8735613b84816139d7565b96506020880135955060408801359450606088013593506080880135925060a088013560028110613bb3575f5ffd5b915060c0880135613bc3816139d7565b8091505092959891949750929550565b634e487b7160e01b5f52602160045260245ffd5b60028110613bf757613bf7613bd3565b9052565b6001600160a01b038e811682528d811660208301528c166040820152606081018b9052608081018a905260a0810189905260c0810188905260e0810187905261010081018690526101a08101613c55610120830187613be7565b60068510613c6557613c65613bd3565b84610140830152613c826101608301856001600160a01b03169052565b826101808301529e9d5050505050505050505050505050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156109ca576109ca613c9b565b5f60208284031215613cd2575f5ffd5b815161105281613b2a565b6020808252600f908201526e151c985b9cd9995c8819985a5b1959608a1b604082015260600190565b602080825260139082015272131bd85b88191bd95cc81b9bdd08195e1a5cdd606a1b604082015260600190565b60208082526019908201527f4c6f616e206e6f7420696e204c69737465642073746174757300000000000000604082015260600190565b808201808211156109ca576109ca613c9b565b80820281158282048414176109ca576109ca613c9b565b5f82613dae57634e487b7160e01b5f52601260045260245ffd5b500490565b6001600160a01b039384168152919092166020820152604081019190915260600190565b602080825260139082015272139195081d1c985b9cd9995c8819985a5b1959606a1b604082015260600190565b602080825260159082015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b6020808252601190820152702737ba103637b0b7103137b93937bbb2b960791b604082015260600190565b5f60208284031215613e6e575f5ffd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215613e99575f5ffd5b8151611052816139d7565b5f60018201613eb557613eb5613c9b565b5060010190565b6001600160a01b03881681526020810187905260408101869052606081018590526080810184905260e08101613ef560a0830185613be7565b6001600160a01b039290921660c091909101529695505050505050565b634e487b7160e01b5f52603160045260245ffdfeb19546dff01e856fb3f010c267a7b1c60363cf8a4664e21cc89c26224620214e241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08a2646970667358221220453c1b00b692d14815345b06344c033036ccec610be965dd7275d35dbc1d393b64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002190a1dba3e0a9f7216efc929e6faead44ad6131000000000000000000000000d9d96fb150136798861363d8ad9fe4033cfc32b3
-----Decoded View---------------
Arg [0] : _govAddress (address): 0x2190A1dba3e0A9f7216eFC929E6FaEAD44aD6131
Arg [1] : _manager (address): 0xD9D96fb150136798861363d8Ad9Fe4033cfC32b3
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000002190a1dba3e0a9f7216efc929e6faead44ad6131
Arg [1] : 000000000000000000000000d9d96fb150136798861363d8ad9fe4033cfc32b3
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.999905 | 1.0302 | $1.03 |
Loading...
Loading
Loading...
Loading
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.