Token
HERC20 Test (hTEST)
ERC-1155
Overview
Max Total Supply
0 hTEST
Holders
3
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
HErc20
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "./HToken.sol"; /** * @title Honey Finance's HErc20 contract * @notice ERC-1155 contract which wraps an ERC-20 underlying liquid asset and an ERC-721 underlying collateral asset * @author Honey Labs */ contract HErc20 is HToken { string public constant name = "HERC20 Test"; string public constant symbol = "hTEST"; string public constant version = "v0.1"; /** * @notice Initialize the market * @param _underlyingToken address of the underlying ERC-20 liquid asset * @param _collateralToken address of the underlying ERC-721 collateral asset * @param _hivemindAddress address of the Hivemind * @param _interestRateModel address of the interest rate model * @param _liquidatorAddress address of the liquidator * @param _initialExchangeRateMantissa initial exchange rate, scaled by 1e18 * @param _reserveFactorMantissa protocol fee rate, scaled by 1e18 * @param _adminFeeMantissa protocol admin fee rate, scaled by 1e18 * @param _hiveFeeMantissa hive fee rate, scaled by 1e18 */ constructor( IERC20Metadata _underlyingToken, IERC721 _collateralToken, HivemindI _hivemindAddress, InterestRateModelI _interestRateModel, address _liquidatorAddress, uint256 _initialExchangeRateMantissa, uint256 _reserveFactorMantissa, uint256 _adminFeeMantissa, uint256 _hiveFeeMantissa, uint256 _protocolFeeMantissa, address _adminFeeReceiver, address _hiveFeeReceiver ) HToken( _underlyingToken, _collateralToken, _hivemindAddress, _interestRateModel, _liquidatorAddress, _initialExchangeRateMantissa, _reserveFactorMantissa, _adminFeeMantissa, _hiveFeeMantissa, _protocolFeeMantissa, _adminFeeReceiver, _hiveFeeReceiver ) { // Work is delegated to HToken constructor } // ----- Lend side functions ----- /** * @notice Deposit underlying ERC-20 asset and mint hTokens * @dev Pull pattern, user must approve the contract before calling. * @param _amount Quantity of underlying ERC-20 to transfer in */ function depositUnderlying(uint256 _amount) external { depositUnderlyingInternal(_amount); } /** * @notice Redeem a specified amount of hTokens for their underlying ERC-20 asset * @param _amount Quantity of hTokens to redeem for underlying ERC-20 */ function redeem(uint256 _amount) external { redeemInternal(_amount); } /** * @notice Withdraws the specified _amount of underlying ERC-20 asset, consuming the minimum amount of hTokens necessary * @param _amount Quantity of underlying ERC-20 tokens to withdraw */ function withdraw(uint256 _amount) external { withdrawInternal(_amount); } // ----- Borrow side functions ----- /** * @notice Deposit a specified token of the underlying ERC-721 asset and mint an ERC-1155 deposit coupon NFT * @dev Pull pattern, user must approve the contract before calling. * @param _collateralId Token ID of underlying ERC-721 to be transferred in */ function depositCollateral(uint256 _collateralId) external { depositCollateralInternal(_collateralId); } /** * @notice Sender borrows assets from the protocol against the specified collateral asset * @dev Collateral must be deposited first. * @param _borrowAmount Amount of underlying ERC-20 to borrow * @param _collateralId Token ID of underlying ERC-721 to be borrowed against */ function borrow(uint256 _borrowAmount, uint256 _collateralId) external { borrowInternal(_borrowAmount, _collateralId); } /** * @notice Sender repays their own borrow taken against the specified collateral asset * @dev Pull pattern, user must approve the contract before calling. * @param _repayAmount Amount of underlying ERC-20 to repay * @param _collateralId Token ID of underlying ERC-721 to be repaid against */ function repayBorrow(uint256 _repayAmount, uint256 _collateralId) external { repayBorrowInternal(msg.sender, _repayAmount, _collateralId); } /** * @notice Sender repays another user's borrow taken against the specified collateral asset * @dev Pull pattern, user must approve the contract before calling. * @param _borrower User whose borrow will be repaid * @param _repayAmount Amount of underlying ERC-20 to repay * @param _collateralId Token ID of underlying ERC-721 to be repaid against */ function repayBorrowBehalf( address _borrower, uint256 _repayAmount, uint256 _collateralId ) external { repayBorrowInternal(_borrower, _repayAmount, _collateralId); } /** * @notice Burn a deposit coupon NFT and withdraw the associated underlying ERC-721 NFT * @param _collateralId collateral Id, aka the NFT token Id */ function withdrawCollateral(uint256 _collateralId) external { withdrawCollateralInternal(_collateralId); } /** * @notice Triggers transfer of an NFT to the liquidation contract * @param _collateralId collateral Id, aka the NFT token Id representing the borrow position to liquidate */ function liquidateBorrow(uint256 _collateralId) external { liquidateBorrowInternal(_collateralId); } // ----- Utility functions ----- /** * @notice A public function to sweep accidental ERC-20 transfers to this contract. * @dev Tokens are sent to the dao for later distribution * @param _token The address of the ERC-20 token to sweep */ function sweepToken(IERC20 _token) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender) || _token == underlyingToken) revert Unauthorized(); uint256 balance = _token.balanceOf(address(this)); _token.transfer(dao, balance); } /** * @notice The sender adds directly to reserves. * @param _amount The amount of underlying token to add as reserves */ function _addReserves(uint256 _amount) external { _addReservesInternal(_amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; import "./interfaces/HivemindI.sol"; import "./interfaces/InterestRateModelI.sol"; import "./ErrorReporter.sol"; import "hardhat/console.sol"; contract HToken is ERC1155, IERC721Receiver, ErrorReporter, AccessControlEnumerable { using SafeERC20 for IERC20Metadata; using SafeERC20 for IERC20; using Counters for Counters.Counter; /*** Market Events ***/ event AccrueInterest(uint256 interestAccumulated, uint256 interestPerToken, uint256 totalBorrows); event AccrueCouponInterest( Coupon activeCoupon, uint256 debtPrior, uint256 interestAccumulated, uint256 interestPerTokenPrior, uint256 interestPerTokenCurrent ); event Mint(address minter, uint256 mintAmount, uint256 mintTokens); event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens); event Borrow(address borrower, uint256 borrowAmount, uint256 tokenId, uint256 totalBorrows); event RepayBorrow(address indexed payer, uint256 repayAmount, uint256 accountBorrows, uint256 totalBorrows, uint256 _collateralId); event LiquidateBorrow( address indexed liquidator, address borrower, uint256 repayAmount, address indexed hTokenCollateral, uint256 seizeTokens ); /*** Admin Events ***/ event NewHivemindAddr(HivemindI oldHivemind, HivemindI newHivemind); event NewLiquidator(address oldLiquidator, address newLiquidator); event NewAdminFeeReceiver(address oldReceuver, address newReceiver); event NewHiveFeeReceiver(address oldReceuver, address newReceiver); event NewMarketInterestRateModel(InterestRateModelI oldInterestRateModel, InterestRateModelI newInterestRateModel); event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa); event ReservesAdded(address benefactor, uint256 addAmount, uint256 newTotalReserves); event ReservesReduced(address admin, uint256 reduceAmount, uint256 newTotalReserves); event NewHiveFee(uint256 oldHiveFeeMantissa, uint256 newHiveFeeMantissa); event NewAdminFee(uint256 oldAdminFeeMantissa, uint256 newAdminFeeMantissa); event AdminFeesWithdrew(uint256 _amount); event HiveFeesWithdrew(uint256 _amount); event NewProtocolFeeMantissa(uint256 _oldFee, uint256 _newFee); // For public inspection bool public constant isHToken = true; /// @notice Maximum borrow rate that can ever be applied (.0005% / block) uint256 public constant borrowRateMaxMantissa = 0.0005e16; /// @notice Maximum fraction of interest that can be set aside for reserves uint256 public constant reserveFactorMaxMantissa = 1e18; /// @notice Initial exchange rate used when minting the first HToken (used when totalSupply = 0) uint256 internal initialExchangeRateMantissa; /// @notice Fraction of interest currently set aside for reserves uint256 public reserveFactorMantissa; /// @notice Fee rates uint256 public adminFeeMantissa; uint256 public hiveFeeMantissa; uint256 public protocolFeeMantissa; uint256 public reserveFactorPlusFeesMaxMantissa = 5e17; // 50% - change later /// @notice receivers of the protocol fees address public adminFeeReceiver; address public hiveFeeReceiver; /// @notice decimals of underlying uint256 public immutable decimals; string internal baseURI; /// @notice dao address where sweeped tokens will be transmitted address constant dao = 0x9adBd648cb2238B72B05f3e488c6A75F8F186620; /// @notice Liquidation handler contract address public liquidator; /// @notice Contract which oversees inter-hToken operations HivemindI public hivemind; /// @notice Model which tells what the current interest rate should be InterestRateModelI public interestRateModel; /// @notice underlying ERC-20 borrowable/lendable token IERC20 public immutable underlyingToken; /// @notice underlying ERC-721 collateral token IERC721 public immutable collateralToken; // Bookkeeping uint256 public totalBorrows; uint256 public totalReserves; uint256 public totalHTokenSupply; uint256 public totalHiveFees; uint256 public totalAdminFees; /// @notice Block number that interest was last accrued at uint256 public accrualBlockNumber; /// @notice Interest that will be earned for each unit of borrow principal uint256 public interestPerTokenStored; uint8 constant COUPON_UNINITIALIZED = 0; uint8 constant COUPON_INACTIVE = 1; uint8 constant COUPON_ACTIVE = 2; // Coupon NFT metadata struct Coupon { uint32 id; //coupon id uint8 active; // Whether this coupon is active and should be counted in calculations etc. 1 = inactive, 2 = active uint256 collateralId; // tokenId of the collateral collection that is borrowed against uint256 borrowAmount; // Principal borrow balance, denominated in underlying ERC20 token. Updated when interest is accrued to the coupon. uint256 interestPerToken; // Mantissa formatted borrow interestPerToken. Updated when interest is accrued to the coupon. address owner; // Who is the onwer of this coupon, this changes at transfer } struct Collateral { uint256 collateralId; bool active; } Counters.Counter public idCounter; /// @notice borrow coupons mapping, saves a coupon like this collateralId => Coupon mapping(uint256 => Coupon) public borrowCoupons; /// @notice borrow coupons indexes per collateral, couponId => collateralId mapping(uint256 => Collateral) public collateralPerBorrowCouponId; /// @notice keeps how many coupons a user has mapping(address => uint256) public userToCoupons; /// @notice keeps the borrowBalancePerUser so we don't interate through the coupons to calculate it mapping(address => uint256) public borrowBalancePerUser; constructor( IERC20Metadata _underlyingToken, IERC721 _collateralToken, HivemindI _hivemindAddress, InterestRateModelI _interestRateModel, address _liquidator, uint256 _initialExchangeRateMantissa, uint256 _reserveFactorMantissa, uint256 _adminFeeMantissa, uint256 _hiveFeeMantissa, uint256 _protocolFeeMantissa, address _adminFeeReceiver, address _hiveFeeReceiver ) ERC1155(baseURI) { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); // Setup underlying token underlyingToken = _underlyingToken; // Setup the collateral NFT collection collateralToken = _collateralToken; if (!_collateralToken.supportsInterface(type(IERC721).interfaceId)) revert WrongParams(); // Set liquidator contract liquidator = _liquidator; // reserving id 0 for hTokens so we need to increment idCounter.increment(); // Set initial exchange rate initialExchangeRateMantissa = _initialExchangeRateMantissa; if (initialExchangeRateMantissa == 0) revert HTokenError(Error.INITIAL_EXCHANGE_MANTISSA); // Setup hivemind hivemind = _hivemindAddress; // Initialize block number accrualBlockNumber = block.number; decimals = _underlyingToken.decimals(); // Setup interest rate interestRateModel = _interestRateModel; adminFeeReceiver = _adminFeeReceiver; hiveFeeReceiver = _hiveFeeReceiver; protocolFeeMantissa = _protocolFeeMantissa; // Set reserve factor and fees _setReserveFactorFresh(_reserveFactorMantissa); _setAdminFeeFresh(_adminFeeMantissa); _setHiveFeeFresh(_hiveFeeMantissa); // Check reserveFactorMantissa + newAdminFeeMantissa + newHiveFeeMantissa ≤ reserveFactorPlusFeesMaxMantissa if (adminFeeMantissa + hiveFeeMantissa + reserveFactorMantissa > reserveFactorPlusFeesMaxMantissa) revert AdminError(Error.BAD_INPUT); } /*///////////////////////////////////////////////////////////// Coupon handler functions /////////////////////////////////////////////////////////////*/ /** * @notice get user's coupon * @param _account the user to search for * @return user's coupons */ function getUserCoupons(address _account) public view returns (Coupon[] memory) { unchecked { Coupon[] memory userCoupons = new Coupon[](userToCoupons[_account]); uint256 i; uint256 length = idCounter.current(); uint256 counter; for (; i < length; i++) { Collateral memory collateral = collateralPerBorrowCouponId[i]; if (!collateral.active) continue; Coupon memory coupon = borrowCoupons[collateral.collateralId]; if (coupon.owner == _account) { userCoupons[counter++] = coupon; } } return userCoupons; } } /** * @notice get tokenIds of all a user's coupons * @param _user the user to search for * @return indices of user's coupons */ function getUserCouponIndices(address _user) public view returns (uint256[] memory) { unchecked { uint256[] memory userCoupons = new uint256[](userToCoupons[_user]); uint256 i; uint256 length = idCounter.current(); uint256 counter; for (; i < length; i++) { Collateral memory collateral = collateralPerBorrowCouponId[i]; if (!collateral.active) continue; Coupon memory coupon = borrowCoupons[collateral.collateralId]; if (coupon.owner == _user) { userCoupons[counter++] = i; } } return userCoupons; } } /** * @notice get a specific coupon for an NFT * @param _collateralId collateral id * @return coupon */ function getSpecificCouponByCollateralId(uint256 _collateralId) external view returns (Coupon memory) { return borrowCoupons[_collateralId]; } /** * @notice Get the number of coupons deposited aka active * @return depositedCoupons An array of coupons */ function getActiveCoupons() external view returns (Coupon[] memory depositedCoupons) { unchecked { uint256 length = idCounter.current(); uint256 deposited; uint256 i; for (; i < length; i++) { if (collateralPerBorrowCouponId[i].active) { ++deposited; } } i = 0; depositedCoupons = new Coupon[](deposited); uint256 j; for (; i < length; i++) { if (collateralPerBorrowCouponId[i].active) { depositedCoupons[j] = borrowCoupons[collateralPerBorrowCouponId[i].collateralId]; j++; } } } } /*///////////////////////////////////////////////////////////// Lending Functions /////////////////////////////////////////////////////////////*/ /** * @dev Deposit underlying tokens and recieve hTokens as proof of deposit * @dev Must be approved to transfer amount of underlying tokens. Accrues interest and updates exchange rate prior to depositing and minting * @param _amount Quantity of underlying tokens to deposit */ function depositUnderlyingInternal(uint256 _amount) internal { uint256 exchangeRate = exchangeRateCurrent(); uint256 deposited = doUnderlyingTransferIn(msg.sender, _amount); uint256 tokensToMint = (deposited * 1e18) / exchangeRate; totalHTokenSupply += tokensToMint; _mint(msg.sender, 0, tokensToMint, ""); } /** * @dev does transfer out, meaning will withdraw underlying token from the contract to `_to` * @param _to transfer to * @param _amount amount to withdraw */ function doUnderlyingTransferOut(address _to, uint256 _amount) internal { underlyingToken.safeTransfer(_to, _amount); } /** * @dev does transfer in, meaning will deposit underlying token to the contract's balance * @dev `_from` needs to approve before hand * @param _from transfer from, it needs to have approved at least `_amount` * @param _amount amount to deposit * @return amount deposited */ function doUnderlyingTransferIn(address _from, uint256 _amount) internal returns (uint256) { uint256 balanceBefore = underlyingToken.balanceOf(address(this)); underlyingToken.safeTransferFrom(_from, address(this), _amount); uint256 balanceAfter = underlyingToken.balanceOf(address(this)); // TODO: Additional checking to handle false returns if (balanceAfter < balanceBefore) revert HTokenError(Error.TRANSFER_ERROR); return balanceAfter - balanceBefore; } /** * @dev Redeem a specified amount of hTokens for their underlying ERC-20 asset * It does a check against Hivemind to see if it is allowed to redeem. * @param _amount the amount of hTokens to redeem. */ function redeemInternal(uint256 _amount) internal { hivemind.redeemAllowed(HTokenI(address(this)), msg.sender, _amount); // Exchange rate is tokens of underlying per hToken uint256 exchangeRate = exchangeRateCurrent(); totalHTokenSupply -= _amount; _burn(msg.sender, 0, _amount); uint256 underlyingToRedeem = (_amount * exchangeRate) / 1e18; /* Fail if redeem not allowed but not in version 1*/ // hivemind.redeemAllowed(HTokenI(address(this)), msg.sender, underlyingToRedeem); doUnderlyingTransferOut(msg.sender, underlyingToRedeem); } /** * @dev Withdraw a specified quantity of underlying ERC-20 asset, redeeming any amount of hTokens necessary * It does a check against Hivemind to see if it is allowed to redeem. * @param _amount of Underlying to be withdraw */ function withdrawInternal(uint256 _amount) internal { hivemind.redeemAllowed(HTokenI(address(this)), msg.sender, _amount); // Exchange rate is tokens of underlying per hToken uint256 exchangeRate = exchangeRateCurrent(); uint256 tokensToRedeem = (_amount * 1e18) / exchangeRate; totalHTokenSupply -= tokensToRedeem; _burn(msg.sender, 0, tokensToRedeem); doUnderlyingTransferOut(msg.sender, _amount); } /*/////////////////////////////////////////////////////////////// Borrowing functions ///////////////////////////////////////////////////////////////*/ /** * @dev used to deposit collateral * @param _tokenId to be deposited as collateral */ function depositCollateralInternal(uint256 _tokenId) internal { doCollateralTransferIn(msg.sender, _tokenId); _mintCoupon(msg.sender, _tokenId, 0); } /** * @dev minting a coupon when depositing collateral, this coupon will accrue borrows * @param _to the receiver (who deposits the collateral) * @param _collateralId the id of the token that is deposited * @param _borrowAmount the amount that was borrowed */ function _mintCoupon( address _to, uint256 _collateralId, uint256 _borrowAmount ) internal { uint256 currentId = idCounter.current(); Coupon memory coupon = borrowCoupons[_collateralId]; if (coupon.active > COUPON_UNINITIALIZED) { currentId = coupon.id; } else { idCounter.increment(); coupon.id = uint32(currentId); } // Construct a coupon coupon.collateralId = _collateralId; coupon.borrowAmount = _borrowAmount; coupon.active = COUPON_ACTIVE; coupon.interestPerToken = interestPerToken(); coupon.owner = _to; borrowCoupons[_collateralId] = coupon; collateralPerBorrowCouponId[currentId] = Collateral(_collateralId, true); // Mint NFT _mint(_to, currentId, 1, ""); // TODO: Set URI } /** * @dev borrows an amount and accrued it to the coupon * @param _borrowAmount borrowed amount */ function borrowInternal(uint256 _borrowAmount, uint256 _collateralId) internal { Coupon storage coupon = borrowCoupons[_collateralId]; // Can't be the null coupon if (coupon.active == COUPON_UNINITIALIZED) revert HTokenError(Error.COUPON_LOOKUP); // Sanity check to make sure the coupon was found correctly if (coupon.collateralId != _collateralId) revert WrongParams(); // Sanity check to make sure the owner is the one who borrows if (coupon.owner != msg.sender) revert NotOwner(); // Our contract must own the relevant tokenId if (collateralToken.ownerOf(_collateralId) != address(this)) revert NotOwner(); // Check for borrow allowed hivemind.borrowAllowed(HTokenI(address(this)), msg.sender, address(collateralToken), _collateralId, _borrowAmount); accrueInterestToCoupon(_collateralId); _borrowAmount += (_borrowAmount * protocolFeeMantissa) / 10**decimals; // Add the borrow amount to the token coupon.borrowAmount += _borrowAmount; // Add the amount to total borrows totalBorrows += _borrowAmount; borrowBalancePerUser[coupon.owner] += _borrowAmount; emit Borrow(msg.sender, _borrowAmount, _collateralId, coupon.borrowAmount); // Transfer the funds to borrower doUnderlyingTransferOut(msg.sender, _borrowAmount); } /** * @dev does collateral transfer out, transfer nft to the _to * @param _to where to transfer the collateral * @param _collateralId what to transfer, the collateral id */ function doCollateralTransferOut(address _to, uint256 _collateralId) internal { collateralToken.transferFrom(address(this), _to, _collateralId); } /** * @dev does collateral transfer in, transfer nft to the hToken * @param _from where to get the collateral * @param _collateralId what to transfer, the collateral id */ function doCollateralTransferIn(address _from, uint256 _collateralId) internal { collateralToken.transferFrom(_from, address(this), _collateralId); } /** * @dev repays borrow for a collateral * @param _repayAmount the amount to repay * @param _collateralId to want collateral id to pay for */ function repayBorrowInternal( address _borrower, uint256 _repayAmount, uint256 _collateralId ) internal { // Can't repay 0 amount if (_repayAmount == 0) revert HTokenError(Error.AMOUNT_ZERO); // Accrue interest accrueInterestToCoupon(_collateralId); hivemind.repayBorrowAllowed(HTokenI(address(this)), _repayAmount, address(collateralToken), _collateralId); // Find the user's coupon Coupon memory coupon = borrowCoupons[_collateralId]; if (coupon.owner != _borrower) revert Unauthorized(); // Sanity check to make sure the coupon was found correctly if (coupon.collateralId != _collateralId) revert WrongParams(); // Our contract must already own the relevant tokenId // if (collateralToken.ownerOf(_collateralId) != address(this)) revert NotOwner(); // Get outstanding debt uint256 debt = coupon.borrowAmount; if (debt == 0) revert HTokenError(Error.NO_DEBT); // Set amount to repay uint256 payment = (_repayAmount > debt) ? debt : _repayAmount; uint256 repayment = doUnderlyingTransferIn(msg.sender, payment); // Credit their account coupon.borrowAmount = debt - repayment; // Decrease balances totalBorrows -= repayment; borrowBalancePerUser[coupon.owner] -= repayment; borrowCoupons[coupon.collateralId] = coupon; emit RepayBorrow(msg.sender, repayment, debt, totalBorrows, _collateralId); } /** * @dev withdraw collateral * @param _collateralId what to withdraw */ function withdrawCollateralInternal(uint256 _collateralId) internal { Coupon memory activeCoupon = borrowCoupons[_collateralId]; if (!withdrawalAllowed(msg.sender, activeCoupon.collateralId)) revert HTokenError(Error.WITHDRAW_NOT_ALLOWED); burnAndDelete(msg.sender, activeCoupon.collateralId, activeCoupon.id); doCollateralTransferOut(msg.sender, activeCoupon.collateralId); } /** * @notice checks if withdrawal are allowed for this token id * @param _user owner of the coupon * @param _collateralId what to pay for * @return returns true if it's allowed */ function withdrawalAllowed(address _user, uint256 _collateralId) public view returns (bool) { Coupon memory coupon = borrowCoupons[_collateralId]; if (coupon.owner != _user) revert Unauthorized(); return coupon.borrowAmount == 0; } /*///////////////////////////////////////////////////////////// Liquidation functions /////////////////////////////////////////////////////////////*/ /** * @dev liquidate borrow once the health factor is over the collateral factor. * This transfers the nft to the liquidator where you can clawback * @param _collateralId what to liquidate */ function liquidateBorrowInternal(uint256 _collateralId) internal { if (!liquidationAllowedByCollateralId(_collateralId)) revert HTokenError(Error.LIQUIDATION_NOT_ALLOWED); Coupon memory activeCoupon = borrowCoupons[_collateralId]; uint256 _tokenId = activeCoupon.id; bytes memory data = abi.encode(address(this)); collateralToken.safeTransferFrom(address(this), liquidator, _tokenId, data); } /** * @dev check if liquidation is allowed for this coupon, meaning it's active * @param _collateralId what coupon to check for * @return true if it's allowed */ function liquidationAllowedByCouponId(uint256 _collateralId) internal view returns (bool) { return borrowCoupons[_collateralId].active == COUPON_ACTIVE; } /** * @dev check if liquidation is allowed for this nft, meaning it's active * @param _collateralId collateral nft id * @return allowed true if it's allowed */ function liquidationAllowedByCollateralId(uint256 _collateralId) internal view returns (bool allowed) { unchecked { uint256 i; uint256 length = idCounter.current(); for (; i < length; i++) { Collateral memory collateral = collateralPerBorrowCouponId[i]; if (!collateral.active) continue; Coupon memory coupon = borrowCoupons[collateral.collateralId]; if (coupon.collateralId == _collateralId) return coupon.active == COUPON_ACTIVE; } } } /** * @notice closing liquidation, meaning that you pay the borrow and burn the coupon * @dev May only be called by the liquidator * @param _borrower borrower who pays * @param _collateralId what to pay for */ // TODO: Make extra sure to have good return checks and requires. Critical function. function closeoutLiquidation(address _borrower, uint256 _collateralId) external { if (msg.sender != liquidator) revert Unauthorized(); accrueInterestToCoupon(_collateralId); Coupon memory coupon = borrowCoupons[_collateralId]; if (coupon.owner != _borrower) revert Unauthorized(); // Repay borrow repayBorrowInternal(_borrower, coupon.borrowAmount, _collateralId); // Burn the NFT coupon burnAndDelete(_borrower, coupon.collateralId, coupon.id); } /** * @dev burns a coupon and deletes it from the data structure * @param _account user to whom to burn * @param _collateralId collateral associated with this coupon * @param _couponId what to burn */ function burnAndDelete( address _account, uint256 _collateralId, uint256 _couponId ) internal { // makes coupon inactive and deletes it from user coupons _burn(_account, _couponId, 1); borrowCoupons[_collateralId].active = COUPON_INACTIVE; collateralPerBorrowCouponId[_couponId].active = false; } /** * @notice Accrue interest then return the up-to-date exchange rate * @return Calculated exchange rate scaled by 1e18 */ function exchangeRateCurrent() public returns (uint256) { accrueInterest(); return exchangeRateStored(); } /** * @notice Calculates the exchange rate from the underlying to the HToken * @dev This function does not accrue interest before calculating the exchange rate * @return (error code, calculated exchange rate scaled by 1e18) */ function exchangeRateStored() public view returns (uint256) { uint256 _totalSupply = totalHTokenSupply; if (_totalSupply == 0) { /* * If there are no tokens minted: * exchangeRate = initialExchangeRate */ return initialExchangeRateMantissa; } else { /* * Otherwise: * exchangeRate = (totalCash + totalBorrows - (totalReserves + totalHiveFees + totalAdminFees)) / totalSupply */ uint256 totalCash = getCashPrior(); uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows - (totalReserves + totalHiveFees + totalAdminFees); uint256 exchangeRate = (cashPlusBorrowsMinusReserves * 10**decimals) / _totalSupply; return exchangeRate; } } /*/////////////////////////////////////////////////////////////// View functions ///////////////////////////////////////////////////////////////*/ /** * @notice Function to simply retrieve block number * This exists mainly for inheriting test contracts to stub this result. * @return current block number */ function getBlockNumber() internal view returns (uint256) { return block.number; } /** * @notice Get cash balance of this hToken in the underlying asset * @return The quantity of underlying asset owned by this contract */ function getCash() external view returns (uint256) { return getCashPrior(); } /** * @notice Get borrow amount for a collateral * @param _collateralId collateral id we want to get the borrow amount for * @return The amount borrowed so far */ function getBorrowAmountForCollateral(uint256 _collateralId) external view returns (uint256) { return getBorrowFromCoupon(_collateralId); } /** * @notice Get underlying balance that is available for withdrawal or borrow * @return The quantity of underlying not tied up */ function getAvailableUnderlying() external view returns (uint256) { return getCashPrior() - totalReserves - totalAdminFees - totalHiveFees; } /** * @notice Get underlying balance for an account * @param _account the account to check the balance for * @return The quantity of underlying asset owned by this account */ function getAvailableUnderlyingForUser(address _account) external view returns (uint256) { return (balanceOf(_account, 0) * 1e18) / (exchangeRateStored()); } /** * @notice Get the number of coupons for a user * @dev this is gas intensive do not use it in any contract calls * @param _account the account we get the quantity for * @return The quantity of the coupons for _account */ function getUserCouponsLength(address _account) external view returns (uint256) { return userToCoupons[_account]; } /** * @notice Get underlying balance that is available to be withdrewn * @return The quantity of underlying that can be borrowed */ function getAvailableUnderlyingToBorrow() external view returns (uint256) { return getCashPrior() - totalReserves - totalAdminFees - totalHiveFees; } /** * @notice Returns the current per-block borrow interest rate for this hToken * @return The borrow interest rate per block, scaled by 1e18 */ function borrowRatePerBlock() external view returns (uint256) { return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves); } /** * @notice get outstanding debt of a coupon * @param _collateralId index of the borrwed coupon * @return Debt denominated in the underlying token */ function getBorrowFromCoupon(uint256 _collateralId) public view returns (uint256) { uint256 principal = borrowCoupons[_collateralId].borrowAmount; // console.log("interestPerToken() ", (principal * (interestPerToken() - borrowCoupons[_collateralId].interestPerToken)) / 10**decimals); return principal + (principal * (interestPerToken() - borrowCoupons[_collateralId].interestPerToken)) / 10**decimals; } // ----- Interest Rate Calculations ----- /** * @notice Calculate the prevailing interest due per token of debt principal * @return Mantissa formatted interest rate per token of debt */ function interestPerToken() public view returns (uint256) { // Short-circuit if no protocol debt if (totalBorrows == 0) { return interestPerTokenStored; } /* Calculate the number of blocks elapsed since the last accrual */ uint256 currentBlockNumber = getBlockNumber(); uint256 accrualBlockNumberPrior = accrualBlockNumber; uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior; /* Read the previous values out of storage */ uint256 cashPrior = getCashPrior() - totalAdminFees - totalHiveFees; uint256 borrowsPrior = totalBorrows; uint256 reservesPrior = totalReserves; /* Calculate and validate the current borrow interest rate */ uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior); if (borrowRateMantissa > borrowRateMaxMantissa) revert AccrueInterestError(Error.BORROW_RATE_TOO_BIG); // console.log("borrowRateMantissa: ", borrowRateMantissa); // console.log("blockDelta: ", blockDelta); uint256 simpleInterestFactor = borrowRateMantissa * blockDelta; // console.log("simpleInterestFactor: ", simpleInterestFactor); // console.log("interestPerToken: ", interestPerTokenStored + (simpleInterestFactor * 10**decimals) / totalBorrows); return interestPerTokenStored + (simpleInterestFactor * 10**decimals) / totalBorrows; } /** * @notice Accrues all interest due to the protocol * @dev Call this before performing calculations using 'totalBorrows' or other contract-wide quantities */ function accrueInterest() public { /* TODO: Update the comment math * Calculate the interest accumulated into borrows and reserves and the new index: * simpleInterestFactor = borrowRate * blockDelta * interestAccumulated = simpleInterestFactor * totalBorrows * totalBorrowsNew = interestAccumulated + totalBorrows * totalReservesNew = interestAccumulated * reserveFactor + totalReserves * totalHiveFeesNew = interestAccumulated * hiveFee + totalHiveFees * totalAdminFeesNew = interestAccumulated * adminFee + totalAdminFees */ uint256 currentBlockNumber = getBlockNumber(); uint256 accrualBlockNumberPrior = accrualBlockNumber; // Only update if they have not already been updated. if (currentBlockNumber > accrualBlockNumberPrior) { interestPerTokenStored = interestPerToken(); accrualBlockNumber = currentBlockNumber; } uint256 interestAccumulated; uint256 i = 1; uint256 length = idCounter.current(); for (i; i <= length; i++) { Coupon memory coupon = borrowCoupons[i]; if (coupon.active == COUPON_ACTIVE) { interestAccumulated += _accrueInterestToCoupon(i); } } totalBorrows += interestAccumulated; totalReserves += (reserveFactorMantissa * interestAccumulated) / 10**decimals; totalHiveFees += (hiveFeeMantissa * interestAccumulated) / 10**decimals; totalAdminFees += (adminFeeMantissa * interestAccumulated) / 10**decimals; emit AccrueInterest(interestAccumulated, interestPerTokenStored, totalBorrows); } /** * @notice Accrue interest due on a single coupon * @dev Call before interacting with any coupon * @dev Updates contract global quantities * @param _couponId Coupon tokenId to accrue for * @return Amount of interest accrued */ function accrueInterestToCoupon(uint256 _couponId) public returns (uint256) { uint256 currentBlockNumber = getBlockNumber(); uint256 accrualBlockNumberPrior = accrualBlockNumber; // Only update if they have not already been updated. if (currentBlockNumber > accrualBlockNumberPrior) { interestPerTokenStored = interestPerToken(); accrualBlockNumber = currentBlockNumber; } uint256 earned = _accrueInterestToCoupon(_couponId); totalBorrows += earned; totalReserves += (reserveFactorMantissa * earned) / 10**decimals; totalHiveFees += (hiveFeeMantissa * earned) / 10**decimals; totalAdminFees += (adminFeeMantissa * earned) / 10**decimals; return earned; } function _accrueInterestToCoupon(uint256 _couponId) internal returns (uint256) { Coupon storage userCoupon = borrowCoupons[_couponId]; uint256 principalPrior = userCoupon.borrowAmount; uint256 interestPerTokenPrior = userCoupon.interestPerToken; uint256 earned = ((principalPrior * (interestPerTokenStored - userCoupon.interestPerToken)) / 10**decimals); // console.log("earned: ", earned); userCoupon.borrowAmount += earned; userCoupon.interestPerToken = interestPerTokenStored; borrowBalancePerUser[userCoupon.owner] += earned; /* We emit an AccrueInterest event */ emit AccrueCouponInterest(borrowCoupons[_couponId], principalPrior, earned, interestPerTokenPrior, interestPerTokenStored); return earned; } /** * @notice accrues interests to a selected set of coupons * @return all accrued interest */ function accrueInterestToCoupons(uint256[] memory _ids) external returns (uint256) { uint256 currentBlockNumber = getBlockNumber(); uint256 accrualBlockNumberPrior = accrualBlockNumber; // Only update if they have not already been updated. if (currentBlockNumber > accrualBlockNumberPrior) { interestPerTokenStored = interestPerToken(); accrualBlockNumber = currentBlockNumber; } uint256 i; uint256 interestAccumulated; uint256 length = _ids.length; // We may start at position 1 as position 0 is reserved for the null coupon for (i = 1; i <= length; i++) { Collateral memory collateral = collateralPerBorrowCouponId[_ids[i]]; if (!collateral.active) continue; Coupon memory coupon = borrowCoupons[_ids[i]]; if (coupon.active == COUPON_ACTIVE) { interestAccumulated += _accrueInterestToCoupon(_ids[i]); } } totalBorrows += interestAccumulated; totalReserves += (reserveFactorMantissa * interestAccumulated) / 10**decimals; totalHiveFees += (hiveFeeMantissa * interestAccumulated) / 10**decimals; totalAdminFees += (adminFeeMantissa * interestAccumulated) / 10**decimals; return interestAccumulated; } /** * @dev adds reserves, accrues interests * @param _addAmount what to add */ function _addReservesInternal(uint256 _addAmount) internal { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); accrueInterest(); // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to. _addReservesFresh(_addAmount); } /** * @dev adds reserves, does not accrues interests * @param _addAmount what to add */ function _addReservesFresh(uint256 _addAmount) internal { // totalReserves + actualAddAmount uint256 totalReservesNew; uint256 actualAddAmount; // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert AdminError(Error.MARKET_NOT_FRESH); } /* * We call doTransferIn for the caller and the addAmount * Note: The hToken must handle variations between ERC-20 and ETH underlying. * On success, the hToken holds an additional addAmount of cash. * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred. * it returns the amount actually transferred, in case of a fee. */ actualAddAmount = doUnderlyingTransferIn(msg.sender, _addAmount); totalReservesNew = totalReserves + actualAddAmount; /* Revert on overflow */ if (totalReservesNew < totalReserves) revert Unexpected("overflow"); // Store reserves[n+1] = reserves[n] + actualAddAmount totalReserves = totalReservesNew; /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */ emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew); } /** * @dev Gets balance of this contract in terms of the underlying * @dev This excludes the value of the current message, if any * @return The quantity of underlying tokens owned by this contract */ function getCashPrior() internal view returns (uint256) { return underlyingToken.balanceOf(address(this)); } /** * @notice Get the outstanding debt of the protocol * @dev call accrueInterest() first to ensure accurate data, otherwise some inaccuracy will result * @return Protocol debt */ function getDebt() external view returns (uint256) { return totalBorrows + ((totalBorrows * (interestPerToken() - interestPerTokenStored)) / 10**decimals); } /** * @notice Get a snapshot of the account's balances, and the cached exchange rate * @dev This is used by hivemind to more efficiently perform liquidity checks. * @param _account Address of the account to snapshot * @return (token balance, borrow balance, exchange rate mantissa) */ function getAccountSnapshot(address _account) external view returns ( uint256, uint256, uint256 ) { return (balanceOf(_account, 0), borrowBalancePerUser[_account], exchangeRateStored()); } /** * Admin functions */ /** * @notice accrues interest and sets a new hive fee for the protocol using _setHiveFeeFresh * @dev Admin function to accrue interest and set a new hive fee * @param _newHiveFeeMantissa new fee hive mantisa */ function _setHiveFee(uint256 _newHiveFeeMantissa) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); accrueInterest(); // _setAdminFeeFresh emits reserve-factor-specific logs on errors, so we don't need to. _setHiveFeeFresh(_newHiveFeeMantissa); } /** * @notice accrues interest and sets a new admin fee for the protocol using _setAdminFeeFresh * @dev Admin function to accrue interest and set a new admin fee * @param _newAdminFeeMantissa new admin fee mantissa */ function _setAdminFee(uint256 _newAdminFeeMantissa) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); accrueInterest(); // _setAdminFeeFresh emits reserve-factor-specific logs on errors, so we don't need to. _setAdminFeeFresh(_newAdminFeeMantissa); } /** * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh * @dev Admin function to accrue interest and set a new reserve factor * @param _newReserveFactorMantissa new reserver factor mantissa */ function _setReserveFactor(uint256 _newReserveFactorMantissa) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); accrueInterest(); // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to. _setReserveFactorFresh(_newReserveFactorMantissa); } /** * @notice Accrues interest and reduces reserves by transferring to admin * @param _reduceAmount Amount of reduction to reserves */ function _reduceReserves(uint256 _reduceAmount) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); accrueInterest(); // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to. _reduceReservesFresh(_reduceAmount); } /** * @notice Withdraw admin fees * @param _amount amount to withdraw */ function _withdrawAdminFees(uint256 _amount) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); accrueInterest(); if (accrualBlockNumber != getBlockNumber()) { revert AdminError(Error.MARKET_NOT_FRESH); } if (totalAdminFees < _amount) { revert AdminError(Error.AMOUNT_TOO_BIG); } if (getCashPrior() < totalAdminFees) { revert AdminError(Error.TOKEN_INSUFFICIENT_CASH); } totalAdminFees -= _amount; doUnderlyingTransferOut(adminFeeReceiver, _amount); emit AdminFeesWithdrew(_amount); } /** * @notice Withdraw hive fees * @param _amount amount to withdraw from the hive fees */ function _withdrawHiveFees(uint256 _amount) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); accrueInterest(); if (accrualBlockNumber != getBlockNumber()) { revert AdminError(Error.MARKET_NOT_FRESH); } if (totalHiveFees < _amount) { revert AdminError(Error.AMOUNT_TOO_BIG); } if (getCashPrior() < totalHiveFees) { revert AdminError(Error.TOKEN_INSUFFICIENT_CASH); } totalHiveFees -= _amount; doUnderlyingTransferOut(hiveFeeReceiver, _amount); emit HiveFeesWithdrew(_amount); } /** * @notice sets liquidator address * @param _newLiquidator new liquidator */ function _setLiquidator(address _newLiquidator) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); address old = liquidator; liquidator = _newLiquidator; emit NewLiquidator(old, _newLiquidator); } /** * @notice sets hivemind address * @param _newHivemind new hivemind */ function _setHivemind(HivemindI _newHivemind) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); HivemindI old = hivemind; hivemind = _newHivemind; emit NewHivemindAddr(old, _newHivemind); } /** * @notice sets a new admin fee receiver * @param _newReceiver new fee receiver */ function _setAdminFeeReceiver(address _newReceiver) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); if (_newReceiver == address(0)) revert WrongParams(); address old = adminFeeReceiver; adminFeeReceiver = _newReceiver; emit NewAdminFeeReceiver(old, _newReceiver); } /** * @notice sets a new hive fee receiver * @param _newReceiver new fee receiver */ function _setHiveFeeReceiver(address _newReceiver) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); if (_newReceiver == address(0)) revert WrongParams(); address old = hiveFeeReceiver; hiveFeeReceiver = _newReceiver; emit NewHiveFeeReceiver(old, _newReceiver); } /** * @notice sets a new protocol fee * @dev can not be more than 1% * @param _newFee new fee mantissa */ function _setProtocolFeeMantissa(uint256 _newFee) external { if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert Unauthorized(); if (_newFee > 1 ether) revert WrongParams(); uint256 old = protocolFeeMantissa; protocolFeeMantissa = _newFee; emit NewProtocolFeeMantissa(old, _newFee); } /** * @notice Sets a new hive fee for the protocol (*requires fresh interest accrual) * @param _newHiveFeeMantissa new hive fee mantisa */ function _setHiveFeeFresh(uint256 _newHiveFeeMantissa) internal { // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert AdminError(Error.MARKET_NOT_FRESH); } // Sanitize newHiveFeeMantissa if (_newHiveFeeMantissa == type(uint256).max) _newHiveFeeMantissa = hiveFeeMantissa; // Check reserveFactorMantissa + newAdminFeeMantissa + newHiveFeeMantissa ≤ reserveFactorPlusFeesMaxMantissa if (reserveFactorMantissa + adminFeeMantissa + _newHiveFeeMantissa > reserveFactorPlusFeesMaxMantissa) { revert AdminError(Error.BAD_INPUT); } // If setting hive fee if (hiveFeeMantissa != _newHiveFeeMantissa) { // Set hive fee uint256 oldHiveFeeMantissa = hiveFeeMantissa; hiveFeeMantissa = _newHiveFeeMantissa; // Emit event emit NewHiveFee(oldHiveFeeMantissa, _newHiveFeeMantissa); } else revert WrongParams(); } /** * @notice Sets a new admin fee for the protocol (*requires fresh interest accrual) * @param _newAdminFeeMantissa new admin fee mantissa */ function _setAdminFeeFresh(uint256 _newAdminFeeMantissa) internal { // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert AdminError(Error.MARKET_NOT_FRESH); } // Sanitize newAdminFeeMantissa if (_newAdminFeeMantissa == type(uint256).max) _newAdminFeeMantissa = adminFeeMantissa; // Check reserveFactorMantissa + newAdminFeeMantissa + newHiveFeeMantissa ≤ reserveFactorPlusFeesMaxMantissa if (reserveFactorMantissa + _newAdminFeeMantissa + hiveFeeMantissa > reserveFactorPlusFeesMaxMantissa) { revert AdminError(Error.BAD_INPUT); } // If setting admin fee if (adminFeeMantissa != _newAdminFeeMantissa) { // Set admin fee uint256 oldAdminFeeMantissa = adminFeeMantissa; adminFeeMantissa = _newAdminFeeMantissa; // Emit event emit NewAdminFee(oldAdminFeeMantissa, _newAdminFeeMantissa); } else revert WrongParams(); } /** * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual) * @param _newReserveFactorMantissa new reserve factor mantissa */ function _setReserveFactorFresh(uint256 _newReserveFactorMantissa) internal { // Verify market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert AdminError(Error.MARKET_NOT_FRESH); } // Check newReserveFactor ≤ maxReserveFactor if (_newReserveFactorMantissa + adminFeeMantissa + hiveFeeMantissa > reserveFactorPlusFeesMaxMantissa) { revert AdminError(Error.BAD_INPUT); } if (reserveFactorMantissa != _newReserveFactorMantissa) { uint256 oldReserveFactorMantissa = reserveFactorMantissa; reserveFactorMantissa = _newReserveFactorMantissa; emit NewReserveFactor(oldReserveFactorMantissa, _newReserveFactorMantissa); } else revert WrongParams(); } /** * @notice Reduces reserves by transferring to admin * @dev Requires fresh interest accrual * @param _reduceAmount Amount of reduction to reserves */ function _reduceReservesFresh(uint256 _reduceAmount) internal { // totalReserves - reduceAmount uint256 totalReservesNew; // We fail gracefully unless market's block number equals current block number if (accrualBlockNumber != getBlockNumber()) { revert AdminError(Error.MARKET_NOT_FRESH); } // Fail gracefully if protocol has insufficient underlying cash if (getCashPrior() < _reduceAmount) { revert AdminError(Error.TOKEN_INSUFFICIENT_CASH); } // Check reduceAmount ≤ reserves[n] (totalReserves) if (_reduceAmount > totalReserves) { revert AdminError(Error.BAD_INPUT); } ///////////////////////// // EFFECTS & INTERACTIONS // (No safe failures beyond this point) // We checked reduceAmount <= totalReserves above, so this should never revert. // Store reserves[n+1] = reserves[n] - reduceAmount totalReserves -= _reduceAmount; // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred. doUnderlyingTransferOut(msg.sender, _reduceAmount); emit ReservesReduced(msg.sender, _reduceAmount, totalReservesNew); } /*/////////////////////////////////////////////////////////////// --- Backend ERC standards compliance below this point --- ///////////////////////////////////////////////////////////////*/ /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 _interfaceId) public view virtual override(ERC1155, AccessControlEnumerable) returns (bool) { _interfaceId == type(IERC1155).interfaceId || _interfaceId == type(AccessControlEnumerable).interfaceId; return super.supportsInterface(_interfaceId); } function _beforeTokenTransfer( address _operator, address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data ) internal virtual override(ERC1155) { if (_from == _to) { super._beforeTokenTransfer(_operator, _from, _to, _ids, _amounts, _data); return; } uint256 j; uint256 lengthToModify; for (j; j < _ids.length; j++) { // HTokens don't require coupon management if (_ids[j] > 0) { Collateral memory collateral = collateralPerBorrowCouponId[_ids[j]]; if (!collateral.active) continue; borrowCoupons[collateral.collateralId].owner = _to; lengthToModify++; } } if (_from != address(0)) { userToCoupons[_from] -= lengthToModify; } if (_to != address(0)) { userToCoupons[_to] += lengthToModify; } super._beforeTokenTransfer(_operator, _from, _to, _ids, _amounts, _data); } function onERC721Received( address, address, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155.sol"; import "./IERC1155Receiver.sol"; import "./extensions/IERC1155MetadataURI.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { using Address for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: balance query for the zero address"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not owner nor approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: transfer caller is not owner nor approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, _asSingletonArray(id), _asSingletonArray(amount), data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), _asSingletonArray(id), _asSingletonArray(amount), ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits a {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "./HTokenI.sol"; abstract contract HivemindI { /*** Assets You Are In ***/ function enterMarkets(HTokenI[] calldata _hTokens) external virtual; function exitMarket(HTokenI _hToken) external virtual; function redeemAllowed( HTokenI _hToken, address _redeemer, uint256 _redeemTokens ) external virtual; function borrowAllowed( HTokenI _hToken, address _borrower, address _collection, uint256 _collateralId, uint256 _borrowAmount ) external virtual; function repayBorrowAllowed( HTokenI _hToken, uint256 _repayAmount, address _collection, uint256 _collateralId ) external virtual; function transferAllowed( HTokenI _hToken, address _src, address _dst, uint256 _transferTokens ) external virtual; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.13; /** * @title Modified Compound's InterestRateModel Interface * @author BowTiedPickle */ interface InterestRateModelI { /** * @notice Calculates the current borrow interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @return The borrow rate per block (as a percentage, and scaled by 1e18) */ function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint); /** * @notice Calculates the current supply interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @param reserveFactorMantissa The current reserve factor the market has * @return The supply rate per block (as a percentage, and scaled by 1e18) */ function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) external view returns (uint); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.13; error Unauthorized(); error AccrueInterestError(ErrorReporter.Error error); error WrongParams(); error Unexpected(string error); error InvalidCoupon(); error HivemindError(ErrorReporter.Error error); error AdminError(ErrorReporter.Error error); error MarketError(ErrorReporter.Error error); error HTokenError(ErrorReporter.Error error); error Paused(); error NotOwner(); error ExternalFailure(string error); error Uninitialized(); contract ErrorReporter { enum Error { UNAUTHORIZED, INSUFFICIENT_SHORTFALL, INSUFFICIENT_LIQUIDITY, INVALID_COLLATERAL_FACTOR, MARKET_NOT_ENTERED, // no longer possible MARKET_NOT_LISTED, MARKET_ALREADY_LISTED, MARKET_CAP_BORROW_REACHED, MARKET_NOT_FRESH, PRICE_ERROR, BAD_INPUT, AMOUNT_ZERO, NO_DEBT, COUPON_NOT_FOUND, LIQUIDATION_NOT_ALLOWED, WITHDRAW_NOT_ALLOWED, INITIAL_EXCHANGE_MANTISSA, TRANSFER_ERROR, COUPON_LOOKUP, TOKEN_INSUFFICIENT_CASH, BORROW_RATE_TOO_BIG, NONZERO_BORROW_BALANCE, AMOUNT_TOO_BIG } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.4.22 <0.9.0; library console { address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); function _sendLogPayload(bytes memory payload) private view { uint256 payloadLength = payload.length; address consoleAddress = CONSOLE_ADDRESS; assembly { let payloadStart := add(payload, 32) let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) } } function log() internal view { _sendLogPayload(abi.encodeWithSignature("log()")); } function logInt(int p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); } function logUint(uint p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); } function logString(string memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function logBool(bool p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function logAddress(address p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function logBytes(bytes memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); } function logBytes1(bytes1 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); } function logBytes2(bytes2 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); } function logBytes3(bytes3 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); } function logBytes4(bytes4 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); } function logBytes5(bytes5 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); } function logBytes6(bytes6 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); } function logBytes7(bytes7 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); } function logBytes8(bytes8 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); } function logBytes9(bytes9 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); } function logBytes10(bytes10 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); } function logBytes11(bytes11 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); } function logBytes12(bytes12 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); } function logBytes13(bytes13 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); } function logBytes14(bytes14 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); } function logBytes15(bytes15 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); } function logBytes16(bytes16 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); } function logBytes17(bytes17 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); } function logBytes18(bytes18 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); } function logBytes19(bytes19 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); } function logBytes20(bytes20 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); } function logBytes21(bytes21 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); } function logBytes22(bytes22 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); } function logBytes23(bytes23 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); } function logBytes24(bytes24 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); } function logBytes25(bytes25 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); } function logBytes26(bytes26 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); } function logBytes27(bytes27 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); } function logBytes28(bytes28 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); } function logBytes29(bytes29 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); } function logBytes30(bytes30 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); } function logBytes31(bytes31 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); } function logBytes32(bytes32 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); } function log(uint p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); } function log(string memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function log(bool p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function log(address p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function log(uint p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); } function log(uint p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); } function log(uint p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); } function log(uint p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); } function log(string memory p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); } function log(string memory p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } function log(string memory p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); } function log(string memory p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); } function log(bool p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); } function log(bool p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); } function log(bool p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); } function log(bool p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); } function log(address p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); } function log(address p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); } function log(address p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); } function log(address p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); } function log(uint p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); } function log(uint p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); } function log(uint p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); } function log(uint p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); } function log(uint p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); } function log(uint p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); } function log(uint p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); } function log(uint p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); } function log(uint p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); } function log(uint p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); } function log(uint p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); } function log(uint p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); } function log(uint p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); } function log(uint p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); } function log(uint p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); } function log(uint p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); } function log(string memory p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); } function log(string memory p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); } function log(string memory p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); } function log(string memory p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); } function log(string memory p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); } function log(string memory p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); } function log(string memory p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); } function log(string memory p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); } function log(string memory p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); } function log(string memory p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); } function log(string memory p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); } function log(string memory p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); } function log(string memory p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); } function log(string memory p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); } function log(string memory p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); } function log(string memory p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); } function log(bool p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); } function log(bool p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); } function log(bool p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); } function log(bool p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); } function log(bool p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); } function log(bool p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); } function log(bool p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); } function log(bool p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); } function log(bool p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); } function log(bool p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); } function log(bool p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); } function log(bool p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); } function log(bool p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); } function log(bool p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); } function log(bool p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); } function log(bool p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); } function log(address p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); } function log(address p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); } function log(address p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); } function log(address p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); } function log(address p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); } function log(address p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); } function log(address p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); } function log(address p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); } function log(address p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); } function log(address p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); } function log(address p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); } function log(address p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); } function log(address p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); } function log(address p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); } function log(address p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); } function log(address p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); } function log(uint p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** @dev Handles the receipt of a single ERC1155 token type. This function is called at the end of a `safeTransferFrom` after the balance has been updated. To accept the transfer, this must return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61, or its own function selector). @param operator The address which initiated the transfer (i.e. msg.sender) @param from The address which previously owned the token @param id The ID of the token being transferred @param value The amount of tokens being transferred @param data Additional data with no specified format @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** @dev Handles the receipt of a multiple ERC1155 token types. This function is called at the end of a `safeBatchTransferFrom` after the balances have been updated. To accept the transfer(s), this must return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81, or its own function selector). @param operator The address which initiated the batch transfer (i.e. msg.sender) @param from The address which previously owned the token @param ids An array containing ids of each token being transferred (order and length must match values array) @param values An array containing amounts of each token being transferred (order and length must match ids array) @param data Additional data with no specified format @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../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: * * ``` * 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}: * * ``` * 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. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @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 override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @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 override 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. */ function grantRole(bytes32 role, address account) public virtual override 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. */ function revokeRole(bytes32 role, address account) public virtual override 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 `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @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 Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @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. * * _Available since v3.1._ */ 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, an admin role * bearer except when using {AccessControl-_setupRole}. */ 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 `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; interface HTokenI { // Coupon NFT metadata struct Coupon { uint32 id; //coupon id uint8 active; // Whether this coupon is active and should be counted in calculations etc. 1 = inactive, 2 = active uint256 collateralId; // tokenId of the collateral collection that is borrowed against uint256 borrowAmount; // Current borrow balance, denominated in underlying ERC20 token uint256 index; // Mantissa formatted borrow index. Updated when interest is accrued to the coupon. address owner; // Who is the onwer of this coupon, this changes at transfer } // ----- Informational ----- function isHToken() external view returns (bool); function decimals() external view returns (uint256); // ----- Addresses ----- function collateralToken() external view returns (IERC721); function underlyingToken() external view returns (IERC20); function hivemind() external view returns (address); function dao() external view returns (address); function interestRateModel() external view returns (address); // ----- Fee Information ----- function reserveFactorMantissa() external view returns (uint256); function reserveFactorMaxMantissa() external view returns (uint256); function borrowRateMaxMantissa() external view returns (uint256); function adminFeeMantissa() external view returns (uint256); function fuseFeeMantissa() external view returns (uint256); function reserveFactorPlusFeesMaxMantissa() external view returns (uint256); // ----- Protocol Accounting ----- function totalBorrows() external view returns (uint256); function totalReserves() external view returns (uint256); function totalHTokenSupply() external view returns (uint256); function totalFuseFees() external view returns (uint256); function totalAdminFees() external view returns (uint256); function accrualBlockNumber() external view returns (uint256); function interestPerTokenStored() external view returns (uint256); function interestPerToken() external view returns (uint256); // ----- Coupon Views ----- function getBorrowFromCoupon(uint256 _index) external view returns (uint256); function getUserCoupons(address _user) external view returns (Coupon[] memory); function getUserCouponIndices(address _user) external view returns (uint256[] memory); function getSpecificCouponByCollateralId(uint256 _collateralId) external view returns (Coupon memory); function userToCoupons(address _account) external view returns (uint256); function getActiveCoupons() external view returns (Coupon[] memory); function getUserCouponsLength(address _account) external view returns (uint256); // ----- Accounting Views ----- function exchangeRateStored() external view returns (uint256); function getCash() external view returns (uint256); function borrowRatePerBlock() external view returns (uint256); function getAccountSnapshot(address _account) external view returns ( uint256, uint256, uint256 ); function getBorrowAmountForCollateral(uint256 _colalteralId) external view returns (uint256); function withdrawalAllowed(address _user, uint256 _tokenId) external view returns (bool); function getAvailableUnderlying() external view returns (uint256); function getAvailableUnderlyingForUser(address _account) external view returns (uint256); function getDebt() external view returns (uint256); // ----- State Changing Permissionless ----- function accrueInterest() external; function accrueInterestToCoupon(uint256 _couponId) external returns (uint256); function accrueInterestToCoupons(uint256[] memory _ids) external returns (uint256); function exchangeRateCurrent() external returns (uint256); // ----- State Changing Permissioned ----- function closeoutLiquidation(address _borrower, uint256 _tokenId) external; // ----- Admin Functions ----- function _setFuseFee(uint256 _newFuseFeeMantissa) external; function _setAdminFee(uint256 _newAdminFeeMantissa) external; function _setReserveFactor(uint256 _newReserveFactorMantissa) external; function _reduceReserves(uint256 _reduceAmount) external; function _withdrawAdminFees(uint256 _amount) external; function _withdrawFuseFees(uint256 _amount) external; function _setLiquidator(address _newLiquidator) external; function _setHivemind(address _newHivemind) external; }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"contract IERC20Metadata","name":"_underlyingToken","type":"address"},{"internalType":"contract IERC721","name":"_collateralToken","type":"address"},{"internalType":"contract HivemindI","name":"_hivemindAddress","type":"address"},{"internalType":"contract InterestRateModelI","name":"_interestRateModel","type":"address"},{"internalType":"address","name":"_liquidatorAddress","type":"address"},{"internalType":"uint256","name":"_initialExchangeRateMantissa","type":"uint256"},{"internalType":"uint256","name":"_reserveFactorMantissa","type":"uint256"},{"internalType":"uint256","name":"_adminFeeMantissa","type":"uint256"},{"internalType":"uint256","name":"_hiveFeeMantissa","type":"uint256"},{"internalType":"uint256","name":"_protocolFeeMantissa","type":"uint256"},{"internalType":"address","name":"_adminFeeReceiver","type":"address"},{"internalType":"address","name":"_hiveFeeReceiver","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"enum ErrorReporter.Error","name":"error","type":"uint8"}],"name":"AccrueInterestError","type":"error"},{"inputs":[{"internalType":"enum ErrorReporter.Error","name":"error","type":"uint8"}],"name":"AdminError","type":"error"},{"inputs":[{"internalType":"enum ErrorReporter.Error","name":"error","type":"uint8"}],"name":"HTokenError","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"string","name":"error","type":"string"}],"name":"Unexpected","type":"error"},{"inputs":[],"name":"WrongParams","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint8","name":"active","type":"uint8"},{"internalType":"uint256","name":"collateralId","type":"uint256"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"uint256","name":"interestPerToken","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"indexed":false,"internalType":"struct HToken.Coupon","name":"activeCoupon","type":"tuple"},{"indexed":false,"internalType":"uint256","name":"debtPrior","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestAccumulated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestPerTokenPrior","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestPerTokenCurrent","type":"uint256"}],"name":"AccrueCouponInterest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"interestAccumulated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestPerToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"}],"name":"AccrueInterest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"AdminFeesWithdrew","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"HiveFeesWithdrew","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"hTokenCollateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"name":"LiquidateBorrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintTokens","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldAdminFeeMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAdminFeeMantissa","type":"uint256"}],"name":"NewAdminFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldReceuver","type":"address"},{"indexed":false,"internalType":"address","name":"newReceiver","type":"address"}],"name":"NewAdminFeeReceiver","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldHiveFeeMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newHiveFeeMantissa","type":"uint256"}],"name":"NewHiveFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldReceuver","type":"address"},{"indexed":false,"internalType":"address","name":"newReceiver","type":"address"}],"name":"NewHiveFeeReceiver","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract HivemindI","name":"oldHivemind","type":"address"},{"indexed":false,"internalType":"contract HivemindI","name":"newHivemind","type":"address"}],"name":"NewHivemindAddr","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldLiquidator","type":"address"},{"indexed":false,"internalType":"address","name":"newLiquidator","type":"address"}],"name":"NewLiquidator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract InterestRateModelI","name":"oldInterestRateModel","type":"address"},{"indexed":false,"internalType":"contract InterestRateModelI","name":"newInterestRateModel","type":"address"}],"name":"NewMarketInterestRateModel","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newFee","type":"uint256"}],"name":"NewProtocolFeeMantissa","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldReserveFactorMantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newReserveFactorMantissa","type":"uint256"}],"name":"NewReserveFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"redeemAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accountBorrows","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"RepayBorrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"benefactor","type":"address"},{"indexed":false,"internalType":"uint256","name":"addAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalReserves","type":"uint256"}],"name":"ReservesAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"reduceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalReserves","type":"uint256"}],"name":"ReservesReduced","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":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"_addReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reduceAmount","type":"uint256"}],"name":"_reduceReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newAdminFeeMantissa","type":"uint256"}],"name":"_setAdminFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newReceiver","type":"address"}],"name":"_setAdminFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newHiveFeeMantissa","type":"uint256"}],"name":"_setHiveFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newReceiver","type":"address"}],"name":"_setHiveFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract HivemindI","name":"_newHivemind","type":"address"}],"name":"_setHivemind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newLiquidator","type":"address"}],"name":"_setLiquidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newFee","type":"uint256"}],"name":"_setProtocolFeeMantissa","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newReserveFactorMantissa","type":"uint256"}],"name":"_setReserveFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"_withdrawAdminFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"_withdrawHiveFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accrualBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrueInterest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_couponId","type":"uint256"}],"name":"accrueInterestToCoupon","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"accrueInterestToCoupons","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminFeeMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminFeeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_borrowAmount","type":"uint256"},{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"borrowBalancePerUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"borrowCoupons","outputs":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint8","name":"active","type":"uint8"},{"internalType":"uint256","name":"collateralId","type":"uint256"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"uint256","name":"interestPerToken","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowRateMaxMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowRatePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"closeoutLiquidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"collateralPerBorrowCouponId","outputs":[{"internalType":"uint256","name":"collateralId","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralToken","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"depositCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositUnderlying","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeRateCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeRateStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getAccountSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getActiveCoupons","outputs":[{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint8","name":"active","type":"uint8"},{"internalType":"uint256","name":"collateralId","type":"uint256"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"uint256","name":"interestPerToken","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct HToken.Coupon[]","name":"depositedCoupons","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAvailableUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getAvailableUnderlyingForUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAvailableUnderlyingToBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"getBorrowAmountForCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"getBorrowFromCoupon","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDebt","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":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"getSpecificCouponByCollateralId","outputs":[{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint8","name":"active","type":"uint8"},{"internalType":"uint256","name":"collateralId","type":"uint256"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"uint256","name":"interestPerToken","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct HToken.Coupon","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getUserCouponIndices","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getUserCoupons","outputs":[{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint8","name":"active","type":"uint8"},{"internalType":"uint256","name":"collateralId","type":"uint256"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"uint256","name":"interestPerToken","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct HToken.Coupon[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getUserCouponsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"hiveFeeMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hiveFeeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hivemind","outputs":[{"internalType":"contract HivemindI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"idCounter","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestRateModel","outputs":[{"internalType":"contract InterestRateModelI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isHToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"liquidateBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"protocolFeeMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_repayAmount","type":"uint256"},{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"repayBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_repayAmount","type":"uint256"},{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"repayBorrowBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveFactorMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserveFactorMaxMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserveFactorPlusFeesMaxMantissa","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","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":"contract IERC20","name":"_token","type":"address"}],"name":"sweepToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAdminFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBorrows","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalHTokenSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalHiveFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userToCoupons","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"withdrawCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_collateralId","type":"uint256"}],"name":"withdrawalAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60e06040526706f05b59d3b20000600a553480156200001d57600080fd5b506040516200697e3803806200697e833981016040819052620000409162000815565b8b8b8b8b8b8b8b8b8b8b8b8b600d80546200005b90620008ef565b80601f01602080910402602001604051908101604052809291908181526020018280546200008990620008ef565b8015620000da5780601f10620000ae57610100808354040283529160200191620000da565b820191906000526020600020905b815481529060010190602001808311620000bc57829003601f168201915b5050505050620000f0816200036460201b60201c565b50620000fe6000336200037d565b6001600160a01b038c811660a0528b1660c08190526040516301ffc9a760e01b81526380ac58cd60e01b60048201526301ffc9a790602401602060405180830381865afa15801562000154573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200017a91906200092b565b6200019857604051635863f78960e01b815260040160405180910390fd5b600e80546001600160a01b0319166001600160a01b038a16179055620001cb6018620003c0602090811b62002a2e17901c565b600587905560008790036200020157601060405163076cbf6360e11b8152600401620001f8919062000956565b60405180910390fd5b89600f60006101000a8154816001600160a01b0302191690836001600160a01b03160217905550436016819055508b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200097f565b60ff16608052601080546001600160a01b03808c166001600160a01b031992831617909255600b8054858416908316179055600c8054928416929091169190911790556009839055620002e786620003c9565b620002f285620004a3565b620002fd846200056a565b600a54600654600854600754620003159190620009a4565b620003219190620009a4565b11156200034657600a6040516342a8a55b60e01b8152600401620001f8919062000956565b505050505050505050505050505050505050505050505050620009cb565b80516200037990600290602084019062000747565b5050565b6200039482826200063160201b62002a371760201c565b6000828152600460209081526040909120620003bb91839062002abd620006d5821b17901c565b505050565b80546001019055565b4360165414620003f15760086040516342a8a55b60e01b8152600401620001f8919062000956565b600a54600854600754620004069084620009a4565b620004129190620009a4565b11156200043757600a6040516342a8a55b60e01b8152600401620001f8919062000956565b80600654146200048757600680549082905560408051828152602081018490527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f82146091015b60405180910390a15050565b604051635863f78960e01b815260040160405180910390fd5b50565b4360165414620004cb5760086040516342a8a55b60e01b8152600401620001f8919062000956565b6000198103620004da57506007545b600a5460085482600654620004f09190620009a4565b620004fc9190620009a4565b11156200052157600a6040516342a8a55b60e01b8152600401620001f8919062000956565b80600754146200048757600780549082905560408051828152602081018490527fcdd0b588250e1398549f79cfdb8217c186688822905d6715b0834ea1c865594a91016200047b565b4360165414620005925760086040516342a8a55b60e01b8152600401620001f8919062000956565b6000198103620005a157506008545b600a5481600754600654620005b79190620009a4565b620005c39190620009a4565b1115620005e857600a6040516342a8a55b60e01b8152600401620001f8919062000956565b80600854146200048757600880549082905560408051828152602081018490527f0572c4d8f505651be671d8c8610d5c981e409e48a4463af0bcee12b843ebd4d291016200047b565b60008281526003602090815260408083206001600160a01b038516845290915290205460ff16620003795760008281526003602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620006913390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620006ec836001600160a01b038416620006f5565b90505b92915050565b60008181526001830160205260408120546200073e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620006ef565b506000620006ef565b8280546200075590620008ef565b90600052602060002090601f016020900481019282620007795760008555620007c4565b82601f106200079457805160ff1916838001178555620007c4565b82800160010185558215620007c4579182015b82811115620007c4578251825591602001919060010190620007a7565b50620007d2929150620007d6565b5090565b5b80821115620007d25760008155600101620007d7565b6001600160a01b0381168114620004a057600080fd5b80516200081081620007ed565b919050565b6000806000806000806000806000806000806101808d8f0312156200083957600080fd5b8c516200084681620007ed565b60208e0151909c506200085981620007ed565b60408e0151909b506200086c81620007ed565b60608e0151909a506200087f81620007ed565b60808e01519099506200089281620007ed565b8098505060a08d0151965060c08d0151955060e08d015194506101008d015193506101208d015192506101408d0151620008cc81620007ed565b9150620008dd6101608e0162000803565b90509295989b509295989b509295989b565b600181811c908216806200090457607f821691505b6020821081036200092557634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156200093e57600080fd5b815180151581146200094f57600080fd5b9392505050565b60208101601783106200097957634e487b7160e01b600052602160045260246000fd5b91905290565b6000602082840312156200099257600080fd5b815160ff811681146200094f57600080fd5b60008219821115620009c657634e487b7160e01b600052601160045260246000fd5b500190565b60805160a05160c051615ec662000ab860003960008181610acf01528181612ba201528181612c5a0152818161322801528181613314015281816149240152614b3001526000818161071a015281816111bb01528181612df601528181613ab3015281816146e30152818161475d015261479d015260008181610792015281816110a4015281816111640152818161152701528181611581015281816115db01528181611a5501528181611aaf01528181611b0901528181611b7f01528181611f8801528181611fe20152818161203c0152818161255501528181612cdc01526135cb0152615ec66000f3fe608060405234801561001057600080fd5b50600436106105035760003560e01c80637dcc491911610299578063c2ead8b911610167578063db006a75116100d9578063ee27a2f211610092578063ee27a2f214610c90578063f242432a14610c9d578063f3fdb15a14610cb0578063f42c2b0414610cc3578063f8f9da2814610ce3578063fca7820b14610ceb57600080fd5b8063db006a7514610bfe578063de30b99714610c11578063e651cb9b14610c24578063e76241c014610c37578063e985e9c514610c4a578063eb08ab2814610c8657600080fd5b8063c8229b6c1161012b578063c8229b6c14610b9f578063c9a04e6a14610bb2578063ca15c87314610bc5578063cac4e657146105e1578063cf9d206114610bd8578063d547741f14610beb57600080fd5b8063c2ead8b914610b45578063c37f68e214610b58578063c40ac4a414610b86578063c626ebf514610b8e578063c81faea214610b9757600080fd5b8063a275370d1161020b578063b2016bd4116101c4578063b2016bd414610aca578063b83f823614610af1578063b9f5be4114610b04578063ba6275ec14610b17578063bad4a01f14610b2a578063bd6d894d14610b3d57600080fd5b8063a275370d14610a5b578063a67fb2ce14610a6a578063a6afed9514610a7d578063a7b820df14610a85578063a81c043514610a98578063ae65d23114610aa157600080fd5b80639010d07c1161025d5780639010d07c146109e357806391d14854146109f657806391dd36c614610a0957806395d89b4114610a1c578063a217fddf14610a40578063a22cb46514610a4857600080fd5b80637dcc4919146109a257806385ded19d146109b55780638d02d9a1146109be5780638df61fcb146109c75780638f840ddd146109da57600080fd5b806334613dab116103d65780634ef286e41161034857806361feacff1161030157806361feacff1461094e5780636236e030146109575780636882510b146109605780636c540baf1461097357806370a5f9821461097c5780637265deae1461098f57600080fd5b80634ef286e4146108b25780634f38d235146108d257806354cc4a78146108f257806354fd4d5014610905578063601a0bf1146109285780636112fe2e1461093b57600080fd5b80633e9410101161039a5780633e941010146108475780634046ebae1461085a57806342fb6ae91461086d57806347bd37181461088057806349dab7f2146108895780634e1273f41461089257600080fd5b806334613dab146107f357806336568abe1461080657806338b0dcce146108195780633943e7b81461082c5780633b1d21a21461083f57600080fd5b8063173b99041161047a5780632495a599116104335780632495a599146107155780632e1a7d4d146107545780632eb2c2d6146107675780632f2ff15d1461077a578063313ce5671461078d57806333483f8f146107b457600080fd5b8063173b990414610628578063182df0f5146106315780631be19560146106395780631c2540c51461064c5780631fb997621461065f578063248a9ca3146106f257600080fd5b80630b2c8f9c116104cc5780630b2c8f9c146105b25780630e89341c146105bb5780630ecbcdab146105ce5780631320eb4c146105e157806314a6bf0f146105e9578063150b7a02146105f157600080fd5b8062fdd58e14610508578063010e53181461052e57806301ffc9a714610543578063045e18ae1461056657806306fdde031461057b575b600080fd5b61051b610516366004615214565b610cfe565b6040519081526020015b60405180910390f35b61054161053c366004615240565b610d98565b005b610556610551366004615273565b610e21565b6040519015158152602001610525565b61056e610e5c565b60405161052591906152d9565b6105a56040518060400160405280600b81526020016a12115490cc8c0815195cdd60aa1b81525081565b604051610525919061537f565b61051b60085481565b6105a56105c9366004615392565b610fc5565b6105416105dc3660046153ab565b611059565b61051b611067565b61051b61109d565b61060f6105ff366004615482565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610525565b61051b60065481565b61051b611103565b610541610647366004615240565b6111a7565b61054161065a366004615240565b611304565b6106b361066d366004615392565b6019602052600090815260409020805460018201546002830154600384015460049094015463ffffffff841694600160201b90940460ff1693906001600160a01b031686565b6040805163ffffffff909716875260ff909516602087015293850192909252606084015260808301526001600160a01b031660a082015260c001610525565b61051b610700366004615392565b60009081526003602052604090206001015490565b61073c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610525565b610541610762366004615392565b611385565b610541610775366004615581565b611391565b61054161078836600461562e565b611428565b61051b7f000000000000000000000000000000000000000000000000000000000000000081565b6107de6107c2366004615392565b601a602052600090815260409020805460019091015460ff1682565b60408051928352901515602083015201610525565b610541610801366004615392565b61144e565b61054161081436600461562e565b611457565b6105416108273660046153ab565b6114d1565b61051b61083a366004615392565b6114dc565b61051b611638565b610541610855366004615392565b611642565b600e5461073c906001600160a01b031681565b600f5461073c906001600160a01b031681565b61051b60115481565b61051b60135481565b6108a56108a036600461565e565b61164b565b6040516105259190615765565b61051b6108c0366004615240565b601c6020526000908152604090205481565b6108e56108e0366004615392565b611774565b6040516105259190615778565b600b5461073c906001600160a01b031681565b6105a56040518060400160405280600481526020016376302e3160e01b81525081565b610541610936366004615392565b6117ea565b610541610949366004615392565b611822565b61051b60155481565b61051b60095481565b61054161096e366004615240565b61182b565b61051b60165481565b61051b61098a366004615786565b6118d3565b61051b61099d366004615392565b611b68565b6105416109b0366004615240565b611bee565b61051b60175481565b61051b60075481565b61056e6109d5366004615240565b611c96565b61051b60125481565b61073c6109f13660046153ab565b611e0c565b610556610a0436600461562e565b611e24565b610541610a17366004615392565b611e4f565b6105a5604051806040016040528060058152602001641a151154d560da1b81525081565b61051b600081565b610541610a563660046157c8565b611e87565b61051b670de0b6b3a764000081565b61051b610a78366004615392565b611e92565b610541611e9d565b610541610a93366004615392565b6120dc565b61051b60145481565b61051b610aaf366004615240565b6001600160a01b03166000908152601b602052604090205490565b61073c7f000000000000000000000000000000000000000000000000000000000000000081565b610556610aff366004615214565b6121e7565b610541610b12366004615392565b61227e565b600c5461073c906001600160a01b031681565b610541610b38366004615392565b612287565b61051b612290565b6108a5610b53366004615240565b6122a2565b610b6b610b66366004615240565b6123ff565b60408051938452602084019290925290820152606001610525565b610556600181565b61051b600a5481565b61051b61243d565b610541610bad366004615214565b6125a9565b61051b610bc0366004615240565b612693565b61051b610bd3366004615392565b6126c4565b610541610be6366004615392565b6126db565b610541610bf936600461562e565b612769565b610541610c0c366004615392565b61278f565b610541610c1f366004615392565b612798565b610541610c32366004615392565b6127d0565b610541610c453660046157f6565b6128d4565b610556610c5836600461582b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b60185461051b9081565b61051b65048c2739500081565b610541610cab366004615859565b6128df565b60105461073c906001600160a01b031681565b61051b610cd1366004615240565b601b6020526000908152604090205481565b61051b612966565b610541610cf9366004615392565b6129f6565b60006001600160a01b038316610d6f5760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084015b60405180910390fd5b506000818152602081815260408083206001600160a01b03861684529091529020545b92915050565b610da3600033611e24565b610dbf576040516282b42960e81b815260040160405180910390fd5b600f80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f17d26dfc8576ef7a5cb27121d1a3845a0b5dea7763c991e76cd2f7c3a612a3d391015b60405180910390a15050565b60006001600160e01b03198216636cdb3d1360e11b1480610e5257506001600160e01b03198216630b7f5a3560e31b145b50610d9282612ad2565b60606000610e6960185490565b90506000805b82811015610ea0576000818152601a602052604090206001015460ff1615610e98578160010191505b600101610e6f565b506000816001600160401b03811115610ebb57610ebb6153cd565b604051908082528060200260200182016040528015610ef457816020015b610ee16151b7565b815260200190600190039081610ed95790505b50935060005b83821015610fbe576000828152601a602052604090206001015460ff1615610fb3576000828152601a602090815260408083205483526019825291829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b031660a08201528551869083908110610fa457610fa46158c1565b60209081029190910101526001015b600190910190610efa565b5050505090565b606060028054610fd4906158d7565b80601f0160208091040260200160405190810160405280929190818152602001828054611000906158d7565b801561104d5780601f106110225761010080835404028352916020019161104d565b820191906000526020600020905b81548152906001019060200180831161103057829003601f168201915b50505050509050919050565b6110638282612af7565b5050565b600060145460155460125461107a612dde565b6110849190615927565b61108e9190615927565b6110989190615927565b905090565b60006110ca7f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b6017546110d561243d565b6110df9190615927565b6011546110ec9190615a2e565b6110f69190615a4d565b6011546110989190615a6f565b60135460009080820361111857505060055490565b6000611122612dde565b905060006015546014546012546111399190615a6f565b6111439190615a6f565b6011546111509084615a6f565b61115a9190615927565b905060008361118a7f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b6111949084615a2e565b61119e9190615a4d565b95945050505050565b6111b2600033611e24565b15806111ef57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316145b1561120c576040516282b42960e81b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611253573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112779190615a87565b60405163a9059cbb60e01b8152739adbd648cb2238b72b05f3e488c6a75f8f1866206004820152602481018290529091506001600160a01b0383169063a9059cbb906044016020604051808303816000875af11580156112db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ff9190615aa0565b505050565b61130f600033611e24565b61132b576040516282b42960e81b815260040160405180910390fd5b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f44f518b033497d0698cc6bffcddfac36c78ff249b688c40ef1ed72943e11efbd9101610e15565b61138e81612e2d565b50565b6001600160a01b0385163314806113ad57506113ad8533610c58565b6114145760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610d66565b6114218585858585612eee565b5050505050565b60008281526003602052604090206001015461144481336130d9565b6112ff838361313d565b61138e8161315f565b6001600160a01b03811633146114c75760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610d66565b611063828261329d565b6110633383836132bf565b6016546000904390808211156114fd576114f461243d565b60175560168290555b6000611508856135ad565b9050806011600082825461151c9190615a6f565b9091555061154d90507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b8160065461155b9190615a2e565b6115659190615a4d565b601260008282546115769190615a6f565b909155506115a790507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b816008546115b59190615a2e565b6115bf9190615a4d565b601460008282546115d09190615a6f565b9091555061160190507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b8160075461160f9190615a2e565b6116199190615a4d565b6015600082825461162a9190615a6f565b909155509095945050505050565b6000611098612dde565b61138e8161371d565b606081518351146116b05760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610d66565b600083516001600160401b038111156116cb576116cb6153cd565b6040519080825280602002602001820160405280156116f4578160200160208202803683370190505b50905060005b845181101561176c5761173f858281518110611718576117186158c1565b6020026020010151858381518110611732576117326158c1565b6020026020010151610cfe565b828281518110611751576117516158c1565b602090810291909101015261176581615abd565b90506116fa565b509392505050565b61177c6151b7565b50600090815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b031660a082015290565b6117f5600033611e24565b611811576040516282b42960e81b815260040160405180910390fd5b611819611e9d565b61138e81613755565b61138e8161382d565b611836600033611e24565b611852576040516282b42960e81b815260040160405180910390fd5b6001600160a01b03811661187957604051635863f78960e01b815260040160405180910390fd5b600c80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f1f671b7f960ea754837d8752ef9b7d5748146fb4ddd41c167f257825341033809101610e15565b6016546000904390808211156118f4576118eb61243d565b60175560168290555b83516001906000905b808311611a38576000601a600089868151811061191c5761191c6158c1565b60209081029190910181015182528181019290925260409081016000208151808301909252805482526001015460ff16151591810182905291506119605750611a26565b6000601960008a8781518110611978576119786158c1565b6020908102919091018101518252818101929092526040908101600020815160c081018352815463ffffffff81168252600160201b900460ff169381018490526001820154928101929092526002810154606083015260038101546080830152600401546001600160a01b031660a0820152915060011901611a2357611a16898681518110611a0957611a096158c1565b60200260200101516135ad565b611a209085615a6f565b93505b50505b82611a3081615abd565b9350506118fd565b8160116000828254611a4a9190615a6f565b90915550611a7b90507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b82600654611a899190615a2e565b611a939190615a4d565b60126000828254611aa49190615a6f565b90915550611ad590507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b82600854611ae39190615a2e565b611aed9190615a4d565b60146000828254611afe9190615a6f565b90915550611b2f90507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b82600754611b3d9190615a2e565b611b479190615a4d565b60156000828254611b589190615a6f565b9091555091979650505050505050565b600081815260196020526040812060020154611ba57f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b600084815260196020526040902060030154611bbf61243d565b611bc99190615927565b611bd39083615a2e565b611bdd9190615a4d565b611be79082615a6f565b9392505050565b611bf9600033611e24565b611c15576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116611c3c57604051635863f78960e01b815260040160405180910390fd5b600b80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fdb492e3d5a171bd9d50e48753e6cc996c55a940a523e0b6f9775bb6613e357fd9101610e15565b6001600160a01b0381166000908152601b6020526040812054606091906001600160401b03811115611cca57611cca6153cd565b604051908082528060200260200182016040528015611d0357816020015b611cf06151b7565b815260200190600190039081611ce85790505b509050600080611d1260185490565b905060005b81831015611e02576000838152601a60209081526040918290208251808401909352805483526001015460ff161515908201819052611d565750611df7565b8051600090815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b0390811660a083018190529089169003611df45780868480600101955081518110611de857611de86158c1565b60200260200101819052505b50505b600190920191611d17565b5091949350505050565b6000828152600460205260408120611be790836138e7565b60009182526003602090815260408084206001600160a01b0393909316845291905290205460ff1690565b611e5a600033611e24565b611e76576040516282b42960e81b815260040160405180910390fd5b611e7e611e9d565b61138e816138f3565b6110633383836139c6565b6000610d9282611b68565b601654439080821115611ebb57611eb261243d565b60175560168290555b6000600181611ec960185490565b90505b808211611f6b57600082815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281018390526001820154938101939093526002810154606084015260038101546080840152600401546001600160a01b031660a083015260011901611f5857611f4b836135ad565b611f559085615a6f565b93505b5081611f6381615abd565b925050611ecc565b8260116000828254611f7d9190615a6f565b90915550611fae90507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b83600654611fbc9190615a2e565b611fc69190615a4d565b60126000828254611fd79190615a6f565b9091555061200890507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b836008546120169190615a2e565b6120209190615a4d565b601460008282546120319190615a6f565b9091555061206290507f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b836007546120709190615a2e565b61207a9190615a4d565b6015600082825461208b9190615a6f565b90915550506017546011546040805186815260208101939093528201527f875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb99060600160405180910390a15050505050565b6120e7600033611e24565b612103576040516282b42960e81b815260040160405180910390fd5b61210b611e9d565b43601654146121305760086040516342a8a55b60e01b8152600401610d669190615ad6565b8060155410156121565760166040516342a8a55b60e01b8152600401610d669190615ad6565b601554612161612dde565b10156121835760136040516342a8a55b60e01b8152600401610d669190615ad6565b80601560008282546121959190615927565b9091555050600b546121b0906001600160a01b031682613aa6565b6040518181527ff02de49094a433b4b58fb50395a7aa7110f62486c358e7a8fcc2e013684b2b50906020015b60405180910390a150565b6000818152601960209081526040808320815160c081018352815463ffffffff81168252600160201b900460ff16938101939093526001810154918301919091526002810154606083015260038101546080830152600401546001600160a01b0390811660a0830181905290851614612272576040516282b42960e81b815260040160405180910390fd5b60600151159392505050565b61138e81613ada565b61138e81613b50565b600061229a611e9d565b611098611103565b6001600160a01b0381166000908152601b6020526040812054606091906001600160401b038111156122d6576122d66153cd565b6040519080825280602002602001820160405280156122ff578160200160208202803683370190505b50905060008061230e60185490565b905060005b81831015611e02576000838152601a60209081526040918290208251808401909352805483526001015460ff16151590820181905261235257506123f4565b8051600090815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b0390811660a0830181905290891690036123f157848684806001019550815181106123e4576123e46158c1565b6020026020010181815250505b50505b600190920191612313565b600080600061240f846000610cfe565b6001600160a01b0385166000908152601c6020526040902054612430611103565b9250925092509193909250565b6000601154600003612450575060175490565b601654439060006124618284615927565b90506000601454601554612473612dde565b61247d9190615927565b6124879190615927565b6011546012546010546040516315f2405360e01b8152600481018590526024810184905260448101839052939450919290916000916001600160a01b03909116906315f2405390606401602060405180830381865afa1580156124ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125129190615a87565b905065048c2739500081111561253e576014604051635890300f60e01b8152600401610d669190615ad6565b600061254a8683615a2e565b60115490915061257b7f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b6125859083615a2e565b61258f9190615a4d565b60175461259c9190615a6f565b9850505050505050505090565b600e546001600160a01b031633146125d3576040516282b42960e81b815260040160405180910390fd5b6125dc816114dc565b50600081815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b0390811660a083018190529084161461266b576040516282b42960e81b815260040160405180910390fd5b61267a838260600151846132bf565b6112ff838260400151836000015163ffffffff16613b66565b600061269d611103565b6126a8836000610cfe565b6126ba90670de0b6b3a7640000615a2e565b610d929190615a4d565b6000818152600460205260408120610d9290613bac565b6126e6600033611e24565b612702576040516282b42960e81b815260040160405180910390fd5b670de0b6b3a764000081111561272b57604051635863f78960e01b815260040160405180910390fd5b600980549082905560408051828152602081018490527fe091c76fcf70119c7721979bfbf8b7113ae93b7665ef11819c87e34de28019159101610e15565b60008281526003602052604090206001015461278581336130d9565b6112ff838361329d565b61138e81613bb6565b6127a3600033611e24565b6127bf576040516282b42960e81b815260040160405180910390fd5b6127c7611e9d565b61138e81613c77565b6127db600033611e24565b6127f7576040516282b42960e81b815260040160405180910390fd5b6127ff611e9d565b43601654146128245760086040516342a8a55b60e01b8152600401610d669190615ad6565b80601454101561284a5760166040516342a8a55b60e01b8152600401610d669190615ad6565b601454612855612dde565b10156128775760136040516342a8a55b60e01b8152600401610d669190615ad6565b80601460008282546128899190615927565b9091555050600c546128a4906001600160a01b031682613aa6565b6040518181527f9b784bc629cf280321a09661d7270771a0f5814811f7145a1f0ae079a1ead479906020016121dc565b6112ff8383836132bf565b6001600160a01b0385163314806128fb57506128fb8533610c58565b6129595760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610d66565b6114218585858585613d31565b6010546000906001600160a01b03166315f24053612982612dde565b6011546012546040516001600160e01b031960e086901b1681526004810193909352602483019190915260448201526064015b602060405180830381865afa1580156129d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110989190615a87565b612a01600033611e24565b612a1d576040516282b42960e81b815260040160405180910390fd5b612a25611e9d565b61138e81613e5d565b80546001019055565b612a418282611e24565b6110635760008281526003602090815260408083206001600160a01b03851684529091529020805460ff19166001179055612a793390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000611be7836001600160a01b038416613f08565b60006001600160e01b03198216635a05180f60e01b1480610d925750610d9282613f57565b60008181526019602052604090208054600160201b900460ff16612b3157601260405163076cbf6360e11b8152600401610d669190615ad6565b81816001015414612b5557604051635863f78960e01b815260040160405180910390fd5b60048101546001600160a01b03163314612b82576040516330cd747160e01b815260040160405180910390fd5b6040516331a9108f60e11b81526004810183905230906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015612be9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0d9190615afe565b6001600160a01b031614612c34576040516330cd747160e01b815260040160405180910390fd5b600f5460405163385b9a3d60e01b81523060048201523360248201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116604483015260648201859052608482018690529091169063385b9a3d9060a401600060405180830381600087803b158015612cb557600080fd5b505af1158015612cc9573d6000803e3d6000fd5b50505050612cd6826114dc565b50612d027f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b600954612d0f9085615a2e565b612d199190615a4d565b612d239084615a6f565b925082816002016000828254612d399190615a6f565b925050819055508260116000828254612d529190615a6f565b909155505060048101546001600160a01b03166000908152601c602052604081208054859290612d83908490615a6f565b9091555050600281015460408051338152602081018690528082018590526060810192909252517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809181900360800190a16112ff3384613aa6565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a08231906024016129b5565b600f5460405163eabe7d9160e01b81526001600160a01b039091169063eabe7d9190612e6190309033908690600401615b1b565b600060405180830381600087803b158015612e7b57600080fd5b505af1158015612e8f573d6000803e3d6000fd5b505050506000612e9d612290565b9050600081612eb484670de0b6b3a7640000615a2e565b612ebe9190615a4d565b90508060136000828254612ed29190615927565b90915550612ee4905033600083613f7c565b6112ff3384613aa6565b8151835114612f505760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610d66565b6001600160a01b038416612f765760405162461bcd60e51b8152600401610d6690615b3f565b33612f858187878787876140f5565b60005b845181101561306b576000858281518110612fa557612fa56158c1565b602002602001015190506000858381518110612fc357612fc36158c1565b602090810291909101810151600084815280835260408082206001600160a01b038e1683529093529190912054909150818110156130135760405162461bcd60e51b8152600401610d6690615b84565b6000838152602081815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290613050908490615a6f565b925050819055505050508061306490615abd565b9050612f88565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516130bb929190615bce565b60405180910390a46130d1818787878787614266565b505050505050565b6130e38282611e24565b611063576130fb816001600160a01b031660146143c1565b6131068360206143c1565b604051602001613117929190615bf3565b60408051601f198184030181529082905262461bcd60e51b8252610d669160040161537f565b6131478282612a37565b60008281526004602052604090206112ff9082612abd565b6131688161455c565b61318857600e60405163076cbf6360e11b8152600401610d669190615ad6565b6000818152601960209081526040808320815160c081018352815463ffffffff8116808352600160201b90910460ff168286015260018301548285015260028301546060830152600383015460808301526004909201546001600160a01b031660a08201528251309481019490945293909290910160408051601f1981840301815290829052600e54635c46a7ef60e11b83529092506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263b88d4fde9261326592309291169087908790600401615c68565b600060405180830381600087803b15801561327f57600080fd5b505af1158015613293573d6000803e3d6000fd5b5050505050505050565b6132a78282614645565b60008281526004602052604090206112ff90826146ac565b816000036132e357600b60405163076cbf6360e11b8152600401610d669190615ad6565b6132ec816114dc565b50600f5460405163e09aeafb60e01b8152306004820152602481018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166044830152606482018490529091169063e09aeafb90608401600060405180830381600087803b15801561336857600080fd5b505af115801561337c573d6000803e3d6000fd5b505050600082815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b0390811660a0830181905291925085161461340f576040516282b42960e81b815260040160405180910390fd5b8181604001511461343357604051635863f78960e01b815260040160405180910390fd5b6060810151600081900361345d57600c60405163076cbf6360e11b8152600401610d669190615ad6565b600081851161346c578461346e565b815b9050600061347c33836146c1565b90506134888184615927565b6060850152601180548291906000906134a2908490615927565b909155505060a08401516001600160a01b03166000908152601c6020526040812080548392906134d3908490615927565b9091555050604084810180516000908152601960209081529083902087518154838a015160ff16600160201b0264ffffffffff1990911663ffffffff90921691909117178155915160018301556060808801516002840155608080890151600385015560a0890151600490940180546001600160a01b039095166001600160a01b0319909516949094179093556011548451868152928301889052828501528101889052915133927ffa8bc83f8aead8e5153719deeddbef9e743a3477190ebd49f3778f389489108f92908290030190a250505050505050565b600081815260196020526040812060028101546003820154836135f17f0000000000000000000000000000000000000000000000000000000000000000600a615a22565b84600301546017546136039190615927565b61360d9085615a2e565b6136179190615a4d565b90508084600201600082825461362d9190615a6f565b9091555050601754600385015560048401546001600160a01b03166000908152601c602052604081208054839290613666908490615a6f565b90915550506000868152601960209081526040918290206017548351825463ffffffff8116825260ff90851c169381019390935260018201548385015260028201546060840152600382015460808401526004909101546001600160a01b031660a083015260c0820186905260e08201849052610100820185905261012082015290517fbec6833599c650e2c7c5ee344dae8b58d4a07bdbd6a096e9172b8c67c4e9d1f6918190036101400190a195945050505050565b613728600033611e24565b613744576040516282b42960e81b815260040160405180910390fd5b61374c611e9d565b61138e81614840565b6000436016541461377c5760086040516342a8a55b60e01b8152600401610d669190615ad6565b81613785612dde565b10156137a75760136040516342a8a55b60e01b8152600401610d669190615ad6565b6012548211156137cd57600a6040516342a8a55b60e01b8152600401610d669190615ad6565b81601260008282546137df9190615927565b909155506137ef90503383613aa6565b60408051338152602081018490529081018290527f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e90606001610e15565b600081815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282018390526002810154606083015260038101546080830152600401546001600160a01b031660a0820152906138a09033906121e7565b6138c057600f60405163076cbf6360e11b8152600401610d669190615ad6565b6138d9338260400151836000015163ffffffff16613b66565b61106333826040015161490d565b6000611be7838361498b565b43601654146139185760086040516342a8a55b60e01b8152600401610d669190615ad6565b600019810361392657506007545b600a546008548260065461393a9190615a6f565b6139449190615a6f565b111561396657600a6040516342a8a55b60e01b8152600401610d669190615ad6565b80600754146139ad57600780549082905560408051828152602081018490527fcdd0b588250e1398549f79cfdb8217c186688822905d6715b0834ea1c865594a9101610e15565b604051635863f78960e01b815260040160405180910390fd5b816001600160a01b0316836001600160a01b031603613a395760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610d66565b6001600160a01b03838116600081815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6110636001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683836149b5565b6000613ae4612290565b90506000613af233846146c1565b9050600082613b0983670de0b6b3a7640000615a2e565b613b139190615a4d565b90508060136000828254613b279190615a6f565b92505081905550613b4a3360008360405180602001604052806000815250614a18565b50505050565b613b5a3382614b19565b61138e33826000614b69565b613b7283826001613f7c565b6000918252601960209081526040808420805464ff000000001916600160201b179055918352601a90529020600101805460ff1916905550565b6000610d92825490565b600f5460405163eabe7d9160e01b81526001600160a01b039091169063eabe7d9190613bea90309033908690600401615b1b565b600060405180830381600087803b158015613c0457600080fd5b505af1158015613c18573d6000803e3d6000fd5b505050506000613c26612290565b90508160136000828254613c3a9190615927565b90915550613c4c905033600084613f7c565b6000670de0b6b3a7640000613c618385615a2e565b613c6b9190615a4d565b90506112ff3382613aa6565b4360165414613c9c5760086040516342a8a55b60e01b8152600401610d669190615ad6565b6000198103613caa57506008545b600a5481600754600654613cbe9190615a6f565b613cc89190615a6f565b1115613cea57600a6040516342a8a55b60e01b8152600401610d669190615ad6565b80600854146139ad57600880549082905560408051828152602081018490527f0572c4d8f505651be671d8c8610d5c981e409e48a4463af0bcee12b843ebd4d29101610e15565b6001600160a01b038416613d575760405162461bcd60e51b8152600401610d6690615b3f565b33613d76818787613d6788614d03565b613d7088614d03565b876140f5565b6000848152602081815260408083206001600160a01b038a16845290915290205483811015613db75760405162461bcd60e51b8152600401610d6690615b84565b6000858152602081815260408083206001600160a01b038b8116855292528083208785039055908816825281208054869290613df4908490615a6f565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613e54828888888888614d4e565b50505050505050565b4360165414613e825760086040516342a8a55b60e01b8152600401610d669190615ad6565b600a54600854600754613e959084615a6f565b613e9f9190615a6f565b1115613ec157600a6040516342a8a55b60e01b8152600401610d669190615ad6565b80600654146139ad57600680549082905560408051828152602081018490527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101610e15565b6000818152600183016020526040812054613f4f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d92565b506000610d92565b60006001600160e01b03198216637965db0b60e01b1480610d925750610d9282614e09565b6001600160a01b038316613fde5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b6064820152608401610d66565b3361400d81856000613fef87614d03565b613ff887614d03565b604051806020016040528060008152506140f5565b6000838152602081815260408083206001600160a01b03881684529091529020548281101561408a5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b6064820152608401610d66565b6000848152602081815260408083206001600160a01b03898116808652918452828520888703905582518981529384018890529092908616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b836001600160a01b0316856001600160a01b031603156130d1576000805b84518210156141e7576000858381518110614130576141306158c1565b602002602001015111156141d5576000601a6000878581518110614156576141566158c1565b60209081029190910181015182528181019290925260409081016000208151808301909252805482526001015460ff161515918101829052915061419a57506141d5565b8051600090815260196020526040902060040180546001600160a01b0319166001600160a01b038916179055816141d081615abd565b925050505b816141df81615abd565b925050614113565b6001600160a01b03871615614224576001600160a01b0387166000908152601b60205260408120805483929061421e908490615927565b90915550505b6001600160a01b03861615614261576001600160a01b0386166000908152601b60205260408120805483929061425b908490615a6f565b90915550505b613293565b6001600160a01b0384163b156130d15760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906142aa9089908990889088908890600401615ca5565b6020604051808303816000875af19250505080156142e5575060408051601f3d908101601f191682019092526142e291810190615d03565b60015b614391576142f1615d20565b806308c379a00361432a5750614305615d3c565b80614310575061432c565b8060405162461bcd60e51b8152600401610d66919061537f565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610d66565b6001600160e01b0319811663bc197c8160e01b14613e545760405162461bcd60e51b8152600401610d6690615dc5565b606060006143d0836002615a2e565b6143db906002615a6f565b6001600160401b038111156143f2576143f26153cd565b6040519080825280601f01601f19166020018201604052801561441c576020820181803683370190505b509050600360fc1b81600081518110614437576144376158c1565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110614466576144666158c1565b60200101906001600160f81b031916908160001a905350600061448a846002615a2e565b614495906001615a6f565b90505b600181111561450d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106144c9576144c96158c1565b1a60f81b8282815181106144df576144df6158c1565b60200101906001600160f81b031916908160001a90535060049490941c9361450681615e0d565b9050614498565b508315611be75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610d66565b600080600061456a60185490565b90505b8082101561463e576000828152601a60209081526040918290208251808401909352805483526001015460ff1615159082018190526145ac5750614633565b8051600090815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282018390526002810154606083015260038101546080830152600401546001600160a01b031660a082015290869003614630576020015160ff1660021495945050505050565b50505b60019091019061456d565b5050919050565b61464f8282611e24565b156110635760008281526003602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000611be7836001600160a01b038416614e59565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561472a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061474e9190615a87565b90506147856001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016853086614f4c565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156147ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148109190615a87565b90508181101561483657601160405163076cbf6360e11b8152600401610d669190615ad6565b61119e8282615927565b60008043601654146148685760086040516342a8a55b60e01b8152600401610d669190615ad6565b61487233846146c1565b9050806012546148829190615a6f565b91506012548210156148c25760405163c83ad1cd60e01b81526020600482015260086024820152676f766572666c6f7760c01b6044820152606401610d66565b601282905560408051338152602081018390529081018390527fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc59060600160405180910390a1505050565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd9061495d90309086908690600401615b1b565b600060405180830381600087803b15801561497757600080fd5b505af11580156130d1573d6000803e3d6000fd5b60008260000182815481106149a2576149a26158c1565b9060005260206000200154905092915050565b6040516001600160a01b0383166024820152604481018290526112ff90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614f6d565b6001600160a01b038416614a785760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610d66565b33614a8981600087613d6788614d03565b6000848152602081815260408083206001600160a01b038916845290915281208054859290614ab9908490615a6f565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461142181600087878787614d4e565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd9061495d90859030908690600401615b1b565b6000614b7460185490565b600084815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281018390526001820154938101939093526002810154606084015260038101546080840152600401546001600160a01b031660a08301529192509015614bf357805163ffffffff169150614c0b565b614c01601880546001019055565b63ffffffff821681525b604081018490526060810183905260026020820152614c2861243d565b608082019081526001600160a01b0386811660a08401908152600087815260196020908152604080832087518154848a015163ffffffff90921664ffffffffff1990911617600160201b60ff909216919091021781558188015160018083019190915560608901516002830155965160038201559351600490940180546001600160a01b031916949095169390931790935581518083018352888152808401858152878352601a85528383209151825551908501805460ff191691151591909117905581519283019091528152611421918791859190614a18565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110614d3d57614d3d6158c1565b602090810291909101015292915050565b6001600160a01b0384163b156130d15760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190614d929089908990889088908890600401615e24565b6020604051808303816000875af1925050508015614dcd575060408051601f3d908101601f19168201909252614dca91810190615d03565b60015b614dd9576142f1615d20565b6001600160e01b0319811663f23a6e6160e01b14613e545760405162461bcd60e51b8152600401610d6690615dc5565b60006001600160e01b03198216636cdb3d1360e11b1480614e3a57506001600160e01b031982166303a24d0760e21b145b80610d9257506301ffc9a760e01b6001600160e01b0319831614610d92565b60008181526001830160205260408120548015614f42576000614e7d600183615927565b8554909150600090614e9190600190615927565b9050818114614ef6576000866000018281548110614eb157614eb16158c1565b9060005260206000200154905080876000018481548110614ed457614ed46158c1565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614f0757614f07615e5e565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d92565b6000915050610d92565b613b4a846323b872dd60e01b8585856040516024016149e193929190615b1b565b6000614fc2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661503f9092919063ffffffff16565b8051909150156112ff5780806020019051810190614fe09190615aa0565b6112ff5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610d66565b606061504e8484600085615056565b949350505050565b6060824710156150b75760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610d66565b843b6151055760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d66565b600080866001600160a01b031685876040516151219190615e74565b60006040518083038185875af1925050503d806000811461515e576040519150601f19603f3d011682016040523d82523d6000602084013e615163565b606091505b509150915061517382828661517e565b979650505050505050565b6060831561518d575081611be7565b82511561519d5782518084602001fd5b8160405162461bcd60e51b8152600401610d66919061537f565b6040518060c00160405280600063ffffffff168152602001600060ff16815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b6001600160a01b038116811461138e57600080fd5b6000806040838503121561522757600080fd5b8235615232816151ff565b946020939093013593505050565b60006020828403121561525257600080fd5b8135611be7816151ff565b6001600160e01b03198116811461138e57600080fd5b60006020828403121561528557600080fd5b8135611be78161525d565b805163ffffffff16825260208082015160ff169083015260408082015190830152606080820151908301526080808201519083015260a0908101516001600160a01b0316910152565b6020808252825182820181905260009190848201906040850190845b8181101561531b57615308838551615290565b9284019260c092909201916001016152f5565b50909695505050505050565b60005b8381101561534257818101518382015260200161532a565b83811115613b4a5750506000910152565b6000815180845261536b816020860160208601615327565b601f01601f19169290920160200192915050565b602081526000611be76020830184615353565b6000602082840312156153a457600080fd5b5035919050565b600080604083850312156153be57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715615408576154086153cd565b6040525050565b600082601f83011261542057600080fd5b81356001600160401b03811115615439576154396153cd565b604051615450601f8301601f1916602001826153e3565b81815284602083860101111561546557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561549857600080fd5b84356154a3816151ff565b935060208501356154b3816151ff565b92506040850135915060608501356001600160401b038111156154d557600080fd5b6154e18782880161540f565b91505092959194509250565b60006001600160401b03821115615506576155066153cd565b5060051b60200190565b600082601f83011261552157600080fd5b8135602061552e826154ed565b60405161553b82826153e3565b83815260059390931b850182019282810191508684111561555b57600080fd5b8286015b84811015615576578035835291830191830161555f565b509695505050505050565b600080600080600060a0868803121561559957600080fd5b85356155a4816151ff565b945060208601356155b4816151ff565b935060408601356001600160401b03808211156155d057600080fd5b6155dc89838a01615510565b945060608801359150808211156155f257600080fd5b6155fe89838a01615510565b9350608088013591508082111561561457600080fd5b506156218882890161540f565b9150509295509295909350565b6000806040838503121561564157600080fd5b823591506020830135615653816151ff565b809150509250929050565b6000806040838503121561567157600080fd5b82356001600160401b038082111561568857600080fd5b818501915085601f83011261569c57600080fd5b813560206156a9826154ed565b6040516156b682826153e3565b83815260059390931b85018201928281019150898411156156d657600080fd5b948201945b838610156156fd5785356156ee816151ff565b825294820194908201906156db565b9650508601359250508082111561571357600080fd5b5061572085828601615510565b9150509250929050565b600081518084526020808501945080840160005b8381101561575a5781518752958201959082019060010161573e565b509495945050505050565b602081526000611be7602083018461572a565b60c08101610d928284615290565b60006020828403121561579857600080fd5b81356001600160401b038111156157ae57600080fd5b61504e84828501615510565b801515811461138e57600080fd5b600080604083850312156157db57600080fd5b82356157e6816151ff565b91506020830135615653816157ba565b60008060006060848603121561580b57600080fd5b8335615816816151ff565b95602085013595506040909401359392505050565b6000806040838503121561583e57600080fd5b8235615849816151ff565b91506020830135615653816151ff565b600080600080600060a0868803121561587157600080fd5b853561587c816151ff565b9450602086013561588c816151ff565b9350604086013592506060860135915060808601356001600160401b038111156158b557600080fd5b6156218882890161540f565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806158eb57607f821691505b60208210810361590b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008282101561593957615939615911565b500390565b600181815b8085111561597957816000190482111561595f5761595f615911565b8085161561596c57918102915b93841c9390800290615943565b509250929050565b60008261599057506001610d92565b8161599d57506000610d92565b81600181146159b357600281146159bd576159d9565b6001915050610d92565b60ff8411156159ce576159ce615911565b50506001821b610d92565b5060208310610133831016604e8410600b84101617156159fc575081810a610d92565b615a06838361593e565b8060001904821115615a1a57615a1a615911565b029392505050565b6000611be78383615981565b6000816000190483118215151615615a4857615a48615911565b500290565b600082615a6a57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115615a8257615a82615911565b500190565b600060208284031215615a9957600080fd5b5051919050565b600060208284031215615ab257600080fd5b8151611be7816157ba565b600060018201615acf57615acf615911565b5060010190565b6020810160178310615af857634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215615b1057600080fd5b8151611be7816151ff565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b604081526000615be1604083018561572a565b828103602084015261119e818561572a565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351615c2b816017850160208801615327565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351615c5c816028840160208801615327565b01602801949350505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615c9b90830184615353565b9695505050505050565b6001600160a01b0386811682528516602082015260a060408201819052600090615cd19083018661572a565b8281036060840152615ce3818661572a565b90508281036080840152615cf78185615353565b98975050505050505050565b600060208284031215615d1557600080fd5b8151611be78161525d565b600060033d1115615d395760046000803e5060005160e01c5b90565b600060443d1015615d4a5790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615d7957505050505090565b8285019150815181811115615d915750505050505090565b843d8701016020828501011115615dab5750505050505090565b615dba602082860101876153e3565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b600081615e1c57615e1c615911565b506000190190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061517390830184615353565b634e487b7160e01b600052603160045260246000fd5b60008251615e86818460208701615327565b919091019291505056fea2646970667358221220860fd6cefccce07dc2ed46f2f29ff78de60186446c2926c721dca4d5225ae2d964736f6c634300080d0033000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf1618700000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf0369000000000000000000000000204d14f8ec875965e623a04a8928b92934ce814300000000000000000000000005365bb2695d531dae858eb49e8199962ba109290000000000000000000000008ba45a0d9a3af55b329d5601139b56782035e59200000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000e87da2a471732b6f82edbf71e740ed8112d00fd2000000000000000000000000e87da2a471732b6f82edbf71e740ed8112d00fd2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106105035760003560e01c80637dcc491911610299578063c2ead8b911610167578063db006a75116100d9578063ee27a2f211610092578063ee27a2f214610c90578063f242432a14610c9d578063f3fdb15a14610cb0578063f42c2b0414610cc3578063f8f9da2814610ce3578063fca7820b14610ceb57600080fd5b8063db006a7514610bfe578063de30b99714610c11578063e651cb9b14610c24578063e76241c014610c37578063e985e9c514610c4a578063eb08ab2814610c8657600080fd5b8063c8229b6c1161012b578063c8229b6c14610b9f578063c9a04e6a14610bb2578063ca15c87314610bc5578063cac4e657146105e1578063cf9d206114610bd8578063d547741f14610beb57600080fd5b8063c2ead8b914610b45578063c37f68e214610b58578063c40ac4a414610b86578063c626ebf514610b8e578063c81faea214610b9757600080fd5b8063a275370d1161020b578063b2016bd4116101c4578063b2016bd414610aca578063b83f823614610af1578063b9f5be4114610b04578063ba6275ec14610b17578063bad4a01f14610b2a578063bd6d894d14610b3d57600080fd5b8063a275370d14610a5b578063a67fb2ce14610a6a578063a6afed9514610a7d578063a7b820df14610a85578063a81c043514610a98578063ae65d23114610aa157600080fd5b80639010d07c1161025d5780639010d07c146109e357806391d14854146109f657806391dd36c614610a0957806395d89b4114610a1c578063a217fddf14610a40578063a22cb46514610a4857600080fd5b80637dcc4919146109a257806385ded19d146109b55780638d02d9a1146109be5780638df61fcb146109c75780638f840ddd146109da57600080fd5b806334613dab116103d65780634ef286e41161034857806361feacff1161030157806361feacff1461094e5780636236e030146109575780636882510b146109605780636c540baf1461097357806370a5f9821461097c5780637265deae1461098f57600080fd5b80634ef286e4146108b25780634f38d235146108d257806354cc4a78146108f257806354fd4d5014610905578063601a0bf1146109285780636112fe2e1461093b57600080fd5b80633e9410101161039a5780633e941010146108475780634046ebae1461085a57806342fb6ae91461086d57806347bd37181461088057806349dab7f2146108895780634e1273f41461089257600080fd5b806334613dab146107f357806336568abe1461080657806338b0dcce146108195780633943e7b81461082c5780633b1d21a21461083f57600080fd5b8063173b99041161047a5780632495a599116104335780632495a599146107155780632e1a7d4d146107545780632eb2c2d6146107675780632f2ff15d1461077a578063313ce5671461078d57806333483f8f146107b457600080fd5b8063173b990414610628578063182df0f5146106315780631be19560146106395780631c2540c51461064c5780631fb997621461065f578063248a9ca3146106f257600080fd5b80630b2c8f9c116104cc5780630b2c8f9c146105b25780630e89341c146105bb5780630ecbcdab146105ce5780631320eb4c146105e157806314a6bf0f146105e9578063150b7a02146105f157600080fd5b8062fdd58e14610508578063010e53181461052e57806301ffc9a714610543578063045e18ae1461056657806306fdde031461057b575b600080fd5b61051b610516366004615214565b610cfe565b6040519081526020015b60405180910390f35b61054161053c366004615240565b610d98565b005b610556610551366004615273565b610e21565b6040519015158152602001610525565b61056e610e5c565b60405161052591906152d9565b6105a56040518060400160405280600b81526020016a12115490cc8c0815195cdd60aa1b81525081565b604051610525919061537f565b61051b60085481565b6105a56105c9366004615392565b610fc5565b6105416105dc3660046153ab565b611059565b61051b611067565b61051b61109d565b61060f6105ff366004615482565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610525565b61051b60065481565b61051b611103565b610541610647366004615240565b6111a7565b61054161065a366004615240565b611304565b6106b361066d366004615392565b6019602052600090815260409020805460018201546002830154600384015460049094015463ffffffff841694600160201b90940460ff1693906001600160a01b031686565b6040805163ffffffff909716875260ff909516602087015293850192909252606084015260808301526001600160a01b031660a082015260c001610525565b61051b610700366004615392565b60009081526003602052604090206001015490565b61073c7f000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf1618781565b6040516001600160a01b039091168152602001610525565b610541610762366004615392565b611385565b610541610775366004615581565b611391565b61054161078836600461562e565b611428565b61051b7f000000000000000000000000000000000000000000000000000000000000001281565b6107de6107c2366004615392565b601a602052600090815260409020805460019091015460ff1682565b60408051928352901515602083015201610525565b610541610801366004615392565b61144e565b61054161081436600461562e565b611457565b6105416108273660046153ab565b6114d1565b61051b61083a366004615392565b6114dc565b61051b611638565b610541610855366004615392565b611642565b600e5461073c906001600160a01b031681565b600f5461073c906001600160a01b031681565b61051b60115481565b61051b60135481565b6108a56108a036600461565e565b61164b565b6040516105259190615765565b61051b6108c0366004615240565b601c6020526000908152604090205481565b6108e56108e0366004615392565b611774565b6040516105259190615778565b600b5461073c906001600160a01b031681565b6105a56040518060400160405280600481526020016376302e3160e01b81525081565b610541610936366004615392565b6117ea565b610541610949366004615392565b611822565b61051b60155481565b61051b60095481565b61054161096e366004615240565b61182b565b61051b60165481565b61051b61098a366004615786565b6118d3565b61051b61099d366004615392565b611b68565b6105416109b0366004615240565b611bee565b61051b60175481565b61051b60075481565b61056e6109d5366004615240565b611c96565b61051b60125481565b61073c6109f13660046153ab565b611e0c565b610556610a0436600461562e565b611e24565b610541610a17366004615392565b611e4f565b6105a5604051806040016040528060058152602001641a151154d560da1b81525081565b61051b600081565b610541610a563660046157c8565b611e87565b61051b670de0b6b3a764000081565b61051b610a78366004615392565b611e92565b610541611e9d565b610541610a93366004615392565b6120dc565b61051b60145481565b61051b610aaf366004615240565b6001600160a01b03166000908152601b602052604090205490565b61073c7f00000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf036981565b610556610aff366004615214565b6121e7565b610541610b12366004615392565b61227e565b600c5461073c906001600160a01b031681565b610541610b38366004615392565b612287565b61051b612290565b6108a5610b53366004615240565b6122a2565b610b6b610b66366004615240565b6123ff565b60408051938452602084019290925290820152606001610525565b610556600181565b61051b600a5481565b61051b61243d565b610541610bad366004615214565b6125a9565b61051b610bc0366004615240565b612693565b61051b610bd3366004615392565b6126c4565b610541610be6366004615392565b6126db565b610541610bf936600461562e565b612769565b610541610c0c366004615392565b61278f565b610541610c1f366004615392565b612798565b610541610c32366004615392565b6127d0565b610541610c453660046157f6565b6128d4565b610556610c5836600461582b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b60185461051b9081565b61051b65048c2739500081565b610541610cab366004615859565b6128df565b60105461073c906001600160a01b031681565b61051b610cd1366004615240565b601b6020526000908152604090205481565b61051b612966565b610541610cf9366004615392565b6129f6565b60006001600160a01b038316610d6f5760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084015b60405180910390fd5b506000818152602081815260408083206001600160a01b03861684529091529020545b92915050565b610da3600033611e24565b610dbf576040516282b42960e81b815260040160405180910390fd5b600f80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f17d26dfc8576ef7a5cb27121d1a3845a0b5dea7763c991e76cd2f7c3a612a3d391015b60405180910390a15050565b60006001600160e01b03198216636cdb3d1360e11b1480610e5257506001600160e01b03198216630b7f5a3560e31b145b50610d9282612ad2565b60606000610e6960185490565b90506000805b82811015610ea0576000818152601a602052604090206001015460ff1615610e98578160010191505b600101610e6f565b506000816001600160401b03811115610ebb57610ebb6153cd565b604051908082528060200260200182016040528015610ef457816020015b610ee16151b7565b815260200190600190039081610ed95790505b50935060005b83821015610fbe576000828152601a602052604090206001015460ff1615610fb3576000828152601a602090815260408083205483526019825291829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b031660a08201528551869083908110610fa457610fa46158c1565b60209081029190910101526001015b600190910190610efa565b5050505090565b606060028054610fd4906158d7565b80601f0160208091040260200160405190810160405280929190818152602001828054611000906158d7565b801561104d5780601f106110225761010080835404028352916020019161104d565b820191906000526020600020905b81548152906001019060200180831161103057829003601f168201915b50505050509050919050565b6110638282612af7565b5050565b600060145460155460125461107a612dde565b6110849190615927565b61108e9190615927565b6110989190615927565b905090565b60006110ca7f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b6017546110d561243d565b6110df9190615927565b6011546110ec9190615a2e565b6110f69190615a4d565b6011546110989190615a6f565b60135460009080820361111857505060055490565b6000611122612dde565b905060006015546014546012546111399190615a6f565b6111439190615a6f565b6011546111509084615a6f565b61115a9190615927565b905060008361118a7f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b6111949084615a2e565b61119e9190615a4d565b95945050505050565b6111b2600033611e24565b15806111ef57507f000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf161876001600160a01b0316816001600160a01b0316145b1561120c576040516282b42960e81b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611253573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112779190615a87565b60405163a9059cbb60e01b8152739adbd648cb2238b72b05f3e488c6a75f8f1866206004820152602481018290529091506001600160a01b0383169063a9059cbb906044016020604051808303816000875af11580156112db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ff9190615aa0565b505050565b61130f600033611e24565b61132b576040516282b42960e81b815260040160405180910390fd5b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f44f518b033497d0698cc6bffcddfac36c78ff249b688c40ef1ed72943e11efbd9101610e15565b61138e81612e2d565b50565b6001600160a01b0385163314806113ad57506113ad8533610c58565b6114145760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610d66565b6114218585858585612eee565b5050505050565b60008281526003602052604090206001015461144481336130d9565b6112ff838361313d565b61138e8161315f565b6001600160a01b03811633146114c75760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610d66565b611063828261329d565b6110633383836132bf565b6016546000904390808211156114fd576114f461243d565b60175560168290555b6000611508856135ad565b9050806011600082825461151c9190615a6f565b9091555061154d90507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b8160065461155b9190615a2e565b6115659190615a4d565b601260008282546115769190615a6f565b909155506115a790507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b816008546115b59190615a2e565b6115bf9190615a4d565b601460008282546115d09190615a6f565b9091555061160190507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b8160075461160f9190615a2e565b6116199190615a4d565b6015600082825461162a9190615a6f565b909155509095945050505050565b6000611098612dde565b61138e8161371d565b606081518351146116b05760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610d66565b600083516001600160401b038111156116cb576116cb6153cd565b6040519080825280602002602001820160405280156116f4578160200160208202803683370190505b50905060005b845181101561176c5761173f858281518110611718576117186158c1565b6020026020010151858381518110611732576117326158c1565b6020026020010151610cfe565b828281518110611751576117516158c1565b602090810291909101015261176581615abd565b90506116fa565b509392505050565b61177c6151b7565b50600090815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b031660a082015290565b6117f5600033611e24565b611811576040516282b42960e81b815260040160405180910390fd5b611819611e9d565b61138e81613755565b61138e8161382d565b611836600033611e24565b611852576040516282b42960e81b815260040160405180910390fd5b6001600160a01b03811661187957604051635863f78960e01b815260040160405180910390fd5b600c80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f1f671b7f960ea754837d8752ef9b7d5748146fb4ddd41c167f257825341033809101610e15565b6016546000904390808211156118f4576118eb61243d565b60175560168290555b83516001906000905b808311611a38576000601a600089868151811061191c5761191c6158c1565b60209081029190910181015182528181019290925260409081016000208151808301909252805482526001015460ff16151591810182905291506119605750611a26565b6000601960008a8781518110611978576119786158c1565b6020908102919091018101518252818101929092526040908101600020815160c081018352815463ffffffff81168252600160201b900460ff169381018490526001820154928101929092526002810154606083015260038101546080830152600401546001600160a01b031660a0820152915060011901611a2357611a16898681518110611a0957611a096158c1565b60200260200101516135ad565b611a209085615a6f565b93505b50505b82611a3081615abd565b9350506118fd565b8160116000828254611a4a9190615a6f565b90915550611a7b90507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b82600654611a899190615a2e565b611a939190615a4d565b60126000828254611aa49190615a6f565b90915550611ad590507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b82600854611ae39190615a2e565b611aed9190615a4d565b60146000828254611afe9190615a6f565b90915550611b2f90507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b82600754611b3d9190615a2e565b611b479190615a4d565b60156000828254611b589190615a6f565b9091555091979650505050505050565b600081815260196020526040812060020154611ba57f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b600084815260196020526040902060030154611bbf61243d565b611bc99190615927565b611bd39083615a2e565b611bdd9190615a4d565b611be79082615a6f565b9392505050565b611bf9600033611e24565b611c15576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116611c3c57604051635863f78960e01b815260040160405180910390fd5b600b80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fdb492e3d5a171bd9d50e48753e6cc996c55a940a523e0b6f9775bb6613e357fd9101610e15565b6001600160a01b0381166000908152601b6020526040812054606091906001600160401b03811115611cca57611cca6153cd565b604051908082528060200260200182016040528015611d0357816020015b611cf06151b7565b815260200190600190039081611ce85790505b509050600080611d1260185490565b905060005b81831015611e02576000838152601a60209081526040918290208251808401909352805483526001015460ff161515908201819052611d565750611df7565b8051600090815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b0390811660a083018190529089169003611df45780868480600101955081518110611de857611de86158c1565b60200260200101819052505b50505b600190920191611d17565b5091949350505050565b6000828152600460205260408120611be790836138e7565b60009182526003602090815260408084206001600160a01b0393909316845291905290205460ff1690565b611e5a600033611e24565b611e76576040516282b42960e81b815260040160405180910390fd5b611e7e611e9d565b61138e816138f3565b6110633383836139c6565b6000610d9282611b68565b601654439080821115611ebb57611eb261243d565b60175560168290555b6000600181611ec960185490565b90505b808211611f6b57600082815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281018390526001820154938101939093526002810154606084015260038101546080840152600401546001600160a01b031660a083015260011901611f5857611f4b836135ad565b611f559085615a6f565b93505b5081611f6381615abd565b925050611ecc565b8260116000828254611f7d9190615a6f565b90915550611fae90507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b83600654611fbc9190615a2e565b611fc69190615a4d565b60126000828254611fd79190615a6f565b9091555061200890507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b836008546120169190615a2e565b6120209190615a4d565b601460008282546120319190615a6f565b9091555061206290507f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b836007546120709190615a2e565b61207a9190615a4d565b6015600082825461208b9190615a6f565b90915550506017546011546040805186815260208101939093528201527f875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb99060600160405180910390a15050505050565b6120e7600033611e24565b612103576040516282b42960e81b815260040160405180910390fd5b61210b611e9d565b43601654146121305760086040516342a8a55b60e01b8152600401610d669190615ad6565b8060155410156121565760166040516342a8a55b60e01b8152600401610d669190615ad6565b601554612161612dde565b10156121835760136040516342a8a55b60e01b8152600401610d669190615ad6565b80601560008282546121959190615927565b9091555050600b546121b0906001600160a01b031682613aa6565b6040518181527ff02de49094a433b4b58fb50395a7aa7110f62486c358e7a8fcc2e013684b2b50906020015b60405180910390a150565b6000818152601960209081526040808320815160c081018352815463ffffffff81168252600160201b900460ff16938101939093526001810154918301919091526002810154606083015260038101546080830152600401546001600160a01b0390811660a0830181905290851614612272576040516282b42960e81b815260040160405180910390fd5b60600151159392505050565b61138e81613ada565b61138e81613b50565b600061229a611e9d565b611098611103565b6001600160a01b0381166000908152601b6020526040812054606091906001600160401b038111156122d6576122d66153cd565b6040519080825280602002602001820160405280156122ff578160200160208202803683370190505b50905060008061230e60185490565b905060005b81831015611e02576000838152601a60209081526040918290208251808401909352805483526001015460ff16151590820181905261235257506123f4565b8051600090815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b0390811660a0830181905290891690036123f157848684806001019550815181106123e4576123e46158c1565b6020026020010181815250505b50505b600190920191612313565b600080600061240f846000610cfe565b6001600160a01b0385166000908152601c6020526040902054612430611103565b9250925092509193909250565b6000601154600003612450575060175490565b601654439060006124618284615927565b90506000601454601554612473612dde565b61247d9190615927565b6124879190615927565b6011546012546010546040516315f2405360e01b8152600481018590526024810184905260448101839052939450919290916000916001600160a01b03909116906315f2405390606401602060405180830381865afa1580156124ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125129190615a87565b905065048c2739500081111561253e576014604051635890300f60e01b8152600401610d669190615ad6565b600061254a8683615a2e565b60115490915061257b7f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b6125859083615a2e565b61258f9190615a4d565b60175461259c9190615a6f565b9850505050505050505090565b600e546001600160a01b031633146125d3576040516282b42960e81b815260040160405180910390fd5b6125dc816114dc565b50600081815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b0390811660a083018190529084161461266b576040516282b42960e81b815260040160405180910390fd5b61267a838260600151846132bf565b6112ff838260400151836000015163ffffffff16613b66565b600061269d611103565b6126a8836000610cfe565b6126ba90670de0b6b3a7640000615a2e565b610d929190615a4d565b6000818152600460205260408120610d9290613bac565b6126e6600033611e24565b612702576040516282b42960e81b815260040160405180910390fd5b670de0b6b3a764000081111561272b57604051635863f78960e01b815260040160405180910390fd5b600980549082905560408051828152602081018490527fe091c76fcf70119c7721979bfbf8b7113ae93b7665ef11819c87e34de28019159101610e15565b60008281526003602052604090206001015461278581336130d9565b6112ff838361329d565b61138e81613bb6565b6127a3600033611e24565b6127bf576040516282b42960e81b815260040160405180910390fd5b6127c7611e9d565b61138e81613c77565b6127db600033611e24565b6127f7576040516282b42960e81b815260040160405180910390fd5b6127ff611e9d565b43601654146128245760086040516342a8a55b60e01b8152600401610d669190615ad6565b80601454101561284a5760166040516342a8a55b60e01b8152600401610d669190615ad6565b601454612855612dde565b10156128775760136040516342a8a55b60e01b8152600401610d669190615ad6565b80601460008282546128899190615927565b9091555050600c546128a4906001600160a01b031682613aa6565b6040518181527f9b784bc629cf280321a09661d7270771a0f5814811f7145a1f0ae079a1ead479906020016121dc565b6112ff8383836132bf565b6001600160a01b0385163314806128fb57506128fb8533610c58565b6129595760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610d66565b6114218585858585613d31565b6010546000906001600160a01b03166315f24053612982612dde565b6011546012546040516001600160e01b031960e086901b1681526004810193909352602483019190915260448201526064015b602060405180830381865afa1580156129d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110989190615a87565b612a01600033611e24565b612a1d576040516282b42960e81b815260040160405180910390fd5b612a25611e9d565b61138e81613e5d565b80546001019055565b612a418282611e24565b6110635760008281526003602090815260408083206001600160a01b03851684529091529020805460ff19166001179055612a793390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000611be7836001600160a01b038416613f08565b60006001600160e01b03198216635a05180f60e01b1480610d925750610d9282613f57565b60008181526019602052604090208054600160201b900460ff16612b3157601260405163076cbf6360e11b8152600401610d669190615ad6565b81816001015414612b5557604051635863f78960e01b815260040160405180910390fd5b60048101546001600160a01b03163314612b82576040516330cd747160e01b815260040160405180910390fd5b6040516331a9108f60e11b81526004810183905230906001600160a01b037f00000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf03691690636352211e90602401602060405180830381865afa158015612be9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0d9190615afe565b6001600160a01b031614612c34576040516330cd747160e01b815260040160405180910390fd5b600f5460405163385b9a3d60e01b81523060048201523360248201526001600160a01b037f00000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf03698116604483015260648201859052608482018690529091169063385b9a3d9060a401600060405180830381600087803b158015612cb557600080fd5b505af1158015612cc9573d6000803e3d6000fd5b50505050612cd6826114dc565b50612d027f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b600954612d0f9085615a2e565b612d199190615a4d565b612d239084615a6f565b925082816002016000828254612d399190615a6f565b925050819055508260116000828254612d529190615a6f565b909155505060048101546001600160a01b03166000908152601c602052604081208054859290612d83908490615a6f565b9091555050600281015460408051338152602081018690528082018590526060810192909252517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809181900360800190a16112ff3384613aa6565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf161876001600160a01b0316906370a08231906024016129b5565b600f5460405163eabe7d9160e01b81526001600160a01b039091169063eabe7d9190612e6190309033908690600401615b1b565b600060405180830381600087803b158015612e7b57600080fd5b505af1158015612e8f573d6000803e3d6000fd5b505050506000612e9d612290565b9050600081612eb484670de0b6b3a7640000615a2e565b612ebe9190615a4d565b90508060136000828254612ed29190615927565b90915550612ee4905033600083613f7c565b6112ff3384613aa6565b8151835114612f505760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610d66565b6001600160a01b038416612f765760405162461bcd60e51b8152600401610d6690615b3f565b33612f858187878787876140f5565b60005b845181101561306b576000858281518110612fa557612fa56158c1565b602002602001015190506000858381518110612fc357612fc36158c1565b602090810291909101810151600084815280835260408082206001600160a01b038e1683529093529190912054909150818110156130135760405162461bcd60e51b8152600401610d6690615b84565b6000838152602081815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290613050908490615a6f565b925050819055505050508061306490615abd565b9050612f88565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516130bb929190615bce565b60405180910390a46130d1818787878787614266565b505050505050565b6130e38282611e24565b611063576130fb816001600160a01b031660146143c1565b6131068360206143c1565b604051602001613117929190615bf3565b60408051601f198184030181529082905262461bcd60e51b8252610d669160040161537f565b6131478282612a37565b60008281526004602052604090206112ff9082612abd565b6131688161455c565b61318857600e60405163076cbf6360e11b8152600401610d669190615ad6565b6000818152601960209081526040808320815160c081018352815463ffffffff8116808352600160201b90910460ff168286015260018301548285015260028301546060830152600383015460808301526004909201546001600160a01b031660a08201528251309481019490945293909290910160408051601f1981840301815290829052600e54635c46a7ef60e11b83529092506001600160a01b037f00000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf036981169263b88d4fde9261326592309291169087908790600401615c68565b600060405180830381600087803b15801561327f57600080fd5b505af1158015613293573d6000803e3d6000fd5b5050505050505050565b6132a78282614645565b60008281526004602052604090206112ff90826146ac565b816000036132e357600b60405163076cbf6360e11b8152600401610d669190615ad6565b6132ec816114dc565b50600f5460405163e09aeafb60e01b8152306004820152602481018490526001600160a01b037f00000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf036981166044830152606482018490529091169063e09aeafb90608401600060405180830381600087803b15801561336857600080fd5b505af115801561337c573d6000803e3d6000fd5b505050600082815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282019290925260028201546060820152600382015460808201526004909101546001600160a01b0390811660a0830181905291925085161461340f576040516282b42960e81b815260040160405180910390fd5b8181604001511461343357604051635863f78960e01b815260040160405180910390fd5b6060810151600081900361345d57600c60405163076cbf6360e11b8152600401610d669190615ad6565b600081851161346c578461346e565b815b9050600061347c33836146c1565b90506134888184615927565b6060850152601180548291906000906134a2908490615927565b909155505060a08401516001600160a01b03166000908152601c6020526040812080548392906134d3908490615927565b9091555050604084810180516000908152601960209081529083902087518154838a015160ff16600160201b0264ffffffffff1990911663ffffffff90921691909117178155915160018301556060808801516002840155608080890151600385015560a0890151600490940180546001600160a01b039095166001600160a01b0319909516949094179093556011548451868152928301889052828501528101889052915133927ffa8bc83f8aead8e5153719deeddbef9e743a3477190ebd49f3778f389489108f92908290030190a250505050505050565b600081815260196020526040812060028101546003820154836135f17f0000000000000000000000000000000000000000000000000000000000000012600a615a22565b84600301546017546136039190615927565b61360d9085615a2e565b6136179190615a4d565b90508084600201600082825461362d9190615a6f565b9091555050601754600385015560048401546001600160a01b03166000908152601c602052604081208054839290613666908490615a6f565b90915550506000868152601960209081526040918290206017548351825463ffffffff8116825260ff90851c169381019390935260018201548385015260028201546060840152600382015460808401526004909101546001600160a01b031660a083015260c0820186905260e08201849052610100820185905261012082015290517fbec6833599c650e2c7c5ee344dae8b58d4a07bdbd6a096e9172b8c67c4e9d1f6918190036101400190a195945050505050565b613728600033611e24565b613744576040516282b42960e81b815260040160405180910390fd5b61374c611e9d565b61138e81614840565b6000436016541461377c5760086040516342a8a55b60e01b8152600401610d669190615ad6565b81613785612dde565b10156137a75760136040516342a8a55b60e01b8152600401610d669190615ad6565b6012548211156137cd57600a6040516342a8a55b60e01b8152600401610d669190615ad6565b81601260008282546137df9190615927565b909155506137ef90503383613aa6565b60408051338152602081018490529081018290527f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e90606001610e15565b600081815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282018390526002810154606083015260038101546080830152600401546001600160a01b031660a0820152906138a09033906121e7565b6138c057600f60405163076cbf6360e11b8152600401610d669190615ad6565b6138d9338260400151836000015163ffffffff16613b66565b61106333826040015161490d565b6000611be7838361498b565b43601654146139185760086040516342a8a55b60e01b8152600401610d669190615ad6565b600019810361392657506007545b600a546008548260065461393a9190615a6f565b6139449190615a6f565b111561396657600a6040516342a8a55b60e01b8152600401610d669190615ad6565b80600754146139ad57600780549082905560408051828152602081018490527fcdd0b588250e1398549f79cfdb8217c186688822905d6715b0834ea1c865594a9101610e15565b604051635863f78960e01b815260040160405180910390fd5b816001600160a01b0316836001600160a01b031603613a395760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610d66565b6001600160a01b03838116600081815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6110636001600160a01b037f000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf161871683836149b5565b6000613ae4612290565b90506000613af233846146c1565b9050600082613b0983670de0b6b3a7640000615a2e565b613b139190615a4d565b90508060136000828254613b279190615a6f565b92505081905550613b4a3360008360405180602001604052806000815250614a18565b50505050565b613b5a3382614b19565b61138e33826000614b69565b613b7283826001613f7c565b6000918252601960209081526040808420805464ff000000001916600160201b179055918352601a90529020600101805460ff1916905550565b6000610d92825490565b600f5460405163eabe7d9160e01b81526001600160a01b039091169063eabe7d9190613bea90309033908690600401615b1b565b600060405180830381600087803b158015613c0457600080fd5b505af1158015613c18573d6000803e3d6000fd5b505050506000613c26612290565b90508160136000828254613c3a9190615927565b90915550613c4c905033600084613f7c565b6000670de0b6b3a7640000613c618385615a2e565b613c6b9190615a4d565b90506112ff3382613aa6565b4360165414613c9c5760086040516342a8a55b60e01b8152600401610d669190615ad6565b6000198103613caa57506008545b600a5481600754600654613cbe9190615a6f565b613cc89190615a6f565b1115613cea57600a6040516342a8a55b60e01b8152600401610d669190615ad6565b80600854146139ad57600880549082905560408051828152602081018490527f0572c4d8f505651be671d8c8610d5c981e409e48a4463af0bcee12b843ebd4d29101610e15565b6001600160a01b038416613d575760405162461bcd60e51b8152600401610d6690615b3f565b33613d76818787613d6788614d03565b613d7088614d03565b876140f5565b6000848152602081815260408083206001600160a01b038a16845290915290205483811015613db75760405162461bcd60e51b8152600401610d6690615b84565b6000858152602081815260408083206001600160a01b038b8116855292528083208785039055908816825281208054869290613df4908490615a6f565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613e54828888888888614d4e565b50505050505050565b4360165414613e825760086040516342a8a55b60e01b8152600401610d669190615ad6565b600a54600854600754613e959084615a6f565b613e9f9190615a6f565b1115613ec157600a6040516342a8a55b60e01b8152600401610d669190615ad6565b80600654146139ad57600680549082905560408051828152602081018490527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101610e15565b6000818152600183016020526040812054613f4f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d92565b506000610d92565b60006001600160e01b03198216637965db0b60e01b1480610d925750610d9282614e09565b6001600160a01b038316613fde5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b6064820152608401610d66565b3361400d81856000613fef87614d03565b613ff887614d03565b604051806020016040528060008152506140f5565b6000838152602081815260408083206001600160a01b03881684529091529020548281101561408a5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b6064820152608401610d66565b6000848152602081815260408083206001600160a01b03898116808652918452828520888703905582518981529384018890529092908616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b836001600160a01b0316856001600160a01b031603156130d1576000805b84518210156141e7576000858381518110614130576141306158c1565b602002602001015111156141d5576000601a6000878581518110614156576141566158c1565b60209081029190910181015182528181019290925260409081016000208151808301909252805482526001015460ff161515918101829052915061419a57506141d5565b8051600090815260196020526040902060040180546001600160a01b0319166001600160a01b038916179055816141d081615abd565b925050505b816141df81615abd565b925050614113565b6001600160a01b03871615614224576001600160a01b0387166000908152601b60205260408120805483929061421e908490615927565b90915550505b6001600160a01b03861615614261576001600160a01b0386166000908152601b60205260408120805483929061425b908490615a6f565b90915550505b613293565b6001600160a01b0384163b156130d15760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906142aa9089908990889088908890600401615ca5565b6020604051808303816000875af19250505080156142e5575060408051601f3d908101601f191682019092526142e291810190615d03565b60015b614391576142f1615d20565b806308c379a00361432a5750614305615d3c565b80614310575061432c565b8060405162461bcd60e51b8152600401610d66919061537f565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610d66565b6001600160e01b0319811663bc197c8160e01b14613e545760405162461bcd60e51b8152600401610d6690615dc5565b606060006143d0836002615a2e565b6143db906002615a6f565b6001600160401b038111156143f2576143f26153cd565b6040519080825280601f01601f19166020018201604052801561441c576020820181803683370190505b509050600360fc1b81600081518110614437576144376158c1565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110614466576144666158c1565b60200101906001600160f81b031916908160001a905350600061448a846002615a2e565b614495906001615a6f565b90505b600181111561450d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106144c9576144c96158c1565b1a60f81b8282815181106144df576144df6158c1565b60200101906001600160f81b031916908160001a90535060049490941c9361450681615e0d565b9050614498565b508315611be75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610d66565b600080600061456a60185490565b90505b8082101561463e576000828152601a60209081526040918290208251808401909352805483526001015460ff1615159082018190526145ac5750614633565b8051600090815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281019290925260018101549282018390526002810154606083015260038101546080830152600401546001600160a01b031660a082015290869003614630576020015160ff1660021495945050505050565b50505b60019091019061456d565b5050919050565b61464f8282611e24565b156110635760008281526003602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000611be7836001600160a01b038416614e59565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf1618716906370a0823190602401602060405180830381865afa15801561472a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061474e9190615a87565b90506147856001600160a01b037f000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf1618716853086614f4c565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf161876001600160a01b0316906370a0823190602401602060405180830381865afa1580156147ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148109190615a87565b90508181101561483657601160405163076cbf6360e11b8152600401610d669190615ad6565b61119e8282615927565b60008043601654146148685760086040516342a8a55b60e01b8152600401610d669190615ad6565b61487233846146c1565b9050806012546148829190615a6f565b91506012548210156148c25760405163c83ad1cd60e01b81526020600482015260086024820152676f766572666c6f7760c01b6044820152606401610d66565b601282905560408051338152602081018390529081018390527fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc59060600160405180910390a1505050565b6040516323b872dd60e01b81526001600160a01b037f00000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf036916906323b872dd9061495d90309086908690600401615b1b565b600060405180830381600087803b15801561497757600080fd5b505af11580156130d1573d6000803e3d6000fd5b60008260000182815481106149a2576149a26158c1565b9060005260206000200154905092915050565b6040516001600160a01b0383166024820152604481018290526112ff90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614f6d565b6001600160a01b038416614a785760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610d66565b33614a8981600087613d6788614d03565b6000848152602081815260408083206001600160a01b038916845290915281208054859290614ab9908490615a6f565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461142181600087878787614d4e565b6040516323b872dd60e01b81526001600160a01b037f00000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf036916906323b872dd9061495d90859030908690600401615b1b565b6000614b7460185490565b600084815260196020908152604091829020825160c081018452815463ffffffff81168252600160201b900460ff169281018390526001820154938101939093526002810154606084015260038101546080840152600401546001600160a01b031660a08301529192509015614bf357805163ffffffff169150614c0b565b614c01601880546001019055565b63ffffffff821681525b604081018490526060810183905260026020820152614c2861243d565b608082019081526001600160a01b0386811660a08401908152600087815260196020908152604080832087518154848a015163ffffffff90921664ffffffffff1990911617600160201b60ff909216919091021781558188015160018083019190915560608901516002830155965160038201559351600490940180546001600160a01b031916949095169390931790935581518083018352888152808401858152878352601a85528383209151825551908501805460ff191691151591909117905581519283019091528152611421918791859190614a18565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110614d3d57614d3d6158c1565b602090810291909101015292915050565b6001600160a01b0384163b156130d15760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190614d929089908990889088908890600401615e24565b6020604051808303816000875af1925050508015614dcd575060408051601f3d908101601f19168201909252614dca91810190615d03565b60015b614dd9576142f1615d20565b6001600160e01b0319811663f23a6e6160e01b14613e545760405162461bcd60e51b8152600401610d6690615dc5565b60006001600160e01b03198216636cdb3d1360e11b1480614e3a57506001600160e01b031982166303a24d0760e21b145b80610d9257506301ffc9a760e01b6001600160e01b0319831614610d92565b60008181526001830160205260408120548015614f42576000614e7d600183615927565b8554909150600090614e9190600190615927565b9050818114614ef6576000866000018281548110614eb157614eb16158c1565b9060005260206000200154905080876000018481548110614ed457614ed46158c1565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614f0757614f07615e5e565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d92565b6000915050610d92565b613b4a846323b872dd60e01b8585856040516024016149e193929190615b1b565b6000614fc2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661503f9092919063ffffffff16565b8051909150156112ff5780806020019051810190614fe09190615aa0565b6112ff5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610d66565b606061504e8484600085615056565b949350505050565b6060824710156150b75760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610d66565b843b6151055760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d66565b600080866001600160a01b031685876040516151219190615e74565b60006040518083038185875af1925050503d806000811461515e576040519150601f19603f3d011682016040523d82523d6000602084013e615163565b606091505b509150915061517382828661517e565b979650505050505050565b6060831561518d575081611be7565b82511561519d5782518084602001fd5b8160405162461bcd60e51b8152600401610d66919061537f565b6040518060c00160405280600063ffffffff168152602001600060ff16815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b6001600160a01b038116811461138e57600080fd5b6000806040838503121561522757600080fd5b8235615232816151ff565b946020939093013593505050565b60006020828403121561525257600080fd5b8135611be7816151ff565b6001600160e01b03198116811461138e57600080fd5b60006020828403121561528557600080fd5b8135611be78161525d565b805163ffffffff16825260208082015160ff169083015260408082015190830152606080820151908301526080808201519083015260a0908101516001600160a01b0316910152565b6020808252825182820181905260009190848201906040850190845b8181101561531b57615308838551615290565b9284019260c092909201916001016152f5565b50909695505050505050565b60005b8381101561534257818101518382015260200161532a565b83811115613b4a5750506000910152565b6000815180845261536b816020860160208601615327565b601f01601f19169290920160200192915050565b602081526000611be76020830184615353565b6000602082840312156153a457600080fd5b5035919050565b600080604083850312156153be57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715615408576154086153cd565b6040525050565b600082601f83011261542057600080fd5b81356001600160401b03811115615439576154396153cd565b604051615450601f8301601f1916602001826153e3565b81815284602083860101111561546557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561549857600080fd5b84356154a3816151ff565b935060208501356154b3816151ff565b92506040850135915060608501356001600160401b038111156154d557600080fd5b6154e18782880161540f565b91505092959194509250565b60006001600160401b03821115615506576155066153cd565b5060051b60200190565b600082601f83011261552157600080fd5b8135602061552e826154ed565b60405161553b82826153e3565b83815260059390931b850182019282810191508684111561555b57600080fd5b8286015b84811015615576578035835291830191830161555f565b509695505050505050565b600080600080600060a0868803121561559957600080fd5b85356155a4816151ff565b945060208601356155b4816151ff565b935060408601356001600160401b03808211156155d057600080fd5b6155dc89838a01615510565b945060608801359150808211156155f257600080fd5b6155fe89838a01615510565b9350608088013591508082111561561457600080fd5b506156218882890161540f565b9150509295509295909350565b6000806040838503121561564157600080fd5b823591506020830135615653816151ff565b809150509250929050565b6000806040838503121561567157600080fd5b82356001600160401b038082111561568857600080fd5b818501915085601f83011261569c57600080fd5b813560206156a9826154ed565b6040516156b682826153e3565b83815260059390931b85018201928281019150898411156156d657600080fd5b948201945b838610156156fd5785356156ee816151ff565b825294820194908201906156db565b9650508601359250508082111561571357600080fd5b5061572085828601615510565b9150509250929050565b600081518084526020808501945080840160005b8381101561575a5781518752958201959082019060010161573e565b509495945050505050565b602081526000611be7602083018461572a565b60c08101610d928284615290565b60006020828403121561579857600080fd5b81356001600160401b038111156157ae57600080fd5b61504e84828501615510565b801515811461138e57600080fd5b600080604083850312156157db57600080fd5b82356157e6816151ff565b91506020830135615653816157ba565b60008060006060848603121561580b57600080fd5b8335615816816151ff565b95602085013595506040909401359392505050565b6000806040838503121561583e57600080fd5b8235615849816151ff565b91506020830135615653816151ff565b600080600080600060a0868803121561587157600080fd5b853561587c816151ff565b9450602086013561588c816151ff565b9350604086013592506060860135915060808601356001600160401b038111156158b557600080fd5b6156218882890161540f565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806158eb57607f821691505b60208210810361590b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008282101561593957615939615911565b500390565b600181815b8085111561597957816000190482111561595f5761595f615911565b8085161561596c57918102915b93841c9390800290615943565b509250929050565b60008261599057506001610d92565b8161599d57506000610d92565b81600181146159b357600281146159bd576159d9565b6001915050610d92565b60ff8411156159ce576159ce615911565b50506001821b610d92565b5060208310610133831016604e8410600b84101617156159fc575081810a610d92565b615a06838361593e565b8060001904821115615a1a57615a1a615911565b029392505050565b6000611be78383615981565b6000816000190483118215151615615a4857615a48615911565b500290565b600082615a6a57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115615a8257615a82615911565b500190565b600060208284031215615a9957600080fd5b5051919050565b600060208284031215615ab257600080fd5b8151611be7816157ba565b600060018201615acf57615acf615911565b5060010190565b6020810160178310615af857634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215615b1057600080fd5b8151611be7816151ff565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b604081526000615be1604083018561572a565b828103602084015261119e818561572a565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351615c2b816017850160208801615327565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351615c5c816028840160208801615327565b01602801949350505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615c9b90830184615353565b9695505050505050565b6001600160a01b0386811682528516602082015260a060408201819052600090615cd19083018661572a565b8281036060840152615ce3818661572a565b90508281036080840152615cf78185615353565b98975050505050505050565b600060208284031215615d1557600080fd5b8151611be78161525d565b600060033d1115615d395760046000803e5060005160e01c5b90565b600060443d1015615d4a5790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615d7957505050505090565b8285019150815181811115615d915750505050505090565b843d8701016020828501011115615dab5750505050505090565b615dba602082860101876153e3565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b600081615e1c57615e1c615911565b506000190190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061517390830184615353565b634e487b7160e01b600052603160045260246000fd5b60008251615e86818460208701615327565b919091019291505056fea2646970667358221220860fd6cefccce07dc2ed46f2f29ff78de60186446c2926c721dca4d5225ae2d964736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf1618700000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf0369000000000000000000000000204d14f8ec875965e623a04a8928b92934ce814300000000000000000000000005365bb2695d531dae858eb49e8199962ba109290000000000000000000000008ba45a0d9a3af55b329d5601139b56782035e59200000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000e87da2a471732b6f82edbf71e740ed8112d00fd2000000000000000000000000e87da2a471732b6f82edbf71e740ed8112d00fd2
-----Decoded View---------------
Arg [0] : _underlyingToken (address): 0xdBe9E49029A4046B672E714Cc2247CF62BF16187
Arg [1] : _collateralToken (address): 0x66Ba090eD8E3D76680F25fd924C90f662daF0369
Arg [2] : _hivemindAddress (address): 0x204d14F8ec875965e623A04A8928b92934cE8143
Arg [3] : _interestRateModel (address): 0x05365BB2695D531DAe858eB49e8199962Ba10929
Arg [4] : _liquidatorAddress (address): 0x8ba45a0D9A3Af55b329d5601139b56782035E592
Arg [5] : _initialExchangeRateMantissa (uint256): 500000000000000000
Arg [6] : _reserveFactorMantissa (uint256): 20000000000000000
Arg [7] : _adminFeeMantissa (uint256): 20000000000000000
Arg [8] : _hiveFeeMantissa (uint256): 20000000000000000
Arg [9] : _protocolFeeMantissa (uint256): 5000000000000000
Arg [10] : _adminFeeReceiver (address): 0xE87Da2a471732B6f82EDBf71E740eD8112d00fD2
Arg [11] : _hiveFeeReceiver (address): 0xE87Da2a471732B6f82EDBf71E740eD8112d00fD2
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 000000000000000000000000dbe9e49029a4046b672e714cc2247cf62bf16187
Arg [1] : 00000000000000000000000066ba090ed8e3d76680f25fd924c90f662daf0369
Arg [2] : 000000000000000000000000204d14f8ec875965e623a04a8928b92934ce8143
Arg [3] : 00000000000000000000000005365bb2695d531dae858eb49e8199962ba10929
Arg [4] : 0000000000000000000000008ba45a0d9a3af55b329d5601139b56782035e592
Arg [5] : 00000000000000000000000000000000000000000000000006f05b59d3b20000
Arg [6] : 00000000000000000000000000000000000000000000000000470de4df820000
Arg [7] : 00000000000000000000000000000000000000000000000000470de4df820000
Arg [8] : 00000000000000000000000000000000000000000000000000470de4df820000
Arg [9] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [10] : 000000000000000000000000e87da2a471732b6f82edbf71e740ed8112d00fd2
Arg [11] : 000000000000000000000000e87da2a471732b6f82edbf71e740ed8112d00fd2
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.