Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
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:
Exec
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";
import "../IRiskManager.sol";
import "../PToken.sol";
import "../Interfaces.sol";
import "../Utils.sol";
/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract
interface IDeferredLiquidityCheck {
function onDeferredLiquidityCheck(bytes memory data) external;
}
/// @notice Batch executions, liquidity check deferrals, and interfaces to fetch prices and account liquidity
contract Exec is BaseLogic {
constructor(bytes32 moduleGitCommit_) BaseLogic(MODULEID__EXEC, moduleGitCommit_) {}
/// @notice Single item in a batch request
struct EulerBatchItem {
bool allowError;
address proxyAddr;
bytes data;
}
/// @notice Single item in a batch response
struct EulerBatchItemResponse {
bool success;
bytes result;
}
// Accessors
// These are not view methods, since they can perform state writes in the uniswap contract while retrieving prices
/// @notice Compute aggregate liquidity for an account
/// @param account User address
/// @return status Aggregate liquidity (sum of all entered assets)
function liquidity(address account) external nonReentrant returns (IRiskManager.LiquidityStatus memory status) {
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
abi.encodeWithSelector(IRiskManager.computeLiquidity.selector, account));
(status) = abi.decode(result, (IRiskManager.LiquidityStatus));
}
/// @notice Compute detailed liquidity for an account, broken down by asset
/// @param account User address
/// @return assets List of user's entered assets and each asset's corresponding liquidity
function detailedLiquidity(address account) public nonReentrant returns (IRiskManager.AssetLiquidity[] memory assets) {
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
abi.encodeWithSelector(IRiskManager.computeAssetLiquidities.selector, account));
(assets) = abi.decode(result, (IRiskManager.AssetLiquidity[]));
}
/// @notice Retrieve Euler's view of an asset's price
/// @param underlying Token address
/// @return twap Time-weighted average price
/// @return twapPeriod TWAP duration, either the twapWindow value in AssetConfig, or less if that duration not available
function getPrice(address underlying) external nonReentrant returns (uint twap, uint twapPeriod) {
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
abi.encodeWithSelector(IRiskManager.getPrice.selector, underlying));
(twap, twapPeriod) = abi.decode(result, (uint, uint));
}
/// @notice Retrieve Euler's view of an asset's price, as well as the current marginal price on uniswap
/// @param underlying Token address
/// @return twap Time-weighted average price
/// @return twapPeriod TWAP duration, either the twapWindow value in AssetConfig, or less if that duration not available
/// @return currPrice The current marginal price on uniswap3 (informational: not used anywhere in the Euler protocol)
function getPriceFull(address underlying) external nonReentrant returns (uint twap, uint twapPeriod, uint currPrice) {
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
abi.encodeWithSelector(IRiskManager.getPriceFull.selector, underlying));
(twap, twapPeriod, currPrice) = abi.decode(result, (uint, uint, uint));
}
// Custom execution methods
/// @notice Defer liquidity checking for an account, to perform rebalancing, flash loans, etc. msg.sender must implement IDeferredLiquidityCheck
/// @param account The account to defer liquidity for. Usually address(this), although not always
/// @param data Passed through to the onDeferredLiquidityCheck() callback, so contracts don't need to store transient data in storage
function deferLiquidityCheck(address account, bytes memory data) external reentrantOK {
address msgSender = unpackTrailingParamMsgSender();
require(accountLookup[account].deferLiquidityStatus == DEFERLIQUIDITY__NONE, "e/defer/reentrancy");
accountLookup[account].deferLiquidityStatus = DEFERLIQUIDITY__CLEAN;
IDeferredLiquidityCheck(msgSender).onDeferredLiquidityCheck(data);
uint8 status = accountLookup[account].deferLiquidityStatus;
accountLookup[account].deferLiquidityStatus = DEFERLIQUIDITY__NONE;
if (status == DEFERLIQUIDITY__DIRTY) checkLiquidity(account);
}
/// @notice Execute several operations in a single transaction
/// @param items List of operations to execute
/// @param deferLiquidityChecks List of user accounts to defer liquidity checks for
/// @return List of operation results
function batchDispatch(EulerBatchItem[] calldata items, address[] calldata deferLiquidityChecks) public reentrantOK returns (EulerBatchItemResponse[] memory) {
address msgSender = unpackTrailingParamMsgSender();
for (uint i = 0; i < deferLiquidityChecks.length; ++i) {
address account = deferLiquidityChecks[i];
require(accountLookup[account].deferLiquidityStatus == DEFERLIQUIDITY__NONE, "e/batch/reentrancy");
accountLookup[account].deferLiquidityStatus = DEFERLIQUIDITY__CLEAN;
}
EulerBatchItemResponse[] memory response = new EulerBatchItemResponse[](items.length);
for (uint i = 0; i < items.length; ++i) {
EulerBatchItem calldata item = items[i];
address proxyAddr = item.proxyAddr;
uint32 moduleId = trustedSenders[proxyAddr].moduleId;
address moduleImpl = trustedSenders[proxyAddr].moduleImpl;
require(moduleId != 0, "e/batch/unknown-proxy-addr");
require(moduleId <= MAX_EXTERNAL_MODULEID, "e/batch/call-to-internal-module");
if (moduleImpl == address(0)) moduleImpl = moduleLookup[moduleId];
require(moduleImpl != address(0), "e/batch/module-not-installed");
bytes memory inputWrapped = abi.encodePacked(item.data, uint160(msgSender), uint160(proxyAddr));
(bool success, bytes memory result) = moduleImpl.delegatecall(inputWrapped);
if (success || item.allowError) {
EulerBatchItemResponse memory r = response[i];
r.success = success;
r.result = result;
} else {
revertBytes(result);
}
}
for (uint i = 0; i < deferLiquidityChecks.length; ++i) {
address account = deferLiquidityChecks[i];
uint8 status = accountLookup[account].deferLiquidityStatus;
accountLookup[account].deferLiquidityStatus = DEFERLIQUIDITY__NONE;
if (status == DEFERLIQUIDITY__DIRTY) checkLiquidity(account);
}
return response;
}
/// @notice Results of a batchDispatch, but with extra information
struct EulerBatchExtra {
EulerBatchItemResponse[] responses;
uint gasUsed;
IRiskManager.AssetLiquidity[][] liquidities;
}
/// @notice Call batchDispatch, but return extra information. Only intended to be used with callStatic.
/// @param items List of operations to execute
/// @param deferLiquidityChecks List of user accounts to defer liquidity checks for
/// @param queryLiquidity List of user accounts to return detailed liquidity information for
/// @return output Structure with extra information
function batchDispatchExtra(EulerBatchItem[] calldata items, address[] calldata deferLiquidityChecks, address[] calldata queryLiquidity) external reentrantOK returns (EulerBatchExtra memory output) {
{
uint origGasLeft = gasleft();
output.responses = batchDispatch(items, deferLiquidityChecks);
output.gasUsed = origGasLeft - gasleft();
}
output.liquidities = new IRiskManager.AssetLiquidity[][](queryLiquidity.length);
for (uint i = 0; i < queryLiquidity.length; ++i) {
output.liquidities[i] = detailedLiquidity(queryLiquidity[i]);
}
}
// Average liquidity tracking
/// @notice Enable average liquidity tracking for your account. Operations will cost more gas, but you may get additional benefits when performing liquidations
/// @param subAccountId subAccountId 0 for primary, 1-255 for a sub-account.
/// @param delegate An address of another account that you would allow to use the benefits of your account's average liquidity (use the null address if you don't care about this). The other address must also reciprocally delegate to your account.
/// @param onlyDelegate Set this flag to skip tracking average liquidity and only set the delegate.
function trackAverageLiquidity(uint subAccountId, address delegate, bool onlyDelegate) external nonReentrant {
address msgSender = unpackTrailingParamMsgSender();
address account = getSubAccount(msgSender, subAccountId);
require(account != delegate, "e/track-liquidity/self-delegation");
emit DelegateAverageLiquidity(account, delegate);
accountLookup[account].averageLiquidityDelegate = delegate;
if (onlyDelegate) return;
emit TrackAverageLiquidity(account);
accountLookup[account].lastAverageLiquidityUpdate = uint40(block.timestamp);
accountLookup[account].averageLiquidity = 0;
}
/// @notice Disable average liquidity tracking for your account and remove delegate
/// @param subAccountId subAccountId 0 for primary, 1-255 for a sub-account
function unTrackAverageLiquidity(uint subAccountId) external nonReentrant {
address msgSender = unpackTrailingParamMsgSender();
address account = getSubAccount(msgSender, subAccountId);
emit UnTrackAverageLiquidity(account);
emit DelegateAverageLiquidity(account, address(0));
accountLookup[account].lastAverageLiquidityUpdate = 0;
accountLookup[account].averageLiquidity = 0;
accountLookup[account].averageLiquidityDelegate = address(0);
}
/// @notice Retrieve the average liquidity for an account
/// @param account User account (xor in subAccountId, if applicable)
/// @return The average liquidity, in terms of the reference asset, and post risk-adjustment
function getAverageLiquidity(address account) external nonReentrant returns (uint) {
return getUpdatedAverageLiquidity(account);
}
/// @notice Retrieve the average liquidity for an account or a delegate account, if set
/// @param account User account (xor in subAccountId, if applicable)
/// @return The average liquidity, in terms of the reference asset, and post risk-adjustment
function getAverageLiquidityWithDelegate(address account) external nonReentrant returns (uint) {
return getUpdatedAverageLiquidityWithDelegate(account);
}
/// @notice Retrieve the account which delegates average liquidity for an account, if set
/// @param account User account (xor in subAccountId, if applicable)
/// @return The average liquidity delegate account
function getAverageLiquidityDelegateAccount(address account) external view returns (address) {
address delegate = accountLookup[account].averageLiquidityDelegate;
return accountLookup[delegate].averageLiquidityDelegate == account ? delegate : address(0);
}
// PToken wrapping/unwrapping
/// @notice Transfer underlying tokens from sender's wallet into the pToken wrapper. Allowance should be set for the euler address.
/// @param underlying Token address
/// @param amount The amount to wrap in underlying units
function pTokenWrap(address underlying, uint amount) external nonReentrant {
address msgSender = unpackTrailingParamMsgSender();
emit PTokenWrap(underlying, msgSender, amount);
address pTokenAddr = reversePTokenLookup[underlying];
require(pTokenAddr != address(0), "e/exec/ptoken-not-found");
{
uint origBalance = IERC20(underlying).balanceOf(pTokenAddr);
Utils.safeTransferFrom(underlying, msgSender, pTokenAddr, amount);
uint newBalance = IERC20(underlying).balanceOf(pTokenAddr);
require(newBalance == origBalance + amount, "e/exec/ptoken-transfer-mismatch");
}
PToken(pTokenAddr).claimSurplus(msgSender);
}
/// @notice Transfer underlying tokens from the pToken wrapper to the sender's wallet.
/// @param underlying Token address
/// @param amount The amount to unwrap in underlying units
function pTokenUnWrap(address underlying, uint amount) external nonReentrant {
address msgSender = unpackTrailingParamMsgSender();
emit PTokenUnWrap(underlying, msgSender, amount);
address pTokenAddr = reversePTokenLookup[underlying];
require(pTokenAddr != address(0), "e/exec/ptoken-not-found");
PToken(pTokenAddr).forceUnwrap(msgSender, amount);
}
}// 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) {
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) {
if (assetCache.totalBalances == 0) return 1e18;
return (assetCache.poolSize + (assetCache.totalBorrows / INTERNAL_DEBT_PRECISION)) * 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: 20000}(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);
} else if (prevOwed > owed) {
uint change = prevOwed - owed;
emit Repay(assetCache.underlying, account, change);
emitViaProxy_Transfer(dTokenAddress, account, address(0), change);
}
}
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) 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 "./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;
function computeLiquidity(address account) external returns (LiquidityStatus memory status);
function computeAssetLiquidities(address account) external returns (AssetLiquidity[] memory assets);
function getPrice(address underlying) external returns (uint twap, uint twapPeriod);
function getPriceFull(address underlying) external returns (uint twap, uint twapPeriod, uint currPrice);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./Interfaces.sol";
import "./Utils.sol";
/// @notice Protected Tokens are simple wrappers for tokens, allowing you to use tokens as collateral without permitting borrowing
contract PToken {
address immutable euler;
address immutable underlyingToken;
constructor(address euler_, address underlying_) {
euler = euler_;
underlyingToken = underlying_;
}
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowances;
uint totalBalances;
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
/// @notice PToken name, ie "Euler Protected DAI"
function name() external view returns (string memory) {
return string(abi.encodePacked("Euler Protected ", IERC20(underlyingToken).name()));
}
/// @notice PToken symbol, ie "pDAI"
function symbol() external view returns (string memory) {
return string(abi.encodePacked("p", IERC20(underlyingToken).symbol()));
}
/// @notice Number of decimals, which is same as the underlying's
function decimals() external view returns (uint8) {
return IERC20(underlyingToken).decimals();
}
/// @notice Address of the underlying asset
function underlying() external view returns (address) {
return underlyingToken;
}
/// @notice Balance of an account's wrapped tokens
function balanceOf(address who) external view returns (uint) {
return balances[who];
}
/// @notice Sum of all wrapped token balances
function totalSupply() external view returns (uint) {
return totalBalances;
}
/// @notice Retrieve the current allowance
/// @param holder Address giving permission to access tokens
/// @param spender Trusted address
function allowance(address holder, address spender) external view returns (uint) {
return allowances[holder][spender];
}
/// @notice Transfer your own pTokens to another address
/// @param recipient Recipient address
/// @param amount Amount of wrapped token to transfer
function transfer(address recipient, uint amount) external returns (bool) {
return transferFrom(msg.sender, recipient, amount);
}
/// @notice Transfer pTokens from one address to another. The euler address is automatically granted approval.
/// @param from This address must've approved the to address
/// @param recipient Recipient address
/// @param amount Amount to transfer
function transferFrom(address from, address recipient, uint amount) public returns (bool) {
require(balances[from] >= amount, "insufficient balance");
if (from != msg.sender && msg.sender != euler && allowances[from][msg.sender] != type(uint).max) {
require(allowances[from][msg.sender] >= amount, "insufficient allowance");
allowances[from][msg.sender] -= amount;
emit Approval(from, msg.sender, allowances[from][msg.sender]);
}
balances[from] -= amount;
balances[recipient] += amount;
emit Transfer(from, recipient, amount);
return true;
}
/// @notice Allow spender to access an amount of your pTokens. It is not necessary to approve the euler address.
/// @param spender Trusted address
/// @param amount Use max uint256 for "infinite" allowance
function approve(address spender, uint amount) external returns (bool) {
allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
/// @notice Convert underlying tokens to pTokens
/// @param amount In underlying units (which are equivalent to pToken units)
function wrap(uint amount) external {
Utils.safeTransferFrom(underlyingToken, msg.sender, address(this), amount);
claimSurplus(msg.sender);
}
/// @notice Convert pTokens to underlying tokens
/// @param amount In pToken units (which are equivalent to underlying units)
function unwrap(uint amount) external {
doUnwrap(msg.sender, amount);
}
// Only callable by the euler contract:
function forceUnwrap(address who, uint amount) external {
require(msg.sender == euler, "permission denied");
doUnwrap(who, amount);
}
/// @notice Claim any surplus tokens held by the PToken contract. This should only be used by contracts.
/// @param who Beneficiary to be credited for the surplus token amount
function claimSurplus(address who) public {
uint currBalance = IERC20(underlyingToken).balanceOf(address(this));
require(currBalance > totalBalances, "no surplus balance to claim");
uint amount = currBalance - totalBalances;
totalBalances += amount;
balances[who] += amount;
emit Transfer(address(0), who, amount);
}
// Internal shared:
function doUnwrap(address who, uint amount) private {
require(balances[who] >= amount, "insufficient balance");
totalBalances -= amount;
balances[who] -= amount;
Utils.safeTransfer(underlyingToken, who, amount);
emit Transfer(who, address(0), amount);
}
}// 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 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: 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 {
mstore(0, 0)
calldatacopy(12, sub(calldatasize(), 40), 20)
msgSender := mload(0)
}
}
function unpackTrailingParams() internal pure returns (address msgSender, address proxyAddr) {
assembly {
mstore(0, 0)
calldatacopy(12, sub(calldatasize(), 40), 20)
msgSender := mload(0)
calldatacopy(12, sub(calldatasize(), 20), 20)
proxyAddr := mload(0)
}
}
// 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: 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 "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
_;
}
// 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 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
}// 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 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 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_INTEREST_ACCUMULATOR = 1e27;
uint internal constant AVERAGE_LIQUIDITY_PERIOD = 24 * 60 * 60;
uint16 internal constant MIN_UNISWAP3_OBSERVATION_CARDINALITY = 10;
uint24 internal constant DEFAULT_TWAP_WINDOW_SECONDS = 30 * 60;
uint32 internal constant DEFAULT_BORROW_FACTOR = uint32(0.28 * 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;
// 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;
// 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;
}{
"optimizer": {
"enabled": true,
"runs": 1000000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"bytes32","name":"moduleGitCommit_","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"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":"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":"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":[{"components":[{"internalType":"bool","name":"allowError","type":"bool"},{"internalType":"address","name":"proxyAddr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Exec.EulerBatchItem[]","name":"items","type":"tuple[]"},{"internalType":"address[]","name":"deferLiquidityChecks","type":"address[]"}],"name":"batchDispatch","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"result","type":"bytes"}],"internalType":"struct Exec.EulerBatchItemResponse[]","name":"","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"allowError","type":"bool"},{"internalType":"address","name":"proxyAddr","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Exec.EulerBatchItem[]","name":"items","type":"tuple[]"},{"internalType":"address[]","name":"deferLiquidityChecks","type":"address[]"},{"internalType":"address[]","name":"queryLiquidity","type":"address[]"}],"name":"batchDispatchExtra","outputs":[{"components":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"result","type":"bytes"}],"internalType":"struct Exec.EulerBatchItemResponse[]","name":"responses","type":"tuple[]"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"components":[{"internalType":"address","name":"underlying","type":"address"},{"components":[{"internalType":"uint256","name":"collateralValue","type":"uint256"},{"internalType":"uint256","name":"liabilityValue","type":"uint256"},{"internalType":"uint256","name":"numBorrows","type":"uint256"},{"internalType":"bool","name":"borrowIsolated","type":"bool"}],"internalType":"struct IRiskManager.LiquidityStatus","name":"status","type":"tuple"}],"internalType":"struct IRiskManager.AssetLiquidity[][]","name":"liquidities","type":"tuple[][]"}],"internalType":"struct Exec.EulerBatchExtra","name":"output","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deferLiquidityCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"detailedLiquidity","outputs":[{"components":[{"internalType":"address","name":"underlying","type":"address"},{"components":[{"internalType":"uint256","name":"collateralValue","type":"uint256"},{"internalType":"uint256","name":"liabilityValue","type":"uint256"},{"internalType":"uint256","name":"numBorrows","type":"uint256"},{"internalType":"bool","name":"borrowIsolated","type":"bool"}],"internalType":"struct IRiskManager.LiquidityStatus","name":"status","type":"tuple"}],"internalType":"struct IRiskManager.AssetLiquidity[]","name":"assets","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAverageLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAverageLiquidityDelegateAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAverageLiquidityWithDelegate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"twap","type":"uint256"},{"internalType":"uint256","name":"twapPeriod","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"}],"name":"getPriceFull","outputs":[{"internalType":"uint256","name":"twap","type":"uint256"},{"internalType":"uint256","name":"twapPeriod","type":"uint256"},{"internalType":"uint256","name":"currPrice","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"liquidity","outputs":[{"components":[{"internalType":"uint256","name":"collateralValue","type":"uint256"},{"internalType":"uint256","name":"liabilityValue","type":"uint256"},{"internalType":"uint256","name":"numBorrows","type":"uint256"},{"internalType":"bool","name":"borrowIsolated","type":"bool"}],"internalType":"struct IRiskManager.LiquidityStatus","name":"status","type":"tuple"}],"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":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"pTokenUnWrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"pTokenWrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"subAccountId","type":"uint256"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"bool","name":"onlyDelegate","type":"bool"}],"name":"trackAverageLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"subAccountId","type":"uint256"}],"name":"unTrackAverageLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c06040523480156200001157600080fd5b5060405162002c7238038062002c72833981016040819052620000349162000042565b600560805260a0526200005c565b6000602082840312156200005557600080fd5b5051919050565b60805160a051612bf062000082600039600061016d015260006102080152612bf06000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063a1308f2711610097578063dec82caf11610066578063dec82caf14610270578063df6b2aab14610290578063e94f487f146102c8578063eb937aeb146102db57600080fd5b8063a1308f2714610203578063b8c876b11461022a578063c053d9561461024a578063d346cb931461025d57600080fd5b80636c744e36116100d35780636c744e361461018f57806379465e9a146101a257806389b7b7a6146101c25780639693fa6b146101d557600080fd5b80632c01aa4d1461010557806341976e091461011a5780635f40fd761461014757806369a92ea314610168575b600080fd5b6101186101133660046120ea565b6102fb565b005b61012d610128366004612116565b6106ac565b604080519283526020830191909152015b60405180910390f35b61015a610155366004612116565b610818565b60405190815260200161013e565b61015a7f000000000000000000000000000000000000000000000000000000000000000081565b61011861019d366004612141565b61089f565b6101b56101b03660046121cf565b610b4b565b60405161013e91906123ba565b6101186101d0366004612546565b610c57565b6101e86101e3366004612116565b610e1b565b6040805193845260208401929092529082015260600161013e565b61015a7f000000000000000000000000000000000000000000000000000000000000000081565b61023d610238366004612116565b610f0e565b60405161013e919061260c565b610118610258366004612639565b611022565b61011861026b3660046120ea565b6111b5565b61028361027e366004612116565b611383565b60405161013e9190612652565b6102a361029e366004612116565b611460565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013e565b61015a6102d6366004612116565b6114b2565b6102ee6102e9366004612665565b61152e565b60405161013e91906126d1565b60016000541461036c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e6379000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6002600090815561037b611a9c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f57b7591996b63beb220451b64468c7ae28028af074ca4808b43e62ccf5363093846040516103dc91815260200190565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff8084166000908152600c60205260409020541680610473576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f652f657865632f70746f6b656e2d6e6f742d666f756e640000000000000000006044820152606401610363565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152600091908616906370a0823190602401602060405180830381865afa1580156104e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105079190612765565b905061051585848487611ab2565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152600091908716906370a0823190602401602060405180830381865afa158015610585573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a99190612765565b90506105b585836127ad565b811461061d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f652f657865632f70746f6b656e2d7472616e736665722d6d69736d61746368006044820152606401610363565b50506040517fb77dfe0300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282169063b77dfe03906024015b600060405180830381600087803b15801561068957600080fd5b505af115801561069d573d6000803e3d6000fd5b50506001600055505050505050565b60008060016000541461071b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815560405173ffffffffffffffffffffffffffffffffffffffff851660248201526107f290620f4240907f41976e0900000000000000000000000000000000000000000000000000000000906044015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611bff565b90508080602001905181019061080891906127c5565b6001600055909590945092505050565b6000600160005414610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b600260005561089482611c98565b600160005592915050565b60016000541461090b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815561091a611a9c565b905060006109288286611d1b565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156109e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f652f747261636b2d6c69717569646974792f73656c662d64656c65676174696f60448201527f6e000000000000000000000000000000000000000000000000000000000000006064820152608401610363565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f051502faf43051388110b7fe115f611d5a926cebe3afba5e97616e187a9d1a8360405160405180910390a373ffffffffffffffffffffffffffffffffffffffff818116600090815260066020526040902060020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169186169190911790558215610aa3575050610b41565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f2f14ab30bf36a91e75ee398a1e22ab477e868b5ff60a364c51617e4b5478355290600090a273ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff166101004264ffffffffff160217815560010155505b5050600160005550565b610b6f60405180606001604052806060815260200160008152602001606081525090565b60005a9050610b808888888861152e565b82525a610b8d90826127e9565b6020830152508167ffffffffffffffff811115610bac57610bac61249f565b604051908082528060200260200182016040528015610bdf57816020015b6060815260200190600190039081610bca5790505b50604082015260005b82811015610c4c57610c1a848483818110610c0557610c05612800565b905060200201602081019061027e9190612116565b82604001518281518110610c3057610c30612800565b602002602001018190525080610c459061282f565b9050610be8565b509695505050505050565b6000610c61611a9c565b73ffffffffffffffffffffffffffffffffffffffff841660009081526006602052604090205490915060ff1615610cf4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f652f64656665722f7265656e7472616e637900000000000000000000000000006044820152606401610363565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fa15db5c50000000000000000000000000000000000000000000000000000000081529082169063a15db5c590610d81908590600401612868565b600060405180830381600087803b158015610d9b57600080fd5b505af1158015610daf573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff8316600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811690915560ff166002811415610e1557610e1584611d8d565b50505050565b6000806000600160005414610e8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815560405173ffffffffffffffffffffffffffffffffffffffff86166024820152610ee590620f4240907f9693fa6b0000000000000000000000000000000000000000000000000000000090604401610770565b905080806020019051810190610efb919061287b565b6001600055919790965090945092505050565b610f3b60405180608001604052806000815260200160008152602001600081526020016000151581525090565b600160005414610fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815560405173ffffffffffffffffffffffffffffffffffffffff8416602482015261100090620f4240907f37fe974a0000000000000000000000000000000000000000000000000000000090604401610770565b9050808060200190518101906110169190612919565b60016000559392505050565b60016000541461108e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815561109d611a9c565b905060006110ab8284611d1b565b60405190915073ffffffffffffffffffffffffffffffffffffffff8216907f3ec5abf257929cda6ab723d94fd209371973b3fe82857ed2e3d114caeb14ec1190600090a260405160009073ffffffffffffffffffffffffffffffffffffffff8316907f051502faf43051388110b7fe115f611d5a926cebe3afba5e97616e187a9d1a83908390a373ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff1681556001808201839055600290910180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590555050565b600160005414611221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b60026000908155611230611a9c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f445b2ab817a8c867c93a3bf9ef795d39620e5ac916be6cba45d7baed85c785ca8460405161129191815260200190565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff8084166000908152600c60205260409020541680611328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f652f657865632f70746f6b656e2d6e6f742d666f756e640000000000000000006044820152606401610363565b6040517f1ed575db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015260248201859052821690631ed575db9060440161066f565b60606001600054146113f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815560405173ffffffffffffffffffffffffffffffffffffffff8416602482015261144a90620f4240907febd7ba190000000000000000000000000000000000000000000000000000000090604401610770565b9050808060200190518101906110169190612935565b73ffffffffffffffffffffffffffffffffffffffff80821660008181526006602052604080822060029081015485168084529183200154919390929116146114a95760006114ab565b805b9392505050565b6000600160005414611520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b600260005561089482611e71565b6060600061153a611a9c565b905060005b8381101561166057600085858381811061155b5761155b612800565b90506020020160208101906115709190612116565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205490915060ff1615611603576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f652f62617463682f7265656e7472616e637900000000000000000000000000006044820152606401610363565b73ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556116598161282f565b905061153f565b5060008567ffffffffffffffff81111561167c5761167c61249f565b6040519080825280602002602001820160405280156116c257816020015b60408051808201909152600081526060602082015281526020019060019003908161169a5790505b50905060005b868110156119ef57368888838181106116e3576116e3612800565b90506020028101906116f59190612a10565b905060006117096040830160208401612116565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526005602052604090205491925063ffffffff821691640100000000900416816117ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f652f62617463682f756e6b6e6f776e2d70726f78792d616464720000000000006044820152606401610363565b620f423f8263ffffffff16111561181e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f652f62617463682f63616c6c2d746f2d696e7465726e616c2d6d6f64756c65006044820152606401610363565b73ffffffffffffffffffffffffffffffffffffffff8116611867575063ffffffff811660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff81166118e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f652f62617463682f6d6f64756c652d6e6f742d696e7374616c6c6564000000006044820152606401610363565b60006118f36040860186612a4e565b89866040516020016119089493929190612ab3565b60405160208183030381529060405290506000808373ffffffffffffffffffffffffffffffffffffffff16836040516119419190612af6565b600060405180830381855af49150503d806000811461197c576040519150601f19603f3d011682016040523d82523d6000602084013e611981565b606091505b5091509150818061199a575061199a6020880188612b08565b156119ce5760008989815181106119b3576119b3612800565b602090810291909101810151841515815201829052506119d7565b6119d781611f04565b50505050505050806119e89061282f565b90506116c8565b5060005b84811015610c4c576000868683818110611a0f57611a0f612800565b9050602002016020810190611a249190612116565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811690915590915060ff166002811415611a8957611a8982611d8d565b505080611a959061282f565b90506119f3565b600080600052601460283603600c375060005190565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691611b519190612af6565b6000604051808303816000865af19150503d8060008114611b8e576040519150601f19603f3d011682016040523d82523d6000602084013e611b93565b606091505b5091509150818015611bbd575080511580611bbd575080806020019051810190611bbd9190612b25565b8190611bf6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103639190612868565b50505050505050565b60008281526003602052604080822054905160609291829173ffffffffffffffffffffffffffffffffffffffff90911690611c3b908690612af6565b600060405180830381855af49150503d8060008114611c76576040519150601f19603f3d011682016040523d82523d6000602084013e611c7b565b606091505b509150915081611c8e57611c8e81611f04565b9150505b92915050565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152600660205260408120600201549091168015801590611d00575073ffffffffffffffffffffffffffffffffffffffff8181166000908152600660205260409020600201548116908416145b611d1257611d0d83611e71565b6114ab565b6114ab81611e71565b60006101008210611d88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f652f7375622d6163636f756e742d69642d746f6f2d62696700000000000000006044820152606401610363565b501890565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff1680611e125760405173ffffffffffffffffffffffffffffffffffffffff83166024820152611e0d90620f4240907fc39b543a0000000000000000000000000000000000000000000000000000000090604401610770565b505050565b60ff811660011415611e6d5773ffffffffffffffffffffffffffffffffffffffff8216600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660021790555b5050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040812054610100900464ffffffffff1680611eb15750600092915050565b6000611ebd82426127e9565b905080611ef25750505073ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604090206001015490565b611efc8482611f75565b949350505050565b805115611f1357805181602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f652f656d7074792d6572726f72000000000000000000000000000000000000006044820152606401610363565b60008062015180831015611f895782611f8e565b620151805b90506000611f9f82620151806127e9565b90506000806000611faf88612040565b91509150808211611fc1576000611fcb565b611fcb81836127e9565b92505050620151808382611fdf9190612b42565b611fe99190612b7f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600660205260409020600101546201518090612022908590612b42565b61202c9190612b7f565b61203691906127ad565b9695505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff821660248201526000908190819061209990620f4240907f37fe974a0000000000000000000000000000000000000000000000000000000090604401610770565b90506000818060200190518101906120b19190612919565b805160209091015190969095509350505050565b73ffffffffffffffffffffffffffffffffffffffff811681146120e757600080fd5b50565b600080604083850312156120fd57600080fd5b8235612108816120c5565b946020939093013593505050565b60006020828403121561212857600080fd5b81356114ab816120c5565b80151581146120e757600080fd5b60008060006060848603121561215657600080fd5b833592506020840135612168816120c5565b9150604084013561217881612133565b809150509250925092565b60008083601f84011261219557600080fd5b50813567ffffffffffffffff8111156121ad57600080fd5b6020830191508360208260051b85010111156121c857600080fd5b9250929050565b600080600080600080606087890312156121e857600080fd5b863567ffffffffffffffff8082111561220057600080fd5b61220c8a838b01612183565b9098509650602089013591508082111561222557600080fd5b6122318a838b01612183565b9096509450604089013591508082111561224a57600080fd5b5061225789828a01612183565b979a9699509497509295939492505050565b60005b8381101561228457818101518382015260200161226c565b83811115610e155750506000910152565b600081518084526122ad816020860160208601612269565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501945080840160005b8381101561235d578151805173ffffffffffffffffffffffffffffffffffffffff168852830151612349848901828051825260208101516020830152604081015160408301526060810151151560608301525050565b5060a09690960195908201906001016122f3565b509495945050505050565b6000815180845260208085019450848260051b860182860160005b858110156123ad57838303895261239b8383516122df565b98850198925090840190600101612383565b5090979650505050505050565b6000602080835260808301845160608386015281815180845260a08701915060a08160051b8801019350848301925060005b8181101561244e578785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600183528351805115158652860151604087870181905261243a81880183612295565b9650505092850192918501916001016123ec565b50505050818501516040850152604085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160608501526124968183612368565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156124f1576124f161249f565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561253e5761253e61249f565b604052919050565b6000806040838503121561255957600080fd5b8235612564816120c5565b915060208381013567ffffffffffffffff8082111561258257600080fd5b818601915086601f83011261259657600080fd5b8135818111156125a8576125a861249f565b6125d8847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016124f7565b915080825287848285010111156125ee57600080fd5b80848401858401376000848284010152508093505050509250929050565b81518152602080830151908201526040808301519082015260608083015115159082015260808101611c92565b60006020828403121561264b57600080fd5b5035919050565b6020815260006114ab60208301846122df565b6000806000806040858703121561267b57600080fd5b843567ffffffffffffffff8082111561269357600080fd5b61269f88838901612183565b909650945060208701359150808211156126b857600080fd5b506126c587828801612183565b95989497509550505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015612757578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180511515845287015187840187905261274487850182612295565b95880195935050908601906001016126f8565b509098975050505050505050565b60006020828403121561277757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156127c0576127c061277e565b500190565b600080604083850312156127d857600080fd5b505080516020909101519092909150565b6000828210156127fb576127fb61277e565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156128615761286161277e565b5060010190565b6020815260006114ab6020830184612295565b60008060006060848603121561289057600080fd5b8351925060208401519150604084015190509250925092565b6000608082840312156128bb57600080fd5b6040516080810181811067ffffffffffffffff821117156128de576128de61249f565b8060405250809150825181526020830151602082015260408301516040820152606083015161290c81612133565b6060919091015292915050565b60006080828403121561292b57600080fd5b6114ab83836128a9565b6000602080838503121561294857600080fd5b825167ffffffffffffffff8082111561296057600080fd5b818501915085601f83011261297457600080fd5b8151818111156129865761298661249f565b612994848260051b016124f7565b818152848101925060a09182028401850191888311156129b357600080fd5b938501935b82851015612a045780858a0312156129d05760008081fd5b6129d86124ce565b85516129e3816120c5565b81526129f18a8789016128a9565b81880152845293840193928501926129b8565b50979650505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112612a4457600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a8357600080fd5b83018035915067ffffffffffffffff821115612a9e57600080fd5b6020019150368190038213156121c857600080fd5b838582377fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606093841b811694909101938452911b166014820152602801919050565b60008251612a44818460208701612269565b600060208284031215612b1a57600080fd5b81356114ab81612133565b600060208284031215612b3757600080fd5b81516114ab81612133565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612b7a57612b7a61277e565b500290565b600082612bb5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220474fd23fba1cc65167cfcecba4c8d28cd4495fe9e3c00fabb0fdbd1b8858a8b164736f6c634300080a0033000000000000000000000000df359cfaa399c01a62b1f64767460715eb7df4d3
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101005760003560e01c8063a1308f2711610097578063dec82caf11610066578063dec82caf14610270578063df6b2aab14610290578063e94f487f146102c8578063eb937aeb146102db57600080fd5b8063a1308f2714610203578063b8c876b11461022a578063c053d9561461024a578063d346cb931461025d57600080fd5b80636c744e36116100d35780636c744e361461018f57806379465e9a146101a257806389b7b7a6146101c25780639693fa6b146101d557600080fd5b80632c01aa4d1461010557806341976e091461011a5780635f40fd761461014757806369a92ea314610168575b600080fd5b6101186101133660046120ea565b6102fb565b005b61012d610128366004612116565b6106ac565b604080519283526020830191909152015b60405180910390f35b61015a610155366004612116565b610818565b60405190815260200161013e565b61015a7f000000000000000000000000df359cfaa399c01a62b1f64767460715eb7df4d381565b61011861019d366004612141565b61089f565b6101b56101b03660046121cf565b610b4b565b60405161013e91906123ba565b6101186101d0366004612546565b610c57565b6101e86101e3366004612116565b610e1b565b6040805193845260208401929092529082015260600161013e565b61015a7f000000000000000000000000000000000000000000000000000000000000000581565b61023d610238366004612116565b610f0e565b60405161013e919061260c565b610118610258366004612639565b611022565b61011861026b3660046120ea565b6111b5565b61028361027e366004612116565b611383565b60405161013e9190612652565b6102a361029e366004612116565b611460565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013e565b61015a6102d6366004612116565b6114b2565b6102ee6102e9366004612665565b61152e565b60405161013e91906126d1565b60016000541461036c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e6379000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6002600090815561037b611a9c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f57b7591996b63beb220451b64468c7ae28028af074ca4808b43e62ccf5363093846040516103dc91815260200190565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff8084166000908152600c60205260409020541680610473576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f652f657865632f70746f6b656e2d6e6f742d666f756e640000000000000000006044820152606401610363565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152600091908616906370a0823190602401602060405180830381865afa1580156104e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105079190612765565b905061051585848487611ab2565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152600091908716906370a0823190602401602060405180830381865afa158015610585573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a99190612765565b90506105b585836127ad565b811461061d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f652f657865632f70746f6b656e2d7472616e736665722d6d69736d61746368006044820152606401610363565b50506040517fb77dfe0300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282169063b77dfe03906024015b600060405180830381600087803b15801561068957600080fd5b505af115801561069d573d6000803e3d6000fd5b50506001600055505050505050565b60008060016000541461071b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815560405173ffffffffffffffffffffffffffffffffffffffff851660248201526107f290620f4240907f41976e0900000000000000000000000000000000000000000000000000000000906044015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611bff565b90508080602001905181019061080891906127c5565b6001600055909590945092505050565b6000600160005414610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b600260005561089482611c98565b600160005592915050565b60016000541461090b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815561091a611a9c565b905060006109288286611d1b565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156109e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f652f747261636b2d6c69717569646974792f73656c662d64656c65676174696f60448201527f6e000000000000000000000000000000000000000000000000000000000000006064820152608401610363565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f051502faf43051388110b7fe115f611d5a926cebe3afba5e97616e187a9d1a8360405160405180910390a373ffffffffffffffffffffffffffffffffffffffff818116600090815260066020526040902060020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169186169190911790558215610aa3575050610b41565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f2f14ab30bf36a91e75ee398a1e22ab477e868b5ff60a364c51617e4b5478355290600090a273ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff166101004264ffffffffff160217815560010155505b5050600160005550565b610b6f60405180606001604052806060815260200160008152602001606081525090565b60005a9050610b808888888861152e565b82525a610b8d90826127e9565b6020830152508167ffffffffffffffff811115610bac57610bac61249f565b604051908082528060200260200182016040528015610bdf57816020015b6060815260200190600190039081610bca5790505b50604082015260005b82811015610c4c57610c1a848483818110610c0557610c05612800565b905060200201602081019061027e9190612116565b82604001518281518110610c3057610c30612800565b602002602001018190525080610c459061282f565b9050610be8565b509695505050505050565b6000610c61611a9c565b73ffffffffffffffffffffffffffffffffffffffff841660009081526006602052604090205490915060ff1615610cf4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f652f64656665722f7265656e7472616e637900000000000000000000000000006044820152606401610363565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fa15db5c50000000000000000000000000000000000000000000000000000000081529082169063a15db5c590610d81908590600401612868565b600060405180830381600087803b158015610d9b57600080fd5b505af1158015610daf573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff8316600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811690915560ff166002811415610e1557610e1584611d8d565b50505050565b6000806000600160005414610e8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815560405173ffffffffffffffffffffffffffffffffffffffff86166024820152610ee590620f4240907f9693fa6b0000000000000000000000000000000000000000000000000000000090604401610770565b905080806020019051810190610efb919061287b565b6001600055919790965090945092505050565b610f3b60405180608001604052806000815260200160008152602001600081526020016000151581525090565b600160005414610fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815560405173ffffffffffffffffffffffffffffffffffffffff8416602482015261100090620f4240907f37fe974a0000000000000000000000000000000000000000000000000000000090604401610770565b9050808060200190518101906110169190612919565b60016000559392505050565b60016000541461108e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815561109d611a9c565b905060006110ab8284611d1b565b60405190915073ffffffffffffffffffffffffffffffffffffffff8216907f3ec5abf257929cda6ab723d94fd209371973b3fe82857ed2e3d114caeb14ec1190600090a260405160009073ffffffffffffffffffffffffffffffffffffffff8316907f051502faf43051388110b7fe115f611d5a926cebe3afba5e97616e187a9d1a83908390a373ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff1681556001808201839055600290910180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590555050565b600160005414611221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b60026000908155611230611a9c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f445b2ab817a8c867c93a3bf9ef795d39620e5ac916be6cba45d7baed85c785ca8460405161129191815260200190565b60405180910390a373ffffffffffffffffffffffffffffffffffffffff8084166000908152600c60205260409020541680611328576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f652f657865632f70746f6b656e2d6e6f742d666f756e640000000000000000006044820152606401610363565b6040517f1ed575db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015260248201859052821690631ed575db9060440161066f565b60606001600054146113f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b6002600090815560405173ffffffffffffffffffffffffffffffffffffffff8416602482015261144a90620f4240907febd7ba190000000000000000000000000000000000000000000000000000000090604401610770565b9050808060200190518101906110169190612935565b73ffffffffffffffffffffffffffffffffffffffff80821660008181526006602052604080822060029081015485168084529183200154919390929116146114a95760006114ab565b805b9392505050565b6000600160005414611520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f652f7265656e7472616e637900000000000000000000000000000000000000006044820152606401610363565b600260005561089482611e71565b6060600061153a611a9c565b905060005b8381101561166057600085858381811061155b5761155b612800565b90506020020160208101906115709190612116565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205490915060ff1615611603576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f652f62617463682f7265656e7472616e637900000000000000000000000000006044820152606401610363565b73ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556116598161282f565b905061153f565b5060008567ffffffffffffffff81111561167c5761167c61249f565b6040519080825280602002602001820160405280156116c257816020015b60408051808201909152600081526060602082015281526020019060019003908161169a5790505b50905060005b868110156119ef57368888838181106116e3576116e3612800565b90506020028101906116f59190612a10565b905060006117096040830160208401612116565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526005602052604090205491925063ffffffff821691640100000000900416816117ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f652f62617463682f756e6b6e6f776e2d70726f78792d616464720000000000006044820152606401610363565b620f423f8263ffffffff16111561181e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f652f62617463682f63616c6c2d746f2d696e7465726e616c2d6d6f64756c65006044820152606401610363565b73ffffffffffffffffffffffffffffffffffffffff8116611867575063ffffffff811660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff81166118e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f652f62617463682f6d6f64756c652d6e6f742d696e7374616c6c6564000000006044820152606401610363565b60006118f36040860186612a4e565b89866040516020016119089493929190612ab3565b60405160208183030381529060405290506000808373ffffffffffffffffffffffffffffffffffffffff16836040516119419190612af6565b600060405180830381855af49150503d806000811461197c576040519150601f19603f3d011682016040523d82523d6000602084013e611981565b606091505b5091509150818061199a575061199a6020880188612b08565b156119ce5760008989815181106119b3576119b3612800565b602090810291909101810151841515815201829052506119d7565b6119d781611f04565b50505050505050806119e89061282f565b90506116c8565b5060005b84811015610c4c576000868683818110611a0f57611a0f612800565b9050602002016020810190611a249190612116565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811690915590915060ff166002811415611a8957611a8982611d8d565b505080611a959061282f565b90506119f3565b600080600052601460283603600c375060005190565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691611b519190612af6565b6000604051808303816000865af19150503d8060008114611b8e576040519150601f19603f3d011682016040523d82523d6000602084013e611b93565b606091505b5091509150818015611bbd575080511580611bbd575080806020019051810190611bbd9190612b25565b8190611bf6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103639190612868565b50505050505050565b60008281526003602052604080822054905160609291829173ffffffffffffffffffffffffffffffffffffffff90911690611c3b908690612af6565b600060405180830381855af49150503d8060008114611c76576040519150601f19603f3d011682016040523d82523d6000602084013e611c7b565b606091505b509150915081611c8e57611c8e81611f04565b9150505b92915050565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152600660205260408120600201549091168015801590611d00575073ffffffffffffffffffffffffffffffffffffffff8181166000908152600660205260409020600201548116908416145b611d1257611d0d83611e71565b6114ab565b6114ab81611e71565b60006101008210611d88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f652f7375622d6163636f756e742d69642d746f6f2d62696700000000000000006044820152606401610363565b501890565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff1680611e125760405173ffffffffffffffffffffffffffffffffffffffff83166024820152611e0d90620f4240907fc39b543a0000000000000000000000000000000000000000000000000000000090604401610770565b505050565b60ff811660011415611e6d5773ffffffffffffffffffffffffffffffffffffffff8216600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660021790555b5050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040812054610100900464ffffffffff1680611eb15750600092915050565b6000611ebd82426127e9565b905080611ef25750505073ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604090206001015490565b611efc8482611f75565b949350505050565b805115611f1357805181602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f652f656d7074792d6572726f72000000000000000000000000000000000000006044820152606401610363565b60008062015180831015611f895782611f8e565b620151805b90506000611f9f82620151806127e9565b90506000806000611faf88612040565b91509150808211611fc1576000611fcb565b611fcb81836127e9565b92505050620151808382611fdf9190612b42565b611fe99190612b7f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600660205260409020600101546201518090612022908590612b42565b61202c9190612b7f565b61203691906127ad565b9695505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff821660248201526000908190819061209990620f4240907f37fe974a0000000000000000000000000000000000000000000000000000000090604401610770565b90506000818060200190518101906120b19190612919565b805160209091015190969095509350505050565b73ffffffffffffffffffffffffffffffffffffffff811681146120e757600080fd5b50565b600080604083850312156120fd57600080fd5b8235612108816120c5565b946020939093013593505050565b60006020828403121561212857600080fd5b81356114ab816120c5565b80151581146120e757600080fd5b60008060006060848603121561215657600080fd5b833592506020840135612168816120c5565b9150604084013561217881612133565b809150509250925092565b60008083601f84011261219557600080fd5b50813567ffffffffffffffff8111156121ad57600080fd5b6020830191508360208260051b85010111156121c857600080fd5b9250929050565b600080600080600080606087890312156121e857600080fd5b863567ffffffffffffffff8082111561220057600080fd5b61220c8a838b01612183565b9098509650602089013591508082111561222557600080fd5b6122318a838b01612183565b9096509450604089013591508082111561224a57600080fd5b5061225789828a01612183565b979a9699509497509295939492505050565b60005b8381101561228457818101518382015260200161226c565b83811115610e155750506000910152565b600081518084526122ad816020860160208601612269565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501945080840160005b8381101561235d578151805173ffffffffffffffffffffffffffffffffffffffff168852830151612349848901828051825260208101516020830152604081015160408301526060810151151560608301525050565b5060a09690960195908201906001016122f3565b509495945050505050565b6000815180845260208085019450848260051b860182860160005b858110156123ad57838303895261239b8383516122df565b98850198925090840190600101612383565b5090979650505050505050565b6000602080835260808301845160608386015281815180845260a08701915060a08160051b8801019350848301925060005b8181101561244e578785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600183528351805115158652860151604087870181905261243a81880183612295565b9650505092850192918501916001016123ec565b50505050818501516040850152604085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160608501526124968183612368565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156124f1576124f161249f565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561253e5761253e61249f565b604052919050565b6000806040838503121561255957600080fd5b8235612564816120c5565b915060208381013567ffffffffffffffff8082111561258257600080fd5b818601915086601f83011261259657600080fd5b8135818111156125a8576125a861249f565b6125d8847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016124f7565b915080825287848285010111156125ee57600080fd5b80848401858401376000848284010152508093505050509250929050565b81518152602080830151908201526040808301519082015260608083015115159082015260808101611c92565b60006020828403121561264b57600080fd5b5035919050565b6020815260006114ab60208301846122df565b6000806000806040858703121561267b57600080fd5b843567ffffffffffffffff8082111561269357600080fd5b61269f88838901612183565b909650945060208701359150808211156126b857600080fd5b506126c587828801612183565b95989497509550505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015612757578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180511515845287015187840187905261274487850182612295565b95880195935050908601906001016126f8565b509098975050505050505050565b60006020828403121561277757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156127c0576127c061277e565b500190565b600080604083850312156127d857600080fd5b505080516020909101519092909150565b6000828210156127fb576127fb61277e565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156128615761286161277e565b5060010190565b6020815260006114ab6020830184612295565b60008060006060848603121561289057600080fd5b8351925060208401519150604084015190509250925092565b6000608082840312156128bb57600080fd5b6040516080810181811067ffffffffffffffff821117156128de576128de61249f565b8060405250809150825181526020830151602082015260408301516040820152606083015161290c81612133565b6060919091015292915050565b60006080828403121561292b57600080fd5b6114ab83836128a9565b6000602080838503121561294857600080fd5b825167ffffffffffffffff8082111561296057600080fd5b818501915085601f83011261297457600080fd5b8151818111156129865761298661249f565b612994848260051b016124f7565b818152848101925060a09182028401850191888311156129b357600080fd5b938501935b82851015612a045780858a0312156129d05760008081fd5b6129d86124ce565b85516129e3816120c5565b81526129f18a8789016128a9565b81880152845293840193928501926129b8565b50979650505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112612a4457600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a8357600080fd5b83018035915067ffffffffffffffff821115612a9e57600080fd5b6020019150368190038213156121c857600080fd5b838582377fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606093841b811694909101938452911b166014820152602801919050565b60008251612a44818460208701612269565b600060208284031215612b1a57600080fd5b81356114ab81612133565b600060208284031215612b3757600080fd5b81516114ab81612133565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612b7a57612b7a61277e565b500290565b600082612bb5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220474fd23fba1cc65167cfcecba4c8d28cd4495fe9e3c00fabb0fdbd1b8858a8b164736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000df359cfaa399c01a62b1f64767460715eb7df4d3
-----Decoded View---------------
Arg [0] : moduleGitCommit_ (bytes32): 0x000000000000000000000000df359cfaa399c01a62b1f64767460715eb7df4d3
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000df359cfaa399c01a62b1f64767460715eb7df4d3
Deployed Bytecode Sourcemap
518:12787:12:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11985:722;;;;;;:::i;:::-;;:::i;:::-;;2515:359;;;;;;:::i;:::-;;:::i;:::-;;;;919:25:14;;;975:2;960:18;;953:34;;;;892:18;2515:359:12;;;;;;;;11034:166;;;;;;:::i;:::-;;:::i;:::-;;;1144:25:14;;;1132:2;1117:18;11034:166:12;998:177:14;241:40:3;;;;;9046:664:12;;;;;;:::i;:::-;;:::i;7773:630::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;4153:631::-;;;;;;:::i;:::-;;:::i;3324:400::-;;;;;;:::i;:::-;;:::i;:::-;;;;9142:25:14;;;9198:2;9183:18;;9176:34;;;;9226:18;;;9219:34;9130:2;9115:18;3324:400:12;8940:319:14;205:30:3;;;;;1234:386:12;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;9884:502::-;;;;;;:::i;:::-;;:::i;12907:396::-;;;;;;:::i;:::-;;:::i;1836:401::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;11428:276::-;;;;;;:::i;:::-;;:::i;:::-;;;10245:42:14;10233:55;;;10215:74;;10203:2;10188:18;11428:276:12;10069:226:14;10624:142:12;;;;;;:::i;:::-;;:::i;5038:2103::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;11985:722::-;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;;;;;;;;;1445:1:4;1459:14:0;:39;;;12090:30:12::1;:28;:30::i;:::-;12070:50;;12159:9;12136:41;;12147:10;12136:41;;;12170:6;12136:41;;;;1144:25:14::0;;1132:2;1117:18;;998:177;12136:41:12::1;;;;;;;;12209:31;::::0;;::::1;12188:18;12209:31:::0;;;:19:::1;:31;::::0;;;;;::::1;12258:24:::0;12250:60:::1;;;::::0;::::1;::::0;;12837:2:14;12250:60:12::1;::::0;::::1;12819:21:14::0;12876:2;12856:18;;;12849:30;12915:25;12895:18;;;12888:53;12958:18;;12250:60:12::1;12635:347:14::0;12250:60:12::1;12354:40;::::0;;;;:28:::1;10233:55:14::0;;;12354:40:12::1;::::0;::::1;10215:74:14::0;12335:16:12::1;::::0;12354:28;;::::1;::::0;::::1;::::0;10188:18:14;;12354:40:12::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12335:59;;12408:65;12431:10;12443:9;12454:10;12466:6;12408:22;:65::i;:::-;12505:40;::::0;;;;:28:::1;10233:55:14::0;;;12505:40:12::1;::::0;::::1;10215:74:14::0;12487:15:12::1;::::0;12505:28;;::::1;::::0;::::1;::::0;10188:18:14;;12505:40:12::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12487:58:::0;-1:-1:-1;12581:20:12::1;12595:6:::0;12581:11;:20:::1;:::i;:::-;12567:10;:34;12559:78;;;::::0;::::1;::::0;;13700:2:14;12559:78:12::1;::::0;::::1;13682:21:14::0;13739:2;13719:18;;;13712:30;13778:33;13758:18;;;13751:61;13829:18;;12559:78:12::1;13498:355:14::0;12559:78:12::1;-1:-1:-1::0;;12658:42:12::1;::::0;;;;:31:::1;10233:55:14::0;;;12658:42:12::1;::::0;::::1;10215:74:14::0;12658:31:12;::::1;::::0;::::1;::::0;10188:18:14;;12658:42:12::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;1390:1:4;1519:14:0;:41;-1:-1:-1;;;;;;11985:722:12:o;2515:359::-;2584:9;2595:15;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;;;2736:66:12::1;::::0;10245:42:14;10233:55;;2736:66:12::1;::::0;::::1;10215:74:14::0;2644:159:12::1;::::0;2522:9:4::1;::::0;2759:30:12;;10188:18:14;;2736:66:12::1;;::::0;;;;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;;2644:18:::1;:159::i;:::-;2622:181;;2846:6;2835:32;;;;;;;;;;;;:::i;:::-;1390:1:4::0;1519:14:0;:41;2814:53:12;;;;-1:-1:-1;2515:359:12;-1:-1:-1;;;2515:359:12:o;11034:166::-;11123:4;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;11146:47:12::1;11185:7:::0;11146:38:::1;:47::i;:::-;1390:1:4::0;1519:14:0;:41;11139:54:12;11034:166;-1:-1:-1;;11034:166:12:o;9046:664::-;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;;;9185:30:12::1;:28;:30::i;:::-;9165:50;;9225:15;9243:38;9257:9;9268:12;9243:13;:38::i;:::-;9225:56;;9310:8;9299:19;;:7;:19;;;;9291:65;;;::::0;::::1;::::0;;14310:2:14;9291:65:12::1;::::0;::::1;14292:21:14::0;14349:2;14329:18;;;14322:30;14388:34;14368:18;;;14361:62;14459:3;14439:18;;;14432:31;14480:19;;9291:65:12::1;14108:397:14::0;9291:65:12::1;9406:8;9372:43;;9397:7;9372:43;;;;;;;;;;;;9425:22;::::0;;::::1;;::::0;;;:13:::1;:22;::::0;;;;:47:::1;;:58:::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;9494:25;::::1;;;9512:7;;;;9494:25;9534:30;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;9575:22;;;::::0;;;:13:::1;:22;::::0;;;;:75;;;::::1;;9634:15;9575:75;;;;::::0;;-1:-1:-1;9660:39:12::1;:43:::0;-1:-1:-1;1508:1:0::1;-1:-1:-1::0;;1390:1:4;1519:14:0;:41;-1:-1:-1;9046:664:12:o;7773:630::-;7940:29;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;7940:29:12;7995:16:::1;8014:9;7995:28;;8056:42;8070:5;;8077:20;;8056:13;:42::i;:::-;8037:61:::0;;8143:9:::1;8129:23;::::0;:11;:23:::1;:::i;:::-;8112:14;::::0;::::1;:40:::0;-1:-1:-1;8230:14:12;8194:58:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;8173:18:12::1;::::0;::::1;:79:::0;8268:6:::1;8263:134;8280:25:::0;;::::1;8263:134;;;8350:36;8368:14;;8383:1;8368:17;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;8350:36::-;8326:6;:18;;;8345:1;8326:21;;;;;;;;:::i;:::-;;;;;;:60;;;;8307:3;;;;:::i;:::-;;;8263:134;;;;7773:630:::0;;;;;;;;:::o;4153:631::-;4249:17:::1;4269:30;:28;:30::i;:::-;4318:22;::::0;::::1;1500:1:4;4318:22:12::0;;;:13:::1;:22;::::0;;;;:43;4249:50;;-1:-1:-1;4318:67:12::1;:43;:67:::0;4310:98:::1;;;::::0;::::1;::::0;;15231:2:14;4310:98:12::1;::::0;::::1;15213:21:14::0;15270:2;15250:18;;;15243:30;15309:20;15289:18;;;15282:48;15347:18;;4310:98:12::1;15029:342:14::0;4310:98:12::1;4418:22;::::0;;::::1;;::::0;;;:13:::1;:22;::::0;;;;;;:67;;;::::1;1555:1:4;4418:67:12;::::0;;4496:65;;;;:59;;::::1;::::0;::::1;::::0;:65:::1;::::0;4556:4;;4496:65:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;;;4587:22:12::1;::::0;::::1;4572:12;4587:22:::0;;;:13:::1;:22;::::0;;;;:43;;4640:66;;::::1;::::0;;;4587:43:::1;;1610:1:4;4721:31:12::0;::::1;4717:60;;;4754:23;4769:7;4754:14;:23::i;:::-;4239:545;;4153:631:::0;;:::o;3324:400::-;3397:9;3408:15;3425:14;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;;;3565:70:12::1;::::0;10245:42:14;10233:55;;3565:70:12::1;::::0;::::1;10215:74:14::0;3473:163:12::1;::::0;2522:9:4::1;::::0;3588:34:12;;10188:18:14;;3565:70:12::1;10069:226:14::0;3473:163:12::1;3451:185;;3690:6;3679:38;;;;;;;;;;;;:::i;:::-;1390:1:4::0;1519:14:0;:41;3647:70:12;;;;-1:-1:-1;3647:70:12;;-1:-1:-1;3324:400:12;-1:-1:-1;;;3324:400:12:o;1234:386::-;1301:42;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1301:42:12;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;;;1469:71:12::1;::::0;10245:42:14;10233:55;;1469:71:12::1;::::0;::::1;10215:74:14::0;1377:164:12::1;::::0;2522:9:4::1;::::0;1492:38:12;;10188:18:14;;1469:71:12::1;10069:226:14::0;1377:164:12::1;1355:186;;1574:6;1563:50;;;;;;;;;;;;:::i;:::-;1390:1:4::0;1519:14:0;:41;1552:61:12;1234:386;-1:-1:-1;;;1234:386:12:o;9884:502::-;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;;;9988:30:12::1;:28;:30::i;:::-;9968:50;;10028:15;10046:38;10060:9;10071:12;10046:13;:38::i;:::-;10100:32;::::0;10028:56;;-1:-1:-1;10100:32:12::1;::::0;::::1;::::0;::::1;::::0;;;::::1;10147:45;::::0;10189:1:::1;::::0;10147:45:::1;::::0;::::1;::::0;::::1;::::0;10189:1;;10147:45:::1;10203:22;;10255:1;10203:22:::0;;;:13:::1;:22;::::0;;;;:53;;;::::1;::::0;;:49:::1;10266:39:::0;;::::1;:43:::0;;;10319:47:::1;::::0;;::::1;:60:::0;;;::::1;::::0;;1519:41:0;;-1:-1:-1;;9884:502:12:o;12907:396::-;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;;;13014:30:12::1;:28;:30::i;:::-;12994:50;;13085:9;13060:43;;13073:10;13060:43;;;13096:6;13060:43;;;;1144:25:14::0;;1132:2;1117:18;;998:177;13060:43:12::1;;;;;;;;13135:31;::::0;;::::1;13114:18;13135:31:::0;;;:19:::1;:31;::::0;;;;;::::1;13184:24:::0;13176:60:::1;;;::::0;::::1;::::0;;12837:2:14;13176:60:12::1;::::0;::::1;12819:21:14::0;12876:2;12856:18;;;12849:30;12915:25;12895:18;;;12888:53;12958:18;;13176:60:12::1;12635:347:14::0;13176:60:12::1;13247:49;::::0;;;;:30:::1;17042:55:14::0;;;13247:49:12::1;::::0;::::1;17024:74:14::0;17114:18;;;17107:34;;;13247:30:12;::::1;::::0;::::1;::::0;16997:18:14;;13247:49:12::1;16850:297:14::0;1836:401:12;1909:43;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;;;2078:78:12::1;::::0;10245:42:14;10233:55;;2078:78:12::1;::::0;::::1;10215:74:14::0;1986:171:12::1;::::0;2522:9:4::1;::::0;2101:45:12;;10188:18:14;;2078:78:12::1;10069:226:14::0;1986:171:12::1;1964:193;;2190:6;2179:51;;;;;;;;;;;;:::i;11428:276::-:0;11550:22;;;;11512:7;11550:22;;;:13;:22;;;;;;:47;;;;;;;11614:23;;;;;;:48;;11512:7;;11550:47;;11614:48;;:59;:83;;11695:1;11614:83;;;11676:8;11614:83;11607:90;11428:276;-1:-1:-1;;;11428:276:12:o;10624:142::-;10701:4;1390:1:4;1389:14:0;;:42;1381:67;;;;;;;12496:2:14;1381:67:0;;;12478:21:14;12535:2;12515:18;;;12508:30;12574:14;12554:18;;;12547:42;12606:18;;1381:67:0;12294:336:14;1381:67:0;1445:1:4;1459:14:0;:39;10724:35:12::1;10751:7:::0;10724:26:::1;:35::i;5038:2103::-:0;5163:31;5206:17:::1;5226:30;:28;:30::i;:::-;5206:50;;5272:6;5267:315;5284:31:::0;;::::1;5267:315;;;5336:15;5354:20;;5375:1;5354:23;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;5400:22;::::0;::::1;1500:1:4;5400:22:12::0;;;:13:::1;:22;::::0;;;;:43;5336:41;;-1:-1:-1;5400:67:12::1;:43;:67:::0;5392:98:::1;;;::::0;::::1;::::0;;18733:2:14;5392:98:12::1;::::0;::::1;18715:21:14::0;18772:2;18752:18;;;18745:30;18811:20;18791:18;;;18784:48;18849:18;;5392:98:12::1;18531:342:14::0;5392:98:12::1;5504:22;;;::::0;;;:13:::1;:22;::::0;;;;:67;;;::::1;1555:1:4;5504:67:12;::::0;;5317:3:::1;::::0;::::1;:::i;:::-;;;5267:315;;;-1:-1:-1::0;5593:40:12::1;5665:5:::0;5636:42:::1;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;;;;;;;;;;;;;5636:42:12::1;;;;;;;;;;;;;;;;5593:85;;5694:6;5689:1060;5706:16:::0;;::::1;5689:1060;;;5743:28;5774:5;;5780:1;5774:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;5743:39:::0;-1:-1:-1;5796:17:12::1;5816:14;::::0;;;::::1;::::0;::::1;;:::i;:::-;5863:25;::::0;;::::1;5845:15;5863:25:::0;;;:14:::1;:25;::::0;;;;:34;5796;;-1:-1:-1;5863:34:12::1;::::0;::::1;::::0;5932:36;;::::1;;5991:13:::0;5983:52:::1;;;::::0;::::1;::::0;;19475:2:14;5983:52:12::1;::::0;::::1;19457:21:14::0;19514:2;19494:18;;;19487:30;19553:28;19533:18;;;19526:56;19599:18;;5983:52:12::1;19273:350:14::0;5983:52:12::1;2436:7:4;6057:8:12;:33;;;;6049:77;;;::::0;::::1;::::0;;19830:2:14;6049:77:12::1;::::0;::::1;19812:21:14::0;19869:2;19849:18;;;19842:30;19908:33;19888:18;;;19881:61;19959:18;;6049:77:12::1;19628:355:14::0;6049:77:12::1;6145:24;::::0;::::1;6141:65;;-1:-1:-1::0;6184:22:12::1;::::0;::::1;;::::0;;;:12:::1;:22;::::0;;;;;::::1;;6141:65;6228:24;::::0;::::1;6220:65;;;::::0;::::1;::::0;;20190:2:14;6220:65:12::1;::::0;::::1;20172:21:14::0;20229:2;20209:18;;;20202:30;20268;20248:18;;;20241:58;20316:18;;6220:65:12::1;19988:352:14::0;6220:65:12::1;6300:25;6345:9;;::::0;::::1;:4:::0;:9:::1;:::i;:::-;6364;6384;6328:67;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;6300:95;;6410:12;6424:19:::0;6447:10:::1;:23;;6471:12;6447:37;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6409:75;;;;6503:7;:26;;;-1:-1:-1::0;6514:15:12::1;;::::0;::::1;:4:::0;:15:::1;:::i;:::-;6499:240;;;6549:31;6583:8;6592:1;6583:11;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;;6612:19;::::1;;::::0;;6649:8:::1;:17:::0;;;-1:-1:-1;6499:240:12::1;;;6705:19;6717:6;6705:11;:19::i;:::-;5729:1020;;;;;;;5724:3;;;;:::i;:::-;;;5689:1060;;;;6765:6;6760:349;6777:31:::0;;::::1;6760:349;;;6829:15;6847:20;;6868:1;6847:23;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;6900:22;::::0;::::1;6885:12;6900:22:::0;;;:13:::1;:22;::::0;;;;:43;;6957:66;;::::1;::::0;;;6829:41;;-1:-1:-1;6900:43:12::1;;1610:1:4;7042:31:12::0;::::1;7038:60;;;7075:23;7090:7;7075:14;:23::i;:::-;6815:294;;6810:3;;;;:::i;:::-;;;6760:349;;459:236:3::0;522:17;584:1;581;574:12;642:2;637;621:14;617:23;613:2;600:45;-1:-1:-1;677:1:3;671:8;;459:236::o;119:312:11:-;264:69;;;253:10;22261:15:14;;;264:69:11;;;22243:34:14;22313:15;;;22293:18;;;22286:43;22345:18;;;;22338:34;;;264:69:11;;;;;;;;;;22155:18:14;;;;264:69:11;;;;;;;;;287:28;264:69;;;253:81;;-1:-1:-1;;;;253:10:11;;;;:81;;264:69;253:81;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;217:117;;;;352:7;:57;;;;-1:-1:-1;364:11:11;;:16;;:44;;;395:4;384:24;;;;;;;;;;;;:::i;:::-;418:4;344:80;;;;;;;;;;;;;;:::i;:::-;;207:224;;119:312;;;;:::o;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;:::-;1308:6;-1:-1:-1;;1063:258:0;;;;;:::o;26258:376:2:-;26376:22;;;;26341:4;26376:22;;;:13;:22;;;;;:47;;;26341:4;;26376:47;26441:22;;;;;:85;;-1:-1:-1;26467:59:2;:23;;;;;;;:13;:23;;;;;:48;;;;;:59;;;;26441:85;:186;;26592:35;26619:7;26592:26;:35::i;:::-;26441:186;;;26541:36;26568:8;26541:26;:36::i;402:229::-;484:7;526:3;511:12;:18;503:55;;;;;;;23059:2:14;503:55:2;;;23041:21:14;23098:2;23078:18;;;23071:30;23137:26;23117:18;;;23110:54;23181:18;;503:55:2;22857:348:14;503:55:2;-1:-1:-1;583:40:2;;402:229::o;24612:446::-;24687:22;;;24672:12;24687:22;;;:13;:22;;;;;:43;;;24745:30;24741:311;;24834:71;;10245:42:14;10233:55;;24834:71:2;;;10215:74:14;24791:115:2;;2522:9:4;;24857:38:2;;10188:18:14;;24834:71:2;10069:226:14;24791:115:2;;24662:396;24612:446;:::o;24741:311::-;24927:31;;;1555:1:4;24927:31:2;24923:129;;;24974:22;;;;;;;:13;:22;;;;;:67;;;;1610:1:4;24974:67:2;;;24923:129;24662:396;24612:446;:::o;25817:435::-;25938:22;;;25888:4;25938:22;;;:13;:22;;;;;:49;;;;;;;25997:45;;-1:-1:-1;26041:1:2;;25817:435;-1:-1:-1;;25817:435:2:o;25997:45::-;26053:11;26067:44;26085:26;26067:15;:44;:::i;:::-;26053:58;-1:-1:-1;26125:11:2;26121:63;;-1:-1:-1;;;26145:22:2;;;;;;:13;:22;;;;;:39;;;;25817:435::o;26121:63::-;26202:43;26229:7;26238:6;26202:26;:43::i;:::-;26195:50;25817:435;-1:-1:-1;;;;25817:435:2:o;2580:232:0:-;2650:13;;:17;2646:126;;2740:6;2734:13;2725:6;2721:2;2717:15;2710:38;2646:126;2782:23;;;;;23412:2:14;2782:23:0;;;23394:21:14;23451:2;23431:18;;;23424:30;23490:15;23470:18;;;23463:43;23523:18;;2782:23:0;23210:337:14;25110:701:2;25193:4;25209:17;1064:12:4;25229:6:2;:34;;:70;;25293:6;25229:70;;;1064:12:4;25229:70:2;25209:90;-1:-1:-1;25309:17:2;25329:39;25209:90;1064:12:4;25329:39:2;:::i;:::-;25309:59;;25379:25;25430:20;25452:19;25475:28;25495:7;25475:19;:28::i;:::-;25429:74;;;;25558:14;25540:15;:32;:71;;25610:1;25540:71;;;25575:32;25593:14;25575:15;:32;:::i;:::-;25517:94;;25415:207;;1064:12:4;25764::2;25741:20;:35;;;;:::i;:::-;:62;;;;:::i;:::-;25640:22;;;;;;;:13;:22;;;;;:39;;;1064:12:4;;25640:54:2;;25682:12;;25640:54;:::i;:::-;:81;;;;:::i;:::-;25639:165;;;;:::i;:::-;25632:172;25110:701;-1:-1:-1;;;;;;25110:701:2:o;24139:467::-;24321:71;;10245:42:14;10233:55;;24321:71:2;;;10215:74:14;24203:20:2;;;;;;24278:115;;2522:9:4;;24344:38:2;;10188:18:14;;24321:71:2;10069:226:14;24278:115:2;24256:137;;24404:42;24461:6;24450:50;;;;;;;;;;;;:::i;:::-;24529:22;;24578:21;;;;;24529:22;;24578:21;;-1:-1:-1;24139:467:2;-1:-1:-1;;;;24139:467:2:o;14:154:14:-;100:42;93:5;89:54;82:5;79:65;69:93;;158:1;155;148:12;69:93;14:154;:::o;173:315::-;241:6;249;302:2;290:9;281:7;277:23;273:32;270:52;;;318:1;315;308:12;270:52;357:9;344:23;376:31;401:5;376:31;:::i;:::-;426:5;478:2;463:18;;;;450:32;;-1:-1:-1;;;173:315:14:o;493:247::-;552:6;605:2;593:9;584:7;580:23;576:32;573:52;;;621:1;618;611:12;573:52;660:9;647:23;679:31;704:5;679:31;:::i;1362:118::-;1448:5;1441:13;1434:21;1427:5;1424:32;1414:60;;1470:1;1467;1460:12;1485:450;1559:6;1567;1575;1628:2;1616:9;1607:7;1603:23;1599:32;1596:52;;;1644:1;1641;1634:12;1596:52;1680:9;1667:23;1657:33;;1740:2;1729:9;1725:18;1712:32;1753:31;1778:5;1753:31;:::i;:::-;1803:5;-1:-1:-1;1860:2:14;1845:18;;1832:32;1873:30;1832:32;1873:30;:::i;:::-;1922:7;1912:17;;;1485:450;;;;;:::o;1940:390::-;2026:8;2036:6;2090:3;2083:4;2075:6;2071:17;2067:27;2057:55;;2108:1;2105;2098:12;2057:55;-1:-1:-1;2131:20:14;;2174:18;2163:30;;2160:50;;;2206:1;2203;2196:12;2160:50;2243:4;2235:6;2231:17;2219:29;;2303:3;2296:4;2286:6;2283:1;2279:14;2271:6;2267:27;2263:38;2260:47;2257:67;;;2320:1;2317;2310:12;2257:67;1940:390;;;;;:::o;2335:1191::-;2527:6;2535;2543;2551;2559;2567;2620:2;2608:9;2599:7;2595:23;2591:32;2588:52;;;2636:1;2633;2626:12;2588:52;2676:9;2663:23;2705:18;2746:2;2738:6;2735:14;2732:34;;;2762:1;2759;2752:12;2732:34;2801:93;2886:7;2877:6;2866:9;2862:22;2801:93;:::i;:::-;2913:8;;-1:-1:-1;2775:119:14;-1:-1:-1;3001:2:14;2986:18;;2973:32;;-1:-1:-1;3017:16:14;;;3014:36;;;3046:1;3043;3036:12;3014:36;3085:95;3172:7;3161:8;3150:9;3146:24;3085:95;:::i;:::-;3199:8;;-1:-1:-1;3059:121:14;-1:-1:-1;3287:2:14;3272:18;;3259:32;;-1:-1:-1;3303:16:14;;;3300:36;;;3332:1;3329;3322:12;3300:36;;3371:95;3458:7;3447:8;3436:9;3432:24;3371:95;:::i;:::-;2335:1191;;;;-1:-1:-1;2335:1191:14;;-1:-1:-1;2335:1191:14;;3485:8;;2335:1191;-1:-1:-1;;;2335:1191:14:o;3531:258::-;3603:1;3613:113;3627:6;3624:1;3621:13;3613:113;;;3703:11;;;3697:18;3684:11;;;3677:39;3649:2;3642:10;3613:113;;;3744:6;3741:1;3738:13;3735:48;;;-1:-1:-1;;3779:1:14;3761:16;;3754:27;3531:258::o;3794:316::-;3835:3;3873:5;3867:12;3900:6;3895:3;3888:19;3916:63;3972:6;3965:4;3960:3;3956:14;3949:4;3942:5;3938:16;3916:63;:::i;:::-;4024:2;4012:15;4029:66;4008:88;3999:98;;;;4099:4;3995:109;;3794:316;-1:-1:-1;;3794:316:14:o;4404:657::-;4471:3;4509:5;4503:12;4536:6;4531:3;4524:19;4562:4;4591:2;4586:3;4582:12;4575:19;;4628:2;4621:5;4617:14;4649:1;4659:377;4673:6;4670:1;4667:13;4659:377;;;4732:13;;4774:9;;4785:42;4770:58;4758:71;;4868:11;;4862:18;4893:61;4941:12;;;4862:18;4202:5;4196:12;4191:3;4184:25;4258:4;4251:5;4247:16;4241:23;4234:4;4229:3;4225:14;4218:47;4314:4;4307:5;4303:16;4297:23;4290:4;4285:3;4281:14;4274:47;4384:4;4377:5;4373:16;4367:23;4360:31;4353:39;4346:4;4341:3;4337:14;4330:63;;;4115:284;4893:61;-1:-1:-1;4983:4:14;4974:14;;;;;5011:15;;;;4695:1;4688:9;4659:377;;;-1:-1:-1;5052:3:14;;4404:657;-1:-1:-1;;;;;4404:657:14:o;5066:617::-;5143:3;5181:5;5175:12;5208:6;5203:3;5196:19;5234:4;5263:2;5258:3;5254:12;5247:19;;5288:3;5328:6;5325:1;5321:14;5316:3;5312:24;5370:2;5363:5;5359:14;5391:1;5401:256;5415:6;5412:1;5409:13;5401:256;;;5486:5;5480:4;5476:16;5471:3;5464:29;5514:63;5572:4;5563:6;5557:13;5514:63;:::i;:::-;5635:12;;;;5506:71;-1:-1:-1;5600:15:14;;;;5437:1;5430:9;5401:256;;;-1:-1:-1;5673:4:14;;5066:617;-1:-1:-1;;;;;;;5066:617:14:o;5688:1495::-;5846:4;5875:2;5904;5893:9;5886:21;5945:3;5934:9;5930:19;5984:6;5978:13;6027:4;6022:2;6011:9;6007:18;6000:32;6052:6;6087:12;6081:19;6124:6;6116;6109:22;6162:3;6151:9;6147:19;6140:26;;6225:3;6215:6;6212:1;6208:14;6197:9;6193:30;6189:40;6175:54;;6270:2;6256:12;6252:21;6238:35;;6291:1;6301:533;6315:6;6312:1;6309:13;6301:533;;;6380:22;;;6404:66;6376:95;6364:108;;6495:13;;6577:9;;6570:17;6563:25;6548:41;;6630:11;;6624:18;6531:4;6662:15;;;6655:27;;;6705:49;6738:15;;;6624:18;6705:49;:::i;:::-;6695:59;-1:-1:-1;;;6777:15:14;;;;6812:12;;;;6337:1;6330:9;6301:533;;;6305:3;;;;6890:2;6882:6;6878:15;6872:22;6865:4;6854:9;6850:20;6843:52;6944:4;6936:6;6932:17;6926:24;6904:46;;7016:66;7004:9;6996:6;6992:22;6988:95;6981:4;6970:9;6966:20;6959:125;7101:76;7170:6;7154:14;7101:76;:::i;:::-;7093:84;5688:1495;-1:-1:-1;;;;;5688:1495:14:o;7188:184::-;7240:77;7237:1;7230:88;7337:4;7334:1;7327:15;7361:4;7358:1;7351:15;7377:257;7449:4;7443:11;;;7481:17;;7528:18;7513:34;;7549:22;;;7510:62;7507:88;;;7575:18;;:::i;:::-;7611:4;7604:24;7377:257;:::o;7639:334::-;7710:2;7704:9;7766:2;7756:13;;7771:66;7752:86;7740:99;;7869:18;7854:34;;7890:22;;;7851:62;7848:88;;;7916:18;;:::i;:::-;7952:2;7945:22;7639:334;;-1:-1:-1;7639:334:14:o;7978:957::-;8055:6;8063;8116:2;8104:9;8095:7;8091:23;8087:32;8084:52;;;8132:1;8129;8122:12;8084:52;8171:9;8158:23;8190:31;8215:5;8190:31;:::i;:::-;8240:5;-1:-1:-1;8264:2:14;8302:18;;;8289:32;8340:18;8370:14;;;8367:34;;;8397:1;8394;8387:12;8367:34;8435:6;8424:9;8420:22;8410:32;;8480:7;8473:4;8469:2;8465:13;8461:27;8451:55;;8502:1;8499;8492:12;8451:55;8538:2;8525:16;8560:2;8556;8553:10;8550:36;;;8566:18;;:::i;:::-;8608:112;8716:2;8647:66;8640:4;8636:2;8632:13;8628:86;8624:95;8608:112;:::i;:::-;8595:125;;8743:2;8736:5;8729:17;8783:7;8778:2;8773;8769;8765:11;8761:20;8758:33;8755:53;;;8804:1;8801;8794:12;8755:53;8859:2;8854;8850;8846:11;8841:2;8834:5;8830:14;8817:45;8903:1;8898:2;8893;8886:5;8882:14;8878:23;8871:34;;8924:5;8914:15;;;;;7978:957;;;;;:::o;9264:271::-;4196:12;;4184:25;;4258:4;4247:16;;;4241:23;4225:14;;;4218:47;4314:4;4303:16;;;4297:23;4281:14;;;4274:47;4384:4;4373:16;;;4367:23;4360:31;4353:39;4337:14;;;4330:63;9464:3;9449:19;;9477:52;4115:284;9540:180;9599:6;9652:2;9640:9;9631:7;9627:23;9623:32;9620:52;;;9668:1;9665;9658:12;9620:52;-1:-1:-1;9691:23:14;;9540:180;-1:-1:-1;9540:180:14:o;9725:339::-;9968:2;9957:9;9950:21;9931:4;9988:70;10054:2;10043:9;10039:18;10031:6;9988:70;:::i;10300:853::-;10456:6;10464;10472;10480;10533:2;10521:9;10512:7;10508:23;10504:32;10501:52;;;10549:1;10546;10539:12;10501:52;10589:9;10576:23;10618:18;10659:2;10651:6;10648:14;10645:34;;;10675:1;10672;10665:12;10645:34;10714:93;10799:7;10790:6;10779:9;10775:22;10714:93;:::i;:::-;10826:8;;-1:-1:-1;10688:119:14;-1:-1:-1;10914:2:14;10899:18;;10886:32;;-1:-1:-1;10930:16:14;;;10927:36;;;10959:1;10956;10949:12;10927:36;;10998:95;11085:7;11074:8;11063:9;11059:24;10998:95;:::i;:::-;10300:853;;;;-1:-1:-1;11112:8:14;-1:-1:-1;;;;10300:853:14:o;11158:1131::-;11380:4;11409:2;11449;11438:9;11434:18;11479:2;11468:9;11461:21;11502:6;11537;11531:13;11568:6;11560;11553:22;11594:2;11584:12;;11627:2;11616:9;11612:18;11605:25;;11689:2;11679:6;11676:1;11672:14;11661:9;11657:30;11653:39;11727:2;11719:6;11715:15;11748:1;11758:502;11772:6;11769:1;11766:13;11758:502;;;11837:22;;;11861:66;11833:95;11821:108;;11952:13;;12007:9;;12000:17;11993:25;11978:41;;12058:11;;12052:18;12090:15;;;12083:27;;;12133:47;12164:15;;;12052:18;12133:47;:::i;:::-;12238:12;;;;12123:57;-1:-1:-1;;12203:15:14;;;;11794:1;11787:9;11758:502;;;-1:-1:-1;12277:6:14;;11158:1131;-1:-1:-1;;;;;;;;11158:1131:14:o;12987:184::-;13057:6;13110:2;13098:9;13089:7;13085:23;13081:32;13078:52;;;13126:1;13123;13116:12;13078:52;-1:-1:-1;13149:16:14;;12987:184;-1:-1:-1;12987:184:14:o;13176:::-;13228:77;13225:1;13218:88;13325:4;13322:1;13315:15;13349:4;13346:1;13339:15;13365:128;13405:3;13436:1;13432:6;13429:1;13426:13;13423:39;;;13442:18;;:::i;:::-;-1:-1:-1;13478:9:14;;13365:128::o;13858:245::-;13937:6;13945;13998:2;13986:9;13977:7;13973:23;13969:32;13966:52;;;14014:1;14011;14004:12;13966:52;-1:-1:-1;;14037:16:14;;14093:2;14078:18;;;14072:25;14037:16;;14072:25;;-1:-1:-1;13858:245:14:o;14510:125::-;14550:4;14578:1;14575;14572:8;14569:34;;;14583:18;;:::i;:::-;-1:-1:-1;14620:9:14;;14510:125::o;14640:184::-;14692:77;14689:1;14682:88;14789:4;14786:1;14779:15;14813:4;14810:1;14803:15;14829:195;14868:3;14899:66;14892:5;14889:77;14886:103;;;14969:18;;:::i;:::-;-1:-1:-1;15016:1:14;15005:13;;14829:195::o;15376:217::-;15523:2;15512:9;15505:21;15486:4;15543:44;15583:2;15572:9;15568:18;15560:6;15543:44;:::i;15598:306::-;15686:6;15694;15702;15755:2;15743:9;15734:7;15730:23;15726:32;15723:52;;;15771:1;15768;15761:12;15723:52;15800:9;15794:16;15784:26;;15850:2;15839:9;15835:18;15829:25;15819:35;;15894:2;15883:9;15879:18;15873:25;15863:35;;15598:306;;;;;:::o;15909:665::-;15982:5;16030:4;16018:9;16013:3;16009:19;16005:30;16002:50;;;16048:1;16045;16038:12;16002:50;16081:2;16075:9;16123:4;16115:6;16111:17;16194:6;16182:10;16179:22;16158:18;16146:10;16143:34;16140:62;16137:88;;;16205:18;;:::i;:::-;16245:10;16241:2;16234:22;;16274:6;16265:15;;16310:9;16304:16;16296:6;16289:32;16375:2;16364:9;16360:18;16354:25;16349:2;16341:6;16337:15;16330:50;16434:2;16423:9;16419:18;16413:25;16408:2;16400:6;16396:15;16389:50;16484:2;16473:9;16469:18;16463:25;16497:30;16519:7;16497:30;:::i;:::-;16555:2;16543:15;;;;16536:32;15909:665;;-1:-1:-1;;15909:665:14:o;16579:266::-;16682:6;16735:3;16723:9;16714:7;16710:23;16706:33;16703:53;;;16752:1;16749;16742:12;16703:53;16775:64;16831:7;16820:9;16775:64;:::i;17152:1374::-;17279:6;17310:2;17353;17341:9;17332:7;17328:23;17324:32;17321:52;;;17369:1;17366;17359:12;17321:52;17402:9;17396:16;17431:18;17472:2;17464:6;17461:14;17458:34;;;17488:1;17485;17478:12;17458:34;17526:6;17515:9;17511:22;17501:32;;17571:7;17564:4;17560:2;17556:13;17552:27;17542:55;;17593:1;17590;17583:12;17542:55;17622:2;17616:9;17644:2;17640;17637:10;17634:36;;;17650:18;;:::i;:::-;17690:36;17722:2;17717;17714:1;17710:10;17706:19;17690:36;:::i;:::-;17760:15;;;17791:12;;;;-1:-1:-1;17822:4:14;17861:11;;;17853:20;;17849:29;;;17890:19;;;17887:39;;;17922:1;17919;17912:12;17887:39;17946:11;;;;17966:530;17982:6;17977:3;17974:15;17966:530;;;18062:2;18056:3;18047:7;18043:17;18039:26;18036:116;;;18106:1;18135:2;18131;18124:14;18036:116;18178:22;;:::i;:::-;18234:3;18228:10;18251:33;18276:7;18251:33;:::i;:::-;18297:22;;18355:67;18414:7;18400:12;;;18355:67;:::i;:::-;18339:14;;;18332:91;18436:18;;17999:12;;;;18474;;;;17966:530;;;-1:-1:-1;18515:5:14;17152:1374;-1:-1:-1;;;;;;;17152:1374:14:o;18878:390::-;18978:4;19036:11;19023:25;19126:66;19115:8;19099:14;19095:29;19091:102;19071:18;19067:127;19057:155;;19208:1;19205;19198:12;19057:155;19229:33;;;;;18878:390;-1:-1:-1;;18878:390:14:o;20345:580::-;20422:4;20428:6;20488:11;20475:25;20578:66;20567:8;20551:14;20547:29;20543:102;20523:18;20519:127;20509:155;;20660:1;20657;20650:12;20509:155;20687:33;;20739:20;;;-1:-1:-1;20782:18:14;20771:30;;20768:50;;;20814:1;20811;20804:12;20768:50;20847:4;20835:17;;-1:-1:-1;20878:14:14;20874:27;;;20864:38;;20861:58;;;20915:1;20912;20905:12;20930:520;21169:6;21161;21156:3;21143:33;21252:66;21346:2;21342:15;;;21338:24;;21195:16;;;;21327:36;;;21396:15;;21392:24;21387:2;21379:11;;21372:45;21441:2;21433:11;;;-1:-1:-1;20930:520:14:o;21455:274::-;21584:3;21622:6;21616:13;21638:53;21684:6;21679:3;21672:4;21664:6;21660:17;21638:53;:::i;21734:241::-;21790:6;21843:2;21831:9;21822:7;21818:23;21814:32;21811:52;;;21859:1;21856;21849:12;21811:52;21898:9;21885:23;21917:28;21939:5;21917:28;:::i;22383:245::-;22450:6;22503:2;22491:9;22482:7;22478:23;22474:32;22471:52;;;22519:1;22516;22509:12;22471:52;22551:9;22545:16;22570:28;22592:5;22570:28;:::i;23552:228::-;23592:7;23718:1;23650:66;23646:74;23643:1;23640:81;23635:1;23628:9;23621:17;23617:105;23614:131;;;23725:18;;:::i;:::-;-1:-1:-1;23765:9:14;;23552:228::o;23785:274::-;23825:1;23851;23841:189;;23886:77;23883:1;23876:88;23987:4;23984:1;23977:15;24015:4;24012:1;24005:15;23841:189;-1:-1:-1;24044:9:14;;23785:274::o
Swarm Source
ipfs://474fd23fba1cc65167cfcecba4c8d28cd4495fe9e3c00fabb0fdbd1b8858a8b1
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.