There are reports that this address was used in a Phishing scam. Please exercise caution when interacting with it. Reported by GoPlusSecurity.
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
EToken
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "../BaseLogic.sol"; /// @notice Tokenised representation of assets contract EToken is BaseLogic { constructor(bytes32 moduleGitCommit_) BaseLogic(MODULEID__ETOKEN, moduleGitCommit_) {} function CALLER() private view returns (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) { (msgSender, proxyAddr) = unpackTrailingParams(); assetStorage = eTokenLookup[proxyAddr]; underlying = assetStorage.underlying; require(underlying != address(0), "e/unrecognized-etoken-caller"); } // Events event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); // External methods /// @notice Pool name, ie "Euler Pool: DAI" function name() external view returns (string memory) { (address underlying,,,) = CALLER(); return string(abi.encodePacked("Euler Pool: ", IERC20(underlying).name())); } /// @notice Pool symbol, ie "eDAI" function symbol() external view returns (string memory) { (address underlying,,,) = CALLER(); return string(abi.encodePacked("e", IERC20(underlying).symbol())); } /// @notice Decimals, always normalised to 18. function decimals() external pure returns (uint8) { return 18; } /// @notice Address of underlying asset function underlyingAsset() external view returns (address) { (address underlying,,,) = CALLER(); return underlying; } /// @notice Sum of all balances, in internal book-keeping units (non-increasing) function totalSupply() external view returns (uint) { (address underlying, AssetStorage storage assetStorage,,) = CALLER(); AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage); return assetCache.totalBalances; } /// @notice Sum of all balances, in underlying units (increases as interest is earned) function totalSupplyUnderlying() external view returns (uint) { (address underlying, AssetStorage storage assetStorage,,) = CALLER(); AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage); return balanceToUnderlyingAmount(assetCache, assetCache.totalBalances) / assetCache.underlyingDecimalsScaler; } /// @notice Balance of a particular account, in internal book-keeping units (non-increasing) function balanceOf(address account) external view returns (uint) { (, AssetStorage storage assetStorage,,) = CALLER(); return assetStorage.users[account].balance; } /// @notice Balance of a particular account, in underlying units (increases as interest is earned) function balanceOfUnderlying(address account) external view returns (uint) { (address underlying, AssetStorage storage assetStorage,,) = CALLER(); AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage); return balanceToUnderlyingAmount(assetCache, assetStorage.users[account].balance) / assetCache.underlyingDecimalsScaler; } /// @notice Balance of the reserves, in internal book-keeping units (non-increasing) function reserveBalance() external view returns (uint) { (address underlying, AssetStorage storage assetStorage,,) = CALLER(); AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage); return assetCache.reserveBalance; } /// @notice Balance of the reserves, in underlying units (increases as interest is earned) function reserveBalanceUnderlying() external view returns (uint) { (address underlying, AssetStorage storage assetStorage,,) = CALLER(); AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage); return balanceToUnderlyingAmount(assetCache, assetCache.reserveBalance) / assetCache.underlyingDecimalsScaler; } /// @notice Convert an eToken balance to an underlying amount, taking into account current exchange rate /// @param balance eToken balance, in internal book-keeping units (18 decimals) /// @return Amount in underlying units, (same decimals as underlying token) function convertBalanceToUnderlying(uint balance) external view returns (uint) { (address underlying, AssetStorage storage assetStorage,,) = CALLER(); AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage); return balanceToUnderlyingAmount(assetCache, balance) / assetCache.underlyingDecimalsScaler; } /// @notice Convert an underlying amount to an eToken balance, taking into account current exchange rate /// @param underlyingAmount Amount in underlying units (same decimals as underlying token) /// @return eToken balance, in internal book-keeping units (18 decimals) function convertUnderlyingToBalance(uint underlyingAmount) external view returns (uint) { (address underlying, AssetStorage storage assetStorage,,) = CALLER(); AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage); return underlyingAmountToBalance(assetCache, decodeExternalAmount(assetCache, underlyingAmount)); } /// @notice Updates interest accumulator and totalBorrows, credits reserves, re-targets interest rate, and logs asset status function touch() external nonReentrant { (address underlying, AssetStorage storage assetStorage,,) = CALLER(); AssetCache memory assetCache = loadAssetCache(underlying, assetStorage); updateInterestRate(assetStorage, assetCache); logAssetStatus(assetCache); } /// @notice Transfer underlying tokens from sender to the Euler pool, and increase account's eTokens /// @param subAccountId 0 for primary, 1-255 for a sub-account /// @param amount In underlying units (use max uint256 for full underlying token balance) function deposit(uint subAccountId, uint amount) external nonReentrant { (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER(); address account = getSubAccount(msgSender, subAccountId); updateAverageLiquidity(account); emit RequestDeposit(account, amount); AssetCache memory assetCache = loadAssetCache(underlying, assetStorage); if (amount == type(uint).max) { amount = callBalanceOf(assetCache, msgSender); } amount = decodeExternalAmount(assetCache, amount); uint amountTransferred = pullTokens(assetCache, msgSender, amount); uint amountInternal; // pullTokens() updates poolSize in the cache, but we need the poolSize before the deposit to determine // the internal amount so temporarily reduce it by the amountTransferred (which is size checked within // pullTokens()). We can't compute this value before the pull because we don't know how much we'll // actually receive (the token might be deflationary). unchecked { assetCache.poolSize -= amountTransferred; amountInternal = underlyingAmountToBalance(assetCache, amountTransferred); assetCache.poolSize += amountTransferred; } increaseBalance(assetStorage, assetCache, proxyAddr, account, amountInternal); if (assetStorage.users[account].owed != 0) checkLiquidity(account); logAssetStatus(assetCache); } /// @notice Transfer underlying tokens from Euler pool to sender, and decrease account's eTokens /// @param subAccountId 0 for primary, 1-255 for a sub-account /// @param amount In underlying units (use max uint256 for full pool balance) function withdraw(uint subAccountId, uint amount) external nonReentrant { (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER(); address account = getSubAccount(msgSender, subAccountId); updateAverageLiquidity(account); emit RequestWithdraw(account, amount); AssetCache memory assetCache = loadAssetCache(underlying, assetStorage); uint amountInternal; (amount, amountInternal) = withdrawAmounts(assetStorage, assetCache, account, amount); require(assetCache.poolSize >= amount, "e/insufficient-pool-size"); pushTokens(assetCache, msgSender, amount); decreaseBalance(assetStorage, assetCache, proxyAddr, account, amountInternal); checkLiquidity(account); logAssetStatus(assetCache); } /// @notice Mint eTokens and a corresponding amount of dTokens ("self-borrow") /// @param subAccountId 0 for primary, 1-255 for a sub-account /// @param amount In underlying units function mint(uint subAccountId, uint amount) external nonReentrant { (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER(); address account = getSubAccount(msgSender, subAccountId); updateAverageLiquidity(account); emit RequestMint(account, amount); AssetCache memory assetCache = loadAssetCache(underlying, assetStorage); amount = decodeExternalAmount(assetCache, amount); uint amountInternal = underlyingAmountToBalanceRoundUp(assetCache, amount); amount = balanceToUnderlyingAmount(assetCache, amountInternal); // Mint ETokens increaseBalance(assetStorage, assetCache, proxyAddr, account, amountInternal); // Mint DTokens increaseBorrow(assetStorage, assetCache, assetStorage.dTokenAddress, account, amount); checkLiquidity(account); logAssetStatus(assetCache); } /// @notice Pay off dToken liability with eTokens ("self-repay") /// @param subAccountId 0 for primary, 1-255 for a sub-account /// @param amount In underlying units (use max uint256 to repay the debt in full or up to the available underlying balance) function burn(uint subAccountId, uint amount) external nonReentrant { (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER(); address account = getSubAccount(msgSender, subAccountId); updateAverageLiquidity(account); emit RequestBurn(account, amount); AssetCache memory assetCache = loadAssetCache(underlying, assetStorage); uint owed = getCurrentOwed(assetStorage, assetCache, account); if (owed == 0) return; uint amountInternal; (amount, amountInternal) = withdrawAmounts(assetStorage, assetCache, account, amount); if (amount > owed) { amount = owed; amountInternal = underlyingAmountToBalanceRoundUp(assetCache, amount); } // Burn ETokens decreaseBalance(assetStorage, assetCache, proxyAddr, account, amountInternal); // Burn DTokens decreaseBorrow(assetStorage, assetCache, assetStorage.dTokenAddress, account, amount); checkLiquidity(account); logAssetStatus(assetCache); } /// @notice Allow spender to access an amount of your eTokens in sub-account 0 /// @param spender Trusted address /// @param amount Use max uint256 for "infinite" allowance function approve(address spender, uint amount) external reentrantOK returns (bool) { return approveSubAccount(0, spender, amount); } /// @notice Allow spender to access an amount of your eTokens in a particular sub-account /// @param subAccountId 0 for primary, 1-255 for a sub-account /// @param spender Trusted address /// @param amount Use max uint256 for "infinite" allowance function approveSubAccount(uint subAccountId, address spender, uint amount) public nonReentrant returns (bool) { (, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER(); address account = getSubAccount(msgSender, subAccountId); require(!isSubAccountOf(spender, account), "e/self-approval"); assetStorage.eTokenAllowance[account][spender] = amount; emitViaProxy_Approval(proxyAddr, account, spender, amount); return true; } /// @notice Retrieve the current allowance /// @param holder Xor with the desired sub-account ID (if applicable) /// @param spender Trusted address function allowance(address holder, address spender) external view returns (uint) { (, AssetStorage storage assetStorage,,) = CALLER(); return assetStorage.eTokenAllowance[holder][spender]; } /// @notice Transfer eTokens to another address (from sub-account 0) /// @param to Xor with the desired sub-account ID (if applicable) /// @param amount In internal book-keeping units (as returned from balanceOf). function transfer(address to, uint amount) external reentrantOK returns (bool) { return transferFrom(address(0), to, amount); } /// @notice Transfer the full eToken balance of an address to another /// @param from This address must've approved the to address, or be a sub-account of msg.sender /// @param to Xor with the desired sub-account ID (if applicable) function transferFromMax(address from, address to) external reentrantOK returns (bool) { (, AssetStorage storage assetStorage,,) = CALLER(); return transferFrom(from, to, assetStorage.users[from].balance); } /// @notice Transfer eTokens from one address to another /// @param from This address must've approved the to address, or be a sub-account of msg.sender /// @param to Xor with the desired sub-account ID (if applicable) /// @param amount In internal book-keeping units (as returned from balanceOf). function transferFrom(address from, address to, uint amount) public nonReentrant returns (bool) { (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER(); AssetCache memory assetCache = loadAssetCache(underlying, assetStorage); if (from == address(0)) from = msgSender; require(from != to, "e/self-transfer"); updateAverageLiquidity(from); updateAverageLiquidity(to); emit RequestTransferEToken(from, to, amount); if (amount == 0) return true; if (!isSubAccountOf(msgSender, from) && assetStorage.eTokenAllowance[from][msgSender] != type(uint).max) { require(assetStorage.eTokenAllowance[from][msgSender] >= amount, "e/insufficient-allowance"); unchecked { assetStorage.eTokenAllowance[from][msgSender] -= amount; } emitViaProxy_Approval(proxyAddr, from, msgSender, assetStorage.eTokenAllowance[from][msgSender]); } transferBalance(assetStorage, assetCache, proxyAddr, from, to, amount); checkLiquidity(from); if (assetStorage.users[to].owed != 0) checkLiquidity(to); logAssetStatus(assetCache); return true; } /// @notice Donate eTokens to the reserves /// @param subAccountId 0 for primary, 1-255 for a sub-account /// @param amount In internal book-keeping units (as returned from balanceOf). function donateToReserves(uint subAccountId, uint amount) external nonReentrant { (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER(); address account = getSubAccount(msgSender, subAccountId); updateAverageLiquidity(account); emit RequestDonate(account, amount); AssetCache memory assetCache = loadAssetCache(underlying, assetStorage); uint origBalance = assetStorage.users[account].balance; uint newBalance; if (amount == type(uint).max) { amount = origBalance; newBalance = 0; } else { require(origBalance >= amount, "e/insufficient-balance"); unchecked { newBalance = origBalance - amount; } } assetStorage.users[account].balance = encodeAmount(newBalance); assetStorage.reserveBalance = assetCache.reserveBalance = encodeSmallAmount(assetCache.reserveBalance + amount); emit Withdraw(assetCache.underlying, account, amount); emitViaProxy_Transfer(proxyAddr, account, address(0), amount); logAssetStatus(assetCache); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./BaseModule.sol"; import "./BaseIRM.sol"; import "./Interfaces.sol"; import "./Utils.sol"; import "./vendor/RPow.sol"; import "./IRiskManager.sol"; abstract contract BaseLogic is BaseModule { constructor(uint moduleId_, bytes32 moduleGitCommit_) BaseModule(moduleId_, moduleGitCommit_) {} // Account auth function getSubAccount(address primary, uint subAccountId) internal pure returns (address) { require(subAccountId < 256, "e/sub-account-id-too-big"); return address(uint160(primary) ^ uint160(subAccountId)); } function isSubAccountOf(address primary, address subAccount) internal pure returns (bool) { return (uint160(primary) | 0xFF) == (uint160(subAccount) | 0xFF); } // Entered markets array function getEnteredMarketsArray(address account) internal view returns (address[] memory) { uint32 numMarketsEntered = accountLookup[account].numMarketsEntered; address firstMarketEntered = accountLookup[account].firstMarketEntered; address[] memory output = new address[](numMarketsEntered); if (numMarketsEntered == 0) return output; address[MAX_POSSIBLE_ENTERED_MARKETS] storage markets = marketsEntered[account]; output[0] = firstMarketEntered; for (uint i = 1; i < numMarketsEntered; ++i) { output[i] = markets[i]; } return output; } function isEnteredInMarket(address account, address underlying) internal view returns (bool) { uint32 numMarketsEntered = accountLookup[account].numMarketsEntered; address firstMarketEntered = accountLookup[account].firstMarketEntered; if (numMarketsEntered == 0) return false; if (firstMarketEntered == underlying) return true; address[MAX_POSSIBLE_ENTERED_MARKETS] storage markets = marketsEntered[account]; for (uint i = 1; i < numMarketsEntered; ++i) { if (markets[i] == underlying) return true; } return false; } function doEnterMarket(address account, address underlying) internal { AccountStorage storage accountStorage = accountLookup[account]; uint32 numMarketsEntered = accountStorage.numMarketsEntered; address[MAX_POSSIBLE_ENTERED_MARKETS] storage markets = marketsEntered[account]; if (numMarketsEntered != 0) { if (accountStorage.firstMarketEntered == underlying) return; // already entered for (uint i = 1; i < numMarketsEntered; i++) { if (markets[i] == underlying) return; // already entered } } require(numMarketsEntered < MAX_ENTERED_MARKETS, "e/too-many-entered-markets"); if (numMarketsEntered == 0) accountStorage.firstMarketEntered = underlying; else markets[numMarketsEntered] = underlying; accountStorage.numMarketsEntered = numMarketsEntered + 1; emit EnterMarket(underlying, account); } // Liquidity check must be done by caller after calling this function doExitMarket(address account, address underlying) internal { AccountStorage storage accountStorage = accountLookup[account]; uint32 numMarketsEntered = accountStorage.numMarketsEntered; address[MAX_POSSIBLE_ENTERED_MARKETS] storage markets = marketsEntered[account]; uint searchIndex = type(uint).max; if (numMarketsEntered == 0) return; // already exited if (accountStorage.firstMarketEntered == underlying) { searchIndex = 0; } else { for (uint i = 1; i < numMarketsEntered; i++) { if (markets[i] == underlying) { searchIndex = i; break; } } if (searchIndex == type(uint).max) return; // already exited } uint lastMarketIndex = numMarketsEntered - 1; if (searchIndex != lastMarketIndex) { if (searchIndex == 0) accountStorage.firstMarketEntered = markets[lastMarketIndex]; else markets[searchIndex] = markets[lastMarketIndex]; } accountStorage.numMarketsEntered = uint32(lastMarketIndex); if (lastMarketIndex != 0) markets[lastMarketIndex] = address(0); // zero out for storage refund emit ExitMarket(underlying, account); } // AssetConfig function resolveAssetConfig(address underlying) internal view returns (AssetConfig memory) { AssetConfig memory config = underlyingLookup[underlying]; require(config.eTokenAddress != address(0), "e/market-not-activated"); if (config.borrowFactor == type(uint32).max) config.borrowFactor = DEFAULT_BORROW_FACTOR; if (config.twapWindow == type(uint24).max) config.twapWindow = DEFAULT_TWAP_WINDOW_SECONDS; return config; } // AssetCache struct AssetCache { address underlying; uint112 totalBalances; uint144 totalBorrows; uint96 reserveBalance; uint interestAccumulator; uint40 lastInterestAccumulatorUpdate; uint8 underlyingDecimals; uint32 interestRateModel; int96 interestRate; uint32 reserveFee; uint16 pricingType; uint32 pricingParameters; uint poolSize; // result of calling balanceOf on underlying (in external units) uint underlyingDecimalsScaler; uint maxExternalAmount; } function initAssetCache(address underlying, AssetStorage storage assetStorage, AssetCache memory assetCache) internal view returns (bool dirty) { dirty = false; assetCache.underlying = underlying; // Storage loads assetCache.lastInterestAccumulatorUpdate = assetStorage.lastInterestAccumulatorUpdate; uint8 underlyingDecimals = assetCache.underlyingDecimals = assetStorage.underlyingDecimals; assetCache.interestRateModel = assetStorage.interestRateModel; assetCache.interestRate = assetStorage.interestRate; assetCache.reserveFee = assetStorage.reserveFee; assetCache.pricingType = assetStorage.pricingType; assetCache.pricingParameters = assetStorage.pricingParameters; assetCache.reserveBalance = assetStorage.reserveBalance; assetCache.totalBalances = assetStorage.totalBalances; assetCache.totalBorrows = assetStorage.totalBorrows; assetCache.interestAccumulator = assetStorage.interestAccumulator; // Derived state unchecked { assetCache.underlyingDecimalsScaler = 10**(18 - underlyingDecimals); assetCache.maxExternalAmount = MAX_SANE_AMOUNT / assetCache.underlyingDecimalsScaler; } uint poolSize = callBalanceOf(assetCache, address(this)); if (poolSize <= assetCache.maxExternalAmount) { unchecked { assetCache.poolSize = poolSize * assetCache.underlyingDecimalsScaler; } } else { assetCache.poolSize = 0; } // Update interest accumulator and reserves if (block.timestamp != assetCache.lastInterestAccumulatorUpdate) { dirty = true; uint deltaT = block.timestamp - assetCache.lastInterestAccumulatorUpdate; // Compute new values uint newInterestAccumulator = (RPow.rpow(uint(int(assetCache.interestRate) + 1e27), deltaT, 1e27) * assetCache.interestAccumulator) / 1e27; uint newTotalBorrows = assetCache.totalBorrows * newInterestAccumulator / assetCache.interestAccumulator; uint newReserveBalance = assetCache.reserveBalance; uint newTotalBalances = assetCache.totalBalances; uint feeAmount = (newTotalBorrows - assetCache.totalBorrows) * (assetCache.reserveFee == type(uint32).max ? DEFAULT_RESERVE_FEE : assetCache.reserveFee) / (RESERVE_FEE_SCALE * INTERNAL_DEBT_PRECISION); if (feeAmount != 0) { uint poolAssets = assetCache.poolSize + (newTotalBorrows / INTERNAL_DEBT_PRECISION); newTotalBalances = poolAssets * newTotalBalances / (poolAssets - feeAmount); newReserveBalance += newTotalBalances - assetCache.totalBalances; } // Store new values in assetCache, only if no overflows will occur if (newTotalBalances <= MAX_SANE_AMOUNT && newTotalBorrows <= MAX_SANE_DEBT_AMOUNT) { assetCache.totalBorrows = encodeDebtAmount(newTotalBorrows); assetCache.interestAccumulator = newInterestAccumulator; assetCache.lastInterestAccumulatorUpdate = uint40(block.timestamp); if (newTotalBalances != assetCache.totalBalances) { assetCache.reserveBalance = encodeSmallAmount(newReserveBalance); assetCache.totalBalances = encodeAmount(newTotalBalances); } } } } function loadAssetCache(address underlying, AssetStorage storage assetStorage) internal returns (AssetCache memory assetCache) { if (initAssetCache(underlying, assetStorage, assetCache)) { assetStorage.lastInterestAccumulatorUpdate = assetCache.lastInterestAccumulatorUpdate; assetStorage.underlying = assetCache.underlying; // avoid an SLOAD of this slot assetStorage.reserveBalance = assetCache.reserveBalance; assetStorage.totalBalances = assetCache.totalBalances; assetStorage.totalBorrows = assetCache.totalBorrows; assetStorage.interestAccumulator = assetCache.interestAccumulator; } } function loadAssetCacheRO(address underlying, AssetStorage storage assetStorage) internal view returns (AssetCache memory assetCache) { require(reentrancyLock == REENTRANCYLOCK__UNLOCKED, "e/ro-reentrancy"); initAssetCache(underlying, assetStorage, assetCache); } function internalLoadAssetCacheRO(address underlying, AssetStorage storage assetStorage) internal view returns (AssetCache memory assetCache) { initAssetCache(underlying, assetStorage, assetCache); } // Utils function decodeExternalAmount(AssetCache memory assetCache, uint externalAmount) internal pure returns (uint scaledAmount) { require(externalAmount <= assetCache.maxExternalAmount, "e/amount-too-large"); unchecked { scaledAmount = externalAmount * assetCache.underlyingDecimalsScaler; } } function encodeAmount(uint amount) internal pure returns (uint112) { require(amount <= MAX_SANE_AMOUNT, "e/amount-too-large-to-encode"); return uint112(amount); } function encodeSmallAmount(uint amount) internal pure returns (uint96) { require(amount <= MAX_SANE_SMALL_AMOUNT, "e/small-amount-too-large-to-encode"); return uint96(amount); } function encodeDebtAmount(uint amount) internal pure returns (uint144) { require(amount <= MAX_SANE_DEBT_AMOUNT, "e/debt-amount-too-large-to-encode"); return uint144(amount); } function computeExchangeRate(AssetCache memory assetCache) private pure returns (uint) { uint totalAssets = assetCache.poolSize + (assetCache.totalBorrows / INTERNAL_DEBT_PRECISION); if (totalAssets == 0 || assetCache.totalBalances == 0) return 1e18; return totalAssets * 1e18 / assetCache.totalBalances; } function underlyingAmountToBalance(AssetCache memory assetCache, uint amount) internal pure returns (uint) { uint exchangeRate = computeExchangeRate(assetCache); return amount * 1e18 / exchangeRate; } function underlyingAmountToBalanceRoundUp(AssetCache memory assetCache, uint amount) internal pure returns (uint) { uint exchangeRate = computeExchangeRate(assetCache); return (amount * 1e18 + (exchangeRate - 1)) / exchangeRate; } function balanceToUnderlyingAmount(AssetCache memory assetCache, uint amount) internal pure returns (uint) { uint exchangeRate = computeExchangeRate(assetCache); return amount * exchangeRate / 1e18; } function callBalanceOf(AssetCache memory assetCache, address account) internal view FREEMEM returns (uint) { // We set a gas limit so that a malicious token can't eat up all gas and cause a liquidity check to fail. (bool success, bytes memory data) = assetCache.underlying.staticcall{gas: 200000}(abi.encodeWithSelector(IERC20.balanceOf.selector, account)); // If token's balanceOf() call fails for any reason, return 0. This prevents malicious tokens from causing liquidity checks to fail. // If the contract doesn't exist (maybe because selfdestructed), then data.length will be 0 and we will return 0. // Data length > 32 is allowed because some legitimate tokens append extra data that can be safely ignored. if (!success || data.length < 32) return 0; return abi.decode(data, (uint256)); } function updateInterestRate(AssetStorage storage assetStorage, AssetCache memory assetCache) internal { uint32 utilisation; { uint totalBorrows = assetCache.totalBorrows / INTERNAL_DEBT_PRECISION; uint poolAssets = assetCache.poolSize + totalBorrows; if (poolAssets == 0) utilisation = 0; // empty pool arbitrarily given utilisation of 0 else utilisation = uint32(totalBorrows * (uint(type(uint32).max) * 1e18) / poolAssets / 1e18); } bytes memory result = callInternalModule(assetCache.interestRateModel, abi.encodeWithSelector(BaseIRM.computeInterestRate.selector, assetCache.underlying, utilisation)); (int96 newInterestRate) = abi.decode(result, (int96)); assetStorage.interestRate = assetCache.interestRate = newInterestRate; } function logAssetStatus(AssetCache memory a) internal { emit AssetStatus(a.underlying, a.totalBalances, a.totalBorrows / INTERNAL_DEBT_PRECISION, a.reserveBalance, a.poolSize, a.interestAccumulator, a.interestRate, block.timestamp); } // Balances function increaseBalance(AssetStorage storage assetStorage, AssetCache memory assetCache, address eTokenAddress, address account, uint amount) internal { assetStorage.users[account].balance = encodeAmount(assetStorage.users[account].balance + amount); assetStorage.totalBalances = assetCache.totalBalances = encodeAmount(uint(assetCache.totalBalances) + amount); updateInterestRate(assetStorage, assetCache); emit Deposit(assetCache.underlying, account, amount); emitViaProxy_Transfer(eTokenAddress, address(0), account, amount); } function decreaseBalance(AssetStorage storage assetStorage, AssetCache memory assetCache, address eTokenAddress, address account, uint amount) internal { uint origBalance = assetStorage.users[account].balance; require(origBalance >= amount, "e/insufficient-balance"); assetStorage.users[account].balance = encodeAmount(origBalance - amount); assetStorage.totalBalances = assetCache.totalBalances = encodeAmount(assetCache.totalBalances - amount); updateInterestRate(assetStorage, assetCache); emit Withdraw(assetCache.underlying, account, amount); emitViaProxy_Transfer(eTokenAddress, account, address(0), amount); } function transferBalance(AssetStorage storage assetStorage, AssetCache memory assetCache, address eTokenAddress, address from, address to, uint amount) internal { uint origFromBalance = assetStorage.users[from].balance; require(origFromBalance >= amount, "e/insufficient-balance"); uint newFromBalance; unchecked { newFromBalance = origFromBalance - amount; } assetStorage.users[from].balance = encodeAmount(newFromBalance); assetStorage.users[to].balance = encodeAmount(assetStorage.users[to].balance + amount); emit Withdraw(assetCache.underlying, from, amount); emit Deposit(assetCache.underlying, to, amount); emitViaProxy_Transfer(eTokenAddress, from, to, amount); } function withdrawAmounts(AssetStorage storage assetStorage, AssetCache memory assetCache, address account, uint amount) internal view returns (uint, uint) { uint amountInternal; if (amount == type(uint).max) { amountInternal = assetStorage.users[account].balance; amount = balanceToUnderlyingAmount(assetCache, amountInternal); } else { amount = decodeExternalAmount(assetCache, amount); amountInternal = underlyingAmountToBalanceRoundUp(assetCache, amount); } return (amount, amountInternal); } // Borrows // Returns internal precision function getCurrentOwedExact(AssetStorage storage assetStorage, AssetCache memory assetCache, address account, uint owed) internal view returns (uint) { // Don't bother loading the user's accumulator if (owed == 0) return 0; // Can't divide by 0 here: If owed is non-zero, we must've initialised the user's interestAccumulator return owed * assetCache.interestAccumulator / assetStorage.users[account].interestAccumulator; } // When non-zero, we round *up* to the smallest external unit so that outstanding dust in a loan can be repaid. // unchecked is OK here since owed is always loaded from storage, so we know it fits into a uint144 (pre-interest accural) // Takes and returns 27 decimals precision. function roundUpOwed(AssetCache memory assetCache, uint owed) private pure returns (uint) { if (owed == 0) return 0; unchecked { uint scale = INTERNAL_DEBT_PRECISION * assetCache.underlyingDecimalsScaler; return (owed + scale - 1) / scale * scale; } } // Returns 18-decimals precision (debt amount is rounded up) function getCurrentOwed(AssetStorage storage assetStorage, AssetCache memory assetCache, address account) internal view returns (uint) { return roundUpOwed(assetCache, getCurrentOwedExact(assetStorage, assetCache, account, assetStorage.users[account].owed)) / INTERNAL_DEBT_PRECISION; } function updateUserBorrow(AssetStorage storage assetStorage, AssetCache memory assetCache, address account) private returns (uint newOwedExact, uint prevOwedExact) { prevOwedExact = assetStorage.users[account].owed; newOwedExact = getCurrentOwedExact(assetStorage, assetCache, account, prevOwedExact); assetStorage.users[account].owed = encodeDebtAmount(newOwedExact); assetStorage.users[account].interestAccumulator = assetCache.interestAccumulator; } function logBorrowChange(AssetCache memory assetCache, address dTokenAddress, address account, uint prevOwed, uint owed) private { prevOwed = roundUpOwed(assetCache, prevOwed) / INTERNAL_DEBT_PRECISION; owed = roundUpOwed(assetCache, owed) / INTERNAL_DEBT_PRECISION; if (owed > prevOwed) { uint change = owed - prevOwed; emit Borrow(assetCache.underlying, account, change); emitViaProxy_Transfer(dTokenAddress, address(0), account, change / assetCache.underlyingDecimalsScaler); } else if (prevOwed > owed) { uint change = prevOwed - owed; emit Repay(assetCache.underlying, account, change); emitViaProxy_Transfer(dTokenAddress, account, address(0), change / assetCache.underlyingDecimalsScaler); } } function increaseBorrow(AssetStorage storage assetStorage, AssetCache memory assetCache, address dTokenAddress, address account, uint amount) internal { amount *= INTERNAL_DEBT_PRECISION; require(assetCache.pricingType != PRICINGTYPE__FORWARDED || pTokenLookup[assetCache.underlying] == address(0), "e/borrow-not-supported"); (uint owed, uint prevOwed) = updateUserBorrow(assetStorage, assetCache, account); if (owed == 0) doEnterMarket(account, assetCache.underlying); owed += amount; assetStorage.users[account].owed = encodeDebtAmount(owed); assetStorage.totalBorrows = assetCache.totalBorrows = encodeDebtAmount(assetCache.totalBorrows + amount); updateInterestRate(assetStorage, assetCache); logBorrowChange(assetCache, dTokenAddress, account, prevOwed, owed); } function decreaseBorrow(AssetStorage storage assetStorage, AssetCache memory assetCache, address dTokenAddress, address account, uint origAmount) internal { uint amount = origAmount * INTERNAL_DEBT_PRECISION; (uint owed, uint prevOwed) = updateUserBorrow(assetStorage, assetCache, account); uint owedRoundedUp = roundUpOwed(assetCache, owed); require(amount <= owedRoundedUp, "e/repay-too-much"); uint owedRemaining; unchecked { owedRemaining = owedRoundedUp - amount; } if (owed > assetCache.totalBorrows) owed = assetCache.totalBorrows; assetStorage.users[account].owed = encodeDebtAmount(owedRemaining); assetStorage.totalBorrows = assetCache.totalBorrows = encodeDebtAmount(assetCache.totalBorrows - owed + owedRemaining); updateInterestRate(assetStorage, assetCache); logBorrowChange(assetCache, dTokenAddress, account, prevOwed, owedRemaining); } function transferBorrow(AssetStorage storage assetStorage, AssetCache memory assetCache, address dTokenAddress, address from, address to, uint origAmount) internal { uint amount = origAmount * INTERNAL_DEBT_PRECISION; (uint fromOwed, uint fromOwedPrev) = updateUserBorrow(assetStorage, assetCache, from); (uint toOwed, uint toOwedPrev) = updateUserBorrow(assetStorage, assetCache, to); if (toOwed == 0) doEnterMarket(to, assetCache.underlying); // If amount was rounded up, transfer exact amount owed if (amount > fromOwed && amount - fromOwed < INTERNAL_DEBT_PRECISION * assetCache.underlyingDecimalsScaler) amount = fromOwed; require(fromOwed >= amount, "e/insufficient-balance"); unchecked { fromOwed -= amount; } // Transfer any residual dust if (fromOwed < INTERNAL_DEBT_PRECISION) { amount += fromOwed; fromOwed = 0; } toOwed += amount; assetStorage.users[from].owed = encodeDebtAmount(fromOwed); assetStorage.users[to].owed = encodeDebtAmount(toOwed); logBorrowChange(assetCache, dTokenAddress, from, fromOwedPrev, fromOwed); logBorrowChange(assetCache, dTokenAddress, to, toOwedPrev, toOwed); } // Reserves function increaseReserves(AssetStorage storage assetStorage, AssetCache memory assetCache, uint amount) internal { assetStorage.reserveBalance = assetCache.reserveBalance = encodeSmallAmount(assetCache.reserveBalance + amount); assetStorage.totalBalances = assetCache.totalBalances = encodeAmount(assetCache.totalBalances + amount); } // Token asset transfers // amounts are in underlying units function pullTokens(AssetCache memory assetCache, address from, uint amount) internal returns (uint amountTransferred) { uint poolSizeBefore = assetCache.poolSize; Utils.safeTransferFrom(assetCache.underlying, from, address(this), amount / assetCache.underlyingDecimalsScaler); uint poolSizeAfter = assetCache.poolSize = decodeExternalAmount(assetCache, callBalanceOf(assetCache, address(this))); require(poolSizeAfter >= poolSizeBefore, "e/negative-transfer-amount"); unchecked { amountTransferred = poolSizeAfter - poolSizeBefore; } } function pushTokens(AssetCache memory assetCache, address to, uint amount) internal returns (uint amountTransferred) { uint poolSizeBefore = assetCache.poolSize; Utils.safeTransfer(assetCache.underlying, to, amount / assetCache.underlyingDecimalsScaler); uint poolSizeAfter = assetCache.poolSize = decodeExternalAmount(assetCache, callBalanceOf(assetCache, address(this))); require(poolSizeBefore >= poolSizeAfter, "e/negative-transfer-amount"); unchecked { amountTransferred = poolSizeBefore - poolSizeAfter; } } // Liquidity function getAssetPrice(address asset) internal returns (uint) { bytes memory result = callInternalModule(MODULEID__RISK_MANAGER, abi.encodeWithSelector(IRiskManager.getPrice.selector, asset)); return abi.decode(result, (uint)); } function getAccountLiquidity(address account) internal returns (uint collateralValue, uint liabilityValue) { bytes memory result = callInternalModule(MODULEID__RISK_MANAGER, abi.encodeWithSelector(IRiskManager.computeLiquidity.selector, account)); (IRiskManager.LiquidityStatus memory status) = abi.decode(result, (IRiskManager.LiquidityStatus)); collateralValue = status.collateralValue; liabilityValue = status.liabilityValue; } function checkLiquidity(address account) internal { uint8 status = accountLookup[account].deferLiquidityStatus; if (status == DEFERLIQUIDITY__NONE) { callInternalModule(MODULEID__RISK_MANAGER, abi.encodeWithSelector(IRiskManager.requireLiquidity.selector, account)); } else if (status == DEFERLIQUIDITY__CLEAN) { accountLookup[account].deferLiquidityStatus = DEFERLIQUIDITY__DIRTY; } } // Optional average liquidity tracking function computeNewAverageLiquidity(address account, uint deltaT) private returns (uint) { uint currDuration = deltaT >= AVERAGE_LIQUIDITY_PERIOD ? AVERAGE_LIQUIDITY_PERIOD : deltaT; uint prevDuration = AVERAGE_LIQUIDITY_PERIOD - currDuration; uint currAverageLiquidity; { (uint collateralValue, uint liabilityValue) = getAccountLiquidity(account); currAverageLiquidity = collateralValue > liabilityValue ? collateralValue - liabilityValue : 0; } return (accountLookup[account].averageLiquidity * prevDuration / AVERAGE_LIQUIDITY_PERIOD) + (currAverageLiquidity * currDuration / AVERAGE_LIQUIDITY_PERIOD); } function getUpdatedAverageLiquidity(address account) internal returns (uint) { uint lastAverageLiquidityUpdate = accountLookup[account].lastAverageLiquidityUpdate; if (lastAverageLiquidityUpdate == 0) return 0; uint deltaT = block.timestamp - lastAverageLiquidityUpdate; if (deltaT == 0) return accountLookup[account].averageLiquidity; return computeNewAverageLiquidity(account, deltaT); } function getUpdatedAverageLiquidityWithDelegate(address account) internal returns (uint) { address delegate = accountLookup[account].averageLiquidityDelegate; return delegate != address(0) && accountLookup[delegate].averageLiquidityDelegate == account ? getUpdatedAverageLiquidity(delegate) : getUpdatedAverageLiquidity(account); } function updateAverageLiquidity(address account) internal { uint lastAverageLiquidityUpdate = accountLookup[account].lastAverageLiquidityUpdate; if (lastAverageLiquidityUpdate == 0) return; uint deltaT = block.timestamp - lastAverageLiquidityUpdate; if (deltaT == 0) return; accountLookup[account].lastAverageLiquidityUpdate = uint40(block.timestamp); accountLookup[account].averageLiquidity = computeNewAverageLiquidity(account, deltaT); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./Base.sol"; abstract contract BaseModule is Base { // Construction // public accessors common to all modules uint immutable public moduleId; bytes32 immutable public moduleGitCommit; constructor(uint moduleId_, bytes32 moduleGitCommit_) { moduleId = moduleId_; moduleGitCommit = moduleGitCommit_; } // Accessing parameters function unpackTrailingParamMsgSender() internal pure returns (address msgSender) { assembly { msgSender := shr(96, calldataload(sub(calldatasize(), 40))) } } function unpackTrailingParams() internal pure returns (address msgSender, address proxyAddr) { assembly { msgSender := shr(96, calldataload(sub(calldatasize(), 40))) proxyAddr := shr(96, calldataload(sub(calldatasize(), 20))) } } // Emit logs via proxies function emitViaProxy_Transfer(address proxyAddr, address from, address to, uint value) internal FREEMEM { (bool success,) = proxyAddr.call(abi.encodePacked( uint8(3), keccak256(bytes('Transfer(address,address,uint256)')), bytes32(uint(uint160(from))), bytes32(uint(uint160(to))), value )); require(success, "e/log-proxy-fail"); } function emitViaProxy_Approval(address proxyAddr, address owner, address spender, uint value) internal FREEMEM { (bool success,) = proxyAddr.call(abi.encodePacked( uint8(3), keccak256(bytes('Approval(address,address,uint256)')), bytes32(uint(uint160(owner))), bytes32(uint(uint160(spender))), value )); require(success, "e/log-proxy-fail"); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./BaseModule.sol"; abstract contract BaseIRM is BaseModule { constructor(uint moduleId_, bytes32 moduleGitCommit_) BaseModule(moduleId_, moduleGitCommit_) {} int96 internal constant MAX_ALLOWED_INTEREST_RATE = int96(int(uint(5 * 1e27) / SECONDS_PER_YEAR)); // 500% APR int96 internal constant MIN_ALLOWED_INTEREST_RATE = 0; function computeInterestRateImpl(address, uint32) internal virtual returns (int96); function computeInterestRate(address underlying, uint32 utilisation) external returns (int96) { int96 rate = computeInterestRateImpl(underlying, utilisation); if (rate > MAX_ALLOWED_INTEREST_RATE) rate = MAX_ALLOWED_INTEREST_RATE; else if (rate < MIN_ALLOWED_INTEREST_RATE) rate = MIN_ALLOWED_INTEREST_RATE; return rate; } function reset(address underlying, bytes calldata resetParams) external virtual {} }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; interface IERC20 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); } interface IERC20Permit { function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; function permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) external; function permit(address owner, address spender, uint value, uint deadline, bytes calldata signature) external; } interface IERC3156FlashBorrower { function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external returns (bytes32); } interface IERC3156FlashLender { function maxFlashLoan(address token) external view returns (uint256); function flashFee(address token, uint256 amount) external view returns (uint256); function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./Interfaces.sol"; library Utils { function safeTransferFrom(address token, address from, address to, uint value) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), string(data)); } function safeTransfer(address token, address to, uint value) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), string(data)); } function safeApprove(address token, address to, uint value) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), string(data)); } }
// SPDX-License-Identifier: AGPL-3.0-or-later // From MakerDAO DSS // Copyright (C) 2018 Rain <[email protected]> // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. pragma solidity ^0.8.0; library RPow { function rpow(uint x, uint n, uint base) internal pure returns (uint z) { assembly { switch x case 0 {switch n case 0 {z := base} default {z := 0}} default { switch mod(n, 2) case 0 { z := base } default { z := x } let half := div(base, 2) // for rounding. for { n := div(n, 2) } n { n := div(n,2) } { let xx := mul(x, x) if iszero(eq(div(xx, x), x)) { revert(0,0) } let xxRound := add(xx, half) if lt(xxRound, xx) { revert(0,0) } x := div(xxRound, base) if mod(n,2) { let zx := mul(z, x) if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) } let zxRound := add(zx, half) if lt(zxRound, zx) { revert(0,0) } z := div(zxRound, base) } } } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./Storage.sol"; // This interface is used to avoid a circular dependency between BaseLogic and RiskManager interface IRiskManager { struct NewMarketParameters { uint16 pricingType; uint32 pricingParameters; Storage.AssetConfig config; } struct LiquidityStatus { uint collateralValue; uint liabilityValue; uint numBorrows; bool borrowIsolated; } struct AssetLiquidity { address underlying; LiquidityStatus status; } function getNewMarketParameters(address underlying) external returns (NewMarketParameters memory); function requireLiquidity(address account) external view; function computeLiquidity(address account) external view returns (LiquidityStatus memory status); function computeAssetLiquidities(address account) external view returns (AssetLiquidity[] memory assets); function getPrice(address underlying) external view returns (uint twap, uint twapPeriod); function getPriceFull(address underlying) external view returns (uint twap, uint twapPeriod, uint currPrice); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; //import "hardhat/console.sol"; // DEV_MODE import "./Storage.sol"; import "./Events.sol"; import "./Proxy.sol"; abstract contract Base is Storage, Events { // Modules function _createProxy(uint proxyModuleId) internal returns (address) { require(proxyModuleId != 0, "e/create-proxy/invalid-module"); require(proxyModuleId <= MAX_EXTERNAL_MODULEID, "e/create-proxy/internal-module"); // If we've already created a proxy for a single-proxy module, just return it: if (proxyLookup[proxyModuleId] != address(0)) return proxyLookup[proxyModuleId]; // Otherwise create a proxy: address proxyAddr = address(new Proxy()); if (proxyModuleId <= MAX_EXTERNAL_SINGLE_PROXY_MODULEID) proxyLookup[proxyModuleId] = proxyAddr; trustedSenders[proxyAddr] = TrustedSenderInfo({ moduleId: uint32(proxyModuleId), moduleImpl: address(0) }); emit ProxyCreated(proxyAddr, proxyModuleId); return proxyAddr; } function callInternalModule(uint moduleId, bytes memory input) internal returns (bytes memory) { (bool success, bytes memory result) = moduleLookup[moduleId].delegatecall(input); if (!success) revertBytes(result); return result; } // Modifiers modifier nonReentrant() { require(reentrancyLock == REENTRANCYLOCK__UNLOCKED, "e/reentrancy"); reentrancyLock = REENTRANCYLOCK__LOCKED; _; reentrancyLock = REENTRANCYLOCK__UNLOCKED; } modifier reentrantOK() { // documentation only _; } // Used to flag functions which do not modify storage, but do perform a delegate call // to a view function, which prohibits a standard view modifier. The flag is used to // patch state mutability in compiled ABIs and interfaces. modifier staticDelegate() { _; } // WARNING: Must be very careful with this modifier. It resets the free memory pointer // to the value it was when the function started. This saves gas if more memory will // be allocated in the future. However, if the memory will be later referenced // (for example because the function has returned a pointer to it) then you cannot // use this modifier. modifier FREEMEM() { uint origFreeMemPtr; assembly { origFreeMemPtr := mload(0x40) } _; /* assembly { // DEV_MODE: overwrite the freed memory with garbage to detect bugs let garbage := 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF for { let i := origFreeMemPtr } lt(i, mload(0x40)) { i := add(i, 32) } { mstore(i, garbage) } } */ assembly { mstore(0x40, origFreeMemPtr) } } // Error handling function revertBytes(bytes memory errMsg) internal pure { if (errMsg.length > 0) { assembly { revert(add(32, errMsg), mload(errMsg)) } } revert("e/empty-error"); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./Constants.sol"; abstract contract Storage is Constants { // Dispatcher and upgrades uint internal reentrancyLock; address upgradeAdmin; address governorAdmin; mapping(uint => address) moduleLookup; // moduleId => module implementation mapping(uint => address) proxyLookup; // moduleId => proxy address (only for single-proxy modules) struct TrustedSenderInfo { uint32 moduleId; // 0 = un-trusted address moduleImpl; // only non-zero for external single-proxy modules } mapping(address => TrustedSenderInfo) trustedSenders; // sender address => moduleId (0 = un-trusted) // Account-level state // Sub-accounts are considered distinct accounts struct AccountStorage { // Packed slot: 1 + 5 + 4 + 20 = 30 uint8 deferLiquidityStatus; uint40 lastAverageLiquidityUpdate; uint32 numMarketsEntered; address firstMarketEntered; uint averageLiquidity; address averageLiquidityDelegate; } mapping(address => AccountStorage) accountLookup; mapping(address => address[MAX_POSSIBLE_ENTERED_MARKETS]) marketsEntered; // Markets and assets struct AssetConfig { // Packed slot: 20 + 1 + 4 + 4 + 3 = 32 address eTokenAddress; bool borrowIsolated; uint32 collateralFactor; uint32 borrowFactor; uint24 twapWindow; } struct UserAsset { uint112 balance; uint144 owed; uint interestAccumulator; } struct AssetStorage { // Packed slot: 5 + 1 + 4 + 12 + 4 + 2 + 4 = 32 uint40 lastInterestAccumulatorUpdate; uint8 underlyingDecimals; // Not dynamic, but put here to live in same storage slot uint32 interestRateModel; int96 interestRate; uint32 reserveFee; uint16 pricingType; uint32 pricingParameters; address underlying; uint96 reserveBalance; address dTokenAddress; uint112 totalBalances; uint144 totalBorrows; uint interestAccumulator; mapping(address => UserAsset) users; mapping(address => mapping(address => uint)) eTokenAllowance; mapping(address => mapping(address => uint)) dTokenAllowance; } mapping(address => AssetConfig) internal underlyingLookup; // underlying => AssetConfig mapping(address => AssetStorage) internal eTokenLookup; // EToken => AssetStorage mapping(address => address) internal dTokenLookup; // DToken => EToken mapping(address => address) internal pTokenLookup; // PToken => underlying mapping(address => address) internal reversePTokenLookup; // underlying => PToken mapping(address => address) internal chainlinkPriceFeedLookup; // underlying => chainlinkAggregator }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./Storage.sol"; abstract contract Events { event Genesis(); event ProxyCreated(address indexed proxy, uint moduleId); event MarketActivated(address indexed underlying, address indexed eToken, address indexed dToken); event PTokenActivated(address indexed underlying, address indexed pToken); event EnterMarket(address indexed underlying, address indexed account); event ExitMarket(address indexed underlying, address indexed account); event Deposit(address indexed underlying, address indexed account, uint amount); event Withdraw(address indexed underlying, address indexed account, uint amount); event Borrow(address indexed underlying, address indexed account, uint amount); event Repay(address indexed underlying, address indexed account, uint amount); event Liquidation(address indexed liquidator, address indexed violator, address indexed underlying, address collateral, uint repay, uint yield, uint healthScore, uint baseDiscount, uint discount); event TrackAverageLiquidity(address indexed account); event UnTrackAverageLiquidity(address indexed account); event DelegateAverageLiquidity(address indexed account, address indexed delegate); event PTokenWrap(address indexed underlying, address indexed account, uint amount); event PTokenUnWrap(address indexed underlying, address indexed account, uint amount); event AssetStatus(address indexed underlying, uint totalBalances, uint totalBorrows, uint96 reserveBalance, uint poolSize, uint interestAccumulator, int96 interestRate, uint timestamp); event RequestDeposit(address indexed account, uint amount); event RequestWithdraw(address indexed account, uint amount); event RequestMint(address indexed account, uint amount); event RequestBurn(address indexed account, uint amount); event RequestTransferEToken(address indexed from, address indexed to, uint amount); event RequestDonate(address indexed account, uint amount); event RequestBorrow(address indexed account, uint amount); event RequestRepay(address indexed account, uint amount); event RequestTransferDToken(address indexed from, address indexed to, uint amount); event RequestLiquidate(address indexed liquidator, address indexed violator, address indexed underlying, address collateral, uint repay, uint minYield); event InstallerSetUpgradeAdmin(address indexed newUpgradeAdmin); event InstallerSetGovernorAdmin(address indexed newGovernorAdmin); event InstallerInstallModule(uint indexed moduleId, address indexed moduleImpl, bytes32 moduleGitCommit); event GovSetAssetConfig(address indexed underlying, Storage.AssetConfig newConfig); event GovSetIRM(address indexed underlying, uint interestRateModel, bytes resetParams); event GovSetPricingConfig(address indexed underlying, uint16 newPricingType, uint32 newPricingParameter); event GovSetReserveFee(address indexed underlying, uint32 newReserveFee); event GovConvertReserves(address indexed underlying, address indexed recipient, uint amount); event GovSetChainlinkPriceFeed(address indexed underlying, address chainlinkAggregator); event RequestSwap(address indexed accountIn, address indexed accountOut, address indexed underlyingIn, address underlyingOut, uint amount, uint swapType); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; contract Proxy { address immutable creator; constructor() { creator = msg.sender; } // External interface fallback() external { address creator_ = creator; if (msg.sender == creator_) { assembly { mstore(0, 0) calldatacopy(31, 0, calldatasize()) switch mload(0) // numTopics case 0 { log0(32, sub(calldatasize(), 1)) } case 1 { log1(64, sub(calldatasize(), 33), mload(32)) } case 2 { log2(96, sub(calldatasize(), 65), mload(32), mload(64)) } case 3 { log3(128, sub(calldatasize(), 97), mload(32), mload(64), mload(96)) } case 4 { log4(160, sub(calldatasize(), 129), mload(32), mload(64), mload(96), mload(128)) } default { revert(0, 0) } return(0, 0) } } else { assembly { mstore(0, 0xe9c4a3ac00000000000000000000000000000000000000000000000000000000) // dispatch() selector calldatacopy(4, 0, calldatasize()) mstore(add(4, calldatasize()), shl(96, caller())) let result := call(gas(), creator_, 0, 0, add(24, calldatasize()), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; abstract contract Constants { // Universal uint internal constant SECONDS_PER_YEAR = 365.2425 * 86400; // Gregorian calendar // Protocol parameters uint internal constant MAX_SANE_AMOUNT = type(uint112).max; uint internal constant MAX_SANE_SMALL_AMOUNT = type(uint96).max; uint internal constant MAX_SANE_DEBT_AMOUNT = type(uint144).max; uint internal constant INTERNAL_DEBT_PRECISION = 1e9; uint internal constant MAX_ENTERED_MARKETS = 10; // per sub-account uint internal constant MAX_POSSIBLE_ENTERED_MARKETS = 2**32; // limited by size of AccountStorage.numMarketsEntered uint internal constant CONFIG_FACTOR_SCALE = 4_000_000_000; // must fit into a uint32 uint internal constant RESERVE_FEE_SCALE = 4_000_000_000; // must fit into a uint32 uint32 internal constant DEFAULT_RESERVE_FEE = uint32(0.23 * 4_000_000_000); uint internal constant INITIAL_RESERVES = 1e6; uint internal constant INITIAL_INTEREST_ACCUMULATOR = 1e27; uint internal constant AVERAGE_LIQUIDITY_PERIOD = 24 * 60 * 60; uint16 internal constant MIN_UNISWAP3_OBSERVATION_CARDINALITY = 144; uint24 internal constant DEFAULT_TWAP_WINDOW_SECONDS = 30 * 60; uint32 internal constant DEFAULT_BORROW_FACTOR = uint32(0.28 * 4_000_000_000); uint32 internal constant SELF_COLLATERAL_FACTOR = uint32(0.95 * 4_000_000_000); // Implementation internals uint internal constant REENTRANCYLOCK__UNLOCKED = 1; uint internal constant REENTRANCYLOCK__LOCKED = 2; uint8 internal constant DEFERLIQUIDITY__NONE = 0; uint8 internal constant DEFERLIQUIDITY__CLEAN = 1; uint8 internal constant DEFERLIQUIDITY__DIRTY = 2; // Pricing types uint16 internal constant PRICINGTYPE__PEGGED = 1; uint16 internal constant PRICINGTYPE__UNISWAP3_TWAP = 2; uint16 internal constant PRICINGTYPE__FORWARDED = 3; uint16 internal constant PRICINGTYPE__CHAINLINK = 4; // Correct pricing types are always less than this value uint16 internal constant PRICINGTYPE__OUT_OF_BOUNDS = 5; // Modules // Public single-proxy modules uint internal constant MODULEID__INSTALLER = 1; uint internal constant MODULEID__MARKETS = 2; uint internal constant MODULEID__LIQUIDATION = 3; uint internal constant MODULEID__GOVERNANCE = 4; uint internal constant MODULEID__EXEC = 5; uint internal constant MODULEID__SWAP = 6; uint internal constant MAX_EXTERNAL_SINGLE_PROXY_MODULEID = 499_999; // Public multi-proxy modules uint internal constant MODULEID__ETOKEN = 500_000; uint internal constant MODULEID__DTOKEN = 500_001; uint internal constant MAX_EXTERNAL_MODULEID = 999_999; // Internal modules uint internal constant MODULEID__RISK_MANAGER = 1_000_000; // Interest rate models // Default for new markets uint internal constant MODULEID__IRM_DEFAULT = 2_000_000; // Testing-only uint internal constant MODULEID__IRM_ZERO = 2_000_001; uint internal constant MODULEID__IRM_FIXED = 2_000_002; uint internal constant MODULEID__IRM_LINEAR = 2_000_100; // Classes uint internal constant MODULEID__IRM_CLASS__STABLE = 2_000_500; uint internal constant MODULEID__IRM_CLASS__MAJOR = 2_000_501; uint internal constant MODULEID__IRM_CLASS__MIDCAP = 2_000_502; uint internal constant MODULEID__IRM_CLASS__MEGA = 2_000_503; // Swap types uint internal constant SWAP_TYPE__UNI_EXACT_INPUT_SINGLE = 1; uint internal constant SWAP_TYPE__UNI_EXACT_INPUT = 2; uint internal constant SWAP_TYPE__UNI_EXACT_OUTPUT_SINGLE = 3; uint internal constant SWAP_TYPE__UNI_EXACT_OUTPUT = 4; uint internal constant SWAP_TYPE__1INCH = 5; uint internal constant SWAP_TYPE__UNI_EXACT_OUTPUT_SINGLE_REPAY = 6; uint internal constant SWAP_TYPE__UNI_EXACT_OUTPUT_REPAY = 7; }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"bytes32","name":"moduleGitCommit_","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalBalances","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBorrows","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"reserveBalance","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"poolSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestAccumulator","type":"uint256"},{"indexed":false,"internalType":"int96","name":"interestRate","type":"int96"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"AssetStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"}],"name":"DelegateAverageLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"EnterMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"ExitMarket","type":"event"},{"anonymous":false,"inputs":[],"name":"Genesis","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"GovConvertReserves","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"components":[{"internalType":"address","name":"eTokenAddress","type":"address"},{"internalType":"bool","name":"borrowIsolated","type":"bool"},{"internalType":"uint32","name":"collateralFactor","type":"uint32"},{"internalType":"uint32","name":"borrowFactor","type":"uint32"},{"internalType":"uint24","name":"twapWindow","type":"uint24"}],"indexed":false,"internalType":"struct Storage.AssetConfig","name":"newConfig","type":"tuple"}],"name":"GovSetAssetConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"address","name":"chainlinkAggregator","type":"address"}],"name":"GovSetChainlinkPriceFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"uint256","name":"interestRateModel","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"resetParams","type":"bytes"}],"name":"GovSetIRM","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"uint16","name":"newPricingType","type":"uint16"},{"indexed":false,"internalType":"uint32","name":"newPricingParameter","type":"uint32"}],"name":"GovSetPricingConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"uint32","name":"newReserveFee","type":"uint32"}],"name":"GovSetReserveFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"moduleId","type":"uint256"},{"indexed":true,"internalType":"address","name":"moduleImpl","type":"address"},{"indexed":false,"internalType":"bytes32","name":"moduleGitCommit","type":"bytes32"}],"name":"InstallerInstallModule","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newGovernorAdmin","type":"address"}],"name":"InstallerSetGovernorAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newUpgradeAdmin","type":"address"}],"name":"InstallerSetUpgradeAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"address","name":"violator","type":"address"},{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"repay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yield","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"healthScore","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseDiscount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"discount","type":"uint256"}],"name":"Liquidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"eToken","type":"address"},{"indexed":true,"internalType":"address","name":"dToken","type":"address"}],"name":"MarketActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"pToken","type":"address"}],"name":"PTokenActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PTokenUnWrap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PTokenWrap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proxy","type":"address"},{"indexed":false,"internalType":"uint256","name":"moduleId","type":"uint256"}],"name":"ProxyCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Repay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestBorrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestDonate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"address","name":"violator","type":"address"},{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":false,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"repay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minYield","type":"uint256"}],"name":"RequestLiquidate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestRepay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"accountIn","type":"address"},{"indexed":true,"internalType":"address","name":"accountOut","type":"address"},{"indexed":true,"internalType":"address","name":"underlyingIn","type":"address"},{"indexed":false,"internalType":"address","name":"underlyingOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapType","type":"uint256"}],"name":"RequestSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestTransferDToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestTransferEToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"TrackAverageLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"UnTrackAverageLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlying","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"subAccountId","type":"uint256"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveSubAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"subAccountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"name":"convertBalanceToUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"underlyingAmount","type":"uint256"}],"name":"convertUnderlyingToBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"subAccountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"subAccountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"donateToReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"subAccountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"moduleGitCommit","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"moduleId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserveBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserveBalanceUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"touch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"transferFromMax","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlyingAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"subAccountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b506040516200499c3803806200499c833981016040819052620000349162000044565b6207a12060805260a0526200005e565b6000602082840312156200005757600080fd5b5051919050565b60805160a0516149186200008460003960006102b40152600061032b01526149186000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370a08231116100ee578063a9059cbb11610097578063dd62ed3e11610071578063dd62ed3e1461038e578063e2bbb158146103a1578063e73277d0146103b4578063fea61faa146103bc57600080fd5b8063a9059cbb14610355578063b390c0ab14610368578063cbfdd7e11461037b57600080fd5b8063a10954fe116100c8578063a10954fe1461031e578063a1308f2714610326578063a55526db1461034d57600080fd5b806370a08231146102d65780637158da7c146102e957806395d89b411461031657600080fd5b8063313ce5671161015b5780633af9e669116101355780633af9e66914610276578063441a3e701461028957806352eac8af1461029c57806369a92ea3146102af57600080fd5b8063313ce5671461024157806332d1ca9b1461025057806336f022aa1461026357600080fd5b806318160ddd1161018c57806318160ddd146102115780631b2ef1ca1461021957806323b872dd1461022e57600080fd5b8063010ad6d1146101b357806306fdde03146101d9578063095ea7b3146101ee575b600080fd5b6101c66101c1366004614268565b6103c4565b6040519081526020015b60405180910390f35b6101e1610408565b6040516101d091906142b1565b6102016101fc36600461432b565b6104cf565b60405190151581526020016101d0565b6101c66104e6565b61022c610227366004614355565b610521565b005b61020161023c366004614377565b6106a0565b604051601281526020016101d0565b61020161025e3660046143b3565b610a7b565b61022c610271366004614355565b610bef565b6101c66102843660046143d8565b610f17565b61022c610297366004614355565b610f83565b6101c66102aa366004614268565b611119565b6101c67f000000000000000000000000000000000000000000000000000000000000000081565b6101c66102e43660046143d8565b61114d565b6102f161119c565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6101e16111b1565b6101c6611263565b6101c67f000000000000000000000000000000000000000000000000000000000000000081565b61022c61129c565b61020161036336600461432b565b611349565b61022c610376366004614355565b611357565b6102016103893660046143f3565b6114e6565b6101c661039c3660046143f3565b611544565b61022c6103af366004614355565b611590565b6101c6611769565b6101c66117be565b60008060006103d1611803565b50509150915060006103e383836118ed565b9050806101a001516103f582876119e2565b6103ff9190614484565b95945050505050565b60606000610414611803565b50505090508073ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610464573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104aa91908101906144ee565b6040516020016104ba91906145b9565b60405160208183030381529060405291505090565b60006104dd60008484610a7b565b90505b92915050565b60008060006104f3611803565b505091509150600061050583836118ed565b602001516dffffffffffffffffffffffffffff16949350505050565b600160005414610592576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e6379000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600260009081558080806105a4611803565b935093509350935060006105b88288611a0d565b90506105c381611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167f7053340faeaa787c14d517bde5b7f4f7e1ebc393c59b246723598563d39af9ed8760405161060b91815260200190565b60405180910390a2600061061f8686611b65565b905061062b8188611cc6565b965060006106398289611d43565b905061064582826119e2565b97506106548683878685611d79565b600286015461067e908790849073ffffffffffffffffffffffffffffffffffffffff16868c611eed565b610687836120c9565b6106908261222b565b5050600160005550505050505050565b600060016000541461070e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b60026000908155808080610720611803565b935093509350935060006107348585611b65565b905073ffffffffffffffffffffffffffffffffffffffff8916610755578198505b8773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156107eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f652f73656c662d7472616e7366657200000000000000000000000000000000006044820152606401610589565b6107f489611a7f565b6107fd88611a7f565b8773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f05c051db3761ec29f60be6db25acec44695498d628df7aa22ebff5a2922f8ffb8960405161085c91815260200190565b60405180910390a38661087757600195505050505050610a6f565b60ff80831773ffffffffffffffffffffffffffffffffffffffff908116918b1716141580156108fa575073ffffffffffffffffffffffffffffffffffffffff808a1660009081526006860160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156109e95773ffffffffffffffffffffffffffffffffffffffff808a16600090815260068601602090815260408083209386168352929052205487111561099d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f652f696e73756666696369656e742d616c6c6f77616e636500000000000000006044820152606401610589565b73ffffffffffffffffffffffffffffffffffffffff898116600090815260068601602090815260408083209386168352929052208054889003908190556109e99084908b90859061230a565b6109f78482858c8c8c6124a2565b610a00896120c9565b73ffffffffffffffffffffffffffffffffffffffff881660009081526005850160205260409020546e010000000000000000000000000000900471ffffffffffffffffffffffffffffffffffff1615610a5c57610a5c886120c9565b610a658161222b565b6001955050505050505b60016000559392505050565b6000600160005414610ae9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b600260009081558080610afa611803565b935093509350506000610b0d8289611a0d565b905060ff80881773ffffffffffffffffffffffffffffffffffffffff908116918317161415610b98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f652f73656c662d617070726f76616c00000000000000000000000000000000006044820152606401610589565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526006860160209081526040808320938b16835292905220869055610bdb8382898961230a565b600194505050505060016000559392505050565b600160005414610c5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b60026000908155808080610c6d611803565b93509350935093506000610c818288611a0d565b9050610c8c81611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167f1e090bfa40abafd9102cc09ab955b704519a275c8e78b2549f66c1b4439ce9d787604051610cd491815260200190565b60405180910390a26000610ce88686611b65565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005870160205260408120549192506dffffffffffffffffffffffffffff909116907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff891415610d5957509650866000610dc8565b88821015610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f652f696e73756666696369656e742d62616c616e6365000000000000000000006044820152606401610589565b508781035b610dd1816126d4565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600589016020526040902080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff929092169190911790556060830151610e5c90610e57908b906bffffffffffffffffffffffff166145fe565b612752565b6bffffffffffffffffffffffff16606084018190526001880180547401000000000000000000000000000000000000000090920273ffffffffffffffffffffffffffffffffffffffff92831617905583516040518683169291909116907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90610ee8908d815260200190565b60405180910390a3610efd868560008c6127f0565b610f068361222b565b505060016000555050505050505050565b6000806000610f24611803565b5050915091506000610f3683836118ed565b6101a081015173ffffffffffffffffffffffffffffffffffffffff87166000908152600585016020526040902054919250906103f59083906dffffffffffffffffffffffffffff166119e2565b600160005414610fef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b60026000908155808080611001611803565b935093509350935060006110158288611a0d565b905061102081611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167f0afd74a2a0a78f6c15e41029f44995ee023fe49276f44a4b2b2cf674829362e68760405161106891815260200190565b60405180910390a2600061107c8686611b65565b9050600061108c8683858b61289d565b6101808401519199509150881115611100576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f652f696e73756666696369656e742d706f6f6c2d73697a6500000000000000006044820152606401610589565b61110b82858a61293a565b5061067e86838786856129f4565b6000806000611126611803565b505091509150600061113883836118ed565b90506103ff816111488388611cc6565b612bcc565b600080611158611803565b505073ffffffffffffffffffffffffffffffffffffffff9094166000908152600590940160205250506040909120546dffffffffffffffffffffffffffff16919050565b6000806111a7611803565b5091949350505050565b606060006111bd611803565b50505090508073ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561120d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261125391908101906144ee565b6040516020016104ba9190614616565b6000806000611270611803565b505091509150600061128283836118ed565b606001516bffffffffffffffffffffffff16949350505050565b600160005414611308576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b6002600090815580611318611803565b505091509150600061132a8383611b65565b90506113368282612bed565b61133f8161222b565b5050600160005550565b60006104dd600084846106a0565b6001600054146113c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b600260009081558080806113d5611803565b935093509350935060006113e98288611a0d565b90506113f481611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167ff05dc13309edd62ddfddf2ba57299daa8fc08d8be6d2fad6c648fa9b2b0d91df8760405161143c91815260200190565b60405180910390a260006114508686611b65565b9050600061145f868385612d56565b90508061147257505050505050506114dd565b60006114808784868c61289d565b90995090508189111561149d5781985061149a838a611d43565b90505b6114aa87848887856129f4565b60028701546114d4908890859073ffffffffffffffffffffffffffffffffffffffff16878d612dc4565b610efd846120c9565b50506001600055565b6000806114f1611803565b505073ffffffffffffffffffffffffffffffffffffffff8616600090815260058201602052604090205490925061153c9150859085906dffffffffffffffffffffffffffff166106a0565b949350505050565b60008061154f611803565b505073ffffffffffffffffffffffffffffffffffffffff95861660009081526006919091016020908152604080832096909716825294909452505050205490565b6001600054146115fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b6002600090815580808061160e611803565b935093509350935060006116228288611a0d565b905061162d81611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167fab5515522df06610b9fbcbbbd8416018226aca39364adcf5524751fcfef40ae58760405161167591815260200190565b60405180910390a260006116898686611b65565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8714156116c0576116bd8184612f9a565b96505b6116ca8188611cc6565b965060006116d982858a6130b8565b610180830180518290039052905060006116f38383612bcc565b6101808401805184019052905061170d8784888785611d79565b73ffffffffffffffffffffffffffffffffffffffff841660009081526005880160205260409020546e010000000000000000000000000000900471ffffffffffffffffffffffffffffffffffff1615610efd57610efd846120c9565b6000806000611776611803565b505091509150600061178883836118ed565b9050806101a001516117ac8283606001516bffffffffffffffffffffffff166119e2565b6117b69190614484565b935050505090565b60008060006117cb611803565b50509150915060006117dd83836118ed565b9050806101a001516117ac8283602001516dffffffffffffffffffffffffffff166119e2565b367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec810135606090811c6000818152600960205260409020600181015473ffffffffffffffffffffffffffffffffffffffff169390927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd890910135901c836118e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f652f756e7265636f676e697a65642d65746f6b656e2d63616c6c6572000000006044820152606401610589565b90919293565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c0810182905290546001146119d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f652f726f2d7265656e7472616e637900000000000000000000000000000000006044820152606401610589565b6119db83838361316e565b5092915050565b6000806119ee846135e1565b9050670de0b6b3a7640000611a03828561465b565b61153c9190614484565b60006101008210611a7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f652f7375622d6163636f756e742d69642d746f6f2d62696700000000000000006044820152606401610589565b501890565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040902054610100900464ffffffffff1680611aba575050565b6000611ac68242614698565b905080611ad257505050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff166101004264ffffffffff1602179055611b34838261368a565b73ffffffffffffffffffffffffffffffffffffffff9093166000908152600660205260409020600101929092555050565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c0810191909152611be983838361316e565b156104e05760a0810151825464ffffffffff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909116178255805160608201516bffffffffffffffffffffffff16740100000000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff9091161760018301556020810151604082015171ffffffffffffffffffffffffffffffffffff166e010000000000000000000000000000026dffffffffffffffffffffffffffff9091161760038301556080810151600483015592915050565b6000826101c00151821115611d37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f652f616d6f756e742d746f6f2d6c6172676500000000000000000000000000006044820152606401610589565b506101a0909101510290565b600080611d4f846135e1565b905080611d5d600182614698565b611d6f85670de0b6b3a764000061465b565b611a0391906145fe565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600586016020526040902054611dc590611dc09083906dffffffffffffffffffffffffffff166145fe565b6126d4565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600587016020908152604090912080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff938416179055850151611e3b91611dc0918491166145fe565b6dffffffffffffffffffffffffffff16602085018190526003860180547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169091179055611e898585612bed565b835160405182815273ffffffffffffffffffffffffffffffffffffffff8085169216907f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629060200160405180910390a3611ee683600084846127f0565b5050505050565b611efb633b9aca008261465b565b61014085015190915061ffff166003141580611f3e5750835173ffffffffffffffffffffffffffffffffffffffff9081166000908152600b602052604090205416155b611fa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f652f626f72726f772d6e6f742d737570706f72746564000000000000000000006044820152606401610589565b600080611fb2878786613755565b915091508160001415611fcd57611fcd848760000151613835565b611fd783836145fe565b9150611fe282613aed565b73ffffffffffffffffffffffffffffffffffffffff851660009081526005890160205260409081902080546dffffffffffffffffffffffffffff166e01000000000000000000000000000071ffffffffffffffffffffffffffffffffffff9485160217905587015161205f9161205a918691166145fe565b613aed565b71ffffffffffffffffffffffffffffffffffff16604087018190526003880180546dffffffffffffffffffffffffffff166e0100000000000000000000000000009092029190911790556120b38787612bed565b6120c08686868486613b91565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff16806121cc5760405173ffffffffffffffffffffffffffffffffffffffff831660248201526121c790620f4240907fc39b543a00000000000000000000000000000000000000000000000000000000906044015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613d04565b505050565b60ff8116600114156122275773ffffffffffffffffffffffffffffffffffffffff8216600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660021790555b5050565b806000015173ffffffffffffffffffffffffffffffffffffffff167f2f2d732e1a7a15fe7a2e51d3482efe83ff791579cebc5e3cd12cd2064374bc7f8260200151633b9aca00846040015171ffffffffffffffffffffffffffffffffffff166122949190614484565b6060808601516101808701516080808901516101008a0151604080516dffffffffffffffffffffffffffff909916895260208901979097526bffffffffffffffffffffffff909416958701959095529285015290830191909152600b0b60a08201524260c082015260e00160405180910390a250565b6000604051905060008573ffffffffffffffffffffffffffffffffffffffff1660036040518060600160405280602181526020016148a160219139805160209182012060405160f89390931b7fff000000000000000000000000000000000000000000000000000000000000001691830191909152602182015273ffffffffffffffffffffffffffffffffffffffff8781166041830152861660618201526081810185905260a1015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526123eb916146af565b6000604051808303816000865af19150503d8060008114612428576040519150601f19603f3d011682016040523d82523d6000602084013e61242d565b606091505b5050905080612498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f652f6c6f672d70726f78792d6661696c000000000000000000000000000000006044820152606401610589565b5060405250505050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005870160205260409020546dffffffffffffffffffffffffffff1681811015612544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f652f696e73756666696369656e742d62616c616e6365000000000000000000006044820152606401610589565b818103612550816126d4565b73ffffffffffffffffffffffffffffffffffffffff868116600090815260058b01602052604080822080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff958616179055918716815220546125c991611dc0918691166145fe565b73ffffffffffffffffffffffffffffffffffffffff858116600090815260058b01602090815260409182902080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff9590951694909417909355895190518681528883169391909216917f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb910160405180910390a3865160405184815273ffffffffffffffffffffffffffffffffffffffff8087169216907f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629060200160405180910390a36126ca868686866127f0565b5050505050505050565b60006dffffffffffffffffffffffffffff82111561274e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f652f616d6f756e742d746f6f2d6c617267652d746f2d656e636f6465000000006044820152606401610589565b5090565b60006bffffffffffffffffffffffff82111561274e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f652f736d616c6c2d616d6f756e742d746f6f2d6c617267652d746f2d656e636f60448201527f64650000000000000000000000000000000000000000000000000000000000006064820152608401610589565b6000604051905060008573ffffffffffffffffffffffffffffffffffffffff1660036040518060600160405280602181526020016148c260219139805160209182012060405160f89390931b7fff000000000000000000000000000000000000000000000000000000000000001691830191909152602182015273ffffffffffffffffffffffffffffffffffffffff8781166041830152861660618201526081810185905260a1016123b3565b60008060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841415612914575073ffffffffffffffffffffffffffffffffffffffff841660009081526005870160205260409020546dffffffffffffffffffffffffffff1661290d86826119e2565b935061292d565b61291e8685611cc6565b935061292a8685611d43565b90505b9296929550919350505050565b61018083015183516101a08501516000929161296191869061295c9087614484565b613d93565b6000612976866129718830612f9a565b611cc6565b61018087018190529050808210156129ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f652f6e656761746976652d7472616e736665722d616d6f756e740000000000006044820152606401610589565b9003949350505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526005860160205260409020546dffffffffffffffffffffffffffff1681811015612a96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f652f696e73756666696369656e742d62616c616e6365000000000000000000006044820152606401610589565b612aa3611dc08383614698565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600588016020908152604090912080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff938416179055860151612b1991611dc091859116614698565b6dffffffffffffffffffffffffffff16602086018190526003870180547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169091179055612b678686612bed565b845160405183815273ffffffffffffffffffffffffffffffffffffffff8086169216907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9060200160405180910390a3612bc484846000856127f0565b505050505050565b600080612bd8846135e1565b905080611a0384670de0b6b3a764000061465b565b600080633b9aca00836040015171ffffffffffffffffffffffffffffffffffff16612c189190614484565b9050600081846101800151612c2d91906145fe565b905080612c3d5760009250612c76565b670de0b6b3a764000081612c5563ffffffff8361465b565b612c5f908561465b565b612c699190614484565b612c739190614484565b92505b505060e0820151825160405173ffffffffffffffffffffffffffffffffffffffff909116602482015263ffffffff8381166044830152600092612ce0929116907fd50c08f80000000000000000000000000000000000000000000000000000000090606401612145565b9050600081806020019051810190612cf891906146cb565b600b81900b61010090950194909452505082546bffffffffffffffffffffffff9092166a0100000000000000000000027fffffffffffffffffffff000000000000000000000000ffffffffffffffffffff9092169190911790915550565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600584016020526040812054633b9aca0090611a03908590612dbf908890839088906e010000000000000000000000000000900471ffffffffffffffffffffffffffffffffffff16613ecf565b613f18565b6000612dd4633b9aca008361465b565b9050600080612de4888887613755565b915091506000612df48884613f18565b905080841115612e60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f652f72657061792d746f6f2d6d756368000000000000000000000000000000006044820152606401610589565b60408801518482039071ffffffffffffffffffffffffffffffffffff16841115612ea057886040015171ffffffffffffffffffffffffffffffffffff1693505b612ea981613aed565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260058c0160205260409081902080546dffffffffffffffffffffffffffff166e01000000000000000000000000000071ffffffffffffffffffffffffffffffffffff948516021790558a0151612f2d918391612f2391889116614698565b61205a91906145fe565b71ffffffffffffffffffffffffffffffffffff1660408a0181905260038b0180546dffffffffffffffffffffffffffff166e010000000000000000000000000000909202919091179055612f818a8a612bed565b612f8e8989898685613b91565b50505050505050505050565b60408051835173ffffffffffffffffffffffffffffffffffffffff848116602480850191909152845180850390910181526044840185526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a0823100000000000000000000000000000000000000000000000000000000179052935160009485938493169162030d4091613032916146af565b6000604051808303818686fa925050503d806000811461306e576040519150601f19603f3d011682016040523d82523d6000602084013e613073565b606091505b5091509150811580613086575060208151105b15613096576000935050506130af565b808060200190518101906130aa91906146ee565b935050505b60405292915050565b61018083015183516101a0850151600092916130e191869030906130dc9088614484565b613f71565b60006130f1866129718830612f9a565b6101808701819052905081811015613165576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f652f6e656761746976652d7472616e736665722d616d6f756e740000000000006044820152606401610589565b03949350505050565b73ffffffffffffffffffffffffffffffffffffffff83168152815464ffffffffff811660a083015265010000000000810460ff90811660c084018190526601000000000000830463ffffffff90811660e08601526a01000000000000000000008404600b0b610100860152760100000000000000000000000000000000000000000000840481166101208601527a010000000000000000000000000000000000000000000000000000840461ffff166101408601527c010000000000000000000000000000000000000000000000000000000090930490921661016084015260018401547401000000000000000000000000000000000000000090046bffffffffffffffffffffffff16606084015260038401546dffffffffffffffffffffffffffff80821660208601526e01000000000000000000000000000090910471ffffffffffffffffffffffffffffffffffff166040850152600485015460808501526012839003909116600a0a6101a0840181905260009291816132f3576132f3614426565b046101c084015260006133068430612f9a565b9050836101c001518111613327576101a08401518102610180850152613330565b60006101808501525b8360a0015164ffffffffff1642146135d8576001925060008460a0015164ffffffffff164261335f9190614698565b905060006b033b2e3c9fd0803ce800000086608001516133ab886101000151600b0b6b033b2e3c9fd0803ce80000006133989190614707565b856b033b2e3c9fd0803ce80000006140b5565b6133b5919061465b565b6133bf9190614484565b90506000866080015182886040015171ffffffffffffffffffffffffffffffffffff166133ec919061465b565b6133f69190614484565b606088015160208901519192506bffffffffffffffffffffffff16906dffffffffffffffffffffffffffff166000613436633b9aca0063ee6b280061465b565b6101208b015163ffffffff90811614613454578a610120015161345a565b6336d616005b63ffffffff168b6040015171ffffffffffffffffffffffffffffffffffff16866134849190614698565b61348e919061465b565b6134989190614484565b905080156135105760006134b0633b9aca0086614484565b8b61018001516134c091906145fe565b90506134cc8282614698565b6134d6848361465b565b6134e09190614484565b92508a602001516dffffffffffffffffffffffffffff16836135029190614698565b61350c90856145fe565b9350505b6dffffffffffffffffffffffffffff8211801590613540575071ffffffffffffffffffffffffffffffffffff8411155b156135d15761354e84613aed565b71ffffffffffffffffffffffffffffffffffff1660408b015260808a0185905264ffffffffff421660a08b015260208a01516dffffffffffffffffffffffffffff1682146135d15761359f83612752565b6bffffffffffffffffffffffff1660608b01526135bb826126d4565b6dffffffffffffffffffffffffffff1660208b01525b5050505050505b50509392505050565b600080633b9aca00836040015171ffffffffffffffffffffffffffffffffffff1661360c9190614484565b83610180015161361c91906145fe565b905080158061363d575060208301516dffffffffffffffffffffffffffff16155b156136525750670de0b6b3a764000092915050565b60208301516dffffffffffffffffffffffffffff1661367982670de0b6b3a764000061465b565b6136839190614484565b9392505050565b6000806201518083101561369e57826136a3565b620151805b905060006136b48262015180614698565b905060008060006136c488614172565b915091508082116136d65760006136e0565b6136e08183614698565b925050506201518083826136f4919061465b565b6136fe9190614484565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260066020526040902060010154620151809061373790859061465b565b6137419190614484565b61374b91906145fe565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005840160205260408120546e010000000000000000000000000000900471ffffffffffffffffffffffffffffffffffff166137af85858584613ecf565b91506137ba82613aed565b73ffffffffffffffffffffffffffffffffffffffff909316600090815260059095016020526040909420805471ffffffffffffffffffffffffffffffffffff939093166e010000000000000000000000000000026dffffffffffffffffffffffffffff90931692909217825560809092015160019091015591565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040808320805460079093529220660100000000000090910463ffffffff1690811561392d57825473ffffffffffffffffffffffffffffffffffffffff8581166a01000000000000000000009092041614156138b5575050505050565b60015b8263ffffffff1681101561392b578473ffffffffffffffffffffffffffffffffffffffff16828264010000000081106138f3576138f361477b565b015473ffffffffffffffffffffffffffffffffffffffff16141561391957505050505050565b80613923816147aa565b9150506138b8565b505b600a8263ffffffff161061399d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f652f746f6f2d6d616e792d656e74657265642d6d61726b6574730000000000006044820152606401610589565b63ffffffff82166139f85782547fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000073ffffffffffffffffffffffffffffffffffffffff861602178355613a5a565b83818363ffffffff166401000000008110613a1557613a1561477b565b0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169190911790555b613a658260016147e3565b835463ffffffff919091166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff90911617835560405173ffffffffffffffffffffffffffffffffffffffff80871691908616907f1c0971b8e0f7bb4e90bdbd87cfe682c36c383e2fc3dc4716ecc02771186293cc90600090a35050505050565b600071ffffffffffffffffffffffffffffffffffff82111561274e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f652f646562742d616d6f756e742d746f6f2d6c617267652d746f2d656e636f6460448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610589565b633b9aca00613ba08684613f18565b613baa9190614484565b9150633b9aca00613bbb8683613f18565b613bc59190614484565b905081811115613c6b576000613bdb8383614698565b90508373ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f312a5e5e1079f5dda4e95dbbd0b908b291fd5b992ef22073643ab691572c5b5283604051613c4091815260200190565b60405180910390a3613c6585600086896101a0015185613c609190614484565b6127f0565b50611ee6565b80821115611ee6576000613c7f8284614698565b90508373ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f05f2eeda0e08e4b437f487c8d7d29b14537d15e3488170dc3de5dbdf8dac468483604051613ce491815260200190565b60405180910390a3612bc485856000896101a0015185613c609190614484565b60008281526003602052604080822054905160609291829173ffffffffffffffffffffffffffffffffffffffff90911690613d409086906146af565b600060405180830381855af49150503d8060008114613d7b576040519150601f19603f3d011682016040523d82523d6000602084013e613d80565b606091505b50915091508161153c5761153c816141f7565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613e2a91906146af565b6000604051808303816000865af19150503d8060008114613e67576040519150601f19603f3d011682016040523d82523d6000602084013e613e6c565b606091505b5091509150818015613e96575080511580613e96575080806020019051810190613e96919061481b565b8190612bc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058991906142b1565b600081613ede5750600061153c565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260058601602052604090206001015460808501516103f5908461465b565b600081613f27575060006104e0565b6101a0830151633b9aca000280807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8582010181613f6757613f67614426565b0402949350505050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161401091906146af565b6000604051808303816000865af19150503d806000811461404d576040519150601f19603f3d011682016040523d82523d6000602084013e614052565b606091505b509150915081801561407c57508051158061407c57508080602001905181019061407c919061481b565b81906120c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058991906142b1565b6000838015614155576001841680156140d0578592506140d4565b8392505b50600283046002850494505b841561414f5785860286878204146140f757600080fd5b8181018181101561410757600080fd5b859004965050600185161561414457858302838782041415871515161561412d57600080fd5b8181018181101561413d57600080fd5b8590049350505b6002850494506140e0565b5061416a565b83801561416557600092506135d8565b839250505b509392505050565b60405173ffffffffffffffffffffffffffffffffffffffff82166024820152600090819081906141cb90620f4240907f37fe974a0000000000000000000000000000000000000000000000000000000090604401612145565b90506000818060200190518101906141e39190614836565b805160209091015190969095509350505050565b80511561420657805181602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f652f656d7074792d6572726f72000000000000000000000000000000000000006044820152606401610589565b60006020828403121561427a57600080fd5b5035919050565b60005b8381101561429c578181015183820152602001614284565b838111156142ab576000848401525b50505050565b60208152600082518060208401526142d0816040850160208701614281565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461432657600080fd5b919050565b6000806040838503121561433e57600080fd5b61434783614302565b946020939093013593505050565b6000806040838503121561436857600080fd5b50508035926020909101359150565b60008060006060848603121561438c57600080fd5b61439584614302565b92506143a360208501614302565b9150604084013590509250925092565b6000806000606084860312156143c857600080fd5b833592506143a360208501614302565b6000602082840312156143ea57600080fd5b6104dd82614302565b6000806040838503121561440657600080fd5b61440f83614302565b915061441d60208401614302565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000826144ba577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561450057600080fd5b815167ffffffffffffffff8082111561451857600080fd5b818401915084601f83011261452c57600080fd5b81518181111561453e5761453e6144bf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715614584576145846144bf565b8160405282815287602084870101111561459d57600080fd5b6145ae836020830160208801614281565b979650505050505050565b7f45756c657220506f6f6c3a2000000000000000000000000000000000000000008152600082516145f181600c850160208701614281565b91909101600c0192915050565b6000821982111561461157614611614455565b500190565b7f650000000000000000000000000000000000000000000000000000000000000081526000825161464e816001850160208701614281565b9190910160010192915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561469357614693614455565b500290565b6000828210156146aa576146aa614455565b500390565b600082516146c1818460208701614281565b9190910192915050565b6000602082840312156146dd57600080fd5b815180600b0b811461368357600080fd5b60006020828403121561470057600080fd5b5051919050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561474157614741614455565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561477557614775614455565b50500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156147dc576147dc614455565b5060010190565b600063ffffffff80831681851680830382111561480257614802614455565b01949350505050565b8051801515811461432657600080fd5b60006020828403121561482d57600080fd5b6104dd8261480b565b60006080828403121561484857600080fd5b6040516080810181811067ffffffffffffffff8211171561486b5761486b6144bf565b80604052508251815260208301516020820152604083015160408201526148946060840161480b565b6060820152939250505056fe417070726f76616c28616464726573732c616464726573732c75696e74323536295472616e7366657228616464726573732c616464726573732c75696e7432353629a26469706673582212202f2cac2fdfae08dfebde13530cc107d5a13009d89b5a63c66288a4eb315bfe6064736f6c634300080a0033000000000000000000000000d7f62927eb58592d82302c87205490c26cccca7c
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370a08231116100ee578063a9059cbb11610097578063dd62ed3e11610071578063dd62ed3e1461038e578063e2bbb158146103a1578063e73277d0146103b4578063fea61faa146103bc57600080fd5b8063a9059cbb14610355578063b390c0ab14610368578063cbfdd7e11461037b57600080fd5b8063a10954fe116100c8578063a10954fe1461031e578063a1308f2714610326578063a55526db1461034d57600080fd5b806370a08231146102d65780637158da7c146102e957806395d89b411461031657600080fd5b8063313ce5671161015b5780633af9e669116101355780633af9e66914610276578063441a3e701461028957806352eac8af1461029c57806369a92ea3146102af57600080fd5b8063313ce5671461024157806332d1ca9b1461025057806336f022aa1461026357600080fd5b806318160ddd1161018c57806318160ddd146102115780631b2ef1ca1461021957806323b872dd1461022e57600080fd5b8063010ad6d1146101b357806306fdde03146101d9578063095ea7b3146101ee575b600080fd5b6101c66101c1366004614268565b6103c4565b6040519081526020015b60405180910390f35b6101e1610408565b6040516101d091906142b1565b6102016101fc36600461432b565b6104cf565b60405190151581526020016101d0565b6101c66104e6565b61022c610227366004614355565b610521565b005b61020161023c366004614377565b6106a0565b604051601281526020016101d0565b61020161025e3660046143b3565b610a7b565b61022c610271366004614355565b610bef565b6101c66102843660046143d8565b610f17565b61022c610297366004614355565b610f83565b6101c66102aa366004614268565b611119565b6101c67f000000000000000000000000d7f62927eb58592d82302c87205490c26cccca7c81565b6101c66102e43660046143d8565b61114d565b6102f161119c565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6101e16111b1565b6101c6611263565b6101c67f000000000000000000000000000000000000000000000000000000000007a12081565b61022c61129c565b61020161036336600461432b565b611349565b61022c610376366004614355565b611357565b6102016103893660046143f3565b6114e6565b6101c661039c3660046143f3565b611544565b61022c6103af366004614355565b611590565b6101c6611769565b6101c66117be565b60008060006103d1611803565b50509150915060006103e383836118ed565b9050806101a001516103f582876119e2565b6103ff9190614484565b95945050505050565b60606000610414611803565b50505090508073ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610464573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104aa91908101906144ee565b6040516020016104ba91906145b9565b60405160208183030381529060405291505090565b60006104dd60008484610a7b565b90505b92915050565b60008060006104f3611803565b505091509150600061050583836118ed565b602001516dffffffffffffffffffffffffffff16949350505050565b600160005414610592576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e6379000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600260009081558080806105a4611803565b935093509350935060006105b88288611a0d565b90506105c381611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167f7053340faeaa787c14d517bde5b7f4f7e1ebc393c59b246723598563d39af9ed8760405161060b91815260200190565b60405180910390a2600061061f8686611b65565b905061062b8188611cc6565b965060006106398289611d43565b905061064582826119e2565b97506106548683878685611d79565b600286015461067e908790849073ffffffffffffffffffffffffffffffffffffffff16868c611eed565b610687836120c9565b6106908261222b565b5050600160005550505050505050565b600060016000541461070e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b60026000908155808080610720611803565b935093509350935060006107348585611b65565b905073ffffffffffffffffffffffffffffffffffffffff8916610755578198505b8773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156107eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f652f73656c662d7472616e7366657200000000000000000000000000000000006044820152606401610589565b6107f489611a7f565b6107fd88611a7f565b8773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f05c051db3761ec29f60be6db25acec44695498d628df7aa22ebff5a2922f8ffb8960405161085c91815260200190565b60405180910390a38661087757600195505050505050610a6f565b60ff80831773ffffffffffffffffffffffffffffffffffffffff908116918b1716141580156108fa575073ffffffffffffffffffffffffffffffffffffffff808a1660009081526006860160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156109e95773ffffffffffffffffffffffffffffffffffffffff808a16600090815260068601602090815260408083209386168352929052205487111561099d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f652f696e73756666696369656e742d616c6c6f77616e636500000000000000006044820152606401610589565b73ffffffffffffffffffffffffffffffffffffffff898116600090815260068601602090815260408083209386168352929052208054889003908190556109e99084908b90859061230a565b6109f78482858c8c8c6124a2565b610a00896120c9565b73ffffffffffffffffffffffffffffffffffffffff881660009081526005850160205260409020546e010000000000000000000000000000900471ffffffffffffffffffffffffffffffffffff1615610a5c57610a5c886120c9565b610a658161222b565b6001955050505050505b60016000559392505050565b6000600160005414610ae9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b600260009081558080610afa611803565b935093509350506000610b0d8289611a0d565b905060ff80881773ffffffffffffffffffffffffffffffffffffffff908116918317161415610b98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f652f73656c662d617070726f76616c00000000000000000000000000000000006044820152606401610589565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526006860160209081526040808320938b16835292905220869055610bdb8382898961230a565b600194505050505060016000559392505050565b600160005414610c5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b60026000908155808080610c6d611803565b93509350935093506000610c818288611a0d565b9050610c8c81611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167f1e090bfa40abafd9102cc09ab955b704519a275c8e78b2549f66c1b4439ce9d787604051610cd491815260200190565b60405180910390a26000610ce88686611b65565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005870160205260408120549192506dffffffffffffffffffffffffffff909116907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff891415610d5957509650866000610dc8565b88821015610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f652f696e73756666696369656e742d62616c616e6365000000000000000000006044820152606401610589565b508781035b610dd1816126d4565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600589016020526040902080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff929092169190911790556060830151610e5c90610e57908b906bffffffffffffffffffffffff166145fe565b612752565b6bffffffffffffffffffffffff16606084018190526001880180547401000000000000000000000000000000000000000090920273ffffffffffffffffffffffffffffffffffffffff92831617905583516040518683169291909116907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90610ee8908d815260200190565b60405180910390a3610efd868560008c6127f0565b610f068361222b565b505060016000555050505050505050565b6000806000610f24611803565b5050915091506000610f3683836118ed565b6101a081015173ffffffffffffffffffffffffffffffffffffffff87166000908152600585016020526040902054919250906103f59083906dffffffffffffffffffffffffffff166119e2565b600160005414610fef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b60026000908155808080611001611803565b935093509350935060006110158288611a0d565b905061102081611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167f0afd74a2a0a78f6c15e41029f44995ee023fe49276f44a4b2b2cf674829362e68760405161106891815260200190565b60405180910390a2600061107c8686611b65565b9050600061108c8683858b61289d565b6101808401519199509150881115611100576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f652f696e73756666696369656e742d706f6f6c2d73697a6500000000000000006044820152606401610589565b61110b82858a61293a565b5061067e86838786856129f4565b6000806000611126611803565b505091509150600061113883836118ed565b90506103ff816111488388611cc6565b612bcc565b600080611158611803565b505073ffffffffffffffffffffffffffffffffffffffff9094166000908152600590940160205250506040909120546dffffffffffffffffffffffffffff16919050565b6000806111a7611803565b5091949350505050565b606060006111bd611803565b50505090508073ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561120d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261125391908101906144ee565b6040516020016104ba9190614616565b6000806000611270611803565b505091509150600061128283836118ed565b606001516bffffffffffffffffffffffff16949350505050565b600160005414611308576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b6002600090815580611318611803565b505091509150600061132a8383611b65565b90506113368282612bed565b61133f8161222b565b5050600160005550565b60006104dd600084846106a0565b6001600054146113c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b600260009081558080806113d5611803565b935093509350935060006113e98288611a0d565b90506113f481611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167ff05dc13309edd62ddfddf2ba57299daa8fc08d8be6d2fad6c648fa9b2b0d91df8760405161143c91815260200190565b60405180910390a260006114508686611b65565b9050600061145f868385612d56565b90508061147257505050505050506114dd565b60006114808784868c61289d565b90995090508189111561149d5781985061149a838a611d43565b90505b6114aa87848887856129f4565b60028701546114d4908890859073ffffffffffffffffffffffffffffffffffffffff16878d612dc4565b610efd846120c9565b50506001600055565b6000806114f1611803565b505073ffffffffffffffffffffffffffffffffffffffff8616600090815260058201602052604090205490925061153c9150859085906dffffffffffffffffffffffffffff166106a0565b949350505050565b60008061154f611803565b505073ffffffffffffffffffffffffffffffffffffffff95861660009081526006919091016020908152604080832096909716825294909452505050205490565b6001600054146115fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610589565b6002600090815580808061160e611803565b935093509350935060006116228288611a0d565b905061162d81611a7f565b8073ffffffffffffffffffffffffffffffffffffffff167fab5515522df06610b9fbcbbbd8416018226aca39364adcf5524751fcfef40ae58760405161167591815260200190565b60405180910390a260006116898686611b65565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8714156116c0576116bd8184612f9a565b96505b6116ca8188611cc6565b965060006116d982858a6130b8565b610180830180518290039052905060006116f38383612bcc565b6101808401805184019052905061170d8784888785611d79565b73ffffffffffffffffffffffffffffffffffffffff841660009081526005880160205260409020546e010000000000000000000000000000900471ffffffffffffffffffffffffffffffffffff1615610efd57610efd846120c9565b6000806000611776611803565b505091509150600061178883836118ed565b9050806101a001516117ac8283606001516bffffffffffffffffffffffff166119e2565b6117b69190614484565b935050505090565b60008060006117cb611803565b50509150915060006117dd83836118ed565b9050806101a001516117ac8283602001516dffffffffffffffffffffffffffff166119e2565b367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec810135606090811c6000818152600960205260409020600181015473ffffffffffffffffffffffffffffffffffffffff169390927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd890910135901c836118e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f652f756e7265636f676e697a65642d65746f6b656e2d63616c6c6572000000006044820152606401610589565b90919293565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c0810182905290546001146119d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f652f726f2d7265656e7472616e637900000000000000000000000000000000006044820152606401610589565b6119db83838361316e565b5092915050565b6000806119ee846135e1565b9050670de0b6b3a7640000611a03828561465b565b61153c9190614484565b60006101008210611a7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f652f7375622d6163636f756e742d69642d746f6f2d62696700000000000000006044820152606401610589565b501890565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040902054610100900464ffffffffff1680611aba575050565b6000611ac68242614698565b905080611ad257505050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff166101004264ffffffffff1602179055611b34838261368a565b73ffffffffffffffffffffffffffffffffffffffff9093166000908152600660205260409020600101929092555050565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c0810191909152611be983838361316e565b156104e05760a0810151825464ffffffffff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909116178255805160608201516bffffffffffffffffffffffff16740100000000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff9091161760018301556020810151604082015171ffffffffffffffffffffffffffffffffffff166e010000000000000000000000000000026dffffffffffffffffffffffffffff9091161760038301556080810151600483015592915050565b6000826101c00151821115611d37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f652f616d6f756e742d746f6f2d6c6172676500000000000000000000000000006044820152606401610589565b506101a0909101510290565b600080611d4f846135e1565b905080611d5d600182614698565b611d6f85670de0b6b3a764000061465b565b611a0391906145fe565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600586016020526040902054611dc590611dc09083906dffffffffffffffffffffffffffff166145fe565b6126d4565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600587016020908152604090912080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff938416179055850151611e3b91611dc0918491166145fe565b6dffffffffffffffffffffffffffff16602085018190526003860180547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169091179055611e898585612bed565b835160405182815273ffffffffffffffffffffffffffffffffffffffff8085169216907f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629060200160405180910390a3611ee683600084846127f0565b5050505050565b611efb633b9aca008261465b565b61014085015190915061ffff166003141580611f3e5750835173ffffffffffffffffffffffffffffffffffffffff9081166000908152600b602052604090205416155b611fa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f652f626f72726f772d6e6f742d737570706f72746564000000000000000000006044820152606401610589565b600080611fb2878786613755565b915091508160001415611fcd57611fcd848760000151613835565b611fd783836145fe565b9150611fe282613aed565b73ffffffffffffffffffffffffffffffffffffffff851660009081526005890160205260409081902080546dffffffffffffffffffffffffffff166e01000000000000000000000000000071ffffffffffffffffffffffffffffffffffff9485160217905587015161205f9161205a918691166145fe565b613aed565b71ffffffffffffffffffffffffffffffffffff16604087018190526003880180546dffffffffffffffffffffffffffff166e0100000000000000000000000000009092029190911790556120b38787612bed565b6120c08686868486613b91565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff16806121cc5760405173ffffffffffffffffffffffffffffffffffffffff831660248201526121c790620f4240907fc39b543a00000000000000000000000000000000000000000000000000000000906044015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613d04565b505050565b60ff8116600114156122275773ffffffffffffffffffffffffffffffffffffffff8216600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660021790555b5050565b806000015173ffffffffffffffffffffffffffffffffffffffff167f2f2d732e1a7a15fe7a2e51d3482efe83ff791579cebc5e3cd12cd2064374bc7f8260200151633b9aca00846040015171ffffffffffffffffffffffffffffffffffff166122949190614484565b6060808601516101808701516080808901516101008a0151604080516dffffffffffffffffffffffffffff909916895260208901979097526bffffffffffffffffffffffff909416958701959095529285015290830191909152600b0b60a08201524260c082015260e00160405180910390a250565b6000604051905060008573ffffffffffffffffffffffffffffffffffffffff1660036040518060600160405280602181526020016148a160219139805160209182012060405160f89390931b7fff000000000000000000000000000000000000000000000000000000000000001691830191909152602182015273ffffffffffffffffffffffffffffffffffffffff8781166041830152861660618201526081810185905260a1015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526123eb916146af565b6000604051808303816000865af19150503d8060008114612428576040519150601f19603f3d011682016040523d82523d6000602084013e61242d565b606091505b5050905080612498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f652f6c6f672d70726f78792d6661696c000000000000000000000000000000006044820152606401610589565b5060405250505050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005870160205260409020546dffffffffffffffffffffffffffff1681811015612544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f652f696e73756666696369656e742d62616c616e6365000000000000000000006044820152606401610589565b818103612550816126d4565b73ffffffffffffffffffffffffffffffffffffffff868116600090815260058b01602052604080822080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff958616179055918716815220546125c991611dc0918691166145fe565b73ffffffffffffffffffffffffffffffffffffffff858116600090815260058b01602090815260409182902080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff9590951694909417909355895190518681528883169391909216917f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb910160405180910390a3865160405184815273ffffffffffffffffffffffffffffffffffffffff8087169216907f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629060200160405180910390a36126ca868686866127f0565b5050505050505050565b60006dffffffffffffffffffffffffffff82111561274e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f652f616d6f756e742d746f6f2d6c617267652d746f2d656e636f6465000000006044820152606401610589565b5090565b60006bffffffffffffffffffffffff82111561274e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f652f736d616c6c2d616d6f756e742d746f6f2d6c617267652d746f2d656e636f60448201527f64650000000000000000000000000000000000000000000000000000000000006064820152608401610589565b6000604051905060008573ffffffffffffffffffffffffffffffffffffffff1660036040518060600160405280602181526020016148c260219139805160209182012060405160f89390931b7fff000000000000000000000000000000000000000000000000000000000000001691830191909152602182015273ffffffffffffffffffffffffffffffffffffffff8781166041830152861660618201526081810185905260a1016123b3565b60008060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841415612914575073ffffffffffffffffffffffffffffffffffffffff841660009081526005870160205260409020546dffffffffffffffffffffffffffff1661290d86826119e2565b935061292d565b61291e8685611cc6565b935061292a8685611d43565b90505b9296929550919350505050565b61018083015183516101a08501516000929161296191869061295c9087614484565b613d93565b6000612976866129718830612f9a565b611cc6565b61018087018190529050808210156129ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f652f6e656761746976652d7472616e736665722d616d6f756e740000000000006044820152606401610589565b9003949350505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526005860160205260409020546dffffffffffffffffffffffffffff1681811015612a96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f652f696e73756666696369656e742d62616c616e6365000000000000000000006044820152606401610589565b612aa3611dc08383614698565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600588016020908152604090912080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff938416179055860151612b1991611dc091859116614698565b6dffffffffffffffffffffffffffff16602086018190526003870180547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169091179055612b678686612bed565b845160405183815273ffffffffffffffffffffffffffffffffffffffff8086169216907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9060200160405180910390a3612bc484846000856127f0565b505050505050565b600080612bd8846135e1565b905080611a0384670de0b6b3a764000061465b565b600080633b9aca00836040015171ffffffffffffffffffffffffffffffffffff16612c189190614484565b9050600081846101800151612c2d91906145fe565b905080612c3d5760009250612c76565b670de0b6b3a764000081612c5563ffffffff8361465b565b612c5f908561465b565b612c699190614484565b612c739190614484565b92505b505060e0820151825160405173ffffffffffffffffffffffffffffffffffffffff909116602482015263ffffffff8381166044830152600092612ce0929116907fd50c08f80000000000000000000000000000000000000000000000000000000090606401612145565b9050600081806020019051810190612cf891906146cb565b600b81900b61010090950194909452505082546bffffffffffffffffffffffff9092166a0100000000000000000000027fffffffffffffffffffff000000000000000000000000ffffffffffffffffffff9092169190911790915550565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600584016020526040812054633b9aca0090611a03908590612dbf908890839088906e010000000000000000000000000000900471ffffffffffffffffffffffffffffffffffff16613ecf565b613f18565b6000612dd4633b9aca008361465b565b9050600080612de4888887613755565b915091506000612df48884613f18565b905080841115612e60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f652f72657061792d746f6f2d6d756368000000000000000000000000000000006044820152606401610589565b60408801518482039071ffffffffffffffffffffffffffffffffffff16841115612ea057886040015171ffffffffffffffffffffffffffffffffffff1693505b612ea981613aed565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260058c0160205260409081902080546dffffffffffffffffffffffffffff166e01000000000000000000000000000071ffffffffffffffffffffffffffffffffffff948516021790558a0151612f2d918391612f2391889116614698565b61205a91906145fe565b71ffffffffffffffffffffffffffffffffffff1660408a0181905260038b0180546dffffffffffffffffffffffffffff166e010000000000000000000000000000909202919091179055612f818a8a612bed565b612f8e8989898685613b91565b50505050505050505050565b60408051835173ffffffffffffffffffffffffffffffffffffffff848116602480850191909152845180850390910181526044840185526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a0823100000000000000000000000000000000000000000000000000000000179052935160009485938493169162030d4091613032916146af565b6000604051808303818686fa925050503d806000811461306e576040519150601f19603f3d011682016040523d82523d6000602084013e613073565b606091505b5091509150811580613086575060208151105b15613096576000935050506130af565b808060200190518101906130aa91906146ee565b935050505b60405292915050565b61018083015183516101a0850151600092916130e191869030906130dc9088614484565b613f71565b60006130f1866129718830612f9a565b6101808701819052905081811015613165576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f652f6e656761746976652d7472616e736665722d616d6f756e740000000000006044820152606401610589565b03949350505050565b73ffffffffffffffffffffffffffffffffffffffff83168152815464ffffffffff811660a083015265010000000000810460ff90811660c084018190526601000000000000830463ffffffff90811660e08601526a01000000000000000000008404600b0b610100860152760100000000000000000000000000000000000000000000840481166101208601527a010000000000000000000000000000000000000000000000000000840461ffff166101408601527c010000000000000000000000000000000000000000000000000000000090930490921661016084015260018401547401000000000000000000000000000000000000000090046bffffffffffffffffffffffff16606084015260038401546dffffffffffffffffffffffffffff80821660208601526e01000000000000000000000000000090910471ffffffffffffffffffffffffffffffffffff166040850152600485015460808501526012839003909116600a0a6101a0840181905260009291816132f3576132f3614426565b046101c084015260006133068430612f9a565b9050836101c001518111613327576101a08401518102610180850152613330565b60006101808501525b8360a0015164ffffffffff1642146135d8576001925060008460a0015164ffffffffff164261335f9190614698565b905060006b033b2e3c9fd0803ce800000086608001516133ab886101000151600b0b6b033b2e3c9fd0803ce80000006133989190614707565b856b033b2e3c9fd0803ce80000006140b5565b6133b5919061465b565b6133bf9190614484565b90506000866080015182886040015171ffffffffffffffffffffffffffffffffffff166133ec919061465b565b6133f69190614484565b606088015160208901519192506bffffffffffffffffffffffff16906dffffffffffffffffffffffffffff166000613436633b9aca0063ee6b280061465b565b6101208b015163ffffffff90811614613454578a610120015161345a565b6336d616005b63ffffffff168b6040015171ffffffffffffffffffffffffffffffffffff16866134849190614698565b61348e919061465b565b6134989190614484565b905080156135105760006134b0633b9aca0086614484565b8b61018001516134c091906145fe565b90506134cc8282614698565b6134d6848361465b565b6134e09190614484565b92508a602001516dffffffffffffffffffffffffffff16836135029190614698565b61350c90856145fe565b9350505b6dffffffffffffffffffffffffffff8211801590613540575071ffffffffffffffffffffffffffffffffffff8411155b156135d15761354e84613aed565b71ffffffffffffffffffffffffffffffffffff1660408b015260808a0185905264ffffffffff421660a08b015260208a01516dffffffffffffffffffffffffffff1682146135d15761359f83612752565b6bffffffffffffffffffffffff1660608b01526135bb826126d4565b6dffffffffffffffffffffffffffff1660208b01525b5050505050505b50509392505050565b600080633b9aca00836040015171ffffffffffffffffffffffffffffffffffff1661360c9190614484565b83610180015161361c91906145fe565b905080158061363d575060208301516dffffffffffffffffffffffffffff16155b156136525750670de0b6b3a764000092915050565b60208301516dffffffffffffffffffffffffffff1661367982670de0b6b3a764000061465b565b6136839190614484565b9392505050565b6000806201518083101561369e57826136a3565b620151805b905060006136b48262015180614698565b905060008060006136c488614172565b915091508082116136d65760006136e0565b6136e08183614698565b925050506201518083826136f4919061465b565b6136fe9190614484565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260066020526040902060010154620151809061373790859061465b565b6137419190614484565b61374b91906145fe565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005840160205260408120546e010000000000000000000000000000900471ffffffffffffffffffffffffffffffffffff166137af85858584613ecf565b91506137ba82613aed565b73ffffffffffffffffffffffffffffffffffffffff909316600090815260059095016020526040909420805471ffffffffffffffffffffffffffffffffffff939093166e010000000000000000000000000000026dffffffffffffffffffffffffffff90931692909217825560809092015160019091015591565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040808320805460079093529220660100000000000090910463ffffffff1690811561392d57825473ffffffffffffffffffffffffffffffffffffffff8581166a01000000000000000000009092041614156138b5575050505050565b60015b8263ffffffff1681101561392b578473ffffffffffffffffffffffffffffffffffffffff16828264010000000081106138f3576138f361477b565b015473ffffffffffffffffffffffffffffffffffffffff16141561391957505050505050565b80613923816147aa565b9150506138b8565b505b600a8263ffffffff161061399d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f652f746f6f2d6d616e792d656e74657265642d6d61726b6574730000000000006044820152606401610589565b63ffffffff82166139f85782547fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000073ffffffffffffffffffffffffffffffffffffffff861602178355613a5a565b83818363ffffffff166401000000008110613a1557613a1561477b565b0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169190911790555b613a658260016147e3565b835463ffffffff919091166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff90911617835560405173ffffffffffffffffffffffffffffffffffffffff80871691908616907f1c0971b8e0f7bb4e90bdbd87cfe682c36c383e2fc3dc4716ecc02771186293cc90600090a35050505050565b600071ffffffffffffffffffffffffffffffffffff82111561274e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f652f646562742d616d6f756e742d746f6f2d6c617267652d746f2d656e636f6460448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610589565b633b9aca00613ba08684613f18565b613baa9190614484565b9150633b9aca00613bbb8683613f18565b613bc59190614484565b905081811115613c6b576000613bdb8383614698565b90508373ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f312a5e5e1079f5dda4e95dbbd0b908b291fd5b992ef22073643ab691572c5b5283604051613c4091815260200190565b60405180910390a3613c6585600086896101a0015185613c609190614484565b6127f0565b50611ee6565b80821115611ee6576000613c7f8284614698565b90508373ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f05f2eeda0e08e4b437f487c8d7d29b14537d15e3488170dc3de5dbdf8dac468483604051613ce491815260200190565b60405180910390a3612bc485856000896101a0015185613c609190614484565b60008281526003602052604080822054905160609291829173ffffffffffffffffffffffffffffffffffffffff90911690613d409086906146af565b600060405180830381855af49150503d8060008114613d7b576040519150601f19603f3d011682016040523d82523d6000602084013e613d80565b606091505b50915091508161153c5761153c816141f7565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613e2a91906146af565b6000604051808303816000865af19150503d8060008114613e67576040519150601f19603f3d011682016040523d82523d6000602084013e613e6c565b606091505b5091509150818015613e96575080511580613e96575080806020019051810190613e96919061481b565b8190612bc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058991906142b1565b600081613ede5750600061153c565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260058601602052604090206001015460808501516103f5908461465b565b600081613f27575060006104e0565b6101a0830151633b9aca000280807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8582010181613f6757613f67614426565b0402949350505050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161401091906146af565b6000604051808303816000865af19150503d806000811461404d576040519150601f19603f3d011682016040523d82523d6000602084013e614052565b606091505b509150915081801561407c57508051158061407c57508080602001905181019061407c919061481b565b81906120c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058991906142b1565b6000838015614155576001841680156140d0578592506140d4565b8392505b50600283046002850494505b841561414f5785860286878204146140f757600080fd5b8181018181101561410757600080fd5b859004965050600185161561414457858302838782041415871515161561412d57600080fd5b8181018181101561413d57600080fd5b8590049350505b6002850494506140e0565b5061416a565b83801561416557600092506135d8565b839250505b509392505050565b60405173ffffffffffffffffffffffffffffffffffffffff82166024820152600090819081906141cb90620f4240907f37fe974a0000000000000000000000000000000000000000000000000000000090604401612145565b90506000818060200190518101906141e39190614836565b805160209091015190969095509350505050565b80511561420657805181602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f652f656d7074792d6572726f72000000000000000000000000000000000000006044820152606401610589565b60006020828403121561427a57600080fd5b5035919050565b60005b8381101561429c578181015183820152602001614284565b838111156142ab576000848401525b50505050565b60208152600082518060208401526142d0816040850160208701614281565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461432657600080fd5b919050565b6000806040838503121561433e57600080fd5b61434783614302565b946020939093013593505050565b6000806040838503121561436857600080fd5b50508035926020909101359150565b60008060006060848603121561438c57600080fd5b61439584614302565b92506143a360208501614302565b9150604084013590509250925092565b6000806000606084860312156143c857600080fd5b833592506143a360208501614302565b6000602082840312156143ea57600080fd5b6104dd82614302565b6000806040838503121561440657600080fd5b61440f83614302565b915061441d60208401614302565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000826144ba577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561450057600080fd5b815167ffffffffffffffff8082111561451857600080fd5b818401915084601f83011261452c57600080fd5b81518181111561453e5761453e6144bf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715614584576145846144bf565b8160405282815287602084870101111561459d57600080fd5b6145ae836020830160208801614281565b979650505050505050565b7f45756c657220506f6f6c3a2000000000000000000000000000000000000000008152600082516145f181600c850160208701614281565b91909101600c0192915050565b6000821982111561461157614611614455565b500190565b7f650000000000000000000000000000000000000000000000000000000000000081526000825161464e816001850160208701614281565b9190910160010192915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561469357614693614455565b500290565b6000828210156146aa576146aa614455565b500390565b600082516146c1818460208701614281565b9190910192915050565b6000602082840312156146dd57600080fd5b815180600b0b811461368357600080fd5b60006020828403121561470057600080fd5b5051919050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561474157614741614455565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561477557614775614455565b50500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156147dc576147dc614455565b5060010190565b600063ffffffff80831681851680830382111561480257614802614455565b01949350505050565b8051801515811461432657600080fd5b60006020828403121561482d57600080fd5b6104dd8261480b565b60006080828403121561484857600080fd5b6040516080810181811067ffffffffffffffff8211171561486b5761486b6144bf565b80604052508251815260208301516020820152604083015160408201526148946060840161480b565b6060820152939250505056fe417070726f76616c28616464726573732c616464726573732c75696e74323536295472616e7366657228616464726573732c616464726573732c75696e7432353629a26469706673582212202f2cac2fdfae08dfebde13530cc107d5a13009d89b5a63c66288a4eb315bfe6064736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d7f62927eb58592d82302c87205490c26cccca7c
-----Decoded View---------------
Arg [0] : moduleGitCommit_ (bytes32): 0x000000000000000000000000d7f62927eb58592d82302c87205490c26cccca7c
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000d7f62927eb58592d82302c87205490c26cccca7c
Deployed Bytecode Sourcemap
147:16248:11:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4302:349;;;;;;:::i;:::-;;:::i;:::-;;;345:25:13;;;333:2;318:18;4302:349:11;;;;;;;;898:189;;;:::i;:::-;;;;;;;:::i;11339:144::-;;;;;;:::i;:::-;;:::i;:::-;;;1716:14:13;;1709:22;1691:41;;1679:2;1664:18;11339:144:11;1551:187:13;1727:262:11;;;:::i;8830:942::-;;;;;;:::i;:::-;;:::i;:::-;;13809:1228;;;;;;:::i;:::-;;:::i;1371:76::-;;;1438:2;2471:36:13;;2459:2;2444:18;1371:76:11;2329:184:13;11752:508:11;;;;;;:::i;:::-;;:::i;15240:1153::-;;;;;;:::i;:::-;;:::i;2833:373::-;;;;;;:::i;:::-;;:::i;7789:842::-;;;;;;:::i;:::-;;:::i;4938:363::-;;;;;;:::i;:::-;;:::i;241:40:3:-;;;;;2539:185:11;;;;;;:::i;:::-;;:::i;1497:137::-;;;:::i;:::-;;;3394:42:13;3382:55;;;3364:74;;3352:2;3337:18;1497:137:11;3218:226:13;1132:182:11;;;:::i;3302:266::-;;;:::i;205:30:3:-;;;;;5437:297:11;;;:::i;12872:139::-;;;;;;:::i;:::-;;:::i;10042:1104::-;;;;;;:::i;:::-;;:::i;13261:228::-;;;;;;:::i;:::-;;:::i;12426:211::-;;;;;;:::i;:::-;;:::i;6007:1526::-;;;;;;:::i;:::-;;:::i;3669:353::-;;;:::i;2086:349::-;;;:::i;4302:::-;4375:4;4392:18;4412:33;4451:8;:6;:8::i;:::-;4391:68;;;;;;4469:28;4500:42;4517:10;4529:12;4500:16;:42::i;:::-;4469:73;;4609:10;:35;;;4560:46;4586:10;4598:7;4560:25;:46::i;:::-;:84;;;;:::i;:::-;4553:91;4302:349;-1:-1:-1;;;;;4302:349:11:o;898:189::-;937:13;963:18;988:8;:6;:8::i;:::-;962:34;;;;;1060:10;1053:23;;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1020:59;;;;;;;;:::i;:::-;;;;;;;;;;;;;1006:74;;;898:189;:::o;11339:144::-;11416:4;11439:37:::1;11457:1;11460:7;11469:6;11439:17;:37::i;:::-;11432:44;;1628:1:0;11339:144:11::0;;;;:::o;1727:262::-;1773:4;1790:18;1810:33;1849:8;:6;:8::i;:::-;1789:68;;;;;;1867:28;1898:42;1915:10;1927:12;1898:16;:42::i;:::-;1958:24;;;1951:31;;;1727:262;-1:-1:-1;;;;1727:262:11:o;8830:942::-;1526:1:4;1389:14:0;;:42;1381:67;;;;;;;6146:2:13;1381:67:0;;;6128:21:13;6185:2;6165:18;;;6158:30;6224:14;6204:18;;;6197:42;6256:18;;1381:67:0;;;;;;;;;1581:1:4;1459:14:0;:39;;;:14;;;9004:8:11::1;:6;:8::i;:::-;8908:104;;;;;;;;9022:15;9040:38;9054:9;9065:12;9040:13;:38::i;:::-;9022:56;;9089:31;9112:7;9089:22;:31::i;:::-;9147:7;9135:28;;;9156:6;9135:28;;;;345:25:13::0;;333:2;318:18;;199:177;9135:28:11::1;;;;;;;;9174;9205:40;9220:10;9232:12;9205:14;:40::i;:::-;9174:71;;9265:40;9286:10;9298:6;9265:20;:40::i;:::-;9256:49;;9315:19;9337:52;9370:10;9382:6;9337:32;:52::i;:::-;9315:74;;9408:53;9434:10;9446:14;9408:25;:53::i;:::-;9399:62;;9497:77;9513:12;9527:10;9539:9;9550:7;9559:14;9497:15;:77::i;:::-;9651:26;::::0;::::1;::::0;9610:85:::1;::::0;9625:12;;9639:10;;9651:26:::1;;9679:7:::0;9688:6;9610:14:::1;:85::i;:::-;9706:23;9721:7;9706:14;:23::i;:::-;9739:26;9754:10;9739:14;:26::i;:::-;-1:-1:-1::0;;1526:1:4;1519:14:0;:41;-1:-1:-1;;;;;;;8830:942:11:o;13809:1228::-;13899:4;1526:1:4;1389:14:0;;:42;1381:67;;;;;;;6146:2:13;1381:67:0;;;6128:21:13;6185:2;6165:18;;;6158:30;6224:14;6204:18;;;6197:42;6256:18;;1381:67:0;5944:336:13;1381:67:0;1581:1:4;1459:14:0;:39;;;:14;;;14011:8:11::1;:6;:8::i;:::-;13915:104;;;;;;;;14030:28;14061:40;14076:10;14088:12;14061:14;:40::i;:::-;14030:71:::0;-1:-1:-1;14116:18:11::1;::::0;::::1;14112:40;;14143:9;14136:16;;14112:40;14178:2;14170:10;;:4;:10;;;;14162:38;;;::::0;::::1;::::0;;6487:2:13;14162:38:11::1;::::0;::::1;6469:21:13::0;6526:2;6506:18;;;6499:30;6565:17;6545:18;;;6538:45;6600:18;;14162:38:11::1;6285:339:13::0;14162:38:11::1;14211:28;14234:4;14211:22;:28::i;:::-;14249:26;14272:2;14249:22;:26::i;:::-;14318:2;14290:39;;14312:4;14290:39;;;14322:6;14290:39;;;;345:25:13::0;;333:2;318:18;;199:177;14290:39:11::1;;;;;;;;14344:11:::0;14340:28:::1;;14364:4;14357:11;;;;;;;;;14340:28;796:4:2::0;745:23;;;744:57;;;;774:26;;;744:57;;14383:32:11::1;:99;;;;-1:-1:-1::0;14419:34:11::1;::::0;;::::1;;::::0;;;:28:::1;::::0;::::1;:34;::::0;;;;;;;:45;;::::1;::::0;;;;;;;14468:14:::1;14419:63;;14383:99;14379:415;;;14506:34;::::0;;::::1;;::::0;;;:28:::1;::::0;::::1;:34;::::0;;;;;;;:45;;::::1;::::0;;;;;;;:55;-1:-1:-1;14506:55:11::1;14498:92;;;::::0;::::1;::::0;;6831:2:13;14498:92:11::1;::::0;::::1;6813:21:13::0;6870:2;6850:18;;;6843:30;6909:26;6889:18;;;6882:54;6953:18;;14498:92:11::1;6629:348:13::0;14498:92:11::1;14616:34;::::0;;::::1;;::::0;;;:28:::1;::::0;::::1;:34;::::0;;;;;;;:45;;::::1;::::0;;;;;;:55;;;;::::1;::::0;;;;14687:96:::1;::::0;14709:9;;14616:34;;:45;;14687:21:::1;:96::i;:::-;14804:70;14820:12;14834:10;14846:9;14857:4;14863:2;14867:6;14804:15;:70::i;:::-;14885:20;14900:4;14885:14;:20::i;:::-;14919:22;::::0;::::1;;::::0;;;:18:::1;::::0;::::1;:22;::::0;;;;:27;;;::::1;;;:32:::0;14915:56:::1;;14953:18;14968:2;14953:14;:18::i;:::-;14982:26;14997:10;14982:14;:26::i;:::-;15026:4;15019:11;;;;;;;1508:1:0;1526::4::0;1519:14:0;:41;13809:1228:11;;-1:-1:-1;;;13809:1228:11:o;11752:508::-;11857:4;1526:1:4;1389:14:0;;:42;1381:67;;;;;;;6146:2:13;1381:67:0;;;6128:21:13;6185:2;6165:18;;;6158:30;6224:14;6204:18;;;6197:42;6256:18;;1381:67:0;5944:336:13;1381:67:0;1581:1:4;1459:14:0;:39;;;:14;;11951:8:11::1;:6;:8::i;:::-;11873:86;;;;;;;11969:15;11987:38;12001:9;12012:12;11987:13;:38::i;:::-;11969:56:::0;-1:-1:-1;796:4:2;745:23;;;744:57;;;;774:26;;;744:57;;12044:33:11::1;12036:61;;;::::0;::::1;::::0;;7184:2:13;12036:61:11::1;::::0;::::1;7166:21:13::0;7223:2;7203:18;;;7196:30;7262:17;7242:18;;;7235:45;7297:18;;12036:61:11::1;6982:339:13::0;12036:61:11::1;12108:37;::::0;;::::1;;::::0;;;:28:::1;::::0;::::1;:37;::::0;;;;;;;:46;;::::1;::::0;;;;;;:55;;;12173:58:::1;12195:9:::0;12137:7;12146;12157:6;12173:21:::1;:58::i;:::-;12249:4;12242:11;;;;;;1526:1:4::0;1519:14:0;:41;11752:508:11;;-1:-1:-1;;;11752:508:11:o;15240:1153::-;1526:1:4;1389:14:0;;:42;1381:67;;;;;;;6146:2:13;1381:67:0;;;6128:21:13;6185:2;6165:18;;;6158:30;6224:14;6204:18;;;6197:42;6256:18;;1381:67:0;5944:336:13;1381:67:0;1581:1:4;1459:14:0;:39;;;:14;;;15426:8:11::1;:6;:8::i;:::-;15330:104;;;;;;;;15444:15;15462:38;15476:9;15487:12;15462:13;:38::i;:::-;15444:56;;15511:31;15534:7;15511:22;:31::i;:::-;15571:7;15557:30;;;15580:6;15557:30;;;;345:25:13::0;;333:2;318:18;;199:177;15557:30:11::1;;;;;;;;15598:28;15629:40;15644:10;15656:12;15629:14;:40::i;:::-;15699:27;::::0;::::1;15680:16;15699:27:::0;;;:18:::1;::::0;::::1;:27;::::0;;;;:35;15598:71;;-1:-1:-1;15699:35:11::1;::::0;;::::1;::::0;15784:14:::1;15774:24:::0;::::1;15770:251;;;-1:-1:-1::0;15823:11:11;-1:-1:-1;15823:11:11;15861:1:::1;15770:251;;;15916:6;15901:11;:21;;15893:56;;;::::0;::::1;::::0;;7528:2:13;15893:56:11::1;::::0;::::1;7510:21:13::0;7567:2;7547:18;;;7540:30;7606:24;7586:18;;;7579:52;7648:18;;15893:56:11::1;7326:346:13::0;15893:56:11::1;-1:-1:-1::0;15988:20:11;;::::1;15770:251;16069:24;16082:10;16069:12;:24::i;:::-;16031:27;::::0;::::1;;::::0;;;:18:::1;::::0;::::1;:27;::::0;;;;:62;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;16179:25:::1;::::0;::::1;::::0;16161:53:::1;::::0;16179:34:::1;::::0;16207:6;;16179:34:::1;;;:::i;:::-;16161:17;:53::i;:::-;16133:81;;:25;::::0;::::1;:81:::0;;;16103:27:::1;::::0;::::1;:111:::0;;;;;::::1;::::0;;;::::1;;::::0;;16239:21;;16230:48:::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;16271:6;345:25:13;;333:2;318:18;;199:177;16230:48:11::1;;;;;;;;16288:61;16310:9;16321:7;16338:1;16342:6;16288:21;:61::i;:::-;16360:26;16375:10;16360:14;:26::i;:::-;-1:-1:-1::0;;1526:1:4;1519:14:0;:41;-1:-1:-1;;;;;;;;15240:1153:11:o;2833:373::-;2902:4;2919:18;2939:33;2978:8;:6;:8::i;:::-;2918:68;;;;;;2996:28;3027:42;3044:10;3056:12;3027:16;:42::i;:::-;3164:35;;;;3125:27;;;;;;;:18;;;:27;;;;;:35;2996:73;;-1:-1:-1;3164:35:11;3087:74;;2996:73;;3125:35;;3087:25;:74::i;7789:842::-;1526:1:4;1389:14:0;;:42;1381:67;;;;;;;6146:2:13;1381:67:0;;;6128:21:13;6185:2;6165:18;;;6158:30;6224:14;6204:18;;;6197:42;6256:18;;1381:67:0;5944:336:13;1381:67:0;1581:1:4;1459:14:0;:39;;;:14;;;7967:8:11::1;:6;:8::i;:::-;7871:104;;;;;;;;7985:15;8003:38;8017:9;8028:12;8003:13;:38::i;:::-;7985:56;;8052:31;8075:7;8052:22;:31::i;:::-;8114:7;8098:32;;;8123:6;8098:32;;;;345:25:13::0;;333:2;318:18;;199:177;8098:32:11::1;;;;;;;;8141:28;8172:40;8187:10;8199:12;8172:14;:40::i;:::-;8141:71;;8223:19;8279:58;8295:12;8309:10;8321:7;8330:6;8279:15;:58::i;:::-;8355:19;::::0;::::1;::::0;8252:85;;-1:-1:-1;8252:85:11;-1:-1:-1;8355:29:11;-1:-1:-1;8355:29:11::1;8347:66;;;::::0;::::1;::::0;;8012:2:13;8347:66:11::1;::::0;::::1;7994:21:13::0;8051:2;8031:18;;;8024:30;8090:26;8070:18;;;8063:54;8134:18;;8347:66:11::1;7810:348:13::0;8347:66:11::1;8424:41;8435:10;8447:9;8458:6;8424:10;:41::i;:::-;;8476:77;8492:12;8506:10;8518:9;8529:7;8538:14;8476:15;:77::i;4938:363::-:0;5020:4;5037:18;5057:33;5096:8;:6;:8::i;:::-;5036:68;;;;;;5114:28;5145:42;5162:10;5174:12;5145:16;:42::i;:::-;5114:73;;5205:89;5231:10;5243:50;5264:10;5276:16;5243:20;:50::i;:::-;5205:25;:89::i;2539:185::-;2598:4;2617:33;2656:8;:6;:8::i;:::-;-1:-1:-1;;2682:27:11;;;;;;;;:18;;;;:27;;-1:-1:-1;;2682:27:11;;;;:35;;;;2539:185;-1:-1:-1;2539:185:11:o;1497:137::-;1547:7;1567:18;1592:8;:6;:8::i;:::-;-1:-1:-1;1566:34:11;;1497:137;-1:-1:-1;;;;1497:137:11:o;1132:182::-;1173:13;1199:18;1224:8;:6;:8::i;:::-;1198:34;;;;;1285:10;1278:25;;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1256:50;;;;;;;;:::i;3302:266::-;3351:4;3368:18;3388:33;3427:8;:6;:8::i;:::-;3367:68;;;;;;3445:28;3476:42;3493:10;3505:12;3476:16;:42::i;:::-;3536:25;;;3529:32;;;3302:266;-1:-1:-1;;;;3302:266:11:o;5437:297::-;1526:1:4;1389:14:0;;:42;1381:67;;;;;;;6146:2:13;1381:67:0;;;6128:21:13;6185:2;6165:18;;;6158:30;6224:14;6204:18;;;6197:42;6256:18;;1381:67:0;5944:336:13;1381:67:0;1581:1:4;1459:14:0;:39;;;:14;5546:8:11::1;:6;:8::i;:::-;5486:68;;;;;;5564:28;5595:40;5610:10;5622:12;5595:14;:40::i;:::-;5564:71;;5646:44;5665:12;5679:10;5646:18;:44::i;:::-;5701:26;5716:10;5701:14;:26::i;:::-;-1:-1:-1::0;;1526:1:4;1519:14:0;:41;-1:-1:-1;5437:297:11:o;12872:139::-;12945:4;12968:36:::1;12989:1;12993:2;12997:6;12968:12;:36::i;10042:1104::-:0;1526:1:4;1389:14:0;;:42;1381:67;;;;;;;6146:2:13;1381:67:0;;;6128:21:13;6185:2;6165:18;;;6158:30;6224:14;6204:18;;;6197:42;6256:18;;1381:67:0;5944:336:13;1381:67:0;1581:1:4;1459:14:0;:39;;;:14;;;10216:8:11::1;:6;:8::i;:::-;10120:104;;;;;;;;10234:15;10252:38;10266:9;10277:12;10252:13;:38::i;:::-;10234:56;;10301:31;10324:7;10301:22;:31::i;:::-;10359:7;10347:28;;;10368:6;10347:28;;;;345:25:13::0;;333:2;318:18;;199:177;10347:28:11::1;;;;;;;;10386;10417:40;10432:10;10444:12;10417:14;:40::i;:::-;10386:71;;10468:9;10480:49;10495:12;10509:10;10521:7;10480:14;:49::i;:::-;10468:61:::0;-1:-1:-1;10543:9:11;10539:22:::1;;10554:7;;;;;;;;;10539:22;10571:19;10627:58;10643:12;10657:10;10669:7;10678:6;10627:15;:58::i;:::-;10600:85:::0;;-1:-1:-1;10600:85:11;-1:-1:-1;10700:13:11;;::::1;10696:140;;;10738:4;10729:13;;10773:52;10806:10;10818:6;10773:32;:52::i;:::-;10756:69;;10696:140;10871:77;10887:12;10901:10;10913:9;10924:7;10933:14;10871:15;:77::i;:::-;11025:26;::::0;::::1;::::0;10984:85:::1;::::0;10999:12;;11013:10;;11025:26:::1;;11053:7:::0;11062:6;10984:14:::1;:85::i;:::-;11080:23;11095:7;11080:14;:23::i;1508:1:0:-;-1:-1:-1::0;;1526:1:4;1519:14:0;:41;10042:1104:11:o;13261:228::-;13342:4;13361:33;13400:8:::1;:6;:8::i;:::-;-1:-1:-1::0;;13449:24:11::1;::::0;::::1;;::::0;;;:18:::1;::::0;::::1;:24;::::0;;;;:32;13358:50;;-1:-1:-1;13426:56:11::1;::::0;-1:-1:-1;13439:4:11;;13445:2;;13449:32:::1;;13426:12;:56::i;:::-;13419:63:::0;13261:228;-1:-1:-1;;;;13261:228:11:o;12426:211::-;12501:4;12520:33;12559:8;:6;:8::i;:::-;-1:-1:-1;;12585:36:11;;;;;;;;:28;;;;;:36;;;;;;;;:45;;;;;;;;;;-1:-1:-1;;;12585:45:11;;;12426:211::o;6007:1526::-;1526:1:4;1389:14:0;;:42;1381:67;;;;;;;6146:2:13;1381:67:0;;;6128:21:13;6185:2;6165:18;;;6158:30;6224:14;6204:18;;;6197:42;6256:18;;1381:67:0;5944:336:13;1381:67:0;1581:1:4;1459:14:0;:39;;;:14;;;6184:8:11::1;:6;:8::i;:::-;6088:104;;;;;;;;6202:15;6220:38;6234:9;6245:12;6220:13;:38::i;:::-;6202:56;;6269:31;6292:7;6269:22;:31::i;:::-;6330:7;6315:31;;;6339:6;6315:31;;;;345:25:13::0;;333:2;318:18;;199:177;6315:31:11::1;;;;;;;;6357:28;6388:40;6403:10;6415:12;6388:14;:40::i;:::-;6357:71;;6453:14;6443:6;:24;6439:100;;;6492:36;6506:10;6518:9;6492:13;:36::i;:::-;6483:45;;6439:100;6558:40;6579:10;6591:6;6558:20;:40::i;:::-;6549:49;;6609:22;6634:41;6645:10;6657:9;6668:6;6634:10;:41::i;:::-;7133:19;::::0;::::1;:40:::0;;;;::::1;::::0;;6609:66;-1:-1:-1;6685:19:11::1;7204:56;7133:10:::0;6609:66;7204:25:::1;:56::i;:::-;7274:19;::::0;::::1;:40:::0;;;::::1;::::0;;7187:73;-1:-1:-1;7335:77:11::1;7351:12:::0;7274:10;7377:9;7388:7;7187:73;7335:15:::1;:77::i;:::-;7427:27;::::0;::::1;;::::0;;;:18:::1;::::0;::::1;:27;::::0;;;;:32;;;::::1;;;:37:::0;7423:66:::1;;7466:23;7481:7;7466:14;:23::i;3669:353::-:0;3728:4;3745:18;3765:33;3804:8;:6;:8::i;:::-;3744:68;;;;;;3822:28;3853:42;3870:10;3882:12;3853:16;:42::i;:::-;3822:73;;3980:10;:35;;;3913:64;3939:10;3951;:25;;;3913:64;;:25;:64::i;:::-;:102;;;;:::i;:::-;3906:109;;;;;3669:353;:::o;2086:349::-;2142:4;2159:18;2179:33;2218:8;:6;:8::i;:::-;2158:68;;;;;;2236:28;2267:42;2284:10;2296:12;2267:16;:42::i;:::-;2236:73;;2393:10;:35;;;2327:63;2353:10;2365;:24;;;2327:63;;:25;:63::i;274:366::-;819:14:3;887:23;;;874:37;798:2;866:46;;;314:18:11;489:23;;;:12;:23;;;;;535;;;;489;535;;489;;815::3;;;;802:37;794:46;;535:23:11;568:65;;;;;;;8788:2:13;568:65:11;;;8770:21:13;8827:2;8807:18;;;8800:30;8866;8846:18;;;8839:58;8914:18;;568:65:11;8586:352:13;568:65:11;274:366;;;;:::o;9715:283:2:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9867:14:2;;1526:1:4;9867:42:2;9859:70;;;;;;;9145:2:13;9859:70:2;;;9127:21:13;9184:2;9164:18;;;9157:30;9223:17;9203:18;;;9196:45;9258:18;;9859:70:2;8943:339:13;9859:70:2;9939:52;9954:10;9966:12;9980:10;9939:14;:52::i;:::-;;9715:283;;;;:::o;11966:220::-;12067:4;12083:17;12103:31;12123:10;12103:19;:31::i;:::-;12083:51;-1:-1:-1;12175:4:2;12151:21;12083:51;12151:6;:21;:::i;:::-;:28;;;;:::i;402:229::-;484:7;526:3;511:12;:18;503:55;;;;;;;9722:2:13;503:55:2;;;9704:21:13;9761:2;9741:18;;;9734:30;9800:26;9780:18;;;9773:54;9844:18;;503:55:2;9520:348:13;503:55:2;-1:-1:-1;583:40:2;;402:229::o;27110:494::-;27212:22;;;27178:31;27212:22;;;:13;:22;;;;;:49;;;;;;;27271:44;;27308:7;27110:494;:::o;27271:44::-;27325:11;27339:44;27357:26;27339:15;:44;:::i;:::-;27325:58;-1:-1:-1;27397:11:2;27393:24;;27410:7;;27110:494;:::o;27393:24::-;27427:22;;;;;;;:13;:22;;;;;:75;;;;;27486:15;27427:75;;;;;;27554:43;27427:22;27590:6;27554:26;:43::i;:::-;27512:22;;;;;;;;:13;:22;;;;;:39;;:85;;;;-1:-1:-1;;27110:494:2:o;9023:686::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9164:52:2;9179:10;9191:12;9205:10;9164:14;:52::i;:::-;9160:543;;;9277:40;;;;9232:85;;;;;;;;;;;;;9358:21;;9454:25;;;;9424:55;;;;9332:47;;;;9424:55;9232:85;9332:23;;9424:55;9523:24;;;;9589:23;;;;9561:51;;;;9494:53;;;;9561:51;9494:26;;;9561:51;9662:30;;;;9627:32;;;:65;9023:686;;;;:::o;10237:308::-;10341:17;10396:10;:28;;;10378:14;:46;;10370:77;;;;;;;10205:2:13;10370:77:2;;;10187:21:13;10244:2;10224:18;;;10217:30;10283:20;10263:18;;;10256:48;10321:18;;10370:77:2;10003:342:13;10370:77:2;-1:-1:-1;10501:35:2;;;;;10484:52;;10237:308::o;11710:250::-;11818:4;11834:17;11854:31;11874:10;11854:19;:31::i;:::-;11834:51;-1:-1:-1;11834:51:2;11920:16;11935:1;11834:51;11920:16;:::i;:::-;11903:13;:6;11912:4;11903:13;:::i;:::-;:34;;;;:::i;14218:578::-;14431:27;;;;;;;:18;;;:27;;;;;:35;14418:58;;14431:44;;14469:6;;14431:35;;:44;:::i;:::-;14418:12;:58::i;:::-;14380:27;;;;;;;:18;;;:27;;;;;;;;:96;;;;;;;;;;;14561:24;;;14543:53;;14556:39;;14589:6;;14556:30;:39;:::i;14543:53::-;14516:80;;:24;;;:80;;;14487:26;;;:109;;;;;;;;;14607:44;14487:12;14516:10;14607:18;:44::i;:::-;14675:21;;14667:47;;345:25:13;;;14667:47:2;;;;;;;;;333:2:13;318:18;14667:47:2;;;;;;;14724:65;14746:13;14769:1;14773:7;14782:6;14724:21;:65::i;:::-;14218:578;;;;;:::o;19645:850::-;19806:33;490:3:4;19806:33:2;;:::i;:::-;19858:22;;;;19806:33;;-1:-1:-1;19858:48:2;;1942:1:4;19858:48:2;;;:101;;-1:-1:-1;19923:21:2;;19910:49;:35;;;19957:1;19910:35;;;:12;:35;;;;;;;:49;19858:101;19850:136;;;;;;;10552:2:13;19850:136:2;;;10534:21:13;10591:2;10571:18;;;10564:30;10630:24;10610:18;;;10603:52;10672:18;;19850:136:2;10350:346:13;19850:136:2;19998:9;20009:13;20026:51;20043:12;20057:10;20069:7;20026:16;:51::i;:::-;19997:80;;;;20092:4;20100:1;20092:9;20088:60;;;20103:45;20117:7;20126:10;:21;;;20103:13;:45::i;:::-;20159:14;20167:6;20159:14;;:::i;:::-;;;20219:22;20236:4;20219:16;:22::i;:::-;20184:27;;;;;;;:18;;;:27;;;;;;;:57;;;;;;;;;;;;;20322:23;;;20305:50;;20322:32;;20348:6;;20322:32;;:::i;:::-;20305:16;:50::i;:::-;20279:76;;:23;;;:76;;;20251:25;;;:104;;;;;;;;;;;;;;20366:44;20251:25;20279:23;20366:18;:44::i;:::-;20421:67;20437:10;20449:13;20464:7;20473:8;20483:4;20421:15;:67::i;:::-;19796:699;;19645:850;;;;;:::o;25082:446::-;25157:22;;;25142:12;25157:22;;;:13;:22;;;;;:43;;;25215:30;25211:311;;25304:71;;3394:42:13;3382:55;;25304:71:2;;;3364:74:13;25261:115:2;;2838:9:4;;25327:38:2;;3337:18:13;;25304:71:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25261:18;:115::i;:::-;;25132:396;25082:446;:::o;25211:311::-;25397:31;;;1691:1:4;25397:31:2;25393:129;;;25444:22;;;;;;;:13;:22;;;;;:67;;;;1746:1:4;25444:67:2;;;25393:129;25132:396;25082:446;:::o;13947:246::-;14028:1;:12;;;14016:170;;;14042:1;:15;;;490:3:4;14059:1:2;:14;;;:40;;;;;;:::i;:::-;14101:16;;;;;14119:10;;;;14131:21;;;;;14154:14;;;;14016:170;;;11040:30:13;11028:43;;;11010:62;;11103:2;11088:18;;11081:34;;;;11163:26;11151:39;;;11131:18;;;11124:67;;;;11207:18;;;11200:34;11250:19;;;11243:35;;;;11326:2;11315:22;11309:3;11294:19;;11287:51;14170:15:2;11369:3:13;11354:19;;11347:35;10997:3;10982:19;14016:170:2;;;;;;;13947:246;:::o;1502:543:3:-;2340:19:0;2417:4;2411:11;2393:29;;1624:12:3::1;1641:9;:14;;1711:1;1756:42;;;;;;;;;;;;;;;;;1746:53:::0;;::::1;::::0;;::::1;::::0;1656:335:::1;::::0;11650:3:13;11646:16;;;;11664:66;11642:89;1656:335:3;;::::1;11630:102:13::0;;;;11748:11;;;11741:27;1840:20:3::1;::::0;;::::1;11784:12:13::0;;;11777:28;1902:22:3;::::1;11821:12:13::0;;;11814:28;11858:12;;;11851:28;;;11895:13;;1656:335:3::1;;::::0;;;;;::::1;::::0;;;;;;;1641:351:::1;::::0;::::1;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1623:369;;;2010:7;2002:36;;;::::0;::::1;::::0;;12400:2:13;2002:36:3::1;::::0;::::1;12382:21:13::0;12439:2;12419:18;;;12412:30;12478:18;12458;;;12451:46;12514:18;;2002:36:3::1;12198:340:13::0;2002:36:3::1;-1:-1:-1::0;2804:4:0;2797:28;-1:-1:-1;;;;1502:543:3:o;15487:749:2:-;15681:24;;;15658:20;15681:24;;;:18;;;:24;;;;;:32;;;15731:25;;;;15723:60;;;;;;;7528:2:13;15723:60:2;;;7510:21:13;7567:2;7547:18;;;7540:30;7606:24;7586:18;;;7579:52;7648:18;;15723:60:2;7326:346:13;15723:60:2;15851:24;;;15923:28;15851:24;15923:12;:28::i;:::-;15888:24;;;;;;;;:18;;;:24;;;;;;:63;;;;;;;;;;;16007:22;;;;;;:30;15994:53;;16007:39;;16040:6;;16007:30;:39;:::i;15994:53::-;15961:22;;;;;;;;:18;;;:22;;;;;;;;;:86;;;;;;;;;;;;;;;;16072:21;;16063:45;;345:25:13;;;16063:45:2;;;;;;;;;;;318:18:13;16063:45:2;;;;;;;16131:21;;16123:42;;345:25:13;;;16123:42:2;;;;;;;;;333:2:13;318:18;16123:42:2;;;;;;;16175:54;16197:13;16212:4;16218:2;16222:6;16175:21;:54::i;:::-;15648:588;;15487:749;;;;;;:::o;10551:182::-;10609:7;280:17:4;10636:25:2;;;10628:66;;;;;;;12745:2:13;10628:66:2;;;12727:21:13;12784:2;12764:18;;;12757:30;12823;12803:18;;;12796:58;12871:18;;10628:66:2;12543:352:13;10628:66:2;-1:-1:-1;10719:6:2;10551:182::o;10739:197::-;10802:6;350:16:4;10828:31:2;;;10820:78;;;;;;;13102:2:13;10820:78:2;;;13084:21:13;13141:2;13121:18;;;13114:30;13180:34;13160:18;;;13153:62;13251:4;13231:18;;;13224:32;13273:19;;10820:78:2;12900:398:13;965:531:3;2340:19:0;2417:4;2411:11;2393:29;;1081:12:3::1;1098:9;:14;;1168:1;1213:42;;;;;;;;;;;;;;;;;1203:53:::0;;::::1;::::0;;::::1;::::0;1113:329:::1;::::0;11650:3:13;11646:16;;;;11664:66;11642:89;1113:329:3;;::::1;11630:102:13::0;;;;11748:11;;;11741:27;1297:19:3::1;::::0;;::::1;11784:12:13::0;;;11777:28;1358:17:3;::::1;11821:12:13::0;;;11814:28;11858:12;;;11851:28;;;11895:13;;1113:329:3::1;11393:521:13::0;16242:588:2;16385:4;16391;16407:19;16450:14;16440:6;:24;16436:346;;;-1:-1:-1;16497:27:2;;;;;;;:18;;;:27;;;;;:35;;;16555:53;16581:10;16497:35;16555:25;:53::i;:::-;16546:62;;16436:346;;;16648:40;16669:10;16681:6;16648:20;:40::i;:::-;16639:49;;16719:52;16752:10;16764:6;16719:32;:52::i;:::-;16702:69;;16436:346;16800:6;;16808:14;;-1:-1:-1;16242:588:2;;-1:-1:-1;;;;16242:588:2:o;23768:559::-;23917:19;;;;23966:21;;24002:35;;;;23861:22;;23917:19;23947:91;;23989:2;;23993:44;;:6;:44;:::i;:::-;23947:18;:91::i;:::-;24048:18;24091:74;24112:10;24124:40;24138:10;24158:4;24124:13;:40::i;:::-;24091:20;:74::i;:::-;24069:19;;;:96;;;;-1:-1:-1;24184:31:2;;;;24176:70;;;;;;;13505:2:13;24176:70:2;;;13487:21:13;13544:2;13524:18;;;13517:30;13583:28;13563:18;;;13556:56;13629:18;;24176:70:2;13303:350:13;24176:70:2;24288:30;;;23768:559;-1:-1:-1;;;;23768:559:2:o;14802:679::-;14983:27;;;14964:16;14983:27;;;:18;;;:27;;;;;:35;;;15036:21;;;;15028:56;;;;;;;7528:2:13;15028:56:2;;;7510:21:13;7567:2;7547:18;;;7540:30;7606:24;7586:18;;;7579:52;7648:18;;15028:56:2;7326:346:13;15028:56:2;15132:34;15145:20;15159:6;15145:11;:20;:::i;15132:34::-;15094:27;;;;;;;:18;;;:27;;;;;;;;:72;;;;;;;;;;;15246:24;;;15233:47;;15246:33;;15273:6;;15246:33;;:::i;15233:47::-;15206:74;;:24;;;:74;;;15177:26;;;:103;;;;;;;;;15291:44;15177:12;15206:10;15291:18;:44::i;:::-;15360:21;;15351:48;;345:25:13;;;15351:48:2;;;;;;;;;333:2:13;318:18;15351:48:2;;;;;;;15409:65;15431:13;15446:7;15463:1;15467:6;15409:21;:65::i;:::-;14954:527;14802:679;;;;;:::o;11484:220::-;11585:4;11601:17;11621:31;11641:10;11621:19;:31::i;:::-;11601:51;-1:-1:-1;11601:51:2;11669:13;:6;11678:4;11669:13;:::i;13056:885::-;13168:18;13211:17;490:3:4;13231:10:2;:23;;;:49;;;;;;:::i;:::-;13211:69;;13294:15;13334:12;13312:10;:19;;;:34;;;;:::i;:::-;13294:52;-1:-1:-1;13364:15:2;13360:192;;13395:1;13381:15;;13360:192;;;13547:4;13534:10;13501:29;13506:16;13547:4;13501:29;:::i;:::-;13485:46;;:12;:46;:::i;:::-;:59;;;;:::i;:::-;:66;;;;:::i;:::-;13464:88;;13360:192;-1:-1:-1;;13614:28:2;;;;13754:21;;13693:96;;13860:42:13;13848:55;;;13693:96:2;;;13830:74:13;13595:195:2;13940:23:13;;;13920:18;;;13913:51;13573:19:2;;13595:195;;;;;13716:36;;13803:18:13;;13693:96:2;13658:312:13;13595:195:2;13573:217;;13802:21;13838:6;13827:27;;;;;;;;;;;;:::i;:::-;13893:41;;;;:23;;;;:41;;;;-1:-1:-1;;13865:69:2;;;;;;;;;;;;;;;;;;;-1:-1:-1;13056:885:2:o;18022:298::-;18253:27;;;18151:4;18253:27;;;:18;;;:27;;;;;:32;490:3:4;;18174:113:2;;18186:10;;18198:88;;18253:18;;18186:10;;18253:27;;:32;;;;;18198:19;:88::i;:::-;18174:11;:113::i;20501:950::-;20666:11;20680:36;490:3:4;20680:10:2;:36;:::i;:::-;20666:50;;20728:9;20739:13;20756:51;20773:12;20787:10;20799:7;20756:16;:51::i;:::-;20727:80;;;;20817:18;20838:29;20850:10;20862:4;20838:11;:29::i;:::-;20817:50;;20896:13;20886:6;:23;;20878:52;;;;;;;14460:2:13;20878:52:2;;;14442:21:13;14499:2;14479:18;;;14472:30;14538:18;14518;;;14511:46;14574:18;;20878:52:2;14258:340:13;20878:52:2;21042:23;;;;20996:22;;;;21035:30;;;;21031:66;;;21074:10;:23;;;21067:30;;;;21031:66;21143:31;21160:13;21143:16;:31::i;:::-;21108:27;;;;;;;:18;;;:27;;;;;;;:66;;;;;;;;;;;;;21255:23;;;21238:64;;21288:13;;21255:30;;21281:4;;21255:30;;:::i;:::-;:46;;;;:::i;21238:64::-;21212:90;;:23;;;:90;;;21184:25;;;:118;;;;;;;;;;;;;;21313:44;21184:25;21212:23;21313:18;:44::i;:::-;21368:76;21384:10;21396:13;21411:7;21420:8;21430:13;21368:15;:76::i;:::-;20656:795;;;;;20501:950;;;;;:::o;12192:858::-;2417:4:0;2411:11;;12460:21:2;;:32:::1;3382:55:13::0;;;12506:58:2::1;::::0;;::::1;3364:74:13::0;;;;12506:58:2;;;;;;;;;;3337:18:13;;;12506:58:2;;::::1;::::0;::::1;::::0;;::::1;;12529:25:::0;12506:58:::1;::::0;;12460:105;;12293:4;;;;;;12460:32:::1;::::0;12498:6:::1;::::0;12460:105:::1;::::0;::::1;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12424:141;;;;12961:7;12960:8;:28;;;;12986:2;12972:4;:11;:16;12960:28;12956:42;;;12997:1;12990:8;;;;;;12956:42;13027:4;13016:27;;;;;;;;;;;;:::i;:::-;13009:34;;;;2442:1:0;2804:4:::0;2797:28;12192:858:2;;-1:-1:-1;;12192:858:2:o;23180:582::-;23331:19;;;;23384:21;;23437:35;;;;23275:22;;23331:19;23361:112;;23407:4;;23421;;23428:44;;:6;:44;:::i;:::-;23361:22;:112::i;:::-;23483:18;23526:74;23547:10;23559:40;23573:10;23593:4;23559:13;:40::i;23526:74::-;23504:19;;;:96;;;;-1:-1:-1;23619:31:2;;;;23611:70;;;;;;;13505:2:13;23611:70:2;;;13487:21:13;13544:2;13524:18;;;13517:30;13583:28;13563:18;;;13556:56;13629:18;;23611:70:2;13303:350:13;23611:70:2;23723:30;;23180:582;-1:-1:-1;;;;23180:582:2:o;5504:3513::-;5682:34;;;;;5796:42;;;;;5753:40;;;:85;5907:31;;;;;;;5875:29;;;:63;;;5979:30;;;;;;;5948:28;;;:61;6045:25;;;;;5796:42;6019:23;;:51;6104:23;;;;;6080:21;;;:47;6162:24;;;;;6137:22;;;:49;6227:30;;;;;;;6196:28;;;:61;5796:42;6296:27;;;;;;;;6268:25;;;:55;6361:26;;;;;;;;6334:24;;;:53;6423:25;;;;;;-1:-1:-1;6397:23:2;;:51;6492:32;;;;-1:-1:-1;6459:30:2;;:65;6628:2;:23;;;6623:29;;;6045:25;6623:29;6585:35;;;:67;;;-1:-1:-1;;5907:31:2;6623:29;6697:53;;;;:::i;:::-;;6666:28;;;:84;6771:13;6787:40;6666:10;6821:4;6787:13;:40::i;:::-;6771:56;;6853:10;:28;;;6841:8;:40;6837:207;;6942:35;;;;6931:46;;6909:19;;;:68;6837:207;;;7032:1;7010:19;;;:23;6837:207;7130:10;:40;;;7111:59;;:15;:59;7107:1904;;7194:4;7186:12;;7213:11;7245:10;:40;;;7227:58;;:15;:58;;;;:::i;:::-;7213:72;;7335:27;7469:4;7435:10;:30;;;7366:66;7385:10;:23;;;7381:28;;7412:4;7381:35;;;;:::i;:::-;7419:6;7427:4;7366:9;:66::i;:::-;:99;;;;:::i;:::-;7365:108;;;;:::i;:::-;7335:138;;7488:20;7562:10;:30;;;7537:22;7511:10;:23;;;:48;;;;;;:::i;:::-;:81;;;;:::i;:::-;7632:25;;;;7695:24;;;;7488:104;;-1:-1:-1;7607:50:2;;;7671:48;;7607:22;7952:43;490:3:4;824:13;7952:43:2;:::i;:::-;7829:21;;;;7854:16;7829:41;;;;:87;;7895:10;:21;;;7829:87;;;923:20:4;7829:87:2;7751:166;;7770:10;:23;;;7752:41;;:15;:41;;;;:::i;:::-;7751:166;;;;:::i;:::-;:245;;;;:::i;:::-;7734:262;-1:-1:-1;8015:14:2;;8011:311;;8049:15;8090:41;490:3:4;8090:15:2;:41;:::i;:::-;8067:10;:19;;;:65;;;;:::i;:::-;8049:83;-1:-1:-1;8202:22:2;8215:9;8049:83;8202:22;:::i;:::-;8169:29;8182:16;8169:10;:29;:::i;:::-;:56;;;;:::i;:::-;8150:75;;8283:10;:24;;;8264:43;;:16;:43;;;;:::i;:::-;8243:64;;;;:::i;:::-;;;8031:291;8011:311;280:17:4;8420:35:2;;;;;:78;;-1:-1:-1;418:17:4;8459:39:2;;;8420:78;8416:585;;;8544:33;8561:15;8544:16;:33::i;:::-;8518:59;;:23;;;:59;8595:30;;;:55;;;8668:66;8718:15;8668:66;:40;;;:66;8777:24;;;;8757:44;;;;8753:234;;8853:36;8871:17;8853;:36::i;:::-;8825:64;;:25;;;:64;8938:30;8951:16;8938:12;:30::i;:::-;8911:57;;:24;;;:57;8753:234;7172:1839;;;;;;7107:1904;5648:3369;;5504:3513;;;;;:::o;11144:334::-;11225:4;11241:16;490:3:4;11283:10:2;:23;;;:49;;;;;;:::i;:::-;11260:10;:19;;;:73;;;;:::i;:::-;11241:92;-1:-1:-1;11347:16:2;;;:49;;-1:-1:-1;11367:24:2;;;;:29;;;11347:49;11343:66;;;-1:-1:-1;11405:4:2;;11144:334;-1:-1:-1;;11144:334:2:o;11343:66::-;11447:24;;;;11426:45;;:18;:11;11440:4;11426:18;:::i;:::-;:45;;;;:::i;:::-;11419:52;11144:334;-1:-1:-1;;;11144:334:2:o;25580:701::-;25663:4;25679:17;1115:12:4;25699:6:2;:34;;:70;;25763:6;25699:70;;;1115:12:4;25699:70:2;25679:90;-1:-1:-1;25779:17:2;25799:39;25679:90;1115:12:4;25799:39:2;:::i;:::-;25779:59;;25849:25;25900:20;25922:19;25945:28;25965:7;25945:19;:28::i;:::-;25899:74;;;;26028:14;26010:15;:32;:71;;26080:1;26010:71;;;26045:32;26063:14;26045:15;:32;:::i;:::-;25987:94;;25885:207;;1115:12:4;26234::2;26211:20;:35;;;;:::i;:::-;:62;;;;:::i;:::-;26110:22;;;;;;;:13;:22;;;;;:39;;;1115:12:4;;26110:54:2;;26152:12;;26110:54;:::i;:::-;:81;;;;:::i;:::-;26109:165;;;;:::i;:::-;26102:172;25580:701;-1:-1:-1;;;;;;25580:701:2:o;18326:490::-;18516:27;;;18451:17;18516:27;;;:18;;;:27;;;;;:32;;;;;;18574:69;18516:18;18608:10;18516:27;:32;18574:19;:69::i;:::-;18559:84;;18689:30;18706:12;18689:16;:30::i;:::-;18654:27;;;;;;;;:18;;;;:27;;;;;;:65;;;;;;;;;;;;;;;;;;;18779:30;;;;;-1:-1:-1;18729:47:2;;;:80;18326:490;:::o;2090:937::-;2209:22;;;2169:37;2209:22;;;:13;:22;;;;;;;;2269:32;;2367:14;:23;;;;;2269:32;;;;;;;2405:22;;2401:277;;2447:33;;:47;;;;:33;;;;;:47;2443:60;;;2496:7;;;2090:937;;:::o;2443:60::-;2549:1;2535:133;2556:17;2552:21;;:1;:21;2535:133;;;2616:10;2602:24;;:7;2610:1;2602:10;;;;;;;:::i;:::-;;;;;:24;2598:37;;;2628:7;;;;2090:937;;:::o;2598:37::-;2575:3;;;;:::i;:::-;;;;2535:133;;;;2401:277;544:2:4;2696:17:2;:39;;;2688:78;;;;;;;15755:2:13;2688:78:2;;;15737:21:13;15794:2;15774:18;;;15767:30;15833:28;15813:18;;;15806:56;15879:18;;2688:78:2;15553:350:13;2688:78:2;2781:22;;;2777:128;;2805:46;;;;;;;;;;;;2777:128;;;2895:10;2866:7;2874:17;2866:26;;;;;;;;;:::i;:::-;;:39;;;;;;;;;;;;;;;2777:128;2951:21;:17;2971:1;2951:21;:::i;:::-;2916:56;;;;;;;;;;;;;;;;2988:32;;;;;;;;;;;;;2916;;2988;2159:868;;;2090:937;;:::o;10942:196::-;11004:7;418:17:4;11031:30:2;;;11023:76;;;;;;;16343:2:13;11023:76:2;;;16325:21:13;16382:2;16362:18;;;16355:30;16421:34;16401:18;;;16394:62;16492:3;16472:18;;;16465:31;16513:19;;11023:76:2;16141:397:13;18822:817:2;490:3:4;18972:33:2;18984:10;18996:8;18972:11;:33::i;:::-;:59;;;;:::i;:::-;18961:70;;490:3:4;19048:29:2;19060:10;19072:4;19048:11;:29::i;:::-;:55;;;;:::i;:::-;19041:62;;19125:8;19118:4;:15;19114:519;;;19149:11;19163:15;19170:8;19163:4;:15;:::i;:::-;19149:29;;19227:7;19197:46;;19204:10;:21;;;19197:46;;;19236:6;19197:46;;;;345:25:13;;333:2;318:18;;199:177;19197:46:2;;;;;;;;19257:103;19279:13;19302:1;19306:7;19324:10;:35;;;19315:6;:44;;;;:::i;:::-;19257:21;:103::i;:::-;19135:236;19114:519;;;19392:4;19381:8;:15;19377:256;;;19412:11;19426:15;19437:4;19426:8;:15;:::i;:::-;19412:29;;19489:7;19460:45;;19466:10;:21;;;19460:45;;;19498:6;19460:45;;;;345:25:13;;333:2;318:18;;199:177;19460:45:2;;;;;;;;19519:103;19541:13;19556:7;19573:1;19586:10;:35;;;19577:6;:44;;;;:::i;1063:258:0:-;1169:12;1206:22;;;:12;:22;;;;;;;:42;;1144:12;;1169;;;1206:22;;;;;:42;;1242:5;;1206:42;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1168:80;;;;1263:7;1258:33;;1272:19;1284:6;1272:11;:19::i;437:284:10:-;564:59;;;553:10;16735:55:13;;;564:59:10;;;16717:74:13;16807:18;;;;16800:34;;;564:59:10;;;;;;;;;;16690:18:13;;;;564:59:10;;;;;;;;;587:24;564:59;;;553:71;;-1:-1:-1;;;;553:10:10;;;;:71;;564:59;553:71;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;517:107;;;;642:7;:57;;;;-1:-1:-1;654:11:10;;:16;;:44;;;685:4;674:24;;;;;;;;;;;;:::i;:::-;708:4;634:80;;;;;;;;;;;;;;:::i;16887:461:2:-;17032:4;17107:9;17103:23;;-1:-1:-1;17125:1:2;17118:8;;17103:23;17294:27;;;;;;;:18;;;:27;;;;;:47;;;17261:30;;;;17254:37;;:4;:37;:::i;17646:304::-;17730:4;17750:9;17746:23;;-1:-1:-1;17768:1:2;17761:8;;17746:23;17843:35;;;;490:3:4;17817:61:2;;;17900:16;:12;;;:16;17817:61;17899:26;;;;:::i;:::-;;:34;;17646:304;-1:-1:-1;;;;17646:304:2:o;119:312:10:-;264:69;;;253:10;17502:15:13;;;264:69:10;;;17484:34:13;17554:15;;;17534:18;;;17527:43;17586:18;;;;17579:34;;;264:69:10;;;;;;;;;;17396:18:13;;;;264:69:10;;;;;;;;;287:28;264:69;;;253:81;;-1:-1:-1;;;;253:10:10;;;;:81;;264:69;253:81;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;217:117;;;;352:7;:57;;;;-1:-1:-1;364:11:10;;:16;;:44;;;395:4;384:24;;;;;;;;;;;;:::i;:::-;418:4;344:80;;;;;;;;;;;;;;:::i;835:1036:12:-;899:6;947:1;949:53;;;;1048:9;;;1058:20;;;;1094:1;1089:6;;1041:56;;1058:20;1072:4;1067:9;;1041:56;;1136:1;1130:4;1126:12;1191:1;1188;1184:9;1179:14;;1173:668;1196:1;1173:668;;;1255:1;1252;1248:9;1303:1;1299;1295:2;1291:10;1288:17;1278:44;;1318:1;1316;1309:11;1278:44;1366:4;1362:2;1358:13;1407:2;1398:7;1395:15;1392:34;;;1422:1;1420;1413:11;1392:34;1452:18;;;;-1:-1:-1;;1494:8:12;;;1491:332;;;1546:1;1543;1539:9;1621:1;1617;1613:2;1609:10;1606:17;1599:25;1594:1;1587:9;1580:17;1576:49;1573:68;;;1637:1;1635;1628:11;1573:68;1689:4;1685:2;1681:13;1734:2;1725:7;1722:15;1719:34;;;1749:1;1747;1740:11;1719:34;1783:18;;;;-1:-1:-1;;1491:332:12;1211:1;1209;1205:8;1200:13;;1173:668;;;1177:18;940:915;;949:53;964:1;966:18;;;;999:1;994:6;;957:44;;966:18;979:4;974:9;;957:44;940:915;;835:1036;;;;;:::o;24609:467:2:-;24791:71;;3394:42:13;3382:55;;24791:71:2;;;3364:74:13;24673:20:2;;;;;;24748:115;;2838:9:4;;24814:38:2;;3337:18:13;;24791:71:2;3218:226:13;24748:115:2;24726:137;;24874:42;24931:6;24920:50;;;;;;;;;;;;:::i;:::-;24999:22;;25048:21;;;;;24999:22;;25048:21;;-1:-1:-1;24609:467:2;-1:-1:-1;;;;24609:467:2:o;2872:232:0:-;2942:13;;:17;2938:126;;3032:6;3026:13;3017:6;3013:2;3009:15;3002:38;2938:126;3074:23;;;;;18481:2:13;3074:23:0;;;18463:21:13;18520:2;18500:18;;;18493:30;18559:15;18539:18;;;18532:43;18592:18;;3074:23:0;18279:337:13;14:180;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:13;;14:180;-1:-1:-1;14:180:13:o;381:258::-;453:1;463:113;477:6;474:1;471:13;463:113;;;553:11;;;547:18;534:11;;;527:39;499:2;492:10;463:113;;;594:6;591:1;588:13;585:48;;;629:1;620:6;615:3;611:16;604:27;585:48;;381:258;;;:::o;644:442::-;793:2;782:9;775:21;756:4;825:6;819:13;868:6;863:2;852:9;848:18;841:34;884:66;943:6;938:2;927:9;923:18;918:2;910:6;906:15;884:66;:::i;:::-;1002:2;990:15;1007:66;986:88;971:104;;;;1077:2;967:113;;644:442;-1:-1:-1;;644:442:13:o;1091:196::-;1159:20;;1219:42;1208:54;;1198:65;;1188:93;;1277:1;1274;1267:12;1188:93;1091:196;;;:::o;1292:254::-;1360:6;1368;1421:2;1409:9;1400:7;1396:23;1392:32;1389:52;;;1437:1;1434;1427:12;1389:52;1460:29;1479:9;1460:29;:::i;:::-;1450:39;1536:2;1521:18;;;;1508:32;;-1:-1:-1;;;1292:254:13:o;1743:248::-;1811:6;1819;1872:2;1860:9;1851:7;1847:23;1843:32;1840:52;;;1888:1;1885;1878:12;1840:52;-1:-1:-1;;1911:23:13;;;1981:2;1966:18;;;1953:32;;-1:-1:-1;1743:248:13:o;1996:328::-;2073:6;2081;2089;2142:2;2130:9;2121:7;2117:23;2113:32;2110:52;;;2158:1;2155;2148:12;2110:52;2181:29;2200:9;2181:29;:::i;:::-;2171:39;;2229:38;2263:2;2252:9;2248:18;2229:38;:::i;:::-;2219:48;;2314:2;2303:9;2299:18;2286:32;2276:42;;1996:328;;;;;:::o;2518:322::-;2595:6;2603;2611;2664:2;2652:9;2643:7;2639:23;2635:32;2632:52;;;2680:1;2677;2670:12;2632:52;2716:9;2703:23;2693:33;;2745:38;2779:2;2768:9;2764:18;2745:38;:::i;2845:186::-;2904:6;2957:2;2945:9;2936:7;2932:23;2928:32;2925:52;;;2973:1;2970;2963:12;2925:52;2996:29;3015:9;2996:29;:::i;3449:260::-;3517:6;3525;3578:2;3566:9;3557:7;3553:23;3549:32;3546:52;;;3594:1;3591;3584:12;3546:52;3617:29;3636:9;3617:29;:::i;:::-;3607:39;;3665:38;3699:2;3688:9;3684:18;3665:38;:::i;:::-;3655:48;;3449:260;;;;;:::o;3714:184::-;3766:77;3763:1;3756:88;3863:4;3860:1;3853:15;3887:4;3884:1;3877:15;3903:184;3955:77;3952:1;3945:88;4052:4;4049:1;4042:15;4076:4;4073:1;4066:15;4092:274;4132:1;4158;4148:189;;4193:77;4190:1;4183:88;4294:4;4291:1;4284:15;4322:4;4319:1;4312:15;4148:189;-1:-1:-1;4351:9:13;;4092:274::o;4371:184::-;4423:77;4420:1;4413:88;4520:4;4517:1;4510:15;4544:4;4541:1;4534:15;4560:943;4640:6;4693:2;4681:9;4672:7;4668:23;4664:32;4661:52;;;4709:1;4706;4699:12;4661:52;4742:9;4736:16;4771:18;4812:2;4804:6;4801:14;4798:34;;;4828:1;4825;4818:12;4798:34;4866:6;4855:9;4851:22;4841:32;;4911:7;4904:4;4900:2;4896:13;4892:27;4882:55;;4933:1;4930;4923:12;4882:55;4962:2;4956:9;4984:2;4980;4977:10;4974:36;;;4990:18;;:::i;:::-;5124:2;5118:9;5186:4;5178:13;;5029:66;5174:22;;;5198:2;5170:31;5166:40;5154:53;;;5222:18;;;5242:22;;;5219:46;5216:72;;;5268:18;;:::i;:::-;5308:10;5304:2;5297:22;5343:2;5335:6;5328:18;5383:7;5378:2;5373;5369;5365:11;5361:20;5358:33;5355:53;;;5404:1;5401;5394:12;5355:53;5417:55;5469:2;5464;5456:6;5452:15;5447:2;5443;5439:11;5417:55;:::i;:::-;5491:6;4560:943;-1:-1:-1;;;;;;;4560:943:13:o;5508:431::-;5770:14;5765:3;5758:27;5740:3;5814:6;5808:13;5830:62;5885:6;5880:2;5875:3;5871:12;5864:4;5856:6;5852:17;5830:62;:::i;:::-;5912:16;;;;5930:2;5908:25;;5508:431;-1:-1:-1;;5508:431:13:o;7677:128::-;7717:3;7748:1;7744:6;7741:1;7738:13;7735:39;;;7754:18;;:::i;:::-;-1:-1:-1;7790:9:13;;7677:128::o;8163:418::-;8425:3;8420;8413:16;8395:3;8458:6;8452:13;8474:61;8528:6;8524:1;8519:3;8515:11;8508:4;8500:6;8496:17;8474:61;:::i;:::-;8555:16;;;;8573:1;8551:24;;8163:418;-1:-1:-1;;8163:418:13:o;9287:228::-;9327:7;9453:1;9385:66;9381:74;9378:1;9375:81;9370:1;9363:9;9356:17;9352:105;9349:131;;;9460:18;;:::i;:::-;-1:-1:-1;9500:9:13;;9287:228::o;9873:125::-;9913:4;9941:1;9938;9935:8;9932:34;;;9946:18;;:::i;:::-;-1:-1:-1;9983:9:13;;9873:125::o;11919:274::-;12048:3;12086:6;12080:13;12102:53;12148:6;12143:3;12136:4;12128:6;12124:17;12102:53;:::i;:::-;12171:16;;;;;11919:274;-1:-1:-1;;11919:274:13:o;13975:278::-;14043:6;14096:2;14084:9;14075:7;14071:23;14067:32;14064:52;;;14112:1;14109;14102:12;14064:52;14144:9;14138:16;14198:5;14194:2;14183:21;14176:5;14173:32;14163:60;;14219:1;14216;14209:12;14603:184;14673:6;14726:2;14714:9;14705:7;14701:23;14697:32;14694:52;;;14742:1;14739;14732:12;14694:52;-1:-1:-1;14765:16:13;;14603:184;-1:-1:-1;14603:184:13:o;14792:367::-;14831:3;14866:1;14863;14859:9;14975:1;14907:66;14903:74;14900:1;14896:82;14891:2;14884:10;14880:99;14877:125;;;14982:18;;:::i;:::-;15101:1;15033:66;15029:74;15026:1;15022:82;15018:2;15014:91;15011:117;;;15108:18;;:::i;:::-;-1:-1:-1;;15144:9:13;;14792:367::o;15164:184::-;15216:77;15213:1;15206:88;15313:4;15310:1;15303:15;15337:4;15334:1;15327:15;15353:195;15392:3;15423:66;15416:5;15413:77;15410:103;;;15493:18;;:::i;:::-;-1:-1:-1;15540:1:13;15529:13;;15353:195::o;15908:228::-;15947:3;15975:10;16012:2;16009:1;16005:10;16042:2;16039:1;16035:10;16073:3;16069:2;16065:12;16060:3;16057:21;16054:47;;;16081:18;;:::i;:::-;16117:13;;15908:228;-1:-1:-1;;;;15908:228:13:o;16845:164::-;16921:13;;16970;;16963:21;16953:32;;16943:60;;16999:1;16996;16989:12;17014:202;17081:6;17134:2;17122:9;17113:7;17109:23;17105:32;17102:52;;;17150:1;17147;17140:12;17102:52;17173:37;17200:9;17173:37;:::i;17624:650::-;17727:6;17780:3;17768:9;17759:7;17755:23;17751:33;17748:53;;;17797:1;17794;17787:12;17748:53;17830:2;17824:9;17872:3;17864:6;17860:16;17942:6;17930:10;17927:22;17906:18;17894:10;17891:34;17888:62;17885:88;;;17953:18;;:::i;:::-;17993:10;17989:2;17982:22;;18034:9;18028:16;18020:6;18013:32;18099:2;18088:9;18084:18;18078:25;18073:2;18065:6;18061:15;18054:50;18158:2;18147:9;18143:18;18137:25;18132:2;18124:6;18120:15;18113:50;18196:46;18238:2;18227:9;18223:18;18196:46;:::i;:::-;18191:2;18179:15;;18172:71;18183:6;17624:650;-1:-1:-1;;;17624:650:13:o
Swarm Source
ipfs://2f2cac2fdfae08dfebde13530cc107d5a13009d89b5a63c66288a4eb315bfe60
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.