Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Latest 25 from a total of 388 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap Money For E... | 208405265 | 629 days ago | IN | 0 ETH | 0.0000096 | ||||
| Swap Money For E... | 208404868 | 629 days ago | IN | 0 ETH | 0.00001005 | ||||
| Swap Money For E... | 208404574 | 629 days ago | IN | 0 ETH | 0.00001014 | ||||
| Swap Exact Money... | 202385805 | 647 days ago | IN | 0 ETH | 0.00000537 | ||||
| Swap Exact Z Tok... | 202385405 | 647 days ago | IN | 0 ETH | 0.00000501 | ||||
| Swap Exact Money... | 199966031 | 654 days ago | IN | 0 ETH | 0.00001002 | ||||
| Swap Exact Money... | 199965349 | 654 days ago | IN | 0 ETH | 0.00000603 | ||||
| Swap Exact Money... | 199165854 | 656 days ago | IN | 0 ETH | 0.00000988 | ||||
| Swap Exact Z Tok... | 196526811 | 664 days ago | IN | 0 ETH | 0.0000154 | ||||
| Swap Exact Money... | 196259611 | 665 days ago | IN | 0 ETH | 0.00001225 | ||||
| Swap Exact Z Tok... | 195585072 | 667 days ago | IN | 0 ETH | 0.00001203 | ||||
| Swap Exact Z Tok... | 195486271 | 667 days ago | IN | 0 ETH | 0.00000763 | ||||
| Swap Exact Z Tok... | 192379895 | 676 days ago | IN | 0 ETH | 0.00001343 | ||||
| Swap Exact Z Tok... | 192379283 | 676 days ago | IN | 0 ETH | 0.0000138 | ||||
| Swap Exact Z Tok... | 192378184 | 676 days ago | IN | 0 ETH | 0.00001484 | ||||
| Swap Exact Z Tok... | 192374086 | 676 days ago | IN | 0 ETH | 0.00000501 | ||||
| Swap Exact Money... | 192290594 | 676 days ago | IN | 0 ETH | 0.0000107 | ||||
| Swap Exact Money... | 192041109 | 677 days ago | IN | 0 ETH | 0.00000642 | ||||
| Swap Exact Z Tok... | 192032838 | 677 days ago | IN | 0 ETH | 0.00000464 | ||||
| Swap Money For E... | 191952405 | 677 days ago | IN | 0 ETH | 0.00001243 | ||||
| Swap Exact Money... | 191950906 | 677 days ago | IN | 0 ETH | 0.00001344 | ||||
| Swap Exact Money... | 188768989 | 687 days ago | IN | 0 ETH | 0.00026684 | ||||
| Swap Exact Z Tok... | 188767031 | 687 days ago | IN | 0 ETH | 0.00024742 | ||||
| Swap Exact Money... | 188401325 | 688 days ago | IN | 0 ETH | 0.00031508 | ||||
| Swap Exact Z Tok... | 188128020 | 689 days ago | IN | 0 ETH | 0.00031068 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TazzHelper
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.17;
import 'hardhat/console.sol';
import {ISwapRouter} from '../dependencies/uniswap-v3-periphery/interfaces/ISwapRouter.sol';
import {IQuoterV2} from '../dependencies/uniswap-v3-periphery/interfaces/IQuoterV2.sol';
import {TransferHelper} from '../dependencies/uniswap-v3-periphery/libraries/TransferHelper.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol';
import {INotionalERC20} from '../interfaces/INotionalERC20.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
import {Errors} from '../protocol/libraries/helpers/Errors.sol';
import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol';
import {IAssetToken} from '../interfaces/IAssetToken.sol';
import {ILiabilityToken} from '../interfaces/ILiabilityToken.sol';
import {IGuild} from '../interfaces/IGuild.sol';
import {IGuildAddressesProvider} from '../interfaces/IGuildAddressesProvider.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {ITazzHelper} from '../interfaces/ITazzHelper.sol';
import {IUniswapQuoterV3} from '../interfaces/IUniswapQuoterV3.sol';
import {X96Math} from '../protocol/libraries/math/X96Math.sol';
import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol';
import {WadRayMath} from '../protocol/libraries/math/WadRayMath.sol';
import {DebtMath} from '../protocol/libraries/math/DebtMath.sol';
import {IUniswapV3PoolState} from '../dependencies/uniswap-v3-core/interfaces/pool/IUniswapV3PoolState.sol';
import {IUniswapV3Pool} from '../dependencies/uniswap-v3-core/interfaces/IUniswapV3Pool.sol';
import {CollateralConfiguration} from '../protocol/libraries/configuration/CollateralConfiguration.sol';
/**
* @title TazzHelper
* @author Tazz Labs
*/
contract TazzHelper is ITazzHelper {
using SafeMath for uint256;
using PercentageMath for uint256;
using WadRayMath for uint256;
using CollateralConfiguration for DataTypes.CollateralConfigurationMap;
uint256 internal constant QUOTE_TIME_BUFFER = 900; //15min buffer for QuoteWithdraw + QuoteBorrow estimtates
ISwapRouter public immutable uniswapRouter;
IUniswapQuoterV3 public immutable uniswapQuoter;
constructor(address _swapRouterAddress, address _quoterAddress) {
uniswapRouter = ISwapRouter(_swapRouterAddress);
uniswapQuoter = IUniswapQuoterV3(_quoterAddress);
}
/// @inheritdoc ITazzHelper
function swapZTokenForExactMoney(
address _guildAddress,
uint256 _moneyOut,
uint256 _zTokenInMax,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalMintedInBaseCurrency_,
uint256 zTokenIn_,
uint256 moneyOut_
)
{
return
_swapZTokenForMoney(
true,
_guildAddress,
_zTokenInMax,
_moneyOut,
msg.sender,
_deadline,
_sqrtPriceLimitX96
);
}
/// @inheritdoc ITazzHelper
function swapExactZTokenForMoney(
address _guildAddress,
uint256 _zTokenIn,
uint256 _moneyOutMin,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalMintedInBaseCurrency_,
uint256 zTokenIn_,
uint256 moneyOut_
)
{
return
_swapZTokenForMoney(
false,
_guildAddress,
_zTokenIn,
_moneyOutMin,
msg.sender,
_deadline,
_sqrtPriceLimitX96
);
}
/// @inheritdoc ITazzHelper
function swapMoneyForExactZToken(
address _guildAddress,
uint256 _ztokenOut,
uint256 _moneyInMax,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalBurneInBaseCurrency_,
uint256 moneyIn_,
uint256 zTokenOut_
)
{
return
_swapMoneyForZToken(
false,
_guildAddress,
_moneyInMax,
_ztokenOut,
msg.sender,
_deadline,
_sqrtPriceLimitX96
);
}
/// @inheritdoc ITazzHelper
function swapExactMoneyForZToken(
address _guildAddress,
uint256 _moneyIn,
uint256 _zTokenOutMin,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalBurnedInBaseCurrency_,
uint256 moneyIn_,
uint256 zTokenOut_
)
{
return
_swapMoneyForZToken(
true,
_guildAddress,
_moneyIn,
_zTokenOutMin,
msg.sender,
_deadline,
_sqrtPriceLimitX96
);
}
/// @inheritdoc ITazzHelper
/// @dev Not to be run on-chain
function quoteSwapZTokenForExactMoney(
address _guildAddress,
uint256 _moneyOutTarget,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalMintedInBaseCurrency_,
uint256 zTokenIn_,
uint256 moneyOut_,
uint256 zTokenPriceBeforeSwap_,
uint256 zTokenPriceAfterSwap_,
uint256 gasEstimate_
)
{
return _quoteSwapZTokenForMoney(true, _guildAddress, 0, _moneyOutTarget, _sqrtPriceLimitX96);
}
/// @inheritdoc ITazzHelper
/// @dev Not to be run on-chain
function quoteSwapExactZTokenForMoney(
address _guildAddress,
uint256 _zTokenInTarget,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalMintedInBaseCurrency_,
uint256 zTokenIn_,
uint256 moneyOut_,
uint256 zTokenPriceBeforeSwap_,
uint256 zTokenPriceAfterSwap_,
uint256 gasEstimate_
)
{
return _quoteSwapZTokenForMoney(false, _guildAddress, _zTokenInTarget, 0, _sqrtPriceLimitX96);
}
/// @inheritdoc ITazzHelper
/// @dev Not to be run on-chain
function quoteSwapMoneyForExactZToken(
address _guildAddress,
uint256 _zTokenOutTarget,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalBurnedInBaseCurrency_,
uint256 moneyIn_,
uint256 zTokenOut_,
uint256 zTokenPriceBeforeSwap_,
uint256 zTokenPriceAfterSwap_,
uint256 gasEstimate_
)
{
return _quoteSwapMoneyForZToken(false, _guildAddress, 0, _zTokenOutTarget, _sqrtPriceLimitX96);
}
/// @inheritdoc ITazzHelper
/// @dev Not to be run on-chain
function quoteSwapExactMoneyForZToken(
address _guildAddress,
uint256 _moneyInTarget,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalBurnedInBaseCurrency_,
uint256 moneyIn_,
uint256 zTokenOut_,
uint256 zTokenPriceBeforeSwap_,
uint256 zTokenPriceAfterSwap_,
uint256 gasEstimate_
)
{
return _quoteSwapMoneyForZToken(true, _guildAddress, _moneyInTarget, 0, _sqrtPriceLimitX96);
}
/// @inheritdoc ITazzHelper
/// @dev Not to be run on-chain
function quoteUserAccountData(address _guildAddress, address user)
external
returns (IGuild.userAccountDataStruc memory userAccountData)
{
IGuild _guild = IGuild(_guildAddress);
//Update states (including APY, notionals)
_guild.refinance();
//return user data
return _guild.getUserAccountData(user);
}
/// @inheritdoc ITazzHelper
function quoteDexLiquidty(address guild) external view returns (uint256 moneyAmount, uint256 zTokenAmount) {
return _quoteDexLiquidty(guild);
}
/// @inheritdoc ITazzHelper
function quoteDeposit(
address guild,
address asset,
uint256 amount
) external view returns (uint256 maxDepositAmount_) {
maxDepositAmount_ = IERC20(asset).balanceOf(msg.sender);
IGuild(guild).validateDeposit(asset, amount, msg.sender);
}
/// @inheritdoc ITazzHelper
function quoteWithdraw(
address guild,
address asset,
uint256 amount
) external returns (uint256 currentCollateralInVault) {
//Run guild validations (except HF validation)
IGuild(guild).validateWithdraw(asset, amount, msg.sender);
//validate this amount can be withdrawn (from a health factor perspective)
uint256 maxCollateralWithdraw = _quoteMaxWithdaw(guild, asset, msg.sender);
require(amount <= maxCollateralWithdraw, Errors.HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD);
currentCollateralInVault = IGuild(guild).getCollateralBalanceOf(msg.sender, asset);
}
struct quoteMaxSwapZTokenForMoneyLocalVars {
address zToken;
address money;
uint24 dexFee;
uint256 walletZTokens;
uint256 availableZTokenBorrows;
}
/// @inheritdoc ITazzHelper
function quoteMaxSwapZTokenForMoney(
address guild,
address user,
uint160 sqrtPriceLimitX96
)
external
returns (
uint256 maxFullZTokenIn,
uint256 maxFullMoneyOut,
uint256 maxLimitZTokenIn,
uint256 maxLimitMoneyOut
)
{
IGuild _guild = IGuild(guild);
quoteMaxSwapZTokenForMoneyLocalVars memory vars;
// Get perpetual debt data
DataTypes.PerpetualDebtData memory _perpetualDebt = _guild.getPerpetualDebt();
vars.zToken = address(_perpetualDebt.zToken);
vars.money = address(_perpetualDebt.money);
vars.dexFee = _perpetualDebt.dexOracle.dex.fee;
_guild.refinance();
//Initialize return defaults
maxFullZTokenIn = 0;
maxFullMoneyOut = 0;
maxLimitZTokenIn = 0;
maxLimitMoneyOut = 0;
//get Max that can be borrowed
IGuild.userAccountDataStruc memory userAccountData = _guild.getUserAccountData(user);
//apply a time buffer (to ensure quote is valid for QUOTE_TIME_BUFFER seconds)
vars.availableZTokenBorrows = userAccountData.availableBorrowsInZTokens.rayDiv(_quoteBufferFactor(guild));
//get users zToken wallet amount
vars.walletZTokens = _guild.getAsset().balanceOf(user);
maxLimitZTokenIn = vars.walletZTokens;
maxFullZTokenIn = vars.walletZTokens + vars.availableZTokenBorrows;
//Calculate Full quote
if (maxFullZTokenIn > 0) {
(maxFullZTokenIn, maxFullMoneyOut, , ) = uniswapQuoter.quoteExactInputSingle(
IUniswapQuoterV3.QuoteExactInputSingleParams({
tokenIn: vars.zToken,
tokenOut: vars.money,
amountIn: maxFullZTokenIn,
fee: vars.dexFee,
sqrtPriceLimitX96: sqrtPriceLimitX96
})
);
}
//Calculate Limit quote
if (maxLimitZTokenIn > 0) {
(maxLimitZTokenIn, maxLimitMoneyOut, , ) = uniswapQuoter.quoteExactInputSingle(
IUniswapQuoterV3.QuoteExactInputSingleParams({
tokenIn: vars.zToken,
tokenOut: vars.money,
amountIn: maxLimitZTokenIn,
fee: vars.dexFee,
sqrtPriceLimitX96: sqrtPriceLimitX96
})
);
}
return (maxFullZTokenIn, maxFullMoneyOut, maxLimitZTokenIn, maxLimitMoneyOut);
}
struct quoteMaxSwapMoneyForZTokenLocalVars {
address zToken;
address dToken;
address money;
uint24 dexFee;
}
/// @inheritdoc ITazzHelper
function quoteMaxSwapMoneyForZToken(
address guild,
address user,
uint160 sqrtPriceLimitX96
)
external
returns (
uint256 maxFullMoneyIn,
uint256 maxFullZTokenOut,
uint256 maxLimitMoneyIn,
uint256 maxLimitZTokenOut
)
{
IGuild _guild = IGuild(guild);
quoteMaxSwapMoneyForZTokenLocalVars memory vars;
// Get perpetual debt data
DataTypes.PerpetualDebtData memory _perpetualDebt = _guild.getPerpetualDebt();
vars.zToken = address(_perpetualDebt.zToken);
vars.dToken = address(_perpetualDebt.dToken);
vars.money = address(_perpetualDebt.money);
vars.dexFee = _perpetualDebt.dexOracle.dex.fee;
//Initialize return defaults
maxFullMoneyIn = 0;
maxFullZTokenOut = 0;
maxLimitMoneyIn = 0;
maxLimitZTokenOut = 0;
//get user money in wallet
maxFullMoneyIn = _guild.getMoney().balanceOf(user);
if (maxFullMoneyIn > 0) {
(maxFullMoneyIn, maxFullZTokenOut, , ) = uniswapQuoter.quoteExactInputSingle(
IUniswapQuoterV3.QuoteExactInputSingleParams({
tokenIn: vars.money,
tokenOut: vars.zToken,
amountIn: maxFullMoneyIn,
fee: vars.dexFee,
sqrtPriceLimitX96: sqrtPriceLimitX96
})
);
}
//Update states (including APY, notionals)
_guild.refinance();
//get zTokens needed to cancel debt
IGuild.userAccountDataStruc memory userAccountData = _guild.getUserAccountData(user);
if (maxFullZTokenOut <= userAccountData.zTokensToRepayDebt) {
//not enough money in wallet to fully cancel debt (or limited by pricelimit), so Limit amount = Full amount
maxLimitMoneyIn = maxFullMoneyIn;
maxLimitZTokenOut = maxFullZTokenOut;
} else {
//calculate money needed to fully cancel debt
if (userAccountData.zTokensToRepayDebt > 0) {
(maxLimitMoneyIn, maxLimitZTokenOut, , ) = uniswapQuoter.quoteExactOutputSingle(
IUniswapQuoterV3.QuoteExactOutputSingleParams({
tokenIn: vars.money,
tokenOut: vars.zToken,
amount: userAccountData.zTokensToRepayDebt,
fee: vars.dexFee,
sqrtPriceLimitX96: sqrtPriceLimitX96
})
);
}
}
return (maxFullMoneyIn, maxFullZTokenOut, maxLimitMoneyIn, maxLimitZTokenOut);
}
/// @inheritdoc ITazzHelper
function quoteMaxDeposit(
address guild,
address asset,
address user
) external view returns (uint256 maxCollateralDeposit) {
maxCollateralDeposit = IERC20(asset).balanceOf(user);
//Check collateral caps, and impose if necessary
DataTypes.CollateralConfigurationMap memory collateralConfig = IGuild(guild).getCollateralConfiguration(asset);
(uint256 maxCollateralAmount, uint256 maxUserCollateralAmount) = collateralConfig.getCaps();
uint256 collateralUnits = 10**collateralConfig.getDecimals();
if (maxCollateralAmount > 0) {
//@dev supplyCap encoded with 0 decimal places (e.g, 1 -> 1 token in collateral's own unit)
maxCollateralAmount = maxCollateralAmount * collateralUnits;
uint256 guildCollateralBalance = IGuild(guild).getCollateralTotalBalance(asset);
uint256 maxCollateralAllowed = (maxCollateralAmount > guildCollateralBalance)
? maxCollateralAmount - guildCollateralBalance
: 0;
if (maxCollateralDeposit > maxCollateralAllowed) maxCollateralDeposit = maxCollateralAllowed;
}
if (maxUserCollateralAmount > 0) {
//@dev userSupplyCap encoded with 2 decimal places (e.g, 100 -> 1 token in collateral's own unit)
maxUserCollateralAmount = (maxUserCollateralAmount * collateralUnits) / 100;
uint256 userCollateralBalance = IGuild(guild).getCollateralBalanceOf(user, asset);
uint256 maxUserCollateralAllowed = (maxUserCollateralAmount > userCollateralBalance)
? maxUserCollateralAmount - userCollateralBalance
: 0;
if (maxCollateralDeposit > maxUserCollateralAllowed) maxCollateralDeposit = maxUserCollateralAllowed;
}
return maxCollateralDeposit;
}
/// @inheritdoc ITazzHelper
function quoteMaxWithdaw(
address guild,
address asset,
address user
) external returns (uint256 maxCollateralWithdraw) {
return _quoteMaxWithdaw(guild, asset, user);
}
/// @inheritdoc ITazzHelper
function quoteCurrentSqrtPriceX96(address _guildAddress) external view returns (uint160 sqrtPriceX96_) {
IGuild _guild = IGuild(_guildAddress);
DataTypes.PerpetualDebtData memory _perpetualDebt = _guild.getPerpetualDebt();
(sqrtPriceX96_, , , , , , ) = IUniswapV3PoolState(_perpetualDebt.dexOracle.dex.poolAddress).slot0();
}
///////////////////////////////////////////////////////////////////////////////////////////////
struct swapMoneyForZTokenLocalVars {
address zToken;
address dToken;
address money;
uint24 fee;
uint256 amountOutMinimum;
uint256 zTokensUsedToRepayDebt;
uint256 debtNotionalToBurn;
uint256 debtNotionalToBurnInBaseCurrency;
uint256 zTokenToTransfer;
uint256 finalMoneyIn;
uint256 finalZTokenOut;
}
function _swapMoneyForZToken(
bool _exactMoney,
address _guildAddress,
uint256 _moneyInTarget,
uint256 _zTokenOutTarget,
address _onBehalfOf,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
internal
returns (
uint256 debtNotionalBurnedInBaseCurrency_,
uint256 moneyIn_,
uint256 zTokenOut_
)
{
// Fetch perpetual debt objects from guild
IGuild _guild = IGuild(_guildAddress);
swapMoneyForZTokenLocalVars memory vars;
// Get perpetual debt data
DataTypes.PerpetualDebtData memory _perpetualDebt = _guild.getPerpetualDebt();
vars.zToken = address(_perpetualDebt.zToken);
vars.dToken = address(_perpetualDebt.dToken);
vars.money = address(_perpetualDebt.money);
vars.fee = _perpetualDebt.dexOracle.dex.fee;
// Refinance debt to update nFactor
_guild.refinance();
// Transfer user money into Helper
TransferHelper.safeTransferFrom(vars.money, _onBehalfOf, address(this), _moneyInTarget);
// Allow Uniswap pool to transfer money
TransferHelper.safeApprove(vars.money, address(uniswapRouter), _moneyInTarget);
if (_exactMoney) {
//EXACT money in
vars.finalMoneyIn = _moneyInTarget;
//swap as per request
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: vars.money,
tokenOut: vars.zToken,
fee: vars.fee,
recipient: address(this),
deadline: _deadline,
amountIn: vars.finalMoneyIn,
amountOutMinimum: _zTokenOutTarget,
sqrtPriceLimitX96: _sqrtPriceLimitX96
});
//swap
vars.finalZTokenOut = uniswapRouter.exactInputSingle(params);
} else {
//EXACT ZTokens out
vars.finalZTokenOut = _zTokenOutTarget;
// Swap money for zTokens
ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({
tokenIn: vars.money,
tokenOut: vars.zToken,
fee: vars.fee,
recipient: address(this),
deadline: _deadline,
amountOut: vars.finalZTokenOut,
amountInMaximum: _moneyInTarget,
sqrtPriceLimitX96: _sqrtPriceLimitX96
});
// The call to `exactOutputSingle` executes the swap.
vars.finalMoneyIn = uniswapRouter.exactOutputSingle(params);
//transfer any money dust back to user (clear this contract)
if (_moneyInTarget > vars.finalMoneyIn) {
TransferHelper.safeTransfer(vars.money, _onBehalfOf, _moneyInTarget - vars.finalMoneyIn);
}
}
// Calculate current user debt being repayed (in zToken terms)
IGuild.userAccountDataStruc memory userAccountData = _guild.getUserAccountData(_onBehalfOf);
//repay debt, if any
if (userAccountData.zTokensToRepayDebt > 0) {
vars.zTokensUsedToRepayDebt = (userAccountData.zTokensToRepayDebt < vars.finalZTokenOut)
? userAccountData.zTokensToRepayDebt
: vars.finalZTokenOut;
vars.debtNotionalToBurn = IAssetToken(vars.zToken).baseToNotional(vars.zTokensUsedToRepayDebt);
_guild.repay(vars.zTokensUsedToRepayDebt, _onBehalfOf);
}
//transfer remaining zToken to user (clear this contract)
//This should be equivalent to any remaining zToken in TazzHelper contract.
vars.zTokenToTransfer = vars.finalZTokenOut - vars.zTokensUsedToRepayDebt;
if (vars.zTokenToTransfer > 0) TransferHelper.safeTransfer(vars.zToken, _onBehalfOf, vars.zTokenToTransfer);
// convert Notional to currency units
uint256 moneyDecimals = IERC20Detailed(vars.money).decimals();
uint256 debtDecimals = IERC20Detailed(vars.dToken).decimals();
vars.debtNotionalToBurnInBaseCurrency = (debtDecimals > moneyDecimals)
? vars.debtNotionalToBurn.div(10**(debtDecimals - moneyDecimals))
: vars.debtNotionalToBurn.mul(10**(moneyDecimals - debtDecimals));
// Emit event
emit SwapAndBurn(_onBehalfOf, vars.debtNotionalToBurnInBaseCurrency, vars.finalMoneyIn, vars.finalZTokenOut);
return (vars.debtNotionalToBurnInBaseCurrency, vars.finalMoneyIn, vars.finalZTokenOut);
}
struct swapZTokenForMoneyLocalVars {
address zToken;
address dToken;
address money;
uint24 fee;
uint256 walletZTokenAmount;
uint256 finalZTokenIn;
uint256 finalMoneyOut;
uint256 zTokensToBorrow;
uint256 zTokensToRepay;
}
function _swapZTokenForMoney(
bool _exactMoney,
address _guildAddress,
uint256 _zTokenInTarget,
uint256 _moneyOutTarget,
address _onBehalfOf,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
internal
returns (
uint256 debtNotionalMintedInBaseCurrency_,
uint256 zTokenIn_,
uint256 moneyOut_
)
{
// Fetch perpetual debt objects from guild
IGuild _guild = IGuild(_guildAddress);
swapZTokenForMoneyLocalVars memory vars;
// Get perpetual debt data
DataTypes.PerpetualDebtData memory _perpetualDebt = _guild.getPerpetualDebt();
vars.zToken = address(_perpetualDebt.zToken);
vars.dToken = address(_perpetualDebt.dToken);
vars.money = address(_perpetualDebt.money);
vars.fee = _perpetualDebt.dexOracle.dex.fee;
// Refinance debt to update nFactor
_guild.refinance();
// Check how many zTokens user has
vars.walletZTokenAmount = IAssetToken(vars.zToken).balanceOf(_onBehalfOf);
//If user needs more zTokens for swap, try and borrow the missing amount
if (_zTokenInTarget > vars.walletZTokenAmount) {
unchecked {
vars.zTokensToBorrow = _zTokenInTarget - vars.walletZTokenAmount;
}
// Mint debt (fails if user does not have enough collateral)
_guild.borrow(vars.zTokensToBorrow, _onBehalfOf);
// Transfer wallet amount into TazzHelper
if (vars.walletZTokenAmount > 0) {
TransferHelper.safeTransferFrom(vars.zToken, _onBehalfOf, address(this), vars.walletZTokenAmount);
}
} else {
// Transfer user asset into Tazz Helper
TransferHelper.safeTransferFrom(vars.zToken, _onBehalfOf, address(this), _zTokenInTarget);
}
// Allow Uniswap pool to transfer zTokens
TransferHelper.safeApprove(vars.zToken, address(uniswapRouter), _zTokenInTarget);
if (_exactMoney) {
// EXACT money out
vars.finalMoneyOut = _moneyOutTarget;
// Swap zTokens for money
ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({
tokenIn: vars.zToken,
tokenOut: vars.money,
fee: vars.fee,
recipient: _onBehalfOf,
deadline: _deadline,
amountOut: vars.finalMoneyOut,
amountInMaximum: _zTokenInTarget,
sqrtPriceLimitX96: _sqrtPriceLimitX96
});
// The call to `exactOutputSingle` executes the swap.
vars.finalZTokenIn = uniswapRouter.exactOutputSingle(params);
// Remove Uniswap pool's zToken transfer allowance
if (vars.finalZTokenIn < _zTokenInTarget) {
TransferHelper.safeApprove(vars.zToken, address(uniswapRouter), 0);
}
// If zTokens were borrowed, but not all were used, then burn excess debt
if ((vars.zTokensToBorrow > 0) && (vars.finalZTokenIn < _zTokenInTarget)) {
//@dev zTokens currently held in TazzHelper
unchecked {vars.zTokensToRepay = _zTokenInTarget - vars.finalZTokenIn;} //prettier-ignore
if (vars.zTokensToRepay > vars.zTokensToBorrow) {
vars.zTokensToRepay = vars.zTokensToBorrow; //don't try and repay more than was borrowed
}
unchecked {vars.zTokensToBorrow -= vars.zTokensToRepay;} //prettier-ignore
_guild.repay(vars.zTokensToRepay, _onBehalfOf);
}
} else {
//EXACT zTokens in
vars.finalZTokenIn = _zTokenInTarget;
//swap as per request
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: vars.zToken,
tokenOut: vars.money,
fee: vars.fee,
recipient: _onBehalfOf,
deadline: _deadline,
amountIn: vars.finalZTokenIn,
amountOutMinimum: _moneyOutTarget,
sqrtPriceLimitX96: _sqrtPriceLimitX96
});
//swap
vars.finalMoneyOut = uniswapRouter.exactInputSingle(params);
}
// calculate Notional minted in base currency units
uint256 moneyDecimals = IERC20Detailed(vars.money).decimals();
uint256 debtDecimals = IERC20Detailed(vars.dToken).decimals();
debtNotionalMintedInBaseCurrency_ = INotionalERC20(vars.zToken).baseToNotional(vars.zTokensToBorrow);
debtNotionalMintedInBaseCurrency_ = (debtDecimals > moneyDecimals)
? debtNotionalMintedInBaseCurrency_.div(10**(debtDecimals - moneyDecimals))
: debtNotionalMintedInBaseCurrency_.mul(10**(moneyDecimals - debtDecimals));
zTokenIn_ = vars.finalZTokenIn;
moneyOut_ = vars.finalMoneyOut;
// Emit event
emit MintAndSwap(_onBehalfOf, debtNotionalMintedInBaseCurrency_, zTokenIn_, moneyOut_);
return (debtNotionalMintedInBaseCurrency_, zTokenIn_, moneyOut_);
}
struct quoteSwapZTokenForMoneyLocalVars {
address zToken;
address dToken;
address money;
address dexPool;
uint24 fee;
uint256 currentWalletZToken;
uint256 zTokensMinted;
uint256 amountZTokenMinted;
uint256 amountNotionalMinted;
uint256 amountNotionalValidation;
uint160 sqrtPriceX96before;
uint160 sqrtPriceX96After;
}
function _quoteSwapZTokenForMoney(
bool _exactMoney,
address _guildAddress,
uint256 _zTokenInTarget,
uint256 _moneyOutTarget,
uint160 _sqrtPriceLimitX96
)
internal
returns (
uint256 debtNotionalMintedInBaseCurrency_,
uint256 zTokenIn_,
uint256 moneyOut_,
uint256 zTokenPriceBeforeSwap_,
uint256 zTokenPriceAfterSwap_,
uint256 gasEstimate_
)
{
// Fetch perpetual debt objects from guild
IGuild _guild = IGuild(_guildAddress);
quoteSwapZTokenForMoneyLocalVars memory vars;
// Get perpetual debt data
DataTypes.PerpetualDebtData memory _perpetualDebt = _guild.getPerpetualDebt();
vars.zToken = address(_perpetualDebt.zToken);
vars.dToken = address(_perpetualDebt.dToken);
vars.money = address(_perpetualDebt.money);
vars.fee = _perpetualDebt.dexOracle.dex.fee;
vars.dexPool = _perpetualDebt.dexOracle.dex.poolAddress;
_guild.refinance();
(vars.sqrtPriceX96before, , , , , , ) = IUniswapV3PoolState(vars.dexPool).slot0();
zTokenPriceBeforeSwap_ = X96Math.getPriceFromSqrtX96(vars.money, vars.zToken, vars.sqrtPriceX96before);
//get uniswap quote (how many zTokens needed)
if (_exactMoney) {
(zTokenIn_, moneyOut_, vars.sqrtPriceX96After, gasEstimate_) = uniswapQuoter.quoteExactOutputSingle(
IUniswapQuoterV3.QuoteExactOutputSingleParams({
tokenIn: vars.zToken,
tokenOut: vars.money,
amount: _moneyOutTarget,
fee: vars.fee,
sqrtPriceLimitX96: _sqrtPriceLimitX96
})
);
} else {
(zTokenIn_, moneyOut_, vars.sqrtPriceX96After, gasEstimate_) = uniswapQuoter.quoteExactInputSingle(
IUniswapQuoterV3.QuoteExactInputSingleParams({
tokenIn: vars.zToken,
tokenOut: vars.money,
amountIn: _zTokenInTarget,
fee: vars.fee,
sqrtPriceLimitX96: _sqrtPriceLimitX96
})
);
}
zTokenPriceAfterSwap_ = X96Math.getPriceFromSqrtX96(vars.money, vars.zToken, vars.sqrtPriceX96After);
//calculate how much debt would need to be minted for this swap
vars.currentWalletZToken = _guild.getAsset().balanceOf(msg.sender);
vars.amountZTokenMinted = (zTokenIn_ > vars.currentWalletZToken) ? zTokenIn_ - vars.currentWalletZToken : 0;
// validate user can mint this amount of debt
if (vars.amountZTokenMinted > 0) {
//apply a time buffer (to ensure quote is valid for QUOTE_TIME_BUFFER seconds)
vars.amountZTokenMinted = vars.amountZTokenMinted.rayMul(_quoteBufferFactor(_guildAddress));
vars.amountNotionalMinted = _guild.getAsset().baseToNotional(vars.amountZTokenMinted);
_guild.validateBorrow(vars.amountZTokenMinted, msg.sender);
}
// convert to base currency units
uint256 moneyDecimals = IERC20Detailed(vars.money).decimals();
uint256 debtDecimals = IERC20Detailed(vars.dToken).decimals();
debtNotionalMintedInBaseCurrency_ = (debtDecimals > moneyDecimals)
? vars.amountNotionalMinted.div(10**(debtDecimals - moneyDecimals))
: vars.amountNotionalMinted.mul(10**(moneyDecimals - debtDecimals));
//Add cte gas estimate from non-Uniswap contract portion
gasEstimate_ += 415000;
return (
debtNotionalMintedInBaseCurrency_,
zTokenIn_,
moneyOut_,
zTokenPriceBeforeSwap_,
zTokenPriceAfterSwap_,
gasEstimate_
);
}
struct quoteSwapMoneyForZTokensLocalVars {
address zToken;
address dToken;
address money;
address dexPool;
uint24 fee;
uint160 sqrtPriceX96before;
uint160 sqrtPriceX96After;
uint256 debtNotionalBurned;
uint256 zTokenToBurn;
}
function _quoteSwapMoneyForZToken(
bool _exactMoney,
address _guildAddress,
uint256 _moneyInTarget,
uint256 _zTokenOutTarget,
uint160 _sqrtPriceLimitX96
)
internal
returns (
uint256 debtNotionalBurnedInBaseCurrency_,
uint256 moneyIn_,
uint256 zTokenOut_,
uint256 zTokenPriceBeforeSwap_,
uint256 zTokenPriceAfterSwap_,
uint256 gasEstimate_
)
{
// Fetch perpetual debt objects from guild
IGuild _guild = IGuild(_guildAddress);
quoteSwapMoneyForZTokensLocalVars memory vars;
// Get perpetual debt data
DataTypes.PerpetualDebtData memory _perpetualDebt = _guild.getPerpetualDebt();
vars.zToken = address(_perpetualDebt.zToken);
vars.dToken = address(_perpetualDebt.dToken);
vars.money = address(_perpetualDebt.money);
vars.fee = _perpetualDebt.dexOracle.dex.fee;
vars.dexPool = _perpetualDebt.dexOracle.dex.poolAddress;
_guild.refinance();
(vars.sqrtPriceX96before, , , , , , ) = IUniswapV3PoolState(vars.dexPool).slot0();
zTokenPriceBeforeSwap_ = X96Math.getPriceFromSqrtX96(vars.money, vars.zToken, vars.sqrtPriceX96before);
//get uniswap quote (how much money needed)
if (_exactMoney) {
(moneyIn_, zTokenOut_, vars.sqrtPriceX96After, gasEstimate_) = uniswapQuoter.quoteExactInputSingle(
IUniswapQuoterV3.QuoteExactInputSingleParams({
tokenIn: vars.money,
tokenOut: vars.zToken,
amountIn: _moneyInTarget,
fee: vars.fee,
sqrtPriceLimitX96: _sqrtPriceLimitX96
})
);
} else {
(moneyIn_, zTokenOut_, vars.sqrtPriceX96After, gasEstimate_) = uniswapQuoter.quoteExactOutputSingle(
IUniswapQuoterV3.QuoteExactOutputSingleParams({
tokenIn: vars.money,
tokenOut: vars.zToken,
amount: _zTokenOutTarget,
fee: vars.fee,
sqrtPriceLimitX96: _sqrtPriceLimitX96
})
);
}
zTokenPriceAfterSwap_ = X96Math.getPriceFromSqrtX96(vars.money, vars.zToken, vars.sqrtPriceX96After);
//calculate how much debt can be burned after this swap
IGuild.userAccountDataStruc memory userAccountData = _guild.getUserAccountData(msg.sender);
vars.zTokenToBurn = (zTokenOut_ > userAccountData.zTokensToRepayDebt)
? userAccountData.zTokensToRepayDebt
: zTokenOut_;
vars.debtNotionalBurned = _guild.getAsset().baseToNotional(vars.zTokenToBurn);
//Validate repay
if (vars.debtNotionalBurned > 0) _guild.validateRepay(vars.zTokenToBurn, msg.sender);
// convert to base currency units
uint256 moneyDecimals = IERC20Detailed(vars.money).decimals();
uint256 debtDecimals = IERC20Detailed(vars.dToken).decimals();
debtNotionalBurnedInBaseCurrency_ = (debtDecimals > moneyDecimals)
? vars.debtNotionalBurned.div(10**(debtDecimals - moneyDecimals))
: vars.debtNotionalBurned.mul(10**(moneyDecimals - debtDecimals));
//Add cte gas estimate from non-Uniswap contract portion
gasEstimate_ += 200000;
return (
debtNotionalBurnedInBaseCurrency_,
moneyIn_,
zTokenOut_,
zTokenPriceBeforeSwap_,
zTokenPriceAfterSwap_,
gasEstimate_
);
}
function _quoteDexLiquidty(address guild) internal view returns (uint256 moneyAmount, uint256 zTokenAmount) {
//get guild DEX address
DataTypes.PerpetualDebtData memory _perpetualDebt = IGuild(guild).getPerpetualDebt();
address dexPoolAddress = _perpetualDebt.dexOracle.dex.poolAddress;
bool moneyIsToken0 = _perpetualDebt.dexOracle.dex.moneyIsToken0;
//get money
IERC20 moneyToken = IGuild(guild).getMoney();
//get zToken
IAssetToken zToken = IGuild(guild).getAsset();
// get money amount in external Dex Pool
moneyAmount = moneyToken.balanceOf(dexPoolAddress);
// get zToken amount in external Dex Pool
zTokenAmount = zToken.balanceOf(dexPoolAddress);
// Correct for LP fees
(uint128 token0amount, uint128 token1amount) = IUniswapV3PoolState(dexPoolAddress).protocolFees();
moneyAmount -= moneyIsToken0 ? uint256(token0amount) : uint256(token1amount);
zTokenAmount -= moneyIsToken0 ? uint256(token1amount) : uint256(token0amount);
return (moneyAmount, zTokenAmount);
}
function _quoteMaxWithdaw(
address guild,
address asset,
address user
) internal returns (uint256 maxCollateralWithdraw) {
IGuild _guild = IGuild(guild);
_guild.refinance();
//get user info
IGuild.userAccountDataStruc memory userAccountData = _guild.getUserAccountData(user);
//calculate how much collateral value user can withdraw
//apply a time buffer (to ensure quote is valid for QUOTE_TIME_BUFFER seconds)
uint256 totalCollateralNeededInBaseCurrency = (userAccountData.ltv > 0)
? userAccountData.totalDebtNotionalInBaseCurrency.percentDiv(userAccountData.ltv).rayMul(
_quoteBufferFactor(guild)
)
: 0; //needed for underwritting purposes....
uint256 availableCollateralWithdrawalsInBaseCurrency = (userAccountData.totalCollateralInBaseCurrency >
totalCollateralNeededInBaseCurrency)
? userAccountData.totalCollateralInBaseCurrency - totalCollateralNeededInBaseCurrency
: 0;
//get collateral price in money units
uint256 assetPrice = IPriceOracleGetter(IGuildAddressesProvider(_guild.ADDRESSES_PROVIDER()).getPriceOracle())
.getAssetPrice(asset);
//convert available collatearl withdrawal to its own decimal unit
uint256 collateralUnits = 10**IERC20Detailed(asset).decimals();
uint256 availableCollateralWithdrawals = availableCollateralWithdrawalsInBaseCurrency.mul(collateralUnits).div(
assetPrice
);
//get how much collateral user has in guild
maxCollateralWithdraw = _guild.getCollateralBalanceOf(user, asset);
//return lower of both
if (maxCollateralWithdraw > availableCollateralWithdrawals)
maxCollateralWithdraw = availableCollateralWithdrawals;
return maxCollateralWithdraw;
}
function _quoteBufferFactor(address guild) internal view returns (uint256 bufferFactor) {
IGuild _guild = IGuild(guild);
uint256 notionalPrice = IGuild(guild).getDebtNotionalPrice(_guild.ADDRESSES_PROVIDER().getPriceOracle());
uint256 perpDebtBeta = IGuild(guild).getPerpetualDebt().beta;
//Get estimated rate per second (in RAY)
int256 logRate = DebtMath.calculateApproxRate(perpDebtBeta, notionalPrice);
//Get estimated factor
bufferFactor = DebtMath.calculateApproxNotionalUpdate(logRate, QUOTE_TIME_BUFFER);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.17;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.17;
import {IERC20} from './IERC20.sol';
interface IERC20Detailed is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.17;
/// @title Optimized overflow and underflow safe math operations
/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost
library SafeMath {
/// @notice Returns x + y, reverts if sum overflows uint256
/// @param x The augend
/// @param y The addend
/// @return z The sum of x and y
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
require((z = x + y) >= x);
}
}
/// @notice Returns x - y, reverts if underflows
/// @param x The minuend
/// @param y The subtrahend
/// @return z The difference of x and y
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
require((z = x - y) <= x);
}
}
/// @notice Returns x - y, reverts if underflows
/// @param x The minuend
/// @param y The subtrahend
/// @param message The error msg
/// @return z The difference of x and y
function sub(
uint256 x,
uint256 y,
string memory message
) internal pure returns (uint256 z) {
unchecked {
require((z = x - y) <= x, message);
}
}
/// @notice Returns x * y, reverts if overflows
/// @param x The multiplicand
/// @param y The multiplier
/// @return z The product of x and y
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
require(x == 0 || (z = x * y) / x == y);
}
}
/// @notice Returns x / y, reverts if overflows - no specific check, solidity reverts on division by 0
/// @param x The numerator
/// @param y The denominator
/// @return z The product of x and y
function div(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x / y;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
import {IUniswapV3PoolImmutables} from './pool/IUniswapV3PoolImmutables.sol';
import {IUniswapV3PoolState} from './pool/IUniswapV3PoolState.sol';
import {IUniswapV3PoolDerivedState} from './pool/IUniswapV3PoolDerivedState.sol';
import {IUniswapV3PoolActions} from './pool/IUniswapV3PoolActions.sol';
import {IUniswapV3PoolOwnerActions} from './pool/IUniswapV3PoolOwnerActions.sol';
import {IUniswapV3PoolErrors} from './pool/IUniswapV3PoolErrors.sol';
import {IUniswapV3PoolEvents} from './pool/IUniswapV3PoolEvents.sol';
/// @title The interface for a Uniswap V3 Pool
/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform
/// to the ERC20 specification
/// @dev The pool interface is broken up into many smaller pieces
interface IUniswapV3Pool is
IUniswapV3PoolImmutables,
IUniswapV3PoolState,
IUniswapV3PoolDerivedState,
IUniswapV3PoolActions,
IUniswapV3PoolOwnerActions,
IUniswapV3PoolErrors,
IUniswapV3PoolEvents
{
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Permissionless pool actions
/// @notice Contains pool methods that can be called by anyone
interface IUniswapV3PoolActions {
/// @notice Sets the initial price for the pool
/// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value
/// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96
function initialize(uint160 sqrtPriceX96) external;
/// @notice Adds liquidity for the given recipient/tickLower/tickUpper position
/// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback
/// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends
/// on tickLower, tickUpper, the amount of liquidity, and the current price.
/// @param recipient The address for which the liquidity will be created
/// @param tickLower The lower tick of the position in which to add liquidity
/// @param tickUpper The upper tick of the position in which to add liquidity
/// @param amount The amount of liquidity to mint
/// @param data Any data that should be passed through to the callback
/// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback
/// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback
function mint(
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount,
bytes calldata data
) external returns (uint256 amount0, uint256 amount1);
/// @notice Collects tokens owed to a position
/// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.
/// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or
/// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the
/// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.
/// @param recipient The address which should receive the fees collected
/// @param tickLower The lower tick of the position for which to collect fees
/// @param tickUpper The upper tick of the position for which to collect fees
/// @param amount0Requested How much token0 should be withdrawn from the fees owed
/// @param amount1Requested How much token1 should be withdrawn from the fees owed
/// @return amount0 The amount of fees collected in token0
/// @return amount1 The amount of fees collected in token1
function collect(
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount0Requested,
uint128 amount1Requested
) external returns (uint128 amount0, uint128 amount1);
/// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position
/// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0
/// @dev Fees must be collected separately via a call to #collect
/// @param tickLower The lower tick of the position for which to burn liquidity
/// @param tickUpper The upper tick of the position for which to burn liquidity
/// @param amount How much liquidity to burn
/// @return amount0 The amount of token0 sent to the recipient
/// @return amount1 The amount of token1 sent to the recipient
function burn(
int24 tickLower,
int24 tickUpper,
uint128 amount
) external returns (uint256 amount0, uint256 amount1);
/// @notice Swap token0 for token1, or token1 for token0
/// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback
/// @param recipient The address to receive the output of the swap
/// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0
/// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
/// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this
/// value after the swap. If one for zero, the price cannot be greater than this value after the swap
/// @param data Any data to be passed through to the callback
/// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive
/// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive
function swap(
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes calldata data
) external returns (int256 amount0, int256 amount1);
/// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback
/// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback
/// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling
/// with 0 amount{0,1} and sending the donation amount(s) from the callback
/// @param recipient The address which will receive the token0 and token1 amounts
/// @param amount0 The amount of token0 to send
/// @param amount1 The amount of token1 to send
/// @param data Any data to be passed through to the callback
function flash(
address recipient,
uint256 amount0,
uint256 amount1,
bytes calldata data
) external;
/// @notice Increase the maximum number of price and liquidity observations that this pool will store
/// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to
/// the input observationCardinalityNext.
/// @param observationCardinalityNext The desired minimum number of observations for the pool to store
function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Pool state that is not stored
/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the
/// blockchain. The functions here may have variable gas costs.
interface IUniswapV3PoolDerivedState {
/// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp
/// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing
/// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,
/// you must call it with secondsAgos = [3600, 0].
/// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in
/// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.
/// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned
/// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp
/// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block
/// timestamp
function observe(uint32[] calldata secondsAgos)
external
view
returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);
/// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range
/// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.
/// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first
/// snapshot is taken and the second snapshot is taken.
/// @param tickLower The lower tick of the range
/// @param tickUpper The upper tick of the range
/// @return tickCumulativeInside The snapshot of the tick accumulator for the range
/// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range
/// @return secondsInside The snapshot of seconds per liquidity for the range
function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)
external
view
returns (
int56 tickCumulativeInside,
uint160 secondsPerLiquidityInsideX128,
uint32 secondsInside
);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Errors emitted by a pool
/// @notice Contains all events emitted by the pool
interface IUniswapV3PoolErrors {
error LOK();
error TLU();
error TLM();
error TUM();
error AI();
error M0();
error M1();
error AS();
error IIA();
error L();
error F0();
error F1();
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Events emitted by a pool
/// @notice Contains all events emitted by the pool
interface IUniswapV3PoolEvents {
/// @notice Emitted exactly once by a pool when #initialize is first called on the pool
/// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize
/// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96
/// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool
event Initialize(uint160 sqrtPriceX96, int24 tick);
/// @notice Emitted when liquidity is minted for a given position
/// @param sender The address that minted the liquidity
/// @param owner The owner of the position and recipient of any minted liquidity
/// @param tickLower The lower tick of the position
/// @param tickUpper The upper tick of the position
/// @param amount The amount of liquidity minted to the position range
/// @param amount0 How much token0 was required for the minted liquidity
/// @param amount1 How much token1 was required for the minted liquidity
event Mint(
address sender,
address indexed owner,
int24 indexed tickLower,
int24 indexed tickUpper,
uint128 amount,
uint256 amount0,
uint256 amount1
);
/// @notice Emitted when fees are collected by the owner of a position
/// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees
/// @param owner The owner of the position for which fees are collected
/// @param tickLower The lower tick of the position
/// @param tickUpper The upper tick of the position
/// @param amount0 The amount of token0 fees collected
/// @param amount1 The amount of token1 fees collected
event Collect(
address indexed owner,
address recipient,
int24 indexed tickLower,
int24 indexed tickUpper,
uint128 amount0,
uint128 amount1
);
/// @notice Emitted when a position's liquidity is removed
/// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect
/// @param owner The owner of the position for which liquidity is removed
/// @param tickLower The lower tick of the position
/// @param tickUpper The upper tick of the position
/// @param amount The amount of liquidity to remove
/// @param amount0 The amount of token0 withdrawn
/// @param amount1 The amount of token1 withdrawn
event Burn(
address indexed owner,
int24 indexed tickLower,
int24 indexed tickUpper,
uint128 amount,
uint256 amount0,
uint256 amount1
);
/// @notice Emitted by the pool for any swaps between token0 and token1
/// @param sender The address that initiated the swap call, and that received the callback
/// @param recipient The address that received the output of the swap
/// @param amount0 The delta of the token0 balance of the pool
/// @param amount1 The delta of the token1 balance of the pool
/// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96
/// @param liquidity The liquidity of the pool after the swap
/// @param tick The log base 1.0001 of price of the pool after the swap
event Swap(
address indexed sender,
address indexed recipient,
int256 amount0,
int256 amount1,
uint160 sqrtPriceX96,
uint128 liquidity,
int24 tick
);
/// @notice Emitted by the pool for any flashes of token0/token1
/// @param sender The address that initiated the swap call, and that received the callback
/// @param recipient The address that received the tokens from flash
/// @param amount0 The amount of token0 that was flashed
/// @param amount1 The amount of token1 that was flashed
/// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee
/// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee
event Flash(
address indexed sender,
address indexed recipient,
uint256 amount0,
uint256 amount1,
uint256 paid0,
uint256 paid1
);
/// @notice Emitted by the pool for increases to the number of observations that can be stored
/// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index
/// just before a mint/swap/burn.
/// @param observationCardinalityNextOld The previous value of the next observation cardinality
/// @param observationCardinalityNextNew The updated value of the next observation cardinality
event IncreaseObservationCardinalityNext(
uint16 observationCardinalityNextOld,
uint16 observationCardinalityNextNew
);
/// @notice Emitted when the protocol fee is changed by the pool
/// @param feeProtocol0Old The previous value of the token0 protocol fee
/// @param feeProtocol1Old The previous value of the token1 protocol fee
/// @param feeProtocol0New The updated value of the token0 protocol fee
/// @param feeProtocol1New The updated value of the token1 protocol fee
event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);
/// @notice Emitted when the collected protocol fees are withdrawn by the factory owner
/// @param sender The address that collects the protocol fees
/// @param recipient The address that receives the collected protocol fees
/// @param amount0 The amount of token0 protocol fees that is withdrawn
/// @param amount0 The amount of token1 protocol fees that is withdrawn
event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Pool state that never changes
/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values
interface IUniswapV3PoolImmutables {
/// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface
/// @return The contract address
function factory() external view returns (address);
/// @notice The first of the two tokens of the pool, sorted by address
/// @return The token contract address
function token0() external view returns (address);
/// @notice The second of the two tokens of the pool, sorted by address
/// @return The token contract address
function token1() external view returns (address);
/// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
/// @return The fee
function fee() external view returns (uint24);
/// @notice The pool tick spacing
/// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive
/// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...
/// This value is an int24 to avoid casting even though it is always positive.
/// @return The tick spacing
function tickSpacing() external view returns (int24);
/// @notice The maximum amount of position liquidity that can use any tick in the range
/// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and
/// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool
/// @return The max amount of liquidity per tick
function maxLiquidityPerTick() external view returns (uint128);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Permissioned pool actions
/// @notice Contains pool methods that may only be called by the factory owner
interface IUniswapV3PoolOwnerActions {
/// @notice Set the denominator of the protocol's % share of the fees
/// @param feeProtocol0 new protocol fee for token0 of the pool
/// @param feeProtocol1 new protocol fee for token1 of the pool
function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;
/// @notice Collect the protocol fee accrued to the pool
/// @param recipient The address to which collected protocol fees should be sent
/// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1
/// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0
/// @return amount0 The protocol fee collected in token0
/// @return amount1 The protocol fee collected in token1
function collectProtocol(
address recipient,
uint128 amount0Requested,
uint128 amount1Requested
) external returns (uint128 amount0, uint128 amount1);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Pool state that can change
/// @notice These methods compose the pool's state, and can change with any frequency including multiple times
/// per transaction
interface IUniswapV3PoolState {
/// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas
/// when accessed externally.
/// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value
/// @return tick The current tick of the pool, i.e. according to the last tick transition that was run.
/// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
/// boundary.
/// @return observationIndex The index of the last oracle observation that was written,
/// @return observationCardinality The current maximum number of observations stored in the pool,
/// @return observationCardinalityNext The next maximum number of observations, to be updated when the observation.
/// @return feeProtocol The protocol fee for both tokens of the pool.
/// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0
/// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.
/// unlocked Whether the pool is currently locked to reentrancy
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
/// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal0X128() external view returns (uint256);
/// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal1X128() external view returns (uint256);
/// @notice The amounts of token0 and token1 that are owed to the protocol
/// @dev Protocol fees will never exceed uint128 max in either token
function protocolFees() external view returns (uint128 token0, uint128 token1);
/// @notice The currently in range liquidity available to the pool
/// @dev This value has no relationship to the total liquidity across all ticks
/// @return The liquidity at the current price of the pool
function liquidity() external view returns (uint128);
/// @notice Look up information about a specific tick in the pool
/// @param tick The tick to look up
/// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or
/// tick upper
/// @return liquidityNet how much liquidity changes when the pool price crosses the tick,
/// @return feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,
/// @return feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,
/// @return tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick
/// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,
/// @return secondsOutside the seconds spent on the other side of the tick from the current tick,
/// @return initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.
/// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.
/// In addition, these values are only relative and must be used only in comparison to previous snapshots for
/// a specific position.
function ticks(int24 tick)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128,
int56 tickCumulativeOutside,
uint160 secondsPerLiquidityOutsideX128,
uint32 secondsOutside,
bool initialized
);
/// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information
function tickBitmap(int16 wordPosition) external view returns (uint256);
/// @notice Returns the information about a position by the position's key
/// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper
/// @return liquidity The amount of liquidity in the position,
/// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,
/// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,
/// @return tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,
/// @return tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke
function positions(bytes32 key)
external
view
returns (
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
/// @notice Returns data about a specific observation index
/// @param index The element of the observations array to fetch
/// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time
/// ago, rather than at a specific index in the array.
/// @return blockTimestamp The timestamp of the observation,
/// @return tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,
/// @return secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,
/// @return initialized whether the observation has been initialized and the values are safe to use
function observations(uint256 index)
external
view
returns (
uint32 blockTimestamp,
int56 tickCumulative,
uint160 secondsPerLiquidityCumulativeX128,
bool initialized
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
function mulDiv(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(a, b, not(0))
prod0 := mul(a, b)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
require(denominator > 0);
assembly {
result := div(prod0, denominator)
}
return result;
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (0 - denominator) & denominator;
// Divide denominator by power of two
assembly {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256
// Now that denominator is an odd number, it has an inverse
// modulo 2**256 such that denominator * inv = 1 mod 2**256.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // inverse mod 2**256
// Because the division is now exact we can divide by multiplying
// with the modular inverse of denominator. This will give us the
// correct result modulo 2**256. Since the precoditions guarantee
// that the outcome is less than 2**256, this is the final result.
// We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
function mulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
error T();
error R();
/// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128
int24 internal constant MIN_TICK = -887272;
/// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128
int24 internal constant MAX_TICK = -MIN_TICK;
/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
uint160 internal constant MIN_SQRT_RATIO = 4295128739;
/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;
/// @notice Calculates sqrt(1.0001^tick) * 2^96
/// @dev Throws if |tick| > max tick
/// @param tick The input tick for the above formula
/// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)
/// at the given tick
function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
unchecked {
uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
if (absTick > uint256(int256(MAX_TICK))) revert T();
uint256 ratio = absTick & 0x1 != 0
? 0xfffcb933bd6fad37aa2d162d1a594001
: 0x100000000000000000000000000000000;
if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
if (tick > 0) ratio = type(uint256).max / ratio;
// this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
// we then downcast because we know the result always fits within 160 bits due to our tick input constraint
// we round up in the division so getTickAtSqrtRatio of the output price is always consistent
sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
}
}
/// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio
/// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may
/// ever return.
/// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96
/// @return tick The greatest tick for which the ratio is less than or equal to the input ratio
function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
unchecked {
// second inequality must be < because the price can never reach the price at the max tick
if (!(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO)) revert R();
uint256 ratio = uint256(sqrtPriceX96) << 32;
uint256 r = ratio;
uint256 msb = 0;
assembly {
let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(5, gt(r, 0xFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(4, gt(r, 0xFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(3, gt(r, 0xFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(2, gt(r, 0xF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(1, gt(r, 0x3))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := gt(r, 0x1)
msb := or(msb, f)
}
if (msb >= 128) r = ratio >> (msb - 127);
else r = ratio << (127 - msb);
int256 log_2 = (int256(msb) - 128) << 64;
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(63, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(62, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(61, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(60, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(59, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(58, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(57, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(56, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(55, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(54, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(53, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(52, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(51, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(50, f))
}
int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number
int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);
tick = tickLow == tickHi ? tickLow : (getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow);
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
/// @title QuoterV2 Interface
/// @notice Supports quoting the calculated amounts from exact input or exact output swaps.
/// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap.
/// @dev These functions are not marked view because they rely on calling non-view functions and reverting
/// to compute the result. They are also not gas efficient and should not be called on-chain.
interface IQuoterV2 {
/// @notice Returns the amount out received for a given exact input swap without executing the swap
/// @param path The path of the swap, i.e. each token pair and the pool fee
/// @param amountIn The amount of the first token to swap
/// @return amountOut The amount of the last token that would be received
/// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
/// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactInput(bytes memory path, uint256 amountIn)
external
returns (
uint256 amountOut,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
struct QuoteExactInputSingleParams {
address tokenIn;
address tokenOut;
uint256 amountIn;
uint24 fee;
uint160 sqrtPriceLimitX96;
}
/// @notice Returns the amount out received for a given exact input but for a swap of a single pool
/// @param params The params for the quote, encoded as `QuoteExactInputSingleParams`
/// tokenIn The token being swapped in
/// tokenOut The token being swapped out
/// fee The fee of the token pool to consider for the pair
/// amountIn The desired input amount
/// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap
/// @return amountOut The amount of `tokenOut` that would be received
/// @return sqrtPriceX96After The sqrt price of the pool after the swap
/// @return initializedTicksCrossed The number of initialized ticks that the swap crossed
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactInputSingle(QuoteExactInputSingleParams memory params)
external
returns (
uint256 amountOut,
uint160 sqrtPriceX96After,
uint32 initializedTicksCrossed,
uint256 gasEstimate
);
/// @notice Returns the amount in required for a given exact output swap without executing the swap
/// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order
/// @param amountOut The amount of the last token to receive
/// @return amountIn The amount of first token required to be paid
/// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
/// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactOutput(bytes memory path, uint256 amountOut)
external
returns (
uint256 amountIn,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
struct QuoteExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint256 amount;
uint24 fee;
uint160 sqrtPriceLimitX96;
}
/// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool
/// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams`
/// tokenIn The token being swapped in
/// tokenOut The token being swapped out
/// fee The fee of the token pool to consider for the pair
/// amountOut The desired output amount
/// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap
/// @return amountIn The amount required as the input for the swap in order to receive `amountOut`
/// @return sqrtPriceX96After The sqrt price of the pool after the swap
/// @return initializedTicksCrossed The number of initialized ticks that the swap crossed
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params)
external
returns (
uint256 amountIn,
uint160 sqrtPriceX96After,
uint32 initializedTicksCrossed,
uint256 gasEstimate
);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
import "../../../dependencies/uniswap-v3-core/interfaces/callback/IUniswapV3SwapCallback.sol";
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params)
external
payable
returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params)
external
payable
returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params)
external
payable
returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params)
external
payable
returns (uint256 amountIn);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;
import "../../../dependencies/@openzeppelin/contracts/token/ERC20/IERC20.sol";
library TransferHelper {
/// @notice Transfers tokens from the targeted address to the given destination
/// @notice Errors with 'STF' if transfer fails
/// @param token The contract address of the token to be transferred
/// @param from The originating address from which the tokens will be transferred
/// @param to The destination address of the transfer
/// @param value The amount to be transferred
function safeTransferFrom(
address token,
address from,
address to,
uint256 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))),
"STF"
);
}
/// @notice Transfers tokens from msg.sender to a recipient
/// @dev Errors with ST if transfer fails
/// @param token The contract address of the token which will be transferred
/// @param to The recipient of the transfer
/// @param value The value of the transfer
function safeTransfer(
address token,
address to,
uint256 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))),
"ST"
);
}
/// @notice Approves the stipulated contract to spend the given allowance in the given token
/// @dev Errors with 'SA' if transfer fails
/// @param token The contract address of the token to be approved
/// @param to The target of the approval
/// @param value The amount of the given token the target will be allowed to spend
function safeApprove(
address token,
address to,
uint256 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))),
"SA"
);
}
/// @notice Transfers ETH to the recipient address
/// @dev Fails with `STE`
/// @param to The destination of the transfer
/// @param value The value to be transferred
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "STE");
}
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.17;
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {INotionalERC20} from './INotionalERC20.sol';
import {IInitializableAssetToken} from './IInitializableAssetToken.sol';
interface IAssetToken is IERC20, INotionalERC20, IInitializableAssetToken {
function mint(address account, uint256 amount) external;
function burn(address account, uint256 amount) external;
function updateNotionalFactor(uint256 multFactor) external returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.17;
/**
* @title ICreditDelegation
* @author Amorphous, inspired by AAVE v3
* @notice Defines the basic interface for a token supporting credit delegation.
**/
interface ICreditDelegation {
/**
* @dev Emitted on `approveDelegation` and `borrowAllowance
* @param fromUser The address of the delegator
* @param toUser The address of the delegatee
* @param amount The amount being delegated
*/
event BorrowAllowanceDelegated(address indexed fromUser, address indexed toUser, uint256 amount);
/**
* @notice Delegates borrowing power to a user on the specific debt token.
* Delegation will still respect the liquidation constraints (even if delegated, a
* delegatee cannot force a delegator HF to go below 1)
* @param delegatee The address receiving the delegated borrowing power
* @param amount The maximum amount being delegated.
**/
function approveDelegation(address delegatee, uint256 amount) external;
/**
* @notice Returns the borrow allowance of the user
* @param fromUser The user to giving allowance
* @param toUser The user to give allowance to
* @return The current allowance of `toUser`
**/
function borrowAllowance(address fromUser, address toUser) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IGuildAddressesProvider} from './IGuildAddressesProvider.sol';
import {IAssetToken} from './IAssetToken.sol';
import {ILiabilityToken} from './ILiabilityToken.sol';
import {IGuildAddressesProvider} from './IGuildAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
/**
* @title IGuild
* @author Amorphous
* @notice Defines the basic interface for a Guild.
**/
interface IGuild {
/**
* @dev Emitted on deposit()
* @param collateral The address of the collateral asset
* @param user The address initiating the deposit
* @param onBehalfOf The beneficiary of the deposit
* @param amount The amount supplied
**/
event Deposit(address indexed collateral, address user, address indexed onBehalfOf, uint256 amount);
/**
* @dev Emitted on withdraw()
* @param collateral The address of the collateral asset
* @param user The address initiating the withdrawal
* @param to The address that will receive the underlying
* @param amount The amount to be withdrawn
**/
event Withdraw(address indexed collateral, address indexed user, address indexed to, uint256 amount);
/**
* @notice Returns the GuildAddressesProvider connected to this contract
* @return The address of the GuildAddressesProvider
**/
function ADDRESSES_PROVIDER() external view returns (IGuildAddressesProvider);
/**
* @notice Refinances perpetual debt.
* @dev Makes uniswap DEX call, and calculates TWAP price vs last time refinance was called.
* Uses TWAP price to calculate interest rate in that period.
**/
function refinance() external;
/**
* @notice Supplies an `amount` of collateral into the Guild.
* @param asset The address of the ERC20 asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that receives the collateral 'credit', same as msg.sender if the user
* wants it to account to their own wallet, or a different address if the beneficiary is someone else
**/
function deposit(
address asset,
uint256 amount,
address onBehalfOf
) external;
/**
* @notice Withdraw an `amount` of underlying asset from the Guild.
* @param asset The addres of the ERC20 asset to withdraw
* @param amount The amount to be withdraw (in WADs if that's the collateral's precision)
* @param to The address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
**/
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256);
/**
* @notice Initializes a perpetual debt.
* @param assetTokenProxyAddress The proxy address of the underlying asset token contract (zToken)
* @param liabilityTokenProxyAddress The proxy address of the underlying liability token contract (dToken)
* @param moneyAddress The address of the money token on which the debt is denominated in
* @param duration The duration, in seconds, of the perpetual debt
* @param notionalPriceLimitMax Maximum price used for refinance purposes
* @param notionalPriceLimitMin Minimum price used for refinance purposes
* @param dexFactory Uniswap v3 Factory address
* @param dexFee Uniswap v3 pool fee (to identify pool used for refinance oracle purposes)
**/
function initPerpetualDebt(
address assetTokenProxyAddress,
address liabilityTokenProxyAddress,
address moneyAddress,
uint256 duration,
uint256 notionalPriceLimitMax,
uint256 notionalPriceLimitMin,
address dexFactory,
uint24 dexFee
) external;
/**
* @notice Initializes a collateral, activating it, and configuring it's parameters
* @dev Only callable by the GuildConfigurator contract
* @param asset The address of the ERC20 collateral
**/
function initCollateral(address asset) external;
/**
* @notice Drop a collateral
* @dev Only callable by the GuildConfigurator contract
* @param asset The address of the ERC20 to drop as an acceptable collateral
**/
function dropCollateral(address asset) external;
/**
* @notice Sets the configuration bitmap of the collateral as a whole
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the ERC20 collateral
* @param configuration The new configuration bitmap
**/
function setConfiguration(address asset, DataTypes.CollateralConfigurationMap calldata configuration) external;
/**
* @notice Returns the configuration of the collateral
* @param asset The address of the ERC20 collateral
* @return The configuration of the collateral
**/
function getCollateralConfiguration(address asset)
external
view
returns (DataTypes.CollateralConfigurationMap memory);
/**
* @notice Returns the collateral balance of a user in the Guild
* @param user The address of the user
* @param asset The address of the collateral asset
* @return The collateral amount deposited in the Guild
**/
function getCollateralBalanceOf(address user, address asset) external view returns (uint256);
/**
* @notice Returns the total collateral balance in the Guild
* @param asset The address of the collateral asset
* @return The total collateral amount deposited in the Guild
**/
function getCollateralTotalBalance(address asset) external view returns (uint256);
/**
* @notice Returns the list of all initialized collaterals
* @dev It does not include dropped collaterals
* @return The addresses of the initialized collaterals
**/
function getCollateralsList() external view returns (address[] memory);
/**
* @notice Returns the address of the underlying collateral by collateral id as stored in the DataTypes.CollateralData struct
* @param id The id of the collateral as stored in the DataTypes.CollateralData struct
* @return The address of the collateral associated with id
**/
function getCollateralAddressById(uint16 id) external view returns (address);
/**
* @notice Returns the maximum number of collaterals supported by this Guild
* @return The maximum number of collaterals supported
*/
function MAX_NUMBER_COLLATERALS() external view returns (uint16);
/**
* @notice Sets the configuration bitmap of the perpetual debt
* @dev Only callable by the GuildConfigurator contract
* @param configuration The new configuration bitmap
**/
function setPerpDebtConfiguration(DataTypes.PerpDebtConfigurationMap calldata configuration) external;
/**
* @notice Returns the configuration of the perpetual debt
* @return The configuration of the perpetual debt
**/
function getPerpDebtConfiguration() external view returns (DataTypes.PerpDebtConfigurationMap memory);
/**
* @dev Emitted on borrow() when debt needs to be opened
* @param user The address of the user initiating the borrow(), receiving the funds on borrow()
* @param onBehalfOf The address that will be getting the debt
* @param amount The zToken amount borrowed out
* @param amountNotional The notional amount borrowed out (in Notional)
**/
event Borrow(address indexed user, address indexed onBehalfOf, uint256 amount, uint256 amountNotional);
/**
* @dev Emitted on repay()
* @param user The address of the account whose zTokens are used to pay back the debt
* @param onBehalfOf The address that will be getting the debt paid back
* @param amount The zToken amount repaid
* @param amountNotional The notional amount borrowed out (in Notional)
**/
event Repay(address indexed user, address indexed onBehalfOf, uint256 amount, uint256 amountNotional);
/**
* @notice Get money token
**/
function getMoney() external view returns (IERC20);
/**
* @notice Get asset token
**/
function getAsset() external view returns (IAssetToken);
/**
* @notice get liability token
**/
function getLiability() external view returns (ILiabilityToken);
/**
* @notice get current spot APY (not historical), given current spot zToken price on external DEX
**/
function getAPY() external view returns (uint256);
/**
* @notice get perpetual debt notional price
**/
function getDebtNotionalPrice(address oracle) external view returns (uint256);
/**
* @notice get perpetual debt data
**/
function getPerpetualDebt() external view returns (DataTypes.PerpetualDebtData memory);
/**
* @notice Updates notional price limits used during refinancing.
* @dev Perpetual debt interest rates are proportional to 1/notionalPrice.
* @param priceMin Minimum notional price to use for refinancing.
* @param priceMax Maximum notional price to use for refinancing.
**/
function setPerpDebtNotionalPriceLimits(uint256 priceMax, uint256 priceMin) external;
/**
* @notice Allows users to borrow a specific `amount` of the zTokens, provided that the borrower
* already supplied enough collateral.
* @param amount The zToken amount to be borrowed
* @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance to msg.sender
**/
function borrow(uint256 amount, address onBehalfOf) external;
/**
* @notice Payback specific borrowed `amount`, which in turn burns the equivalent amount of dTokens
* @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @param amount The zToken amount to be paid back
* @return The final notional amount repaid
**/
function repay(uint256 amount, address onBehalfOf) external returns (uint256);
/**
* @notice Return structure for getUserAccountData function
* @return totalCollateralInBaseCurrency The total collateral of the user in the base currency used by the price feed
* @return totalDebtNotionalInBaseCurrency The total debt of the user in the base currency used by the price feed
* @return availableBorrowsInBaseCurrency The borrowing power left of the user in the base currency used by the price feed
* @return currentLiquidationThreshold The liquidation threshold of the user
* @return ltv The loan to value of The user
* @return healthFactor The current health factor of the user
* @return totalDebtNotional The total debt of the user in the native dToken decimal unit
* @return availableBorrowsInZTokens The total zTokens that can be minted given borrowing capacity
* @return availableNotionalBorrows The total notional that can be minted given borrowing capacity
* @return zTokensToRepayDebt The total zTokens required to repay the accounts totalDebtNotional (in native zToken decimal unit)
**/
struct userAccountDataStruc {
uint256 totalCollateralInBaseCurrency;
uint256 totalDebtNotionalInBaseCurrency;
uint256 availableBorrowsInBaseCurrency;
uint256 currentLiquidationThreshold;
uint256 ltv;
uint256 healthFactor;
uint256 totalDebtNotional;
uint256 availableBorrowsInZTokens;
uint256 availableNotionalBorrows;
uint256 zTokensToRepayDebt;
}
/**
* @notice Returns the user account data across all the collaterals
* @param user The address of the user
* @return userData User variables as per userAccountDataStruc structure
**/
function getUserAccountData(address user) external view returns (userAccountDataStruc memory userData);
/**
* @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtNotionalToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the collateral asset, to receive as result of the liquidation
* @param user The address of the borrower getting liquidated
* @param debtNotionalToCover The debt Notional amount the liquidator wants to cover
* @param receiveCollateral True if the liquidators wants to take ownership of the collateral asset and transfer it into their Guild account (as collateral deposited)
*`false` if they want to receive (transfer) the collateral asset directly into their wallet.
**/
function liquidationCall(
address collateralAsset,
address user,
uint256 debtNotionalToCover,
bool receiveCollateral
) external;
/**
* @notice Executes validation of deposit() function, and reverts with same validation logic
* @dev does not update on-chain state
* @param asset The address of the ERC20 asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that receives the collateral 'credit', same as msg.sender if the user
* wants it to account to their own wallet, or a different address if the beneficiary is someone else
**/
function validateDeposit(
address asset,
uint256 amount,
address onBehalfOf
) external view;
/**
* @notice Executes validation of withdraw() function, and reverts with same validation logic
* @dev does not update on-chain state
* @param asset The address of the ERC20 asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that receives the collateral 'withdrawal', same as msg.sender if the user
* wants it to account to their own wallet, or a different address if the beneficiary is someone else
**/
function validateWithdraw(
address asset,
uint256 amount,
address onBehalfOf
) external view;
/**
* @notice Executes validation of borrow() function, and reverts with same validation logic
* @param amount The zToken amount to be borrowed
* @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance to msg.sender
**/
function validateBorrow(uint256 amount, address onBehalfOf) external view;
/**
* @notice Executes validation of repay() function, and reverts with same validation logic
* @param amount The zToken amount to be paid back
* @param onBehalfOf The address of the user who will have debt repaid.
**/
function validateRepay(uint256 amount, address onBehalfOf) external view;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IGuildAddressesProvider
* @author Amorphous (cloned from AAVE core v3 commit d5fafce)
* @notice Defines the basic interface for a Guild Addresses Provider.
**/
interface IGuildAddressesProvider {
/**
* @dev Emitted when the market identifier is updated.
* @param oldGuildId The old id of the market
* @param newGuildId The new id of the market
*/
event GuildIdSet(string indexed oldGuildId, string indexed newGuildId);
/**
* @dev Emitted when the Guild is updated.
* @param oldAddress The old address of the Guild
* @param newAddress The new address of the Guild
*/
event GuildUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the Guild configurator is updated.
* @param oldAddress The old address of the GuildConfigurator
* @param newAddress The new address of the GuildConfigurator
*/
event GuildConfiguratorUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle is updated.
* @param oldAddress The old address of the PriceOracle
* @param newAddress The new address of the PriceOracle
*/
event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL manager is updated.
* @param oldAddress The old address of the ACLManager
* @param newAddress The new address of the ACLManager
*/
event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL admin is updated.
* @param oldAddress The old address of the ACLAdmin
* @param newAddress The new address of the ACLAdmin
*/
event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the Guild data provider is updated.
* @param oldAddress The old address of the GuildDataProvider
* @param newAddress The new address of the GuildDataProvider
*/
event GuildDataProviderUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when a new proxy is created.
* @param id The identifier of the proxy
* @param proxyAddress The address of the created proxy contract
* @param implementationAddress The address of the implementation contract
*/
event ProxyCreated(bytes32 indexed id, address indexed proxyAddress, address indexed implementationAddress);
/**
* @dev Emitted when a new non-proxied contract address is registered.
* @param id The identifier of the contract
* @param oldAddress The address of the old contract
* @param newAddress The address of the new contract
*/
event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the implementation of the proxy registered with id is updated
* @param id The identifier of the contract
* @param proxyAddress The address of the proxy contract
* @param oldImplementationAddress The address of the old implementation contract
* @param newImplementationAddress The address of the new implementation contract
*/
event AddressSetAsProxy(
bytes32 indexed id,
address indexed proxyAddress,
address oldImplementationAddress,
address indexed newImplementationAddress
);
/**
* @notice Returns the id of the Aave market to which this contract points to.
* @return The market id
**/
function getGuildId() external view returns (string memory);
/**
* @notice Associates an id with a specific GuildAddressesProvider.
* @dev This can be used to create an onchain registry of GuildAddressesProviders to
* identify and validate multiple Aave markets.
* @param newGuildId The market id
*/
function setGuildId(string calldata newGuildId) external;
/**
* @notice Returns an address by its identifier.
* @dev The returned address might be an EOA or a contract, potentially proxied
* @dev It returns ZERO if there is no registered address with the given id
* @param id The id
* @return The address of the registered for the specified id
*/
function getAddress(bytes32 id) external view returns (address);
/**
* @notice General function to update the implementation of a proxy registered with
* certain `id`. If there is no proxy registered, it will instantiate one and
* set as implementation the `newImplementationAddress`.
* @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit
* setter function, in order to avoid unexpected consequences
* @param id The id
* @param newImplementationAddress The address of the new implementation
*/
function setAddressAsProxy(bytes32 id, address newImplementationAddress) external;
/**
* @notice Sets an address for an id replacing the address saved in the addresses map.
* @dev IMPORTANT Use this function carefully, as it will do a hard replacement
* @param id The id
* @param newAddress The address to set
*/
function setAddress(bytes32 id, address newAddress) external;
/**
* @notice Returns the address of the Guild proxy.
* @return The Guild proxy address
**/
function getGuild() external view returns (address);
/**
* @notice Updates the implementation of the Guild, or creates a proxy
* setting the new `Guild` implementation when the function is called for the first time.
* @param newGuildImpl The new Guild implementation
**/
function setGuildImpl(address newGuildImpl) external;
/**
* @notice Returns the address of the GuildConfigurator proxy.
* @return The GuildConfigurator proxy address
**/
function getGuildConfigurator() external view returns (address);
/**
* @notice Updates the implementation of the GuildConfigurator, or creates a proxy
* setting the new `GuildConfigurator` implementation when the function is called for the first time.
* @param newGuildConfiguratorImpl The new GuildConfigurator implementation
**/
function setGuildConfiguratorImpl(address newGuildConfiguratorImpl) external;
/**
* @notice Returns the address of the price oracle.
* @return The address of the PriceOracle
*/
function getPriceOracle() external view returns (address);
/**
* @notice Updates the address of the price oracle.
* @param newPriceOracle The address of the new PriceOracle
*/
function setPriceOracle(address newPriceOracle) external;
/**
* @notice Returns the address of the ACL manager.
* @return The address of the ACLManager
*/
function getACLManager() external view returns (address);
/**
* @notice Updates the address of the ACL manager.
* @param newAclManager The address of the new ACLManager
**/
function setACLManager(address newAclManager) external;
/**
* @notice Returns the address of the ACL admin.
* @return The address of the ACL admin
*/
function getACLAdmin() external view returns (address);
/**
* @notice Updates the address of the ACL admin.
* @param newAclAdmin The address of the new ACL admin
*/
function setACLAdmin(address newAclAdmin) external;
/**
* @notice Returns the address of the data provider.
* @return The address of the DataProvider
*/
function getGuildDataProvider() external view returns (address);
/**
* @notice Updates the address of the data provider.
* @param newDataProvider The address of the new DataProvider
**/
function setGuildDataProvider(address newDataProvider) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.17;
import {IGuild} from './IGuild.sol';
/**
* @title IInitializableAssetToken
* @author Amorphous
* @notice Interface for the initialize function on zToken
**/
interface IInitializableAssetToken {
/**
* @dev Emitted when an aToken is initialized
* @param guild The address of the associated guild
* @param zTokenDecimals The decimals of the underlying
* @param zTokenName The name of the zToken
* @param zTokenSymbol The symbol of the zToken
* @param params A set of encoded parameters for additional initialization
**/
event Initialized(
address indexed guild,
uint8 zTokenDecimals,
string zTokenName,
string zTokenSymbol,
bytes params
);
/**
* @notice Initializes the zToken
* @param guild The guild contract that is initializing this contract
* @param zTokenDecimals The decimals of the zToken, same as the underlying asset's
* @param zTokenName The name of the zToken
* @param zTokenSymbol The symbol of the zToken
* @param params A set of encoded parameters for additional initialization
*/
function initialize(
IGuild guild,
uint8 zTokenDecimals,
string calldata zTokenName,
string calldata zTokenSymbol,
bytes calldata params
) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.17;
import {IGuild} from './IGuild.sol';
/**
* @title IInitializableLiabilityToken
* @author Amorphous
* @notice Interface for the initialize function on dToken
**/
interface IInitializableLiabilityToken {
/**
* @dev Emitted when an aToken is initialized
* @param guild The address of the associated guild
* @param dTokenDecimals The decimals of the underlying
* @param dTokenName The name of the dToken
* @param dTokenSymbol The symbol of the dToken
* @param params A set of encoded parameters for additional initialization
**/
event Initialized(
address indexed guild,
uint8 dTokenDecimals,
string dTokenName,
string dTokenSymbol,
bytes params
);
/**
* @notice Initializes the dToken
* @param guild The guild contract that is initializing this contract
* @param dTokenDecimals The decimals of the zToken, same as the underlying asset's
* @param dTokenName The name of the zToken
* @param dTokenSymbol The symbol of the zToken
* @param params A set of encoded parameters for additional initialization
*/
function initialize(
IGuild guild,
uint8 dTokenDecimals,
string calldata dTokenName,
string calldata dTokenSymbol,
bytes calldata params
) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.17;
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {INotionalERC20} from './INotionalERC20.sol';
import {IInitializableLiabilityToken} from './IInitializableLiabilityToken.sol';
import {ICreditDelegation} from './ICreditDelegation.sol';
interface ILiabilityToken is IERC20, INotionalERC20, IInitializableLiabilityToken, ICreditDelegation {
/**
* @dev Emitted when new stable debt is minted
* @param user The address of the user who triggered the minting
* @param onBehalfOf The recipient of stable debt tokens
* @param amount The amount minted
**/
event Mint(address indexed user, address indexed onBehalfOf, uint256 amount);
/**
* @notice Mints liability token to the `onBehalfOf` address
* @param user The address receiving the borrowed underlying, being the delegatee in case
* of credit delegate, or same as `onBehalfOf` otherwise
* @param onBehalfOf The address receiving the debt tokens
* @param amount The amount of debt being minted
**/
function mint(
address user,
address onBehalfOf,
uint256 amount
) external;
function burn(address account, uint256 amount) external;
function updateNotionalFactor(uint256 multFactor) external returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.17;
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
/**
* @dev Implementation of notional rebase functionality.
*
* Forms the basis of a notional ERC20 token, where the ERC20 interface is non-rebasing,
* (ie, the quantities tracked by the ERC20 token are normalized), and here we create
* functions that access the full 'rebased' quantities as a 'Notional' amount
*
**/
interface INotionalERC20 is IERC20 {
event UpdateNotionalFactor(uint256 _value);
function getNotionalFactor() external view returns (uint256); // @dev gets the Notional factor [ray]
function totalNotionalSupply() external view returns (uint256);
function balanceNotionalOf(address account) external view returns (uint256);
function notionalToBase(uint256 amount) external view returns (uint256);
function baseToNotional(uint256 amount) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IPriceOracleGetter
* @author Amorphous
* @notice Interface for the Tazz price oracle.
**/
interface IPriceOracleGetter {
/**
* @notice Returns the base currency address
* @dev Address 0x0 is reserved for USD as base currency.
* @return Returns the base currency address.
**/
function BASE_CURRENCY() external view returns (address);
/**
* @notice Returns the asset price in the base currency
* @param asset The address of the asset
* @return The price of the asset
**/
function getAssetPrice(address asset) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IGuild} from './IGuild.sol';
/**
* @title ITazzHelper
* @author Tazz Labs
* @notice Defines the user interface for the TazzHelper function
**/
interface ITazzHelper {
/**
* @dev Emitted on borrowMoney()
* @param user The address of borrower
* @param debtNotionalMintedInBaseCurrency The debt Notional minted (is 0 if only a swap)
* @param zTokensIn The zTokens swapped
* @param moneyOut The money obtained from swapping zTokens
**/
event MintAndSwap(
address indexed user,
uint256 debtNotionalMintedInBaseCurrency,
uint256 zTokensIn,
uint256 moneyOut
);
/**
* @dev Emitted on repayMoney()
* @param user The address of borrower
* @param debtNotionalBurnedInBaseCurrency The debt Notional burned
* @param moneyIn The zTokens burned (base)
* @param zTokensOut The money swapped for the the zTokens that were burned
**/
event SwapAndBurn(
address indexed user,
uint256 debtNotionalBurnedInBaseCurrency,
uint256 moneyIn,
uint256 zTokensOut
);
/**
* @notice Swaps zToken for money. Mints zTokens if needed (and collateral is available)
* @param _guildAddress The Guild we are minting debt from
* @param _moneyOut The amount of money looking to swap debt for
* @param _zTokenInMax The maximum zTokens we are willing to mint (in base amount)
* @param _deadline The deadline timestamp after which the swap will not be accepted
* @param _sqrtPriceLimitX96 Price limit of swap
* @return debtNotionalMintedInBaseCurrency_ Debt notional minted for user in this transaction (in money decimal units)
* @return zTokenIn_ Debt swapped for money in this transaction
* @return moneyOut_ Money recieved from swap in this transaction
* @dev Function swaps zTokens for exact money amount
* @dev If user does not have enough zTokens, function will request Guild to mint missing zTokens
* @dev This will be allowed, if user has enough collateral in Guild to mint zTokens
* @dev Function over mints debt, and at the end cleans up by burning any unused (overminted) zTokens/debt.
**/
function swapZTokenForExactMoney(
address _guildAddress,
uint256 _moneyOut,
uint256 _zTokenInMax,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalMintedInBaseCurrency_,
uint256 zTokenIn_,
uint256 moneyOut_
);
/**
* @notice Swaps money for zToken, and burns debt if it can
* @param _guildAddress The Guild we are minting debt from
* @param _zTokenOut The amount of zTokens we want out of this swap
* @param _moneyInMax The maximum money we are willing to use
* @param _deadline The deadline timestamp after which the swap will not be accepted
* @param _sqrtPriceLimitX96 Price limit of swap
* @return debtNotionalBurnedInBaseCurrency_ Debt notional burned for user in this transaction (in money decimal units)
* @return moneyIn_ Money swapped for zToken in this transaction
* @return zTokenOut_ zToken recieved from swap in this transaction
* @dev Function swaps zTokens for exact money amount
* @dev If user does not have enough zTokens, function will request Guild to mint missing zTokens
* @dev This will be allowed, if user has enough collateral in Guild to mint zTokens
* @dev Function over mints debt, and at the end cleans up by burning any unused (overminted) zTokens/debt.
**/
function swapMoneyForExactZToken(
address _guildAddress,
uint256 _zTokenOut,
uint256 _moneyInMax,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalBurnedInBaseCurrency_,
uint256 moneyIn_,
uint256 zTokenOut_
);
/**
* @notice Swaps money for zToken, and burns debt if it can
* @param _guildAddress The Guild we are minting debt from
* @param _moneyIn The amount of money used to repay debt
* @param _zTokenOutMin money will be swapped for zTokens. This is the minimum amount of zTokens expected from the swap
* @param _deadline The deadline timestamp after which the swap will not be accepted
* @param _sqrtPriceLimitX96 Price limit of swap
* @return debtNotionalBurnedInBaseCurrency_ Debt notional burned for user in this transaction (in money decimal units)
* @return moneyIn_ Money swapped for zToken in this transaction
* @return zTokenOut_ zToken recieved from swap in this transaction
* @dev Money from msg.sender is swapped for zTokens
* @dev If msg.sender has debt, zTokens are used to burn as much debt as possible
* @dev Excess zTokens are left in msg.senders wallet
**/
function swapExactMoneyForZToken(
address _guildAddress,
uint256 _moneyIn,
uint256 _zTokenOutMin,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalBurnedInBaseCurrency_,
uint256 moneyIn_,
uint256 zTokenOut_
);
/**
* @notice Swaps zToken for money. Mints zTokens if needed (and collateral is available)
* @param _guildAddress The Guild we are minting debt from
* @param _zTokenIn The amount of zTokens (base) swapped for money. If msg.sender does not have enough zTokens in their wallet, then zTokens are minted as new debt (if enough collateral)
* @param _moneyOutMin zTokens will be swapped for money. This is the minimum amount of money expected from the swap
* @param _deadline The deadline timestamp after which the swap will not be accepted
* @param _sqrtPriceLimitX96 Price limit of swap
* @return debtNotionalMintedInBaseCurrency_ Debt notional minted for user in this transaction (in money decimal units)
* @return zTokenIn_ Debt swapped for money in this transaction
* @return moneyOut_ Money recieved from swap in this transaction
**/
function swapExactZTokenForMoney(
address _guildAddress,
uint256 _zTokenIn,
uint256 _moneyOutMin,
uint256 _deadline,
uint160 _sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalMintedInBaseCurrency_,
uint256 zTokenIn_,
uint256 moneyOut_
);
/**
* @notice calculates zToken swap for money. Calculates zTokens that will be minted if needed (and collateral is available)
* @dev They are also not gas efficient and should not be called on-chain.
* @param guildAddress the guild address
* @param moneyOutTarget The amount of money to receive after transaction
* @param sqrtPriceLimitX96 Price limit of swap
* @return debtNotionalMintedInBaseCurrency The amount of Debt Notional minted in users account to support transaction (in money decimal units)
* @return zTokenIn The amount of zToken required for transaction
* @return moneyOut The amount of money received from swap
* @return zTokenPriceBeforeSwap zToken price before the swap in money units
* @return zTokenPriceAfterSwap zToken price after the swap in money units
* @return gasEstimate The estimate of the gas that the swap consumes
**/
function quoteSwapZTokenForExactMoney(
address guildAddress,
uint256 moneyOutTarget,
uint160 sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalMintedInBaseCurrency,
uint256 zTokenIn,
uint256 moneyOut,
uint256 zTokenPriceBeforeSwap,
uint256 zTokenPriceAfterSwap,
uint256 gasEstimate
);
/**
* @notice calculates zToken swap for money. Calculates zTokens that will be minted if needed (and collateral is available)
* @dev They are also not gas efficient and should not be called on-chain.
* @param guildAddress the guild address
* @param zTokenInTarget The amount of zToken to swap for money in transaction
* @param sqrtPriceLimitX96 Price limit of swap
* @return debtNotionalMintedInBaseCurrency The amount of Debt Notional minted in users account to support transaction (in money decimal units)
* @return zTokenIn The amount of zToken required for transaction
* @return moneyOut The amount of money received from swap
* @return zTokenPriceBeforeSwap zToken price before the swap in money units
* @return zTokenPriceAfterSwap zToken price after the swap in money units
* @return gasEstimate The estimate of the gas that the swap consumes
**/
function quoteSwapExactZTokenForMoney(
address guildAddress,
uint256 zTokenInTarget,
uint160 sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalMintedInBaseCurrency,
uint256 zTokenIn,
uint256 moneyOut,
uint256 zTokenPriceBeforeSwap,
uint256 zTokenPriceAfterSwap,
uint256 gasEstimate
);
/**
* @notice quote for swapping money for zToken. Calculates estimated debt that will be burned.
* @dev They are also not gas efficient and should not be called on-chain.
* @param guildAddress the guild address
* @param moneyInTarget The amount of money to swap for zToken in transaction
* @param sqrtPriceLimitX96 Price limit of swap
* @return debtNotionalBurnedInBaseCurrency The amount of Debt Notional that is estimated will be burned after this transaction (in money decimal units)
* @return moneyIn The amount of money required for transaction
* @return zTokenOut The amount of zToken received from swap
* @return zTokenPriceBeforeSwap zToken price before the swap in money units
* @return zTokenPriceAfterSwap zToken price after the swap in money units
* @return gasEstimate The estimate of the gas that the swap consumes
**/
function quoteSwapExactMoneyForZToken(
address guildAddress,
uint256 moneyInTarget,
uint160 sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalBurnedInBaseCurrency,
uint256 moneyIn,
uint256 zTokenOut,
uint256 zTokenPriceBeforeSwap,
uint256 zTokenPriceAfterSwap,
uint256 gasEstimate
);
/**
* @notice quote for swapping money for zToken. Calculates estimated debt that will be burned.
* @dev They are also not gas efficient and should not be called on-chain.
* @param guildAddress the guild address
* @param zTokenOutTarget The amount of zTokens targeted after the swap (before being burned if debt is available)
* @param sqrtPriceLimitX96 Price limit of swap
* @return debtNotionalBurnedInBaseCurrency The amount of Debt Notional that is estimated will be burned after this transaction (in money decimal units)
* @return moneyIn The amount of money required for transaction
* @return zTokenOut The amount of zToken received from swap
* @return zTokenPriceBeforeSwap zToken price before the swap in money units
* @return zTokenPriceAfterSwap zToken price after the swap in money units
* @return gasEstimate The estimate of the gas that the swap consumes
**/
function quoteSwapMoneyForExactZToken(
address guildAddress,
uint256 zTokenOutTarget,
uint160 sqrtPriceLimitX96
)
external
returns (
uint256 debtNotionalBurnedInBaseCurrency,
uint256 moneyIn,
uint256 zTokenOut,
uint256 zTokenPriceBeforeSwap,
uint256 zTokenPriceAfterSwap,
uint256 gasEstimate
);
/**
* @notice Updates guild states (refinance) and then returns the user account data across all the collaterals
* @dev This function is not gas efficient, and is meant to be called off-chain
* @param guild The address of the guild
* @param user The address of the user
* @return userAccountData User variables as per IGuild.userAccountDataStruc structure with the following parameters
* StrucParam: totalCollateralInBaseCurrency The total collateral of the user in the base currency used by the price feed
* StrucParam: totalDebtNotionalInBaseCurrency The total debt of the user in the base currency used by the price feed
* StrucParam: availableBorrowsInBaseCurrency The borrowing power left of the user in the base currency used by the price feed
* StrucParam: currentLiquidationThreshold The liquidation threshold of the user
* StrucParam: ltv The loan to value of The user
* StrucParam: healthFactor The current health factor of the user
* StrucParam: totalDebtNotional The total debt of the user in the native dToken decimal unit
* StrucParam: availableBorrowsInZTokens The total zTokens that can be minted given borrowing capacity
* StrucParam: availableNotionalBorrows The total notional that can be minted given borrowing capacity
**/
function quoteUserAccountData(address guild, address user)
external
returns (IGuild.userAccountDataStruc memory userAccountData);
/**
* @notice Returns the total money / ztokens in DEX placed as liquidity (irrespective of the actual price range it is placed at)
* @param guild The address of the guild
* @return moneyAmount amount of money tokens in DEX associated to Guild (in money units)
* @return zTokenAmount amount of zTokens in DEX associated to Guild (in zToken units)
**/
function quoteDexLiquidty(address guild) external returns (uint256 moneyAmount, uint256 zTokenAmount);
/**
* @notice Returns the max amount of a collateral asset the user can deposit. Validates whether that collateral is enabled.
* @param guild The address of the guild
* @param asset collateral asset to be deposited as collateral
* @param amount amount of collateral to deposit
* @return maxDepositAmount_ max amount that can be deposited. Returns 0 if none (and/or reverts with validation errors)
**/
function quoteDeposit(
address guild,
address asset,
uint256 amount
) external returns (uint256 maxDepositAmount_);
/**
* @notice Validates collateral withdrawal. Returns current amount of that collateral in vault
* @dev To check if the withdrawal can actually be made, an amount needs to be specified in the input. This cannot be calculated a prior.
* @dev The returned amount only indicates amount held by the Guild, and not how much can actually be withdrawn
* @param guild The address of the guild
* @param asset collateral asset to be deposited as collateral
* @param amount amount of collateral to withdraw
* @return currentCollateralInVault current collateral in Vault. Returns 0 if none (and/or reverts with validation errors)
**/
function quoteWithdraw(
address guild,
address asset,
uint256 amount
) external returns (uint256 currentCollateralInVault);
/**
* @notice Estimates max a user can deposit. Analyzes business logic + returns errors if collateral is locked, etc.
* @dev
* @param guild The address of the guild
* @param asset collateral asset to be deposited as collateral
* @param user user that will deposit collateral
* @return maxCollateralDeposit max amount that can be deposited.
**/
function quoteMaxDeposit(
address guild,
address asset,
address user
) external returns (uint256 maxCollateralDeposit);
/**
* @notice Estimates max collateral a user can withdraw. Analyzes business logic + returns errors if collateral is locked, etc.
* @dev business logic included whether user's health goes < 1
* @param guild The address of the guild
* @param asset collateral asset to be deposited as collateral
* @param user user that will deposit collateral
* @return maxCollateralWithdraw max amount that can be withdrawn.
**/
function quoteMaxWithdaw(
address guild,
address asset,
address user
) external returns (uint256 maxCollateralWithdraw);
/**
* @notice Estimates max ztoken in and money out for a swapZTokenForMoney call
* @dev will analyze user debt mint capacity + dex liquidity
* @param guild The address of the guild
* @param user user that will be executing the swap
* @param sqrtPriceLimitX96 Price limit of swap
* @return maxFullZTokenIn max ztoken amount that can be taken in. This considers both zTokens currently in the wallet, as well as maximum debt account can take (ie, max new zTokens that can be minted)
* @return maxFullMoneyOut max money amount that can be taken out. This considers both zTokens currently in the wallet, as well as maximum debt account can take (ie, max new zTokens that can be minted)
* @return maxLimitZTokenIn max ztoken amount that can be taken in. This only considers zTokens in wallet both zTokens currently in the wallet (ie, postion closeout without new debt issued).
* @return maxLimitMoneyOut max money amount that can be taken out. This only considers zTokens in wallet both zTokens currently in the wallet (ie, postion closeout without new debt issued).
**/
function quoteMaxSwapZTokenForMoney(
address guild,
address user,
uint160 sqrtPriceLimitX96
)
external
returns (
uint256 maxFullZTokenIn,
uint256 maxFullMoneyOut,
uint256 maxLimitZTokenIn,
uint256 maxLimitMoneyOut
);
/**
* @notice Estimates max ztoken in and money out for a swapZTokenForMoney call
* @dev will analyze user debt mint capacity + dex liquidity
* @dev For 'Full', will calculate zTokens obtained from swapping all the money in users wallet for zTokens, only limited by sqrtPriceLimitX96.
* @dev For 'Limit', will try and swap money in users wallet for zTokens, to cancel dToken amount, and also limited by sqrtPriceLimitX96.
* @param guild The address of the guild
* @param user user that will be executing the swap
* @param sqrtPriceLimitX96 Price limit of swap
* @return maxFullMoneyIn max money amount that can be taken in. This considers all money in the wallet, cancels existing debt, and issuance of new zTokens.
* @return maxFullZTokenOut max zToken amount that can be taken out. This considers all money in the wallet, cancels existing debt, and issuance of new zTokens. The returned value are the amount of zTokens from the swap, before debt cancellation.
* @return maxLimitMoneyIn max money amount that can be taken in. This is limited by money in the wallet, and returns the money needed to repay debt (without buying zTokens with surplus)
* @return maxLimitZTokenOut max zToken amount that can be taken out. This is limited by money in the wallet, and returns the money needed to repay debt (without buying zTokens with surplus)
**/
function quoteMaxSwapMoneyForZToken(
address guild,
address user,
uint160 sqrtPriceLimitX96
)
external
returns (
uint256 maxFullMoneyIn,
uint256 maxFullZTokenOut,
uint256 maxLimitMoneyIn,
uint256 maxLimitZTokenOut
);
/**
* @notice Returns current price (slot0) for the DEX associated with Guild's zToken
* @param guild The address of the guild
* @return sqrtPriceX96_ Price limit of swap
**/
function quoteCurrentSqrtPriceX96(address guild) external view returns (uint160 sqrtPriceX96_);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
/// @title UniswapQuoterV3 Interface
/// @notice Same as UniswapV3 QuoterV2 Interface, but always returns both estimated amountIn AND amountOut
/// @notice As well, has more verbose pass through reporting of Uniswap Errors (these are passed through instead of renaming as 'Unknown error')
/// @notice Supports quoting the calculated amounts from exact input or exact output swaps.
/// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap.
/// @dev These functions are not marked view because they rely on calling non-view functions and reverting
/// to compute the result. They are also not gas efficient and should not be called on-chain.
interface IUniswapQuoterV3 {
struct QuoteExactInputSingleParams {
address tokenIn;
address tokenOut;
uint256 amountIn;
uint24 fee;
uint160 sqrtPriceLimitX96;
}
/// @notice Returns the amount out received for a given exact input but for a swap of a single pool
/// @param params The params for the quote, encoded as `QuoteExactInputSingleParams`
/// tokenIn The token being swapped in
/// tokenOut The token being swapped out
/// fee The fee of the token pool to consider for the pair
/// amountIn The desired input amount
/// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap
/// @return amountInQuote The amount of input Token used for the swap given params (could be less than specified amount given dex liquidity or price limit)
/// @return amountOutQuote The amount of `tokenOut` that would be received from the swap given params
/// @return sqrtPriceX96After The sqrt price of the pool after the swap
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactInputSingle(QuoteExactInputSingleParams memory params)
external
returns (
uint256 amountInQuote,
uint256 amountOutQuote,
uint160 sqrtPriceX96After,
uint256 gasEstimate
);
struct QuoteExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint256 amount;
uint24 fee;
uint160 sqrtPriceLimitX96;
}
/// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool
/// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams`
/// tokenIn The token being swapped in
/// tokenOut The token being swapped out
/// fee The fee of the token pool to consider for the pair
/// amountOut The desired output amount
/// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap
/// @return amountInQuote The amount required as the input for the swap in order to receive `amountOut` or reach price limit
/// @return amountOutQuote The amount expected at output from the swap given params (could be less than specified amount given dex liquidity or price limit)
/// @return sqrtPriceX96After The sqrt price of the pool after the swap
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params)
external
returns (
uint256 amountInQuote,
uint256 amountOutQuote,
uint160 sqrtPriceX96After,
uint256 gasEstimate
);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;
import {Errors} from '../helpers/Errors.sol';
import {DataTypes} from '../types/DataTypes.sol';
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: collateral is active
//bit 57-115: reserved
//bit 116-151: supply cap in whole tokens, supplyCap == 0 => no cap
//bit 152-167: liquidation protocol fee
//bit 168-255: reserved
/**
* @title CollateralConfiguration library
* @author Amorphous, inspired by AAVE v3
* @notice Handles the collateral configuration (not storage optimized)
*/
library CollateralConfiguration {
uint256 internal constant LTV_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000; // prettier-ignore
uint256 internal constant LIQUIDATION_THRESHOLD_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF; // prettier-ignore
uint256 internal constant LIQUIDATION_BONUS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF; // prettier-ignore
uint256 internal constant DECIMALS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF; // prettier-ignore
uint256 internal constant ACTIVE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF; // prettier-ignore
uint256 internal constant FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; // prettier-ignore
uint256 internal constant PAUSED_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFF; // prettier-ignore
uint256 internal constant USER_SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore
uint256 internal constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore
uint256 internal constant LIQUIDATION_PROTOCOL_FEE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore
/// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed
uint256 internal constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16;
uint256 internal constant LIQUIDATION_BONUS_START_BIT_POSITION = 32;
uint256 internal constant COLLATERAL_DECIMALS_START_BIT_POSITION = 48;
uint256 internal constant IS_ACTIVE_START_BIT_POSITION = 56;
uint256 internal constant IS_FROZEN_START_BIT_POSITION = 57;
uint256 internal constant IS_PAUSED_START_BIT_POSITION = 60;
uint256 internal constant USER_SUPPLY_CAP_START_BIT_POSITION = 80;
uint256 internal constant SUPPLY_CAP_START_BIT_POSITION = 116;
uint256 internal constant LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION = 152;
uint256 internal constant MAX_VALID_LTV = 65535;
uint256 internal constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535;
uint256 internal constant MAX_VALID_LIQUIDATION_BONUS = 65535;
uint256 internal constant MAX_VALID_DECIMALS = 255;
uint256 internal constant MAX_VALID_USER_SUPPLY_CAP = 68719476735;
uint256 internal constant MAX_VALID_SUPPLY_CAP = 68719476735;
uint256 internal constant MAX_VALID_LIQUIDATION_PROTOCOL_FEE = 65535;
uint16 public constant MAX_COLLATERALS_COUNT = 128;
/**
* @notice Sets the Loan to Value of the collateral
* @param self The collateral configuration
* @param ltv The new ltv
**/
function setLtv(DataTypes.CollateralConfigurationMap memory self, uint256 ltv) internal pure {
require(ltv <= MAX_VALID_LTV, Errors.INVALID_LTV);
self.data = (self.data & LTV_MASK) | ltv;
}
/**
* @notice Gets the Loan to Value of the collateral
* @param self The collateral configuration
* @return The loan to value
**/
function getLtv(DataTypes.CollateralConfigurationMap memory self) internal pure returns (uint256) {
return self.data & ~LTV_MASK;
}
/**
* @notice Sets the liquidation threshold of the collateral
* @param self The collateral configuration
* @param threshold The new liquidation threshold
**/
function setLiquidationThreshold(DataTypes.CollateralConfigurationMap memory self, uint256 threshold)
internal
pure
{
require(threshold <= MAX_VALID_LIQUIDATION_THRESHOLD, Errors.INVALID_LIQ_THRESHOLD);
self.data = (self.data & LIQUIDATION_THRESHOLD_MASK) | (threshold << LIQUIDATION_THRESHOLD_START_BIT_POSITION);
}
/**
* @notice Gets the liquidation threshold of the collateral
* @param self The collateral configuration
* @return The liquidation threshold
**/
function getLiquidationThreshold(DataTypes.CollateralConfigurationMap memory self) internal pure returns (uint256) {
return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION;
}
/**
* @notice Sets the liquidation bonus of the collateral
* @param self The collateral configuration
* @param bonus The new liquidation bonus
**/
function setLiquidationBonus(DataTypes.CollateralConfigurationMap memory self, uint256 bonus) internal pure {
require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.INVALID_LIQ_BONUS);
self.data = (self.data & LIQUIDATION_BONUS_MASK) | (bonus << LIQUIDATION_BONUS_START_BIT_POSITION);
}
/**
* @notice Gets the liquidation bonus of the collateral
* @param self The collateral configuration
* @return The liquidation bonus
**/
function getLiquidationBonus(DataTypes.CollateralConfigurationMap memory self) internal pure returns (uint256) {
return (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION;
}
/**
* @notice Sets the decimals of the underlying asset of the collateral
* @param self The collateral configuration
* @param decimals The decimals
**/
function setDecimals(DataTypes.CollateralConfigurationMap memory self, uint256 decimals) internal pure {
require(decimals <= MAX_VALID_DECIMALS, Errors.INVALID_DECIMALS);
self.data = (self.data & DECIMALS_MASK) | (decimals << COLLATERAL_DECIMALS_START_BIT_POSITION);
}
/**
* @notice Gets the decimals of the underlying asset of the collateral
* @param self The collateral configuration
* @return The decimals of the asset
**/
function getDecimals(DataTypes.CollateralConfigurationMap memory self) internal pure returns (uint256) {
return (self.data & ~DECIMALS_MASK) >> COLLATERAL_DECIMALS_START_BIT_POSITION;
}
/**
* @notice Sets the active state of the collateral
* @param self The collateral configuration
* @param active The active state
**/
function setActive(DataTypes.CollateralConfigurationMap memory self, bool active) internal pure {
self.data = (self.data & ACTIVE_MASK) | (uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION);
}
/**
* @notice Gets the active state of the collateral
* @param self The collateral configuration
* @return The active state
**/
function getActive(DataTypes.CollateralConfigurationMap memory self) internal pure returns (bool) {
return (self.data & ~ACTIVE_MASK) != 0;
}
/**
* @notice Sets the frozen state of the reserve
* @param self The reserve configuration
* @param frozen The frozen state
**/
function setFrozen(DataTypes.CollateralConfigurationMap memory self, bool frozen) internal pure {
self.data = (self.data & FROZEN_MASK) | (uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION);
}
/**
* @notice Gets the frozen state of the reserve
* @param self The reserve configuration
* @return The frozen state
**/
function getFrozen(DataTypes.CollateralConfigurationMap memory self) internal pure returns (bool) {
return (self.data & ~FROZEN_MASK) != 0;
}
/**
* @notice Sets the paused state of the reserve
* @param self The reserve configuration
* @param paused The paused state
**/
function setPaused(DataTypes.CollateralConfigurationMap memory self, bool paused) internal pure {
self.data = (self.data & PAUSED_MASK) | (uint256(paused ? 1 : 0) << IS_PAUSED_START_BIT_POSITION);
}
/**
* @notice Gets the paused state of the reserve
* @param self The reserve configuration
* @return The paused state
**/
function getPaused(DataTypes.CollateralConfigurationMap memory self) internal pure returns (bool) {
return (self.data & ~PAUSED_MASK) != 0;
}
/**
* @notice Sets the supply cap of the collateral
* @param self The collateral configuration
* @param supplyCap The supply cap
* @dev supplyCap at guild level encoded with 0 decimal places (e.g, 1 -> 1 token in collateral's own unit)
**/
function setSupplyCap(DataTypes.CollateralConfigurationMap memory self, uint256 supplyCap) internal pure {
require(supplyCap <= MAX_VALID_SUPPLY_CAP, Errors.INVALID_SUPPLY_CAP);
self.data = (self.data & SUPPLY_CAP_MASK) | (supplyCap << SUPPLY_CAP_START_BIT_POSITION);
}
/**
* @notice Gets the supply cap of the collateral
* @param self The collateral configuration
* @return The supply cap
* @dev supplyCap at guild level encoded with 0 decimal places (e.g, 1 -> 1 token in collateral's own unit)
**/
function getSupplyCap(DataTypes.CollateralConfigurationMap memory self) internal pure returns (uint256) {
return (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION;
}
/**
* @notice Sets the user supply cap of the collateral (wallet level)
* @param self The collateral configuration
* @param supplyCap The supply cap
* @dev supplyCap at user level encoded with 2 decimal places (e.g, 100 -> 1 token in collateral's own unit)
**/
function setUserSupplyCap(DataTypes.CollateralConfigurationMap memory self, uint256 supplyCap) internal pure {
require(supplyCap <= MAX_VALID_USER_SUPPLY_CAP, Errors.INVALID_SUPPLY_CAP);
self.data = (self.data & USER_SUPPLY_CAP_MASK) | (supplyCap << USER_SUPPLY_CAP_START_BIT_POSITION);
}
/**
* @notice Gets the user supply cap of the collateral (wallet level)
* @param self The collateral configuration
* @return The supply cap
* @dev supplyCap at user level encoded with 2 decimal places (e.g, 100 -> 1 token in collateral's own unit)
**/
function getUserSupplyCap(DataTypes.CollateralConfigurationMap memory self) internal pure returns (uint256) {
return (self.data & ~USER_SUPPLY_CAP_MASK) >> USER_SUPPLY_CAP_START_BIT_POSITION;
}
/**
* @notice Sets the liquidation protocol fee of the collateral
* @param self The collateral configuration
* @param liquidationProtocolFee The liquidation protocol fee
**/
function setLiquidationProtocolFee(DataTypes.CollateralConfigurationMap memory self, uint256 liquidationProtocolFee)
internal
pure
{
require(liquidationProtocolFee <= MAX_VALID_LIQUIDATION_PROTOCOL_FEE, Errors.INVALID_LIQUIDATION_PROTOCOL_FEE);
self.data =
(self.data & LIQUIDATION_PROTOCOL_FEE_MASK) |
(liquidationProtocolFee << LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION);
}
/**
* @dev Gets the liquidation protocol fee
* @param self The collateral configuration
* @return The liquidation protocol fee
**/
function getLiquidationProtocolFee(DataTypes.CollateralConfigurationMap memory self)
internal
pure
returns (uint256)
{
return (self.data & ~LIQUIDATION_PROTOCOL_FEE_MASK) >> LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION;
}
/**
* @notice Gets the configuration flags of the collateral
* @param self The collateral configuration
* @return The state flag representing active
* @return The state flag representing frozen
* @return The state flag representing paused
**/
function getFlags(DataTypes.CollateralConfigurationMap memory self)
internal
pure
returns (
bool,
bool,
bool
)
{
uint256 dataLocal = self.data;
return ((dataLocal & ~ACTIVE_MASK) != 0, (dataLocal & ~FROZEN_MASK) != 0, (dataLocal & ~PAUSED_MASK) != 0);
}
/**
* @notice Gets the configuration parameters of the collateral from storage
* @param self The collateral configuration
* @return The state param representing ltv
* @return The state param representing liquidation threshold
* @return The state param representing liquidation bonus
* @return The state param representing collateral decimals
**/
function getParams(DataTypes.CollateralConfigurationMap memory self)
internal
pure
returns (
uint256,
uint256,
uint256,
uint256
)
{
uint256 dataLocal = self.data;
return (
dataLocal & ~LTV_MASK,
(dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION,
(dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION,
(dataLocal & ~DECIMALS_MASK) >> COLLATERAL_DECIMALS_START_BIT_POSITION
);
}
/**
* @notice Gets the caps parameters of the collateral from storage
* @param self The collateral configuration
* @return The state param representing supply cap.
* @return The state param representing user supply cap.
**/
function getCaps(DataTypes.CollateralConfigurationMap memory self) internal pure returns (uint256, uint256) {
uint256 dataLocal = self.data;
return (
(dataLocal & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION,
(dataLocal & ~USER_SUPPLY_CAP_MASK) >> USER_SUPPLY_CAP_START_BIT_POSITION
);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.17;
/**
* @title Errors library
* @author Tazz Labs
* @notice Defines the error messages emitted by the different contracts of the Tazz protocol
*/
library Errors {
string public constant LOCKED = '0'; // 'Guild is locked'
string public constant NOT_CONTRACT = '1'; // 'Address is not a contract'
string public constant AMOUNT_NEED_TO_BE_GREATER = '2'; // 'A greater amount needed for action'
string public constant TRANSFER_FAIL = '3'; // 'Failed to transfer'
string public constant NOT_APPROVED = '4'; // 'Not approved'
string public constant NOT_ENOUGH_BALANCE = '5'; // 'Not enough balance'
string public constant ASSET_NEEDS_TO_BE_APPROVED = '6'; // 'Asset needs to be whitelisted'
string public constant OPERATION_NOT_SUPPORTED = '7'; // 'Operation not supported'
string public constant OPERATION_NOT_AUTHORIZED = '8'; // 'Operation not authorized, not enough permissions for the operation'
string public constant REFINANCE_INVALID_TIMESTAMP = '9'; // 'The current block has a timestamp that is older vs that last refinance'
string public constant NOT_ENOUGH_COLLATERAL = '10'; // 'Not enough collateral'
string public constant AMOUNT_NEED_TO_MORE_THAN_ZERO = '11'; // '"Your asset amount must be greater then you are trying to deposit"'
string public constant CANNOT_BURN_MORE_THAN_CURRENT_DEBT = '12'; // "Amount exceeds current debt level"
string public constant UNHEALTHY_POSITION = '13'; // Users position is currently higher than liquidation threshold
string public constant CANNOT_LIQUIDATE_HEALTHY = '14'; // Cannot liqudate healthy users position
string public constant WITHDRAWAL_AMOUNT_EXCEEDS_AVAILABLE = '15'; // Amount exceeds max withdrawable amount
string public constant HELPER_INSUFFICIENT_FUNDS = '16'; // Internal error, insufficient funds to place on dex as requested
string public constant AMOUNT_NEEDS_TO_EQUAL_COLLATERAL_VALUE = '17'; // Amount needs to be the same to exchange money for collateral
string public constant AMOUNT_NEEDS_TO_LOWER_THAN_DEBT = '18'; // Amount needs to be lower than current debt level
string public constant NOT_ENOUGH_Z_TOKENS = '19'; // "Not enough zTokens in account"
string public constant PRICE_LIMIT_OUT_OF_BOUNDS = '20'; // "PerpetualDebt.sol - price limit initialization out of bounds"
string public constant PRICE_LIMIT_ERROR = '21'; // "PerpetualDebt.sol - price limit min larger than max"
string public constant ACL_ADMIN_CANNOT_BE_ZERO = '22'; // "ACLManager.sol - cannot set a 0x0 address as admin"
string public constant INVALID_ADDRESSES_PROVIDER_ID = '23'; // "GuildAddressesProviderRegistry.sol - cannot set ID 0"
string public constant ADDRESSES_PROVIDER_NOT_REGISTERED = '24'; // 'GuildAddressesProviderRegistry.sol - Guild addresses provider is not registered'
string public constant INVALID_ADDRESSES_PROVIDER = '25'; // 'The address of the guild addresses provider is invalid'
string public constant ADDRESSES_PROVIDER_ALREADY_ADDED = '26'; // 'GuildAddressesProviderRegistry.sol - Reserve has already been added to collateral list'
string public constant CALLER_NOT_GUILD_ADMIN = '27'; // 'The caller of the function is not a guild admin'
string public constant CALLER_NOT_EMERGENCY_ADMIN = '28'; // 'The caller of the function is not an emergency admin'
string public constant CALLER_NOT_GUILD_OR_EMERGENCY_ADMIN = '29'; // 'The caller of the function is not a guild or emergency admin'
string public constant CALLER_NOT_RISK_OR_GUILD_ADMIN = '30'; // 'The caller of the function is not a risk or guild admin'
string public constant TRANSFER_INVALID_SENDER = '31'; // 'ERC20: Cannot send from address 0'
string public constant TRANSFER_INVALID_RECEIVER = '32'; // 'ERC20: Cannot send to address 0'
string public constant CALLER_MUST_BE_GUILD = '33'; // 'The caller of the function must be the guild'
string public constant GUILD_ADDRESSES_DO_NOT_MATCH = '34'; // 'Incorrect Guild address when initializing token'
string public constant PERPETUAL_DEBT_ALREADY_INITIALIZED = '35'; // 'Perpetual Debt structure already initialized'
string public constant DEX_ORACLE_ALREADY_INITIALIZED = '36'; // 'Dex Oracle structure already initialized'
string public constant DEX_ORACLE_POOL_NOT_INITIALIZED = '37'; // 'Dex pool should be initialized before Dex oracle'
string public constant CALLER_NOT_GUILD_CONFIGURATOR = '38'; // 'The caller of the function is not the guild configurator contract'
string public constant COLLATERAL_ALREADY_ADDED = '39'; // 'Collateral has already been added to collateral list'
string public constant NO_MORE_COLLATERALS_ALLOWED = '40'; // 'Maximum amount of collaterals in the guild reached'
string public constant INVALID_LTV = '41'; // 'Invalid ltv parameter for the collateral'
string public constant INVALID_LIQ_THRESHOLD = '42'; // 'Invalid liquidity threshold parameter for the collateral'
string public constant INVALID_LIQ_BONUS = '43'; // 'Invalid liquidity bonus parameter for the collateral'
string public constant INVALID_DECIMALS = '44'; // 'Invalid decimals parameter of the underlying asset of the collateral'
string public constant INVALID_SUPPLY_CAP = '45'; // 'Invalid supply cap for the collateral'
string public constant INVALID_LIQUIDATION_PROTOCOL_FEE = '46'; // 'Invalid liquidation protocol fee for the collateral'
string public constant ZERO_ADDRESS_NOT_VALID = '47'; // 'Zero address not valid'
string public constant COLLATERAL_NOT_LISTED = '48'; // 'Collateral is not listed (not initialized or has been dropped)'
string public constant COLLATERAL_BALANCE_IS_ZERO = '49'; // 'The collateral balance is 0'
string public constant LTV_VALIDATION_FAILED = '50'; // 'Ltv validation failed'
string public constant HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '51'; // 'Health factor is lower than the liquidation threshold'
string public constant COLLATERAL_CANNOT_COVER_NEW_BORROW = '52'; // 'There is not enough collateral to cover a new borrow'
string public constant INVALID_COLLATERAL_PARAMS = '53'; //'Invalid risk parameters for the collateral'
string public constant INVALID_AMOUNT = '54'; // 'Amount must be greater than 0'
string public constant NOT_ENOUGH_AVAILABLE_USER_BALANCE = '55'; //'User cannot withdraw more than the available balance'
string public constant COLLATERAL_INACTIVE = '56'; //'Action requires an active collateral'
string public constant SUPPLY_CAP_EXCEEDED = '57'; // 'Supply cap is exceeded'
string public constant ACL_MANAGER_NOT_SET = '58'; // 'The ACL Manager has not been set for the addresses provider'
string public constant ARRAY_SIZE_MISMATCH = '59'; // 'The arrays are of different sizes'
string public constant DEX_POOL_DOES_NOT_CONTAIN_ASSET_PAIR = '60'; // 'The dex pool does not contain pricing info for token pair'
string public constant ASSET_NOT_TRACKED_IN_ORACLE = '61'; // 'The asset is not tracked by the pricing oracle'
string public constant INVALID_MINT_CAP = '62'; // 'Invalid mint cap for the perpetual debt'
string public constant DEBT_PAUSED = '63'; // 'Action requires a non-paused debt'
string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '64'; // 'Action requires health factor to be below liquidation threshold'
string public constant COLLATERAL_CANNOT_BE_LIQUIDATED = '65'; // 'The collateral chosen cannot be liquidated'
string public constant USER_HAS_NO_DEBT = '66'; // 'User has no debt to be liquidated'
string public constant INSUFFICIENT_CREDIT_DELEGATION = '67'; // 'Insufficient credit delegation to 3rd party borrower'
string public constant INSUFFICIENT_TOKENIN_FOR_TARGET_TOKENOUT = '68'; // 'Insufficient tokenIn to swap for target tokenOut value'
string public constant COLLATERAL_FROZEN = '69'; // 'Action cannot be performed because the collateral is frozen'
string public constant COLLATERAL_PAUSED = '70'; // 'Action cannot be performed because the collateral is paused'
string public constant PERPETUAL_DEBT_FROZEN = '71'; // 'Action cannot be performed because the perpetual debt is frozen'
string public constant PERPETUAL_DEBT_PAUSED = '72'; // 'Action cannot be performed because the perpetual debt is paused'
string public constant TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE = '73'; // 'Account does not have sufficient allowance to transfer on behalf of other account'
string public constant NEGATIVE_ALLOWANCE_NOT_ALLOWED = '74'; // 'Cannot allocate negative value for allowances'
string public constant INSUFFICIENT_BALANCE_TO_BURN = '75'; // 'Cannot burn more than amount in balance'
string public constant TRANSFER_EXCEEDS_BALANCE = '76'; // 'ERC20: Transfer amount exceeds balance'
string public constant PERPETUAL_DEBT_CAP_EXCEEDED = '77'; // 'Perpetual debt cap is exceeded'
string public constant NEGATIVE_DELEGATION_NOT_ALLOWED = '78'; // 'Cannot allocate negative value for delegation allowances'
string public constant OWNABLE_ONLY_OWNER = 'Ownable: caller is not the owner';
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;
import {WadRayMath} from './WadRayMath.sol';
import {DataTypes} from '../types/DataTypes.sol';
/**
* @title DebtMath library
* @author Tazz Labs
* @notice Provides approximations for Perpetual Debt calculations
*/
library DebtMath {
using WadRayMath for uint256;
//returns approximation of rate = -beta * ln(price)
//Taylor expansion as per whitepaper
function calculateApproxRate(uint256 _beta, uint256 _price) internal pure returns (int256 rate_) {
//separate calculation depending on whether (1-_price) is positive or negative
if (_price <= WadRayMath.ray()) {
uint256 rate1 = WadRayMath.ray() - _price;
uint256 rate2 = rate1.rayMul(rate1);
uint256 rate3 = rate2.rayMul(rate1);
uint256 rate4 = rate2.rayMul(rate2);
uint256 rate5 = rate3.rayMul(rate2);
uint256 rate6 = rate3.rayMul(rate3);
rate1 = rate1 + rate2 / 2 + rate3 / 3 + rate4 / 4 + rate5 / 5 + rate6 / 6;
rate_ = int256(rate1.rayMul(_beta));
} else {
uint256 rate1 = _price - WadRayMath.ray();
uint256 rate2 = rate1.rayMul(rate1);
uint256 rate3 = rate2.rayMul(rate1);
uint256 rate4 = rate2.rayMul(rate2);
uint256 rate5 = rate3.rayMul(rate2);
uint256 rate6 = rate3.rayMul(rate3);
rate1 = rate1 - rate2 / 2 + rate3 / 3 - rate4 / 4 + rate5 / 5 - rate6 / 6;
rate_ = -int256(rate1.rayMul(_beta));
}
}
//Taylor expansion to calculate compounding rate update as per whitepaper
function calculateApproxNotionalUpdate(int256 _rate, uint256 _timeDelta)
internal
pure
returns (uint256 updateMultiplier_)
{
_rate = _rate * int256(_timeDelta);
if (_rate >= 0) {
uint256 rate1 = uint256(_rate);
uint256 rate2 = rate1.rayMul(rate1) / 2;
uint256 rate3 = rate2.rayMul(rate1) / 3;
updateMultiplier_ = WadRayMath.ray() + rate1 + rate2 + rate3;
} else {
uint256 rate1 = uint256(-_rate);
uint256 rate2 = rate1.rayMul(rate1) / 2;
uint256 rate3 = rate2.rayMul(rate1) / 3;
updateMultiplier_ = WadRayMath.ray() - rate1 + rate2 - rate3;
}
}
}// SPDX-License-Identifier: MIT
// Notice: license change Jan 27, 2023
pragma solidity 0.8.17;
/**
* @title PercentageMath library
* @author Aave
* @notice Provides functions to perform percentage calculations
* @dev Percentages are defined by default with 2 decimals of precision (100.00). The precision is indicated by PERCENTAGE_FACTOR
* @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.
**/
library PercentageMath {
// Maximum percentage factor (100.00%)
uint256 internal constant PERCENTAGE_FACTOR = 1e4;
// Half percentage factor (50.00%)
uint256 internal constant HALF_PERCENTAGE_FACTOR = 0.5e4;
/**
* @notice Executes a percentage multiplication
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param value The value of which the percentage needs to be calculated
* @param percentage The percentage of the value to be calculated
* @return result value percentmul percentage
**/
function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256 result) {
// to avoid overflow, value <= (type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage
assembly {
if iszero(or(iszero(percentage), iszero(gt(value, div(sub(not(0), HALF_PERCENTAGE_FACTOR), percentage))))) {
revert(0, 0)
}
result := div(add(mul(value, percentage), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR)
}
}
/**
* @notice Executes a percentage division
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param value The value of which the percentage needs to be calculated
* @param percentage The percentage of the value to be calculated
* @return result value percentdiv percentage
**/
function percentDiv(uint256 value, uint256 percentage) internal pure returns (uint256 result) {
// to avoid overflow, value <= (type(uint256).max - halfPercentage) / PERCENTAGE_FACTOR
assembly {
if or(
iszero(percentage),
iszero(iszero(gt(value, div(sub(not(0), div(percentage, 2)), PERCENTAGE_FACTOR))))
) {
revert(0, 0)
}
result := div(add(mul(value, PERCENTAGE_FACTOR), div(percentage, 2)), percentage)
}
}
}// SPDX-License-Identifier: MIT
// Notice: license change Jan 27, 2023
pragma solidity ^0.8.0;
/**
* @title WadRayMath library
* @author Aave (not rayPow)
* @notice Provides functions to perform calculations with Wad and Ray units
* @dev Provides mul and div function for wads (decimal numbers with 18 digits of precision) and rays (decimal numbers
* with 27 digits of precision)
* @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.
*/
library WadRayMath {
// HALF_WAD and HALF_RAY expressed with extended notation as constant with operations are not supported in Yul assembly
uint256 internal constant WAD = 1e18;
uint256 internal constant HALF_WAD = 0.5e18;
uint256 internal constant RAY = 1e27;
uint256 internal constant HALF_RAY = 0.5e27;
uint256 internal constant WAD_RAY_RATIO = 1e9;
function ray() internal pure returns (uint256) {
return RAY;
}
function wad() internal pure returns (uint256) {
return WAD;
}
function halfRay() internal pure returns (uint256) {
return HALF_RAY;
}
function halfWad() internal pure returns (uint256) {
return HALF_WAD;
}
/**
* @dev Multiplies two wad, rounding half up to the nearest wad
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Wad
* @param b Wad
* @return c = a*b, in wad
*/
function wadMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
// to avoid overflow, a <= (type(uint256).max - HALF_WAD) / b
assembly {
if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_WAD), b))))) {
revert(0, 0)
}
c := div(add(mul(a, b), HALF_WAD), WAD)
}
}
/**
* @dev Divides two wad, rounding half up to the nearest wad
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Wad
* @param b Wad
* @return c = a/b, in wad
*/
function wadDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
// to avoid overflow, a <= (type(uint256).max - halfB) / WAD
assembly {
if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), WAD))))) {
revert(0, 0)
}
c := div(add(mul(a, WAD), div(b, 2)), b)
}
}
/**
* @notice Multiplies two ray, rounding half up to the nearest ray
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Ray
* @param b Ray
* @return c = a raymul b
*/
function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
// to avoid overflow, a <= (type(uint256).max - HALF_RAY) / b
assembly {
if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) {
revert(0, 0)
}
c := div(add(mul(a, b), HALF_RAY), RAY)
}
}
/**
* @notice Divides two ray, rounding half up to the nearest ray
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Ray
* @param b Ray
* @return c = a raydiv b
*/
function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
// to avoid overflow, a <= (type(uint256).max - halfB) / RAY
assembly {
if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), RAY))))) {
revert(0, 0)
}
c := div(add(mul(a, RAY), div(b, 2)), b)
}
}
/**
* @dev Casts ray down to wad
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Ray
* @return b = a converted to wad, rounded half up to the nearest wad
*/
function rayToWad(uint256 a) internal pure returns (uint256 b) {
assembly {
b := div(a, WAD_RAY_RATIO)
let remainder := mod(a, WAD_RAY_RATIO)
if iszero(lt(remainder, div(WAD_RAY_RATIO, 2))) {
b := add(b, 1)
}
}
}
/**
* @dev Converts wad up to ray
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Wad
* @return b = a converted in ray
*/
function wadToRay(uint256 a) internal pure returns (uint256 b) {
// to avoid overflow, b/WAD_RAY_RATIO == a
assembly {
b := mul(a, WAD_RAY_RATIO)
if iszero(eq(div(b, WAD_RAY_RATIO), a)) {
revert(0, 0)
}
}
}
/**
* @dev Calculates x to the power of n (x^n)
* @dev Power calculated through a loop of binary powers. Not optimized.
* @param x ray
* @param n unsigned integer
* @return z x^n
**/
function rayPow(uint256 x, uint256 n) internal pure returns (uint256 z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rayMul(x, x);
if (n % 2 != 0) {
z = rayMul(z, x);
}
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;
import {IERC20Detailed} from '../../../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {FullMath} from '../../../dependencies/uniswap-v3-core/libraries/FullMath.sol';
import {TickMath} from '../../../dependencies/uniswap-v3-core/libraries/TickMath.sol';
/**
* @title X96Math library
* @author Tazz Labs
* @notice Math conversion for sqrt X96 ratios used by Uniswap
*/
library X96Math {
//@Dev - asset price returned in money units (with money Decimal places)
function getPriceFromSqrtX96(
address moneyToken,
address assetToken,
uint160 sqrtRatioX96
) internal view returns (uint256 price_) {
uint256 baseDecimals = IERC20Detailed(assetToken).decimals();
uint256 baseAmount = 10**baseDecimals;
return quoteFromSqrtPriceX96(baseAmount, sqrtRatioX96, assetToken, moneyToken);
}
//@dev code from https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/OracleLibrary.sol, getQuoteaTick function
// Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself
function quoteFromSqrtPriceX96(
uint256 baseAmount,
uint160 sqrtPriceX96,
address baseToken,
address quoteToken
) internal pure returns (uint256 quoteAmount) {
if (sqrtPriceX96 <= type(uint128).max) {
uint256 ratioX192 = uint256(sqrtPriceX96) * sqrtPriceX96;
quoteAmount = baseToken < quoteToken
? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)
: FullMath.mulDiv(1 << 192, baseAmount, ratioX192);
} else {
uint256 ratioX128 = FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, 1 << 64);
quoteAmount = baseToken < quoteToken
? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)
: FullMath.mulDiv(1 << 128, baseAmount, ratioX128);
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {ILiabilityToken} from '../../../interfaces/ILiabilityToken.sol';
import {IAssetToken} from '../../../interfaces/IAssetToken.sol';
library DataTypes {
//@dev Uniswap requires the address of token0 < token1.
//@dev All oracle prices by uniswap are given as a ratio of token0/token1.
struct DexPoolData {
address token0;
address token1;
uint24 fee;
bool moneyIsToken0; //indicates whether token0 is the money token
address poolAddress;
}
struct DexOracleData {
address dexFactory; // Uniswap v3 factory
DexPoolData dex; // Dex pool details
uint256 currentPrice;
uint256 TWAPPrice;
uint256 lastTWAPObservationTime; // Timestamp of last oracle consult for TWAP price
uint256 lastCurrentObservationTime; // Timestamp of last oracle consult for current price
int56 lastTWAPTickCumulative; //For Uniswap v3.0 TWAP calculation
uint256 lastTWAPTimeDelta; //recording of last time delta
}
struct PerpetualDebtData {
//stores the perpetual debt configuration
PerpDebtConfigurationMap configuration;
//Token addresses
IAssetToken zToken;
ILiabilityToken dToken;
IERC20 money;
//beta multiplier, indicating duration of debt instrument
uint256 beta;
//Dex Oracle
DexOracleData dexOracle;
//last refinance block number
uint256 lastRefinance;
//Price limit variables when refinancing
uint256 notionalPriceMax; //[ray]
uint256 notionalPriceMin; //[ray]
}
struct CollateralData {
//stores the collateral configuration
CollateralConfigurationMap configuration;
//the id of the collateral. Represents the position in the list of the active ERC20 collaterals
uint16 id;
//map of user balances (for a given collateral)
mapping(address => uint256) balances;
//total collateral balance held by the Guild
uint256 totalBalance;
}
struct CollateralConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: collateral is active
//bit 57-115: unused
//bit 116-151: supply cap in whole tokens, supplyCap == 0 => no cap
//bit 152-167: liquidation protocol fee
//bit 168-255: unused
uint256 data;
}
struct PerpDebtConfigurationMap {
//bit 0: perpetual debt is paused (no mint, no burn/distribute, no liquidate, no refinance)
//bit 1: perpetual debt is frozen (no mint, yes burn/distribute, yes liquidate, yes refinance)
//bit 2-37: borrow cap in whole tokens, borrowCap ==0 => no cap
//bit 38-255: unused
uint256 data;
}
struct ExecuteDepositParams {
address asset;
uint256 amount;
address onBehalfOf;
}
struct ExecuteWithdrawParams {
address asset;
uint256 amount;
address to;
uint256 collateralsCount;
address oracle;
}
struct ExecuteSupplyParams {
address collateral;
uint256 amount;
address user;
}
struct ExecuteBorrowParams {
address user;
address onBehalfOf;
uint256 amount;
uint256 collateralsCount;
address oracle;
// address priceOracleSentinel;
}
struct ExecuteRepayParams {
address onBehalfOf;
uint256 amount;
}
struct CalculateUserAccountDataParams {
uint256 collateralsCount;
address user;
address oracle;
}
struct ValidateBorrowParams {
address user;
uint256 amount;
uint256 collateralsCount;
address oracle;
}
struct ValidateBorrowLocalVars {
uint256 currentLtv;
uint256 collateralNeededInBaseCurrency;
uint256 userCollateralInBaseCurrency;
uint256 userDebtInBaseCurrency;
uint256 availableLiquidity;
uint256 healthFactor;
uint256 totalDebt;
uint256 totalSupplyVariableDebt;
uint256 reserveDecimals;
uint256 borrowCap;
uint256 amountInBaseCurrency;
address eModePriceSource;
address siloedBorrowingAddress;
}
struct ExecuteLiquidationCallParams {
uint256 collateralsCount;
uint256 debtNotionalToCover;
address collateralAsset;
address user;
bool receiveCollateral;
address priceOracle;
}
struct ValidateLiquidationCallParams {
uint256 totalDebtNotional;
uint256 healthFactor;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS =
0x000000000000000000636F6e736F6c652e6c6f67;
function _sendLogPayloadImplementation(bytes memory payload) internal view {
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
pop(
staticcall(
gas(),
consoleAddress,
add(payload, 32),
mload(payload),
0,
0
)
)
}
}
function _castToPure(
function(bytes memory) internal view fnIn
) internal pure returns (function(bytes memory) pure fnOut) {
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castToPure(_sendLogPayloadImplementation)(payload);
}
function log() internal pure {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_swapRouterAddress","type":"address"},{"internalType":"address","name":"_quoterAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"debtNotionalMintedInBaseCurrency","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"zTokensIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"moneyOut","type":"uint256"}],"name":"MintAndSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"debtNotionalBurnedInBaseCurrency","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"moneyIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"zTokensOut","type":"uint256"}],"name":"SwapAndBurn","type":"event"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"}],"name":"quoteCurrentSqrtPriceX96","outputs":[{"internalType":"uint160","name":"sqrtPriceX96_","type":"uint160"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"guild","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"quoteDeposit","outputs":[{"internalType":"uint256","name":"maxDepositAmount_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"guild","type":"address"}],"name":"quoteDexLiquidty","outputs":[{"internalType":"uint256","name":"moneyAmount","type":"uint256"},{"internalType":"uint256","name":"zTokenAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"guild","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"quoteMaxDeposit","outputs":[{"internalType":"uint256","name":"maxCollateralDeposit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"guild","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"name":"quoteMaxSwapMoneyForZToken","outputs":[{"internalType":"uint256","name":"maxFullMoneyIn","type":"uint256"},{"internalType":"uint256","name":"maxFullZTokenOut","type":"uint256"},{"internalType":"uint256","name":"maxLimitMoneyIn","type":"uint256"},{"internalType":"uint256","name":"maxLimitZTokenOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guild","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"name":"quoteMaxSwapZTokenForMoney","outputs":[{"internalType":"uint256","name":"maxFullZTokenIn","type":"uint256"},{"internalType":"uint256","name":"maxFullMoneyOut","type":"uint256"},{"internalType":"uint256","name":"maxLimitZTokenIn","type":"uint256"},{"internalType":"uint256","name":"maxLimitMoneyOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guild","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"quoteMaxWithdaw","outputs":[{"internalType":"uint256","name":"maxCollateralWithdraw","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"uint256","name":"_moneyInTarget","type":"uint256"},{"internalType":"uint160","name":"_sqrtPriceLimitX96","type":"uint160"}],"name":"quoteSwapExactMoneyForZToken","outputs":[{"internalType":"uint256","name":"debtNotionalBurnedInBaseCurrency_","type":"uint256"},{"internalType":"uint256","name":"moneyIn_","type":"uint256"},{"internalType":"uint256","name":"zTokenOut_","type":"uint256"},{"internalType":"uint256","name":"zTokenPriceBeforeSwap_","type":"uint256"},{"internalType":"uint256","name":"zTokenPriceAfterSwap_","type":"uint256"},{"internalType":"uint256","name":"gasEstimate_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"uint256","name":"_zTokenInTarget","type":"uint256"},{"internalType":"uint160","name":"_sqrtPriceLimitX96","type":"uint160"}],"name":"quoteSwapExactZTokenForMoney","outputs":[{"internalType":"uint256","name":"debtNotionalMintedInBaseCurrency_","type":"uint256"},{"internalType":"uint256","name":"zTokenIn_","type":"uint256"},{"internalType":"uint256","name":"moneyOut_","type":"uint256"},{"internalType":"uint256","name":"zTokenPriceBeforeSwap_","type":"uint256"},{"internalType":"uint256","name":"zTokenPriceAfterSwap_","type":"uint256"},{"internalType":"uint256","name":"gasEstimate_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"uint256","name":"_zTokenOutTarget","type":"uint256"},{"internalType":"uint160","name":"_sqrtPriceLimitX96","type":"uint160"}],"name":"quoteSwapMoneyForExactZToken","outputs":[{"internalType":"uint256","name":"debtNotionalBurnedInBaseCurrency_","type":"uint256"},{"internalType":"uint256","name":"moneyIn_","type":"uint256"},{"internalType":"uint256","name":"zTokenOut_","type":"uint256"},{"internalType":"uint256","name":"zTokenPriceBeforeSwap_","type":"uint256"},{"internalType":"uint256","name":"zTokenPriceAfterSwap_","type":"uint256"},{"internalType":"uint256","name":"gasEstimate_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"uint256","name":"_moneyOutTarget","type":"uint256"},{"internalType":"uint160","name":"_sqrtPriceLimitX96","type":"uint160"}],"name":"quoteSwapZTokenForExactMoney","outputs":[{"internalType":"uint256","name":"debtNotionalMintedInBaseCurrency_","type":"uint256"},{"internalType":"uint256","name":"zTokenIn_","type":"uint256"},{"internalType":"uint256","name":"moneyOut_","type":"uint256"},{"internalType":"uint256","name":"zTokenPriceBeforeSwap_","type":"uint256"},{"internalType":"uint256","name":"zTokenPriceAfterSwap_","type":"uint256"},{"internalType":"uint256","name":"gasEstimate_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"quoteUserAccountData","outputs":[{"components":[{"internalType":"uint256","name":"totalCollateralInBaseCurrency","type":"uint256"},{"internalType":"uint256","name":"totalDebtNotionalInBaseCurrency","type":"uint256"},{"internalType":"uint256","name":"availableBorrowsInBaseCurrency","type":"uint256"},{"internalType":"uint256","name":"currentLiquidationThreshold","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"uint256","name":"healthFactor","type":"uint256"},{"internalType":"uint256","name":"totalDebtNotional","type":"uint256"},{"internalType":"uint256","name":"availableBorrowsInZTokens","type":"uint256"},{"internalType":"uint256","name":"availableNotionalBorrows","type":"uint256"},{"internalType":"uint256","name":"zTokensToRepayDebt","type":"uint256"}],"internalType":"struct IGuild.userAccountDataStruc","name":"userAccountData","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guild","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"quoteWithdraw","outputs":[{"internalType":"uint256","name":"currentCollateralInVault","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"uint256","name":"_moneyIn","type":"uint256"},{"internalType":"uint256","name":"_zTokenOutMin","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint160","name":"_sqrtPriceLimitX96","type":"uint160"}],"name":"swapExactMoneyForZToken","outputs":[{"internalType":"uint256","name":"debtNotionalBurnedInBaseCurrency_","type":"uint256"},{"internalType":"uint256","name":"moneyIn_","type":"uint256"},{"internalType":"uint256","name":"zTokenOut_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"uint256","name":"_zTokenIn","type":"uint256"},{"internalType":"uint256","name":"_moneyOutMin","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint160","name":"_sqrtPriceLimitX96","type":"uint160"}],"name":"swapExactZTokenForMoney","outputs":[{"internalType":"uint256","name":"debtNotionalMintedInBaseCurrency_","type":"uint256"},{"internalType":"uint256","name":"zTokenIn_","type":"uint256"},{"internalType":"uint256","name":"moneyOut_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"uint256","name":"_ztokenOut","type":"uint256"},{"internalType":"uint256","name":"_moneyInMax","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint160","name":"_sqrtPriceLimitX96","type":"uint160"}],"name":"swapMoneyForExactZToken","outputs":[{"internalType":"uint256","name":"debtNotionalBurneInBaseCurrency_","type":"uint256"},{"internalType":"uint256","name":"moneyIn_","type":"uint256"},{"internalType":"uint256","name":"zTokenOut_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guildAddress","type":"address"},{"internalType":"uint256","name":"_moneyOut","type":"uint256"},{"internalType":"uint256","name":"_zTokenInMax","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint160","name":"_sqrtPriceLimitX96","type":"uint160"}],"name":"swapZTokenForExactMoney","outputs":[{"internalType":"uint256","name":"debtNotionalMintedInBaseCurrency_","type":"uint256"},{"internalType":"uint256","name":"zTokenIn_","type":"uint256"},{"internalType":"uint256","name":"moneyOut_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapQuoter","outputs":[{"internalType":"contract IUniswapQuoterV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60c06040523480156200001157600080fd5b5060405162004e2938038062004e29833981016040819052620000349162000069565b6001600160a01b039182166080521660a052620000a1565b80516001600160a01b03811681146200006457600080fd5b919050565b600080604083850312156200007d57600080fd5b62000088836200004c565b915062000098602084016200004c565b90509250929050565b60805160a051614cf962000130600039600081816102bc0152818161077701528181610996015281816112600152818161134f015281816125160152818161261401528181613341015261343e01526000818161031e015281816115c8015281816116610152818161175301528181611de501528181611e7c01528181611f0c01526120700152614cf96000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063638d641a116100ad578063cc741cbd11610071578063cc741cbd14610379578063eb2ef3781461038c578063ebe56e611461039f578063fd891e14146103b2578063fe75c700146103c557600080fd5b8063638d641a14610306578063735de9f7146103195780638488bbea14610340578063a2c90f4814610353578063c2a944251461036657600080fd5b8063439db753116100f4578063439db753146101d857806343a95d28146101eb5780634c5d75261461022b5780634db4a352146102b7578063549c78b0146102de57600080fd5b80630a5fb4d1146101265780632bb9ebd6146101565780633c57dd5d146101845780634019ac29146101a5575b600080fd5b610139610134366004614315565b6103d8565b6040516001600160a01b0390911681526020015b60405180910390f35b610169610164366004614332565b6104c2565b6040805193845260208401929092529082015260600161014d565b610197610192366004614388565b6104e8565b60405190815260200161014d565b6101b86101b33660046143c9565b6105c4565b60408051948552602085019390935291830152606082015260800161014d565b6101696101e6366004614332565b610a23565b6101fe6101f9366004614414565b610a38565b604080519687526020870195909552938501929092526060840152608083015260a082015260c00161014d565b61023e61023936600461444b565b610a66565b60405161014d9190600061014082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151818401525092915050565b6101397f000000000000000000000000000000000000000000000000000000000000000081565b6102f16102ec366004614315565b610b89565b6040805192835260208301919091520161014d565b610197610314366004614388565b610b9e565b6101397f000000000000000000000000000000000000000000000000000000000000000081565b6101fe61034e366004614414565b610cd7565b610169610361366004614332565b610cef565b6101fe610374366004614414565b610d04565b6101976103873660046143c9565b610d1c565b6101b861039a3660046143c9565b610fb2565b6101696103ad366004614332565b6113eb565b6101fe6103c0366004614414565b611400565b6101976103d33660046143c9565b611418565b6000808290506000816001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa15801561041f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044391906146db565b90508060a0015160200151608001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801561048f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b3919061479d565b50949998505050505050505050565b60008060006104d7600089888a338a8a61142d565b925092509250955095509592505050565b6040516370a0823160e01b81523360048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561052f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610553919061482f565b604051630c66612360e41b81526001600160a01b038581166004830152602482018590523360448301529192509085169063c66612309060640160006040518083038186803b1580156105a557600080fd5b505afa1580156105b9573d6000803e3d6000fd5b505050509392505050565b604080516080810182526000808252602082018190529181018290526060810182905281908190819087906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa158015610630573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065491906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a085015184015182015162ffffff1690870152805163098e1b4160e41b8152905160009b508b9a508a9950899850939450908616926398e1b410926004808401939192918290030181865afa1580156106dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107019190614848565b6040516370a0823160e01b81526001600160a01b038b8116600483015291909116906370a0823190602401602060405180830381865afa158015610749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076d919061482f565b9650861561085e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c6a5026a6040518060a0016040528085604001516001600160a01b0316815260200185600001516001600160a01b031681526020018a8152602001856060015162ffffff1681526020018b6001600160a01b03168152506040518263ffffffff1660e01b81526004016108139190614865565b6080604051808303816000875af1158015610832573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085691906148ae565b509198509650505b826001600160a01b031663d4267dee6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561089957600080fd5b505af11580156108ad573d6000803e3d6000fd5b5050604051632fe4a15f60e21b81526001600160a01b038c81166004830152600093508616915063bf92857c9060240161014060405180830381865afa1580156108fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f91906148ed565b9050806101200151871161093857879550869450610a16565b61012081015115610a16576040805160a081018252848201516001600160a01b0390811682528551811660208301526101208401518284015260608087015162ffffff16908301528b811660808301529151635e90b82560e11b81527f00000000000000000000000000000000000000000000000000000000000000009092169163bd21704a916109cb91600401614865565b6080604051808303816000875af11580156109ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0e91906148ae565b509197509550505b5050505093509350935093565b60008060006104d7600189888a338a8a611b77565b600080600080600080610a5060018a60008b8b6122fe565b949e939d50919b50995097509095509350505050565b610abc604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000839050806001600160a01b031663d4267dee6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610afc57600080fd5b505af1158015610b10573d6000803e3d6000fd5b5050604051632fe4a15f60e21b81526001600160a01b0386811660048301528416925063bf92857c915060240161014060405180830381865afa158015610b5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7f91906148ed565b9150505b92915050565b600080610b9583612ad1565b91509150915091565b60405163136e4c9160e31b81526001600160a01b0383811660048301526024820183905233604483015260009190851690639b7264889060640160006040518083038186803b158015610bf057600080fd5b505afa158015610c04573d6000803e3d6000fd5b505050506000610c15858533612dcf565b90508083111560405180604001604052806002815260200161353160f01b81525090610c5d5760405162461bcd60e51b8152600401610c549190614998565b60405180910390fd5b5060405163406e6fb960e01b81523360048201526001600160a01b03858116602483015286169063406e6fb990604401602060405180830381865afa158015610caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cce919061482f565b95945050505050565b600080600080600080610a5060008a8a60008b6122fe565b60008060006104d76001898989338a8a61142d565b600080600080600080610a5060018a8a60008b613142565b6040516370a0823160e01b81526001600160a01b038281166004830152600091908416906370a0823190602401602060405180830381865afa158015610d66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8a919061482f565b604051636e059fa960e11b81526001600160a01b03858116600483015291925060009186169063dc0b3f5290602401602060405180830381865afa158015610dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfa91906149cb565b9050600080610e1c8351640fffffffff607482901c81169260509290921c1690565b8451919350915060009060301c60ff16610e3790600a614ae1565b90508215610ee657610e498184614aed565b604051631ff3872f60e21b81526001600160a01b0389811660048301529194506000918a1690637fce1cbc90602401602060405180830381865afa158015610e95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb9919061482f565b90506000818511610ecb576000610ed5565b610ed58286614b04565b905080871115610ee3578096505b50505b81156105b9576064610ef88284614aed565b610f029190614b2d565b60405163406e6fb960e01b81526001600160a01b03888116600483015289811660248301529193506000918a169063406e6fb990604401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061482f565b90506000818411610f8c576000610f96565b610f968285614b04565b905080871115610fa4578096505b5050505050505b9392505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905281908190819087906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa158015611025573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104991906146db565b6020808201516001600160a01b039081168552606083015181168583015260a08301519091015160409081015162ffffff16818601528051636a133ef760e11b815290519293509085169163d4267dee9160048082019260009290919082900301818387803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050604051632fe4a15f60e21b81526001600160a01b038c8116600483015260009a508a99508998508897508793508616915063bf92857c9060240161014060405180830381865afa158015611129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114d91906148ed565b905061116661115b8c613877565b60e083015190613a4a565b836080018181525050836001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d19190614848565b6040516370a0823160e01b81526001600160a01b038c8116600483015291909116906370a0823190602401602060405180830381865afa158015611219573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123d919061482f565b6060840181905260808401519096506112569087614b4f565b97508715611347577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c6a5026a6040518060a0016040528086600001516001600160a01b0316815260200186602001516001600160a01b031681526020018b8152602001866040015162ffffff1681526020018c6001600160a01b03168152506040518263ffffffff1660e01b81526004016112fc9190614865565b6080604051808303816000875af115801561131b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133f91906148ae565b509199509750505b8515610a16577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c6a5026a6040518060a0016040528086600001516001600160a01b0316815260200186602001516001600160a01b03168152602001898152602001866040015162ffffff1681526020018c6001600160a01b03168152506040518263ffffffff1660e01b81526004016109cb9190614865565b60008060006104d76000898989338a8a611b77565b600080600080600080610a5060008a60008b8b613142565b6000611425848484612dcf565b949350505050565b6000806000808990506114b360405180610160016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600062ffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa1580156114f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151891906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a08501519093015181015162ffffff16928601929092528151636a133ef760e11b8152915192935085169163d4267dee9160048082019260009290919082900301818387803b15801561159657600080fd5b505af11580156115aa573d6000803e3d6000fd5b505050506115be82604001518a308e613a87565b6115ed82604001517f00000000000000000000000000000000000000000000000000000000000000008d613b91565b8c156116e55761012082018b81526040805161010081018252818501516001600160a01b03908116825285518116602083015260608087015162ffffff16838501523090830152608082018c9052925160a082015260c081018d905289831660e0820152905163414bf38960e01b815290917f0000000000000000000000000000000000000000000000000000000000000000169063414bf38990611696908490600401614b62565b6020604051808303816000875af11580156116b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d9919061482f565b610140840152506117fb565b61014082018a81526040805161010081018252818501516001600160a01b03908116825285518116602083015260608087015162ffffff16838501523090830152608082018c9052925160a082015260c081018e905289831660e08201529051631b67c43360e31b815290917f0000000000000000000000000000000000000000000000000000000000000000169063db3e219890611788908490600401614b62565b6020604051808303816000875af11580156117a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117cb919061482f565b61012084018190528c11156117f9576117f983604001518b8561012001518f6117f49190614b04565b613c91565b505b604051632fe4a15f60e21b81526001600160a01b038a811660048301526000919085169063bf92857c9060240161014060405180830381865afa158015611846573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186a91906148ed565b6101208101519091501561198d57826101400151816101200151106118945782610140015161189b565b8061012001515b60a08401819052835160405163020f64ad60e41b815260048101929092526001600160a01b0316906320f64ad090602401602060405180830381865afa1580156118e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190d919061482f565b60c084015260a083015160405163acb7081560e01b815260048101919091526001600160a01b038b8116602483015285169063acb70815906044016020604051808303816000875af1158015611967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198b919061482f565b505b8260a001518361014001516119a29190614b04565b6101008401819052156119c3576119c383600001518b856101000151613c91565b600083604001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2b9190614bcc565b60ff169050600084602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a989190614bcc565b60ff169050818111611acc57611ac7611ab18284614b04565b611abc90600a614ae1565b60c087015190613d8a565b611aef565b611aef611ad98383614b04565b611ae490600a614ae1565b60c087015190613db4565b60e08601819052610120860151610140870151604080519384526020840192909252908201526001600160a01b038d16907fb9ef09514218d6db102f20bb5056bd07fece2bbf77002333123958920498fa5c9060600160405180910390a28460e001518561012001518661014001519850985098505050505050509750975097945050505050565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290528190819089906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa158015611c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2a91906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a08501519093015181015162ffffff16928601929092528151636a133ef760e11b8152915192935085169163d4267dee9160048082019260009290919082900301818387803b158015611ca857600080fd5b505af1158015611cbc573d6000803e3d6000fd5b505083516040516370a0823160e01b81526001600160a01b038d8116600483015290911692506370a082319150602401602060405180830381865afa158015611d09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2d919061482f565b608083018190528b1115611dcf5760808201518b0360e08301819052604051630967fa2960e31b815260048101919091526001600160a01b038a81166024830152841690634b3fd14890604401600060405180830381600087803b158015611d9457600080fd5b505af1158015611da8573d6000803e3d6000fd5b50505050608082015115611dca57611dca82600001518a308560800151613a87565b611ddd565b8151611ddd908a308e613a87565b8151611e0a907f00000000000000000000000000000000000000000000000000000000000000008d613b91565b8c156120015760c08083018b8152604080516101008101825285516001600160a01b039081168252828701518116602083015260608088015162ffffff16838501528e821690830152608082018d9052925160a08201529283018e905289821660e084015251631b67c43360e31b81527f00000000000000000000000000000000000000000000000000000000000000009091169063db3e219890611eb3908490600401614b62565b6020604051808303816000875af1158015611ed2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef6919061482f565b60a084018190528c1115611f32578251611f32907f00000000000000000000000000000000000000000000000000000000000000006000613b91565b60008360e00151118015611f4957508b8360a00151105b15611ffb5760a08301518c03610100840181905260e08401511015611f745760e08301516101008401525b61010083015160e084018051829003905260405163acb7081560e01b815260048101919091526001600160a01b038b8116602483015285169063acb70815906044016020604051808303816000875af1158015611fd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ff9919061482f565b505b506120f1565b60a08083018c8152604080516101008101825285516001600160a01b039081168252828701518116602083015260608088015162ffffff16838501528e821690830152608082018d905292519381019390935260c083018d905289821660e08401525163414bf38960e01b81527f00000000000000000000000000000000000000000000000000000000000000009091169063414bf389906120a7908490600401614b62565b6020604051808303816000875af11580156120c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ea919061482f565b60c0840152505b600082604001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612135573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121599190614bcc565b60ff169050600083602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c69190614bcc565b60ff16905083600001516001600160a01b03166320f64ad08560e001516040518263ffffffff1660e01b815260040161220191815260200190565b602060405180830381865afa15801561221e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612242919061482f565b975081811161226f5761226a6122588284614b04565b61226390600a614ae1565b8990613d8a565b61228e565b61228e61227c8383614b04565b61228790600a614ae1565b8990613db4565b60a085015160c08601516040805184815260208101849052908101829052929a5090985096506001600160a01b038c16907f95fbac5804a49f4f9dc9b51ff09d525ff5653da7aa08129ee89cecc0d14d2c069060600160405180910390a250505050509750975097945050505050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290526101608101829052819081908190819081908a906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa1580156123ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123cf91906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a08501805185015183015162ffffff166080808a0191909152905190940151909301518216928601929092528151636a133ef760e11b8152915192935085169163d4267dee9160048082019260009290919082900301818387803b15801561246257600080fd5b505af1158015612476573d6000803e3d6000fd5b5050505081606001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156124bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e0919061479d565b5050506001600160a01b0390931661014086018190526040860151865161250c95509093509150613dc0565b95508d15612612577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd21704a6040518060a0016040528085600001516001600160a01b0316815260200185604001516001600160a01b031681526020018e8152602001856080015162ffffff1681526020018d6001600160a01b03168152506040518263ffffffff1660e01b81526004016125b29190614865565b6080604051808303816000875af11580156125d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f591906148ae565b6001600160a01b039091166101608601529199509750935061270c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c6a5026a6040518060a0016040528085600001516001600160a01b0316815260200185604001516001600160a01b031681526020018f8152602001856080015162ffffff1681526020018d6001600160a01b03168152506040518263ffffffff1660e01b81526004016126b09190614865565b6080604051808303816000875af11580156126cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f391906148ae565b6001600160a01b03909116610160860152919950975093505b61272482604001518360000151846101600151613dc0565b9450826001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612764573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127889190614848565b6040516370a0823160e01b81523360048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa1580156127ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f2919061482f565b60a083018190528811612806576000612815565b60a08201516128159089614b04565b60e08301819052156129805761283861282d8e613877565b60e084015190613e45565b8260e0018181525050826001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561287f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a39190614848565b6001600160a01b03166320f64ad08360e001516040518263ffffffff1660e01b81526004016128d491815260200190565b602060405180830381865afa1580156128f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612915919061482f565b61010083015260e08201516040516353c3747360e11b815260048101919091523360248201526001600160a01b0384169063a786e8e69060440160006040518083038186803b15801561296757600080fd5b505afa15801561297b573d6000803e3d6000fd5b505050505b600082604001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e89190614bcc565b60ff169050600083602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a559190614bcc565b60ff169050818111612a8a57612a85612a6e8284614b04565b612a7990600a614ae1565b61010086015190613d8a565b612aae565b612aae612a978383614b04565b612aa290600a614ae1565b61010086015190613db4565b9a50612abd6206551887614b4f565b955050505050509550955095509550955095565b6000806000836001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa158015612b15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b3991906146db565b905060008160a001516020015160800151905060008260a00151602001516060015190506000866001600160a01b03166398e1b4106040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc19190614848565b90506000876001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c279190614848565b6040516370a0823160e01b81526001600160a01b038681166004830152919250908316906370a0823190602401602060405180830381865afa158015612c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c95919061482f565b6040516370a0823160e01b81526001600160a01b038681166004830152919850908216906370a0823190602401602060405180830381865afa158015612cdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d03919061482f565b9550600080856001600160a01b0316631ad8b03b6040518163ffffffff1660e01b81526004016040805180830381865afa158015612d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d699190614bfe565b9150915084612d8157806001600160801b0316612d8c565b816001600160801b03165b612d96908a614b04565b985084612dac57816001600160801b0316612db7565b806001600160801b03165b612dc19089614b04565b975050505050505050915091565b600080849050806001600160a01b031663d4267dee6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612e1057600080fd5b505af1158015612e24573d6000803e3d6000fd5b5050604051632fe4a15f60e21b81526001600160a01b038681166004830152600093508416915063bf92857c9060240161014060405180830381865afa158015612e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e9691906148ed565b9050600080826080015111612eac576000612ed1565b612ed1612eb888613877565b60808401516020850151612ecb91613e88565b90613e45565b9050600081836000015111612ee7576000612ef4565b8251612ef4908390614b04565b90506000846001600160a01b0316630542975c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5a9190614848565b6001600160a01b031663fca513a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbb9190614848565b60405163b3596f0760e01b81526001600160a01b038a81166004830152919091169063b3596f0790602401602060405180830381865afa158015613003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613027919061482f565b90506000886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d9190614bcc565b61309890600a614c31565b905060006130b0836130aa8685613d8a565b90613db4565b60405163406e6fb960e01b81526001600160a01b038b811660048301528c811660248301529192509088169063406e6fb990604401602060405180830381865afa158015613102573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613126919061482f565b975080881115613134578097505b505050505050509392505050565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052819081908190819081908a906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa1580156131d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fb91906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a08501805185015183015162ffffff166080808a0191909152905190940151909301518216928601929092528151636a133ef760e11b8152915192935085169163d4267dee9160048082019260009290919082900301818387803b15801561328e57600080fd5b505af11580156132a2573d6000803e3d6000fd5b5050505081606001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156132e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330c919061479d565b5050506001600160a01b0390931660a086018190526040860151865161333795509093509150613dc0565b95508d1561343c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c6a5026a6040518060a0016040528085604001516001600160a01b0316815260200185600001516001600160a01b031681526020018f8152602001856080015162ffffff1681526020018d6001600160a01b03168152506040518263ffffffff1660e01b81526004016133dd9190614865565b6080604051808303816000875af11580156133fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342091906148ae565b6001600160a01b0390911660c086015291995097509350613535565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bd21704a6040518060a0016040528085604001516001600160a01b0316815260200185600001516001600160a01b031681526020018e8152602001856080015162ffffff1681526020018d6001600160a01b03168152506040518263ffffffff1660e01b81526004016134da9190614865565b6080604051808303816000875af11580156134f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351d91906148ae565b6001600160a01b0390911660c0860152919950975093505b61354c826040015183600001518460c00151613dc0565b604051632fe4a15f60e21b81523360048201529095506000906001600160a01b0385169063bf92857c9060240161014060405180830381865afa158015613597573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135bb91906148ed565b905080610120015188116135cf57876135d6565b8061012001515b83610100018181525050836001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561361e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136429190614848565b6001600160a01b03166320f64ad08461010001516040518263ffffffff1660e01b815260040161367491815260200190565b602060405180830381865afa158015613691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136b5919061482f565b60e084018190521561372757610100830151604051630b7cba2760e21b815260048101919091523360248201526001600160a01b03851690632df2e89c9060440160006040518083038186803b15801561370e57600080fd5b505afa158015613722573d6000803e3d6000fd5b505050505b600083604001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561376b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061378f9190614bcc565b60ff169050600084602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137fc9190614bcc565b60ff1690508181116138305761382b6138158284614b04565b61382090600a614ae1565b60e087015190613d8a565b613853565b61385361383d8383614b04565b61384890600a614ae1565b60e087015190613db4565b9b5061386262030d4088614b4f565b96505050505050509550955095509550955095565b6000808290506000836001600160a01b0316630bbe26da836001600160a01b0316630542975c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f09190614848565b6001600160a01b031663fca513a86040518163ffffffff1660e01b8152600401602060405180830381865afa15801561392d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139519190614848565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139b9919061482f565b90506000846001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa1580156139fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a2091906146db565b6080015190506000613a328284613eb3565b9050613a4081610384614092565b9695505050505050565b60008115676765c793fa10079d601b1b60028404190484111715613a6d57600080fd5b50676765c793fa10079d601b1b9190910260028204010490565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691613aeb9190614c40565b6000604051808303816000865af19150503d8060008114613b28576040519150601f19603f3d011682016040523d82523d6000602084013e613b2d565b606091505b5091509150818015613b57575080511580613b57575080806020019051810190613b579190614c5c565b613b895760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401610c54565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151600092839290871691613bed9190614c40565b6000604051808303816000865af19150503d8060008114613c2a576040519150601f19603f3d011682016040523d82523d6000602084013e613c2f565b606091505b5091509150818015613c59575080511580613c59575080806020019051810190613c599190614c5c565b613c8a5760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401610c54565b5050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691613ced9190614c40565b6000604051808303816000865af19150503d8060008114613d2a576040519150601f19603f3d011682016040523d82523d6000602084013e613d2f565b606091505b5091509150818015613d59575080511580613d59575080806020019051810190613d599190614c5c565b613c8a5760405162461bcd60e51b815260206004820152600260248201526114d560f21b6044820152606401610c54565b6000821580613dab57505081810281838281613da857613da8614b17565b04145b610b8357600080fd5b6000610fab8284614b2d565b600080836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e259190614bcc565b60ff1690506000613e3782600a614ae1565b9050613a408185878961417e565b600081156b019d971e4fe8401e740000001983900484111517613e6757600080fd5b50676765c793fa10079d601b1b91026b019d971e4fe8401e74000000010490565b6000811561271060028404190484111715613ea257600080fd5b506127109190910260028204010490565b6000676765c793fa10079d601b1b8211613fa8576000613ede83676765c793fa10079d601b1b614b04565b90506000613eec8280613e45565b90506000613efa8284613e45565b90506000613f088380613e45565b90506000613f168385613e45565b90506000613f248480613e45565b9050613f31600682614b2d565b613f3c600584614b2d565b613f47600486614b2d565b613f52600388614b2d565b613f5d60028a614b2d565b613f67908b614b4f565b613f719190614b4f565b613f7b9190614b4f565b613f859190614b4f565b613f8f9190614b4f565b9550613f9b868a613e45565b9650505050505050610b83565b6000613fbf676765c793fa10079d601b1b84614b04565b90506000613fcd8280613e45565b90506000613fdb8284613e45565b90506000613fe98380613e45565b90506000613ff78385613e45565b905060006140058480613e45565b9050614012600682614b2d565b61401d600584614b2d565b614028600486614b2d565b614033600388614b2d565b61403e60028a614b2d565b614048908b614b04565b6140529190614b4f565b61405c9190614b04565b6140669190614b4f565b6140709190614b04565b955061407c868a613e45565b61408590614c77565b9998505050505050505050565b600061409e8284614c93565b9250600083126141125782600060026140b78380613e45565b6140c19190614b2d565b9050600060036140d18385613e45565b6140db9190614b2d565b905080826140f485676765c793fa10079d601b1b614b4f565b6140fe9190614b4f565b6141089190614b4f565b9350505050610b83565b600061411d84614c77565b90506000600261412d8380613e45565b6141379190614b2d565b9050600060036141478385613e45565b6141519190614b2d565b9050808261416a85676765c793fa10079d601b1b614b04565b6141749190614b4f565b613a409190614b04565b60006001600160801b036001600160a01b038516116141f25760006141ac6001600160a01b03861680614aed565b9050826001600160a01b0316846001600160a01b0316106141db576141d6600160c01b878361424b565b6141ea565b6141ea8187600160c01b61424b565b915050611425565b60006142116001600160a01b038616806801000000000000000061424b565b9050826001600160a01b0316846001600160a01b0316106142405761423b600160801b878361424b565b613a40565b613a408187600160801b5b6000808060001985870985870292508281108382030391505080600003614284576000841161427957600080fd5b508290049050610fab565b80841161429057600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6001600160a01b038116811461431257600080fd5b50565b60006020828403121561432757600080fd5b8135610fab816142fd565b600080600080600060a0868803121561434a57600080fd5b8535614355816142fd565b9450602086013593506040860135925060608601359150608086013561437a816142fd565b809150509295509295909350565b60008060006060848603121561439d57600080fd5b83356143a8816142fd565b925060208401356143b8816142fd565b929592945050506040919091013590565b6000806000606084860312156143de57600080fd5b83356143e9816142fd565b925060208401356143f9816142fd565b91506040840135614409816142fd565b809150509250925092565b60008060006060848603121561442957600080fd5b8335614434816142fd565b9250602084013591506040840135614409816142fd565b6000806040838503121561445e57600080fd5b8235614469816142fd565b91506020830135614479816142fd565b809150509250929050565b604051610100810167ffffffffffffffff811182821017156144b657634e487b7160e01b600052604160045260246000fd5b60405290565b604051610120810167ffffffffffffffff811182821017156144b657634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff811182821017156144b657634e487b7160e01b600052604160045260246000fd5b60006020828403121561453257600080fd5b6040516020810181811067ffffffffffffffff8211171561456357634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b805161457b816142fd565b919050565b8051801515811461457b57600080fd5b600060a082840312156145a257600080fd5b60405160a0810181811067ffffffffffffffff821117156145d357634e487b7160e01b600052604160045260246000fd5b806040525080915082516145e6816142fd565b815260208301516145f6816142fd565b6020820152604083015162ffffff8116811461461157600080fd5b604082015261462260608401614580565b60608201526080830151614635816142fd565b6080919091015292915050565b8051600681900b811461457b57600080fd5b6000610180828403121561466757600080fd5b61466f614484565b905061467a82614570565b81526146898360208401614590565b602082015260c0820151604082015260e08201516060820152610100820151608082015261012082015160a08201526146c56101408301614642565b60c082015261016082015160e082015292915050565b600061028082840312156146ee57600080fd5b6146f66144bc565b6147008484614520565b815261470e60208401614570565b602082015261471f60408401614570565b604082015261473060608401614570565b60608201526080830151608082015261474c8460a08501614654565b60a082015261022083015160c082015261024083015160e08201526102609092015161010083015250919050565b805161ffff8116811461457b57600080fd5b805160ff8116811461457b57600080fd5b600080600080600080600060e0888a0312156147b857600080fd5b87516147c3816142fd565b8097505060208801518060020b81146147db57600080fd5b95506147e96040890161477a565b94506147f76060890161477a565b93506148056080890161477a565b925061481360a0890161478c565b915061482160c08901614580565b905092959891949750929550565b60006020828403121561484157600080fd5b5051919050565b60006020828403121561485a57600080fd5b8151610fab816142fd565b60a08101610b83828480516001600160a01b0390811683526020808301518216908401526040808301519084015260608083015162ffffff169084015260809182015116910152565b600080600080608085870312156148c457600080fd5b845193506020850151925060408501516148dd816142fd565b6060959095015193969295505050565b6000610140828403121561490057600080fd5b6149086144ee565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152508091505092915050565b60005b8381101561498f578181015183820152602001614977565b50506000910152565b60208152600082518060208401526149b7816040850160208701614974565b601f01601f19169190910160400192915050565b6000602082840312156149dd57600080fd5b610fab8383614520565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115614a38578160001904821115614a1e57614a1e6149e7565b80851615614a2b57918102915b93841c9390800290614a02565b509250929050565b600082614a4f57506001610b83565b81614a5c57506000610b83565b8160018114614a725760028114614a7c57614a98565b6001915050610b83565b60ff841115614a8d57614a8d6149e7565b50506001821b610b83565b5060208310610133831016604e8410600b8410161715614abb575081810a610b83565b614ac583836149fd565b8060001904821115614ad957614ad96149e7565b029392505050565b6000610fab8383614a40565b8082028115828204841417610b8357610b836149e7565b81810381811115610b8357610b836149e7565b634e487b7160e01b600052601260045260246000fd5b600082614b4a57634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610b8357610b836149e7565b6101008101610b83828480516001600160a01b03908116835260208083015182169084015260408083015162ffffff16908401526060808301518216908401526080808301519084015260a0828101519084015260c0808301519084015260e09182015116910152565b600060208284031215614bde57600080fd5b610fab8261478c565b80516001600160801b038116811461457b57600080fd5b60008060408385031215614c1157600080fd5b614c1a83614be7565b9150614c2860208401614be7565b90509250929050565b6000610fab60ff841683614a40565b60008251614c52818460208701614974565b9190910192915050565b600060208284031215614c6e57600080fd5b610fab82614580565b6000600160ff1b8201614c8c57614c8c6149e7565b5060000390565b80820260008212600160ff1b84141615614caf57614caf6149e7565b8181058314821517610b8357610b836149e756fea26469706673582212203b3c95dc32de99ff9eb4d4158a4e07cdf605adb686707a24a16545ee4da6fd0a64736f6c63430008110033000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a42
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063638d641a116100ad578063cc741cbd11610071578063cc741cbd14610379578063eb2ef3781461038c578063ebe56e611461039f578063fd891e14146103b2578063fe75c700146103c557600080fd5b8063638d641a14610306578063735de9f7146103195780638488bbea14610340578063a2c90f4814610353578063c2a944251461036657600080fd5b8063439db753116100f4578063439db753146101d857806343a95d28146101eb5780634c5d75261461022b5780634db4a352146102b7578063549c78b0146102de57600080fd5b80630a5fb4d1146101265780632bb9ebd6146101565780633c57dd5d146101845780634019ac29146101a5575b600080fd5b610139610134366004614315565b6103d8565b6040516001600160a01b0390911681526020015b60405180910390f35b610169610164366004614332565b6104c2565b6040805193845260208401929092529082015260600161014d565b610197610192366004614388565b6104e8565b60405190815260200161014d565b6101b86101b33660046143c9565b6105c4565b60408051948552602085019390935291830152606082015260800161014d565b6101696101e6366004614332565b610a23565b6101fe6101f9366004614414565b610a38565b604080519687526020870195909552938501929092526060840152608083015260a082015260c00161014d565b61023e61023936600461444b565b610a66565b60405161014d9190600061014082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151818401525092915050565b6101397f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a4281565b6102f16102ec366004614315565b610b89565b6040805192835260208301919091520161014d565b610197610314366004614388565b610b9e565b6101397f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b6101fe61034e366004614414565b610cd7565b610169610361366004614332565b610cef565b6101fe610374366004614414565b610d04565b6101976103873660046143c9565b610d1c565b6101b861039a3660046143c9565b610fb2565b6101696103ad366004614332565b6113eb565b6101fe6103c0366004614414565b611400565b6101976103d33660046143c9565b611418565b6000808290506000816001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa15801561041f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044391906146db565b90508060a0015160200151608001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801561048f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b3919061479d565b50949998505050505050505050565b60008060006104d7600089888a338a8a61142d565b925092509250955095509592505050565b6040516370a0823160e01b81523360048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561052f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610553919061482f565b604051630c66612360e41b81526001600160a01b038581166004830152602482018590523360448301529192509085169063c66612309060640160006040518083038186803b1580156105a557600080fd5b505afa1580156105b9573d6000803e3d6000fd5b505050509392505050565b604080516080810182526000808252602082018190529181018290526060810182905281908190819087906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa158015610630573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065491906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a085015184015182015162ffffff1690870152805163098e1b4160e41b8152905160009b508b9a508a9950899850939450908616926398e1b410926004808401939192918290030181865afa1580156106dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107019190614848565b6040516370a0823160e01b81526001600160a01b038b8116600483015291909116906370a0823190602401602060405180830381865afa158015610749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076d919061482f565b9650861561085e577f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a426001600160a01b031663c6a5026a6040518060a0016040528085604001516001600160a01b0316815260200185600001516001600160a01b031681526020018a8152602001856060015162ffffff1681526020018b6001600160a01b03168152506040518263ffffffff1660e01b81526004016108139190614865565b6080604051808303816000875af1158015610832573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085691906148ae565b509198509650505b826001600160a01b031663d4267dee6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561089957600080fd5b505af11580156108ad573d6000803e3d6000fd5b5050604051632fe4a15f60e21b81526001600160a01b038c81166004830152600093508616915063bf92857c9060240161014060405180830381865afa1580156108fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f91906148ed565b9050806101200151871161093857879550869450610a16565b61012081015115610a16576040805160a081018252848201516001600160a01b0390811682528551811660208301526101208401518284015260608087015162ffffff16908301528b811660808301529151635e90b82560e11b81527f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a429092169163bd21704a916109cb91600401614865565b6080604051808303816000875af11580156109ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0e91906148ae565b509197509550505b5050505093509350935093565b60008060006104d7600189888a338a8a611b77565b600080600080600080610a5060018a60008b8b6122fe565b949e939d50919b50995097509095509350505050565b610abc604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000839050806001600160a01b031663d4267dee6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610afc57600080fd5b505af1158015610b10573d6000803e3d6000fd5b5050604051632fe4a15f60e21b81526001600160a01b0386811660048301528416925063bf92857c915060240161014060405180830381865afa158015610b5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7f91906148ed565b9150505b92915050565b600080610b9583612ad1565b91509150915091565b60405163136e4c9160e31b81526001600160a01b0383811660048301526024820183905233604483015260009190851690639b7264889060640160006040518083038186803b158015610bf057600080fd5b505afa158015610c04573d6000803e3d6000fd5b505050506000610c15858533612dcf565b90508083111560405180604001604052806002815260200161353160f01b81525090610c5d5760405162461bcd60e51b8152600401610c549190614998565b60405180910390fd5b5060405163406e6fb960e01b81523360048201526001600160a01b03858116602483015286169063406e6fb990604401602060405180830381865afa158015610caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cce919061482f565b95945050505050565b600080600080600080610a5060008a8a60008b6122fe565b60008060006104d76001898989338a8a61142d565b600080600080600080610a5060018a8a60008b613142565b6040516370a0823160e01b81526001600160a01b038281166004830152600091908416906370a0823190602401602060405180830381865afa158015610d66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8a919061482f565b604051636e059fa960e11b81526001600160a01b03858116600483015291925060009186169063dc0b3f5290602401602060405180830381865afa158015610dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfa91906149cb565b9050600080610e1c8351640fffffffff607482901c81169260509290921c1690565b8451919350915060009060301c60ff16610e3790600a614ae1565b90508215610ee657610e498184614aed565b604051631ff3872f60e21b81526001600160a01b0389811660048301529194506000918a1690637fce1cbc90602401602060405180830381865afa158015610e95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb9919061482f565b90506000818511610ecb576000610ed5565b610ed58286614b04565b905080871115610ee3578096505b50505b81156105b9576064610ef88284614aed565b610f029190614b2d565b60405163406e6fb960e01b81526001600160a01b03888116600483015289811660248301529193506000918a169063406e6fb990604401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061482f565b90506000818411610f8c576000610f96565b610f968285614b04565b905080871115610fa4578096505b5050505050505b9392505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905281908190819087906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa158015611025573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104991906146db565b6020808201516001600160a01b039081168552606083015181168583015260a08301519091015160409081015162ffffff16818601528051636a133ef760e11b815290519293509085169163d4267dee9160048082019260009290919082900301818387803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050604051632fe4a15f60e21b81526001600160a01b038c8116600483015260009a508a99508998508897508793508616915063bf92857c9060240161014060405180830381865afa158015611129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114d91906148ed565b905061116661115b8c613877565b60e083015190613a4a565b836080018181525050836001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d19190614848565b6040516370a0823160e01b81526001600160a01b038c8116600483015291909116906370a0823190602401602060405180830381865afa158015611219573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123d919061482f565b6060840181905260808401519096506112569087614b4f565b97508715611347577f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a426001600160a01b031663c6a5026a6040518060a0016040528086600001516001600160a01b0316815260200186602001516001600160a01b031681526020018b8152602001866040015162ffffff1681526020018c6001600160a01b03168152506040518263ffffffff1660e01b81526004016112fc9190614865565b6080604051808303816000875af115801561131b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133f91906148ae565b509199509750505b8515610a16577f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a426001600160a01b031663c6a5026a6040518060a0016040528086600001516001600160a01b0316815260200186602001516001600160a01b03168152602001898152602001866040015162ffffff1681526020018c6001600160a01b03168152506040518263ffffffff1660e01b81526004016109cb9190614865565b60008060006104d76000898989338a8a611b77565b600080600080600080610a5060008a60008b8b613142565b6000611425848484612dcf565b949350505050565b6000806000808990506114b360405180610160016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600062ffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa1580156114f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151891906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a08501519093015181015162ffffff16928601929092528151636a133ef760e11b8152915192935085169163d4267dee9160048082019260009290919082900301818387803b15801561159657600080fd5b505af11580156115aa573d6000803e3d6000fd5b505050506115be82604001518a308e613a87565b6115ed82604001517f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615648d613b91565b8c156116e55761012082018b81526040805161010081018252818501516001600160a01b03908116825285518116602083015260608087015162ffffff16838501523090830152608082018c9052925160a082015260c081018d905289831660e0820152905163414bf38960e01b815290917f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169063414bf38990611696908490600401614b62565b6020604051808303816000875af11580156116b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d9919061482f565b610140840152506117fb565b61014082018a81526040805161010081018252818501516001600160a01b03908116825285518116602083015260608087015162ffffff16838501523090830152608082018c9052925160a082015260c081018e905289831660e08201529051631b67c43360e31b815290917f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169063db3e219890611788908490600401614b62565b6020604051808303816000875af11580156117a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117cb919061482f565b61012084018190528c11156117f9576117f983604001518b8561012001518f6117f49190614b04565b613c91565b505b604051632fe4a15f60e21b81526001600160a01b038a811660048301526000919085169063bf92857c9060240161014060405180830381865afa158015611846573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186a91906148ed565b6101208101519091501561198d57826101400151816101200151106118945782610140015161189b565b8061012001515b60a08401819052835160405163020f64ad60e41b815260048101929092526001600160a01b0316906320f64ad090602401602060405180830381865afa1580156118e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190d919061482f565b60c084015260a083015160405163acb7081560e01b815260048101919091526001600160a01b038b8116602483015285169063acb70815906044016020604051808303816000875af1158015611967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198b919061482f565b505b8260a001518361014001516119a29190614b04565b6101008401819052156119c3576119c383600001518b856101000151613c91565b600083604001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2b9190614bcc565b60ff169050600084602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a989190614bcc565b60ff169050818111611acc57611ac7611ab18284614b04565b611abc90600a614ae1565b60c087015190613d8a565b611aef565b611aef611ad98383614b04565b611ae490600a614ae1565b60c087015190613db4565b60e08601819052610120860151610140870151604080519384526020840192909252908201526001600160a01b038d16907fb9ef09514218d6db102f20bb5056bd07fece2bbf77002333123958920498fa5c9060600160405180910390a28460e001518561012001518661014001519850985098505050505050509750975097945050505050565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290528190819089906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa158015611c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2a91906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a08501519093015181015162ffffff16928601929092528151636a133ef760e11b8152915192935085169163d4267dee9160048082019260009290919082900301818387803b158015611ca857600080fd5b505af1158015611cbc573d6000803e3d6000fd5b505083516040516370a0823160e01b81526001600160a01b038d8116600483015290911692506370a082319150602401602060405180830381865afa158015611d09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2d919061482f565b608083018190528b1115611dcf5760808201518b0360e08301819052604051630967fa2960e31b815260048101919091526001600160a01b038a81166024830152841690634b3fd14890604401600060405180830381600087803b158015611d9457600080fd5b505af1158015611da8573d6000803e3d6000fd5b50505050608082015115611dca57611dca82600001518a308560800151613a87565b611ddd565b8151611ddd908a308e613a87565b8151611e0a907f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615648d613b91565b8c156120015760c08083018b8152604080516101008101825285516001600160a01b039081168252828701518116602083015260608088015162ffffff16838501528e821690830152608082018d9052925160a08201529283018e905289821660e084015251631b67c43360e31b81527f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615649091169063db3e219890611eb3908490600401614b62565b6020604051808303816000875af1158015611ed2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef6919061482f565b60a084018190528c1115611f32578251611f32907f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646000613b91565b60008360e00151118015611f4957508b8360a00151105b15611ffb5760a08301518c03610100840181905260e08401511015611f745760e08301516101008401525b61010083015160e084018051829003905260405163acb7081560e01b815260048101919091526001600160a01b038b8116602483015285169063acb70815906044016020604051808303816000875af1158015611fd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ff9919061482f565b505b506120f1565b60a08083018c8152604080516101008101825285516001600160a01b039081168252828701518116602083015260608088015162ffffff16838501528e821690830152608082018d905292519381019390935260c083018d905289821660e08401525163414bf38960e01b81527f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615649091169063414bf389906120a7908490600401614b62565b6020604051808303816000875af11580156120c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ea919061482f565b60c0840152505b600082604001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612135573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121599190614bcc565b60ff169050600083602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c69190614bcc565b60ff16905083600001516001600160a01b03166320f64ad08560e001516040518263ffffffff1660e01b815260040161220191815260200190565b602060405180830381865afa15801561221e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612242919061482f565b975081811161226f5761226a6122588284614b04565b61226390600a614ae1565b8990613d8a565b61228e565b61228e61227c8383614b04565b61228790600a614ae1565b8990613db4565b60a085015160c08601516040805184815260208101849052908101829052929a5090985096506001600160a01b038c16907f95fbac5804a49f4f9dc9b51ff09d525ff5653da7aa08129ee89cecc0d14d2c069060600160405180910390a250505050509750975097945050505050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290526101608101829052819081908190819081908a906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa1580156123ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123cf91906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a08501805185015183015162ffffff166080808a0191909152905190940151909301518216928601929092528151636a133ef760e11b8152915192935085169163d4267dee9160048082019260009290919082900301818387803b15801561246257600080fd5b505af1158015612476573d6000803e3d6000fd5b5050505081606001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156124bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e0919061479d565b5050506001600160a01b0390931661014086018190526040860151865161250c95509093509150613dc0565b95508d15612612577f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a426001600160a01b031663bd21704a6040518060a0016040528085600001516001600160a01b0316815260200185604001516001600160a01b031681526020018e8152602001856080015162ffffff1681526020018d6001600160a01b03168152506040518263ffffffff1660e01b81526004016125b29190614865565b6080604051808303816000875af11580156125d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f591906148ae565b6001600160a01b039091166101608601529199509750935061270c565b7f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a426001600160a01b031663c6a5026a6040518060a0016040528085600001516001600160a01b0316815260200185604001516001600160a01b031681526020018f8152602001856080015162ffffff1681526020018d6001600160a01b03168152506040518263ffffffff1660e01b81526004016126b09190614865565b6080604051808303816000875af11580156126cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f391906148ae565b6001600160a01b03909116610160860152919950975093505b61272482604001518360000151846101600151613dc0565b9450826001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612764573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127889190614848565b6040516370a0823160e01b81523360048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa1580156127ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f2919061482f565b60a083018190528811612806576000612815565b60a08201516128159089614b04565b60e08301819052156129805761283861282d8e613877565b60e084015190613e45565b8260e0018181525050826001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561287f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a39190614848565b6001600160a01b03166320f64ad08360e001516040518263ffffffff1660e01b81526004016128d491815260200190565b602060405180830381865afa1580156128f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612915919061482f565b61010083015260e08201516040516353c3747360e11b815260048101919091523360248201526001600160a01b0384169063a786e8e69060440160006040518083038186803b15801561296757600080fd5b505afa15801561297b573d6000803e3d6000fd5b505050505b600082604001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e89190614bcc565b60ff169050600083602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a559190614bcc565b60ff169050818111612a8a57612a85612a6e8284614b04565b612a7990600a614ae1565b61010086015190613d8a565b612aae565b612aae612a978383614b04565b612aa290600a614ae1565b61010086015190613db4565b9a50612abd6206551887614b4f565b955050505050509550955095509550955095565b6000806000836001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa158015612b15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b3991906146db565b905060008160a001516020015160800151905060008260a00151602001516060015190506000866001600160a01b03166398e1b4106040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc19190614848565b90506000876001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c279190614848565b6040516370a0823160e01b81526001600160a01b038681166004830152919250908316906370a0823190602401602060405180830381865afa158015612c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c95919061482f565b6040516370a0823160e01b81526001600160a01b038681166004830152919850908216906370a0823190602401602060405180830381865afa158015612cdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d03919061482f565b9550600080856001600160a01b0316631ad8b03b6040518163ffffffff1660e01b81526004016040805180830381865afa158015612d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d699190614bfe565b9150915084612d8157806001600160801b0316612d8c565b816001600160801b03165b612d96908a614b04565b985084612dac57816001600160801b0316612db7565b806001600160801b03165b612dc19089614b04565b975050505050505050915091565b600080849050806001600160a01b031663d4267dee6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612e1057600080fd5b505af1158015612e24573d6000803e3d6000fd5b5050604051632fe4a15f60e21b81526001600160a01b038681166004830152600093508416915063bf92857c9060240161014060405180830381865afa158015612e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e9691906148ed565b9050600080826080015111612eac576000612ed1565b612ed1612eb888613877565b60808401516020850151612ecb91613e88565b90613e45565b9050600081836000015111612ee7576000612ef4565b8251612ef4908390614b04565b90506000846001600160a01b0316630542975c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5a9190614848565b6001600160a01b031663fca513a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbb9190614848565b60405163b3596f0760e01b81526001600160a01b038a81166004830152919091169063b3596f0790602401602060405180830381865afa158015613003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613027919061482f565b90506000886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d9190614bcc565b61309890600a614c31565b905060006130b0836130aa8685613d8a565b90613db4565b60405163406e6fb960e01b81526001600160a01b038b811660048301528c811660248301529192509088169063406e6fb990604401602060405180830381865afa158015613102573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613126919061482f565b975080881115613134578097505b505050505050509392505050565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052819081908190819081908a906000826001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa1580156131d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fb91906146db565b6020808201516001600160a01b03908116855260408084015182168684015260608085015183168288015260a08501805185015183015162ffffff166080808a0191909152905190940151909301518216928601929092528151636a133ef760e11b8152915192935085169163d4267dee9160048082019260009290919082900301818387803b15801561328e57600080fd5b505af11580156132a2573d6000803e3d6000fd5b5050505081606001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156132e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330c919061479d565b5050506001600160a01b0390931660a086018190526040860151865161333795509093509150613dc0565b95508d1561343c577f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a426001600160a01b031663c6a5026a6040518060a0016040528085604001516001600160a01b0316815260200185600001516001600160a01b031681526020018f8152602001856080015162ffffff1681526020018d6001600160a01b03168152506040518263ffffffff1660e01b81526004016133dd9190614865565b6080604051808303816000875af11580156133fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342091906148ae565b6001600160a01b0390911660c086015291995097509350613535565b7f000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a426001600160a01b031663bd21704a6040518060a0016040528085604001516001600160a01b0316815260200185600001516001600160a01b031681526020018e8152602001856080015162ffffff1681526020018d6001600160a01b03168152506040518263ffffffff1660e01b81526004016134da9190614865565b6080604051808303816000875af11580156134f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351d91906148ae565b6001600160a01b0390911660c0860152919950975093505b61354c826040015183600001518460c00151613dc0565b604051632fe4a15f60e21b81523360048201529095506000906001600160a01b0385169063bf92857c9060240161014060405180830381865afa158015613597573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135bb91906148ed565b905080610120015188116135cf57876135d6565b8061012001515b83610100018181525050836001600160a01b0316635c222bad6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561361e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136429190614848565b6001600160a01b03166320f64ad08461010001516040518263ffffffff1660e01b815260040161367491815260200190565b602060405180830381865afa158015613691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136b5919061482f565b60e084018190521561372757610100830151604051630b7cba2760e21b815260048101919091523360248201526001600160a01b03851690632df2e89c9060440160006040518083038186803b15801561370e57600080fd5b505afa158015613722573d6000803e3d6000fd5b505050505b600083604001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561376b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061378f9190614bcc565b60ff169050600084602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137fc9190614bcc565b60ff1690508181116138305761382b6138158284614b04565b61382090600a614ae1565b60e087015190613d8a565b613853565b61385361383d8383614b04565b61384890600a614ae1565b60e087015190613db4565b9b5061386262030d4088614b4f565b96505050505050509550955095509550955095565b6000808290506000836001600160a01b0316630bbe26da836001600160a01b0316630542975c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f09190614848565b6001600160a01b031663fca513a86040518163ffffffff1660e01b8152600401602060405180830381865afa15801561392d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139519190614848565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139b9919061482f565b90506000846001600160a01b031663f3cc6e046040518163ffffffff1660e01b815260040161028060405180830381865afa1580156139fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a2091906146db565b6080015190506000613a328284613eb3565b9050613a4081610384614092565b9695505050505050565b60008115676765c793fa10079d601b1b60028404190484111715613a6d57600080fd5b50676765c793fa10079d601b1b9190910260028204010490565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691613aeb9190614c40565b6000604051808303816000865af19150503d8060008114613b28576040519150601f19603f3d011682016040523d82523d6000602084013e613b2d565b606091505b5091509150818015613b57575080511580613b57575080806020019051810190613b579190614c5c565b613b895760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401610c54565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151600092839290871691613bed9190614c40565b6000604051808303816000865af19150503d8060008114613c2a576040519150601f19603f3d011682016040523d82523d6000602084013e613c2f565b606091505b5091509150818015613c59575080511580613c59575080806020019051810190613c599190614c5c565b613c8a5760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401610c54565b5050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691613ced9190614c40565b6000604051808303816000865af19150503d8060008114613d2a576040519150601f19603f3d011682016040523d82523d6000602084013e613d2f565b606091505b5091509150818015613d59575080511580613d59575080806020019051810190613d599190614c5c565b613c8a5760405162461bcd60e51b815260206004820152600260248201526114d560f21b6044820152606401610c54565b6000821580613dab57505081810281838281613da857613da8614b17565b04145b610b8357600080fd5b6000610fab8284614b2d565b600080836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e259190614bcc565b60ff1690506000613e3782600a614ae1565b9050613a408185878961417e565b600081156b019d971e4fe8401e740000001983900484111517613e6757600080fd5b50676765c793fa10079d601b1b91026b019d971e4fe8401e74000000010490565b6000811561271060028404190484111715613ea257600080fd5b506127109190910260028204010490565b6000676765c793fa10079d601b1b8211613fa8576000613ede83676765c793fa10079d601b1b614b04565b90506000613eec8280613e45565b90506000613efa8284613e45565b90506000613f088380613e45565b90506000613f168385613e45565b90506000613f248480613e45565b9050613f31600682614b2d565b613f3c600584614b2d565b613f47600486614b2d565b613f52600388614b2d565b613f5d60028a614b2d565b613f67908b614b4f565b613f719190614b4f565b613f7b9190614b4f565b613f859190614b4f565b613f8f9190614b4f565b9550613f9b868a613e45565b9650505050505050610b83565b6000613fbf676765c793fa10079d601b1b84614b04565b90506000613fcd8280613e45565b90506000613fdb8284613e45565b90506000613fe98380613e45565b90506000613ff78385613e45565b905060006140058480613e45565b9050614012600682614b2d565b61401d600584614b2d565b614028600486614b2d565b614033600388614b2d565b61403e60028a614b2d565b614048908b614b04565b6140529190614b4f565b61405c9190614b04565b6140669190614b4f565b6140709190614b04565b955061407c868a613e45565b61408590614c77565b9998505050505050505050565b600061409e8284614c93565b9250600083126141125782600060026140b78380613e45565b6140c19190614b2d565b9050600060036140d18385613e45565b6140db9190614b2d565b905080826140f485676765c793fa10079d601b1b614b4f565b6140fe9190614b4f565b6141089190614b4f565b9350505050610b83565b600061411d84614c77565b90506000600261412d8380613e45565b6141379190614b2d565b9050600060036141478385613e45565b6141519190614b2d565b9050808261416a85676765c793fa10079d601b1b614b04565b6141749190614b4f565b613a409190614b04565b60006001600160801b036001600160a01b038516116141f25760006141ac6001600160a01b03861680614aed565b9050826001600160a01b0316846001600160a01b0316106141db576141d6600160c01b878361424b565b6141ea565b6141ea8187600160c01b61424b565b915050611425565b60006142116001600160a01b038616806801000000000000000061424b565b9050826001600160a01b0316846001600160a01b0316106142405761423b600160801b878361424b565b613a40565b613a408187600160801b5b6000808060001985870985870292508281108382030391505080600003614284576000841161427957600080fd5b508290049050610fab565b80841161429057600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6001600160a01b038116811461431257600080fd5b50565b60006020828403121561432757600080fd5b8135610fab816142fd565b600080600080600060a0868803121561434a57600080fd5b8535614355816142fd565b9450602086013593506040860135925060608601359150608086013561437a816142fd565b809150509295509295909350565b60008060006060848603121561439d57600080fd5b83356143a8816142fd565b925060208401356143b8816142fd565b929592945050506040919091013590565b6000806000606084860312156143de57600080fd5b83356143e9816142fd565b925060208401356143f9816142fd565b91506040840135614409816142fd565b809150509250925092565b60008060006060848603121561442957600080fd5b8335614434816142fd565b9250602084013591506040840135614409816142fd565b6000806040838503121561445e57600080fd5b8235614469816142fd565b91506020830135614479816142fd565b809150509250929050565b604051610100810167ffffffffffffffff811182821017156144b657634e487b7160e01b600052604160045260246000fd5b60405290565b604051610120810167ffffffffffffffff811182821017156144b657634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff811182821017156144b657634e487b7160e01b600052604160045260246000fd5b60006020828403121561453257600080fd5b6040516020810181811067ffffffffffffffff8211171561456357634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b805161457b816142fd565b919050565b8051801515811461457b57600080fd5b600060a082840312156145a257600080fd5b60405160a0810181811067ffffffffffffffff821117156145d357634e487b7160e01b600052604160045260246000fd5b806040525080915082516145e6816142fd565b815260208301516145f6816142fd565b6020820152604083015162ffffff8116811461461157600080fd5b604082015261462260608401614580565b60608201526080830151614635816142fd565b6080919091015292915050565b8051600681900b811461457b57600080fd5b6000610180828403121561466757600080fd5b61466f614484565b905061467a82614570565b81526146898360208401614590565b602082015260c0820151604082015260e08201516060820152610100820151608082015261012082015160a08201526146c56101408301614642565b60c082015261016082015160e082015292915050565b600061028082840312156146ee57600080fd5b6146f66144bc565b6147008484614520565b815261470e60208401614570565b602082015261471f60408401614570565b604082015261473060608401614570565b60608201526080830151608082015261474c8460a08501614654565b60a082015261022083015160c082015261024083015160e08201526102609092015161010083015250919050565b805161ffff8116811461457b57600080fd5b805160ff8116811461457b57600080fd5b600080600080600080600060e0888a0312156147b857600080fd5b87516147c3816142fd565b8097505060208801518060020b81146147db57600080fd5b95506147e96040890161477a565b94506147f76060890161477a565b93506148056080890161477a565b925061481360a0890161478c565b915061482160c08901614580565b905092959891949750929550565b60006020828403121561484157600080fd5b5051919050565b60006020828403121561485a57600080fd5b8151610fab816142fd565b60a08101610b83828480516001600160a01b0390811683526020808301518216908401526040808301519084015260608083015162ffffff169084015260809182015116910152565b600080600080608085870312156148c457600080fd5b845193506020850151925060408501516148dd816142fd565b6060959095015193969295505050565b6000610140828403121561490057600080fd5b6149086144ee565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152508091505092915050565b60005b8381101561498f578181015183820152602001614977565b50506000910152565b60208152600082518060208401526149b7816040850160208701614974565b601f01601f19169190910160400192915050565b6000602082840312156149dd57600080fd5b610fab8383614520565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115614a38578160001904821115614a1e57614a1e6149e7565b80851615614a2b57918102915b93841c9390800290614a02565b509250929050565b600082614a4f57506001610b83565b81614a5c57506000610b83565b8160018114614a725760028114614a7c57614a98565b6001915050610b83565b60ff841115614a8d57614a8d6149e7565b50506001821b610b83565b5060208310610133831016604e8410600b8410161715614abb575081810a610b83565b614ac583836149fd565b8060001904821115614ad957614ad96149e7565b029392505050565b6000610fab8383614a40565b8082028115828204841417610b8357610b836149e7565b81810381811115610b8357610b836149e7565b634e487b7160e01b600052601260045260246000fd5b600082614b4a57634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610b8357610b836149e7565b6101008101610b83828480516001600160a01b03908116835260208083015182169084015260408083015162ffffff16908401526060808301518216908401526080808301519084015260a0828101519084015260c0808301519084015260e09182015116910152565b600060208284031215614bde57600080fd5b610fab8261478c565b80516001600160801b038116811461457b57600080fd5b60008060408385031215614c1157600080fd5b614c1a83614be7565b9150614c2860208401614be7565b90509250929050565b6000610fab60ff841683614a40565b60008251614c52818460208701614974565b9190910192915050565b600060208284031215614c6e57600080fd5b610fab82614580565b6000600160ff1b8201614c8c57614c8c6149e7565b5060000390565b80820260008212600160ff1b84141615614caf57614caf6149e7565b8181058314821517610b8357610b836149e756fea26469706673582212203b3c95dc32de99ff9eb4d4158a4e07cdf605adb686707a24a16545ee4da6fd0a64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a42
-----Decoded View---------------
Arg [0] : _swapRouterAddress (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
Arg [1] : _quoterAddress (address): 0xee533bfC5813B89CdbF2B5A24636d5AB0A1C9A42
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Arg [1] : 000000000000000000000000ee533bfc5813b89cdbf2b5a24636d5ab0a1c9a42
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.