Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/Assistant.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Interfaces
import {IQuoter} from "./interfaces/IQuoter.sol";
import {IVault} from "core/interfaces/IVault.sol";
import {IOracle} from "core/interfaces/IOracle.sol";
import {IUniswapV3Pool} from "v3-core/interfaces/IUniswapV3Pool.sol";
// Contracts and libraries
import {SirStructs} from "core/libraries/SirStructs.sol";
import {SystemConstants} from "core/libraries/SystemConstants.sol";
import {FullMath} from "core/libraries/FullMath.sol";
import {IWETH9, IERC20} from "core/interfaces/IWETH9.sol";
import {UniswapPoolAddress} from "core/libraries/UniswapPoolAddress.sol";
import {AddressClone} from "core/libraries/AddressClone.sol";
import "forge-std/console.sol";
/**
* @notice Helper functions for SIR protocol
*/
contract Assistant {
IVault public immutable VAULT;
IOracle private immutable SIR_ORACLE;
address private immutable UNISWAPV3_FACTORY;
IQuoter private immutable UNISWAPV3_QUOTER;
error VaultDoesNotExist();
error AmountTooLow();
error TooMuchCollateral();
error TEAMaxSupplyExceeded();
enum VaultStatus {
InvalidVault,
NoUniswapPool,
VaultCanBeCreated,
VaultAlreadyExists
}
constructor(address vault, address oracle, address uniswapV3Factory) {
VAULT = IVault(vault);
SIR_ORACLE = IOracle(oracle);
UNISWAPV3_FACTORY = uniswapV3Factory;
if (block.chainid == 1) UNISWAPV3_QUOTER = IQuoter(0x5e55C9e631FAE526cd4B0526C4818D6e0a9eF0e3);
else if (block.chainid == 11155111) UNISWAPV3_QUOTER = IQuoter(0xe3c07ebF66b9D070b589bCCa30903891F71A92Be);
else revert("Network not supported");
}
/**
* @notice It returns the reserves of the vaults specified in vaultIds
*/
function getReserves(uint48[] calldata vaultIds) external view returns (SirStructs.Reserves[] memory reserves) {
reserves = new SirStructs.Reserves[](vaultIds.length);
SirStructs.VaultParameters memory vaultParams;
for (uint256 i = 0; i < vaultIds.length; i++) {
vaultParams = VAULT.paramsById(vaultIds[i]);
reserves[i] = VAULT.getReserves(vaultParams);
}
}
/**
* @notice It returns the balances of the user in vaults [offset + 1, offset + numVaults].
* @param user The address of the user.
* @param offset The offset of the vaults.
* @param numVaults The number of vaults.
*/
function getUserBalances(
address user,
uint offset,
uint numVaults
)
external
view
returns (uint256[] memory apeBalances, uint256[] memory teaBalances, uint80[] memory unclaimedSirRewards)
{
IERC20 ape;
apeBalances = new uint256[](numVaults);
teaBalances = new uint256[](numVaults);
unclaimedSirRewards = new uint80[](numVaults);
for (uint256 vaultId = offset + 1; vaultId <= offset + numVaults; vaultId++) {
ape = IERC20(AddressClone.getAddress(address(VAULT), vaultId));
apeBalances[vaultId - offset - 1] = ape.balanceOf(user);
teaBalances[vaultId - offset - 1] = VAULT.balanceOf(user, vaultId);
unclaimedSirRewards[vaultId - offset - 1] = VAULT.unclaimedRewards(vaultId, user);
}
}
/**
* @notice It returns the ideal price of TEA.
* To get the price as [units of Collateral][per unit of TEA], divide num by den.
*/
function priceOfTEA(
SirStructs.VaultParameters calldata vaultParams
) external view returns (uint256 num, uint256 den) {
// Get current reserves
SirStructs.Reserves memory reserves = VAULT.getReserves(vaultParams);
num = reserves.reserveLPers;
// Get supply of TEA
SirStructs.VaultState memory vaultState = VAULT.vaultStates(vaultParams);
den = VAULT.totalSupply(vaultState.vaultId);
}
/**
* @notice It returns the price of the APE token.
* To get the price as [units of Collateral][per unit of APE], divide num by den.
*/
function priceOfAPE(
SirStructs.VaultParameters calldata vaultParams
) external view returns (uint256 num, uint256 den) {
// Get current reserves
SirStructs.Reserves memory reserves = VAULT.getReserves(vaultParams);
// Get system parameters
SirStructs.SystemParameters memory systemParams = VAULT.systemParams();
// Substract fees
num = _feeAPE(reserves.reserveApes, systemParams.baseFee.fee, vaultParams.leverageTier);
// Get supply of APE
SirStructs.VaultState memory vaultState = VAULT.vaultStates(vaultParams);
den = IERC20(getAddressAPE(vaultState.vaultId)).totalSupply();
}
/**
* @notice It returns the status of the vault.
* 0: InvalidVault - returned when the ERC20 tokens are not valid.
* 1: NoUniswapPool - returned when no Uniswap pool of the two tokens does not exist.
* 2: VaultCanBeCreated - vault does not exist and it can be created.
* 3: VaultAlreadyExists - vault already exists.
*/
function getVaultStatus(SirStructs.VaultParameters calldata vaultParams) external view returns (VaultStatus) {
// Check if the token addresses are a smart contract
if (vaultParams.collateralToken.code.length == 0) return VaultStatus.InvalidVault;
if (vaultParams.debtToken.code.length == 0) return VaultStatus.InvalidVault;
// Check if the token returns total supply
(bool success, ) = vaultParams.collateralToken.staticcall(abi.encodeWithSelector(IERC20.totalSupply.selector));
if (!success) return VaultStatus.InvalidVault;
(success, ) = vaultParams.debtToken.staticcall(abi.encodeWithSelector(IERC20.totalSupply.selector));
if (!success) return VaultStatus.InvalidVault;
// Check if the leverage tier is valid
if (
vaultParams.leverageTier < SystemConstants.MIN_LEVERAGE_TIER ||
vaultParams.leverageTier > SystemConstants.MAX_LEVERAGE_TIER
) return VaultStatus.InvalidVault;
// Check if a Uniswap pool exists
if (
!_checkFeeTierExists(vaultParams, 100) &&
!_checkFeeTierExists(vaultParams, 500) &&
!_checkFeeTierExists(vaultParams, 3000) &&
!_checkFeeTierExists(vaultParams, 10000)
) return VaultStatus.NoUniswapPool;
// Check if vault already exists
SirStructs.VaultState memory vaultState = VAULT.vaultStates(vaultParams);
if (vaultState.vaultId == 0) return VaultStatus.VaultCanBeCreated;
return VaultStatus.VaultAlreadyExists;
}
function getAddressAPE(uint48 vaultId) public view returns (address) {
return AddressClone.getAddress(address(VAULT), vaultId);
}
/*////////////////////////////////////////////////////////////////
QUOTE FUNCTIONS
////////////////////////////////////////////////////////////////*/
/**
* @notice It returns the amount of TEA/APE tokens that would be obtained by depositing collateral token.
* @dev If quoteMint reverts, mint will revert as well; vice versa is not necessarily true.
* @return amountTokens that would be obtained by depositing amountCollateral.
*/
function quoteMint(
bool isAPE,
SirStructs.VaultParameters calldata vaultParams,
uint144 amountCollateral
) public view returns (uint256 amountTokens) {
// Get vault state
SirStructs.VaultState memory vaultState = VAULT.vaultStates(vaultParams);
if (vaultState.vaultId == 0) revert VaultDoesNotExist();
if (amountCollateral == 0) revert AmountTooLow();
// Get current reserves
SirStructs.Reserves memory reserves = VAULT.getReserves(vaultParams);
SirStructs.SystemParameters memory systemParams = VAULT.systemParams();
if (isAPE) {
// Compute how much collateral actually gets deposited
uint256 collateralIn = _feeAPE(amountCollateral, systemParams.baseFee.fee, vaultParams.leverageTier);
// Get supply of APE
address ape = getAddressAPE(vaultState.vaultId);
uint256 supplyAPE = IERC20(ape).totalSupply();
// Calculate tokens
amountTokens = supplyAPE == 0
? collateralIn + reserves.reserveApes
: FullMath.mulDiv(supplyAPE, collateralIn, reserves.reserveApes);
} else {
// Get collateralIn
uint256 collateralIn = _feeMintTEA(amountCollateral, systemParams.lpFee.fee);
// Get supply of TEA
uint256 supplyTEA = VAULT.totalSupply(vaultState.vaultId);
// Calculate tokens
amountTokens = supplyTEA == 0
? _amountFirstMint(vaultParams.collateralToken, amountCollateral + reserves.reserveLPers)
: FullMath.mulDiv(supplyTEA, amountCollateral, reserves.reserveLPers);
// Check that total supply does not overflow
if (amountTokens > SystemConstants.TEA_MAX_SUPPLY - supplyTEA) revert TEAMaxSupplyExceeded();
// Minter's share of TEA
amountTokens = FullMath.mulDiv(
amountTokens,
collateralIn,
supplyTEA == 0
? amountCollateral + reserves.reserveLPers // In the first mint, reserveLPers contains orphaned fees from apes
: amountCollateral
);
}
if (amountTokens == 0) revert AmountTooLow();
}
/**
* @notice It returns the amount of TEA/APE tokens that would be obtained by depositing debt token
* @dev If quoteMint reverts, mint will revert as well; vice versa is not necessarily true.
* @return amountTokens that would be obtained.
*/
function quoteMintWithDebtToken(
bool isAPE,
SirStructs.VaultParameters calldata vaultParams,
uint256 amountDebtToken
) external view returns (uint256 amountTokens, uint256 amountCollateral, uint256 amountCollateralIdeal) {
if (amountDebtToken == 0) revert AmountTooLow();
// Get fee tier
uint24 feeTier = SIR_ORACLE.uniswapFeeTierOf(vaultParams.debtToken, vaultParams.collateralToken);
// Quote Uniswap v3
(amountCollateral, , , ) = UNISWAPV3_QUOTER.quoteExactInputSingle(
IQuoter.QuoteExactInputSingleParams({
tokenIn: vaultParams.debtToken,
tokenOut: vaultParams.collateralToken,
amountIn: amountDebtToken,
fee: feeTier,
sqrtPriceLimitX96: 0
})
);
// Check that amountCollateral does not overflow
if (amountCollateral > type(uint144).max) revert TooMuchCollateral();
// Calculate ideal collateral amount using instant pool price (no slippage)
// Get Uniswap pool
address uniswapPool = SIR_ORACLE.uniswapFeeTierAddressOf(vaultParams.debtToken, vaultParams.collateralToken);
// Get current price
(uint160 sqrtPriceX96, , , , , , ) = IUniswapV3Pool(uniswapPool).slot0();
// Calculate price fraction with better precision if it doesn't overflow when multiplied by itself
bool inverse = vaultParams.collateralToken == IUniswapV3Pool(uniswapPool).token1();
if (sqrtPriceX96 <= type(uint128).max) {
uint256 priceX192 = uint256(sqrtPriceX96) * sqrtPriceX96;
amountCollateralIdeal = inverse
? FullMath.mulDiv(priceX192, amountDebtToken, 1 << 192)
: FullMath.mulDiv(1 << 192, amountDebtToken, priceX192);
} else {
uint256 priceX128 = FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, 1 << 64);
amountCollateralIdeal = inverse
? FullMath.mulDiv(priceX128, amountDebtToken, 1 << 128)
: FullMath.mulDiv(1 << 128, amountDebtToken, priceX128);
}
// Given that we know how much collateral we will get from Uniswap, we can now use the quoteMint function
amountTokens = quoteMint(isAPE, vaultParams, uint144(amountCollateral));
}
function quoteCollateralToDebtToken(
address debtToken,
address collateralToken,
uint256 amountCollateral
) external view returns (uint256 amountDebtToken) {
// Get Uniswap pool
address uniswapPool = SIR_ORACLE.uniswapFeeTierAddressOf(debtToken, collateralToken);
// Get current price
(uint160 sqrtPriceX96, , , , , , ) = IUniswapV3Pool(uniswapPool).slot0();
// Calculate price fraction with better precision if it doesn't overflow when multiplied by itself
bool inverse = collateralToken == IUniswapV3Pool(uniswapPool).token1();
if (sqrtPriceX96 <= type(uint128).max) {
uint256 priceX192 = uint256(sqrtPriceX96) * sqrtPriceX96;
return
!inverse
? FullMath.mulDiv(priceX192, amountCollateral, 1 << 192)
: FullMath.mulDiv(1 << 192, amountCollateral, priceX192);
} else {
uint256 priceX128 = FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, 1 << 64);
return
!inverse
? FullMath.mulDiv(priceX128, amountCollateral, 1 << 128)
: FullMath.mulDiv(1 << 128, amountCollateral, priceX128);
}
}
/**
* @notice If quoteBurn reverts, burn in Vault.sol will revert as well; vice versa is not necessarily true.
* @return amountCollateral that would be obtained by burning amountTokens.
*/
function quoteBurn(
bool isAPE,
SirStructs.VaultParameters calldata vaultParams,
uint256 amountTokens
) external view returns (uint144 amountCollateral) {
// Get vault state
SirStructs.VaultState memory vaultState = VAULT.vaultStates(vaultParams);
if (vaultState.vaultId == 0) revert VaultDoesNotExist();
if (amountTokens == 0) revert AmountTooLow();
// Get current reserves
SirStructs.Reserves memory reserves = VAULT.getReserves(vaultParams);
if (isAPE) {
// Get supply of APE
address ape = getAddressAPE(vaultState.vaultId);
uint256 supplyAPE = IERC20(ape).totalSupply();
// Get collateralOut
uint144 collateralOut = uint144(FullMath.mulDiv(reserves.reserveApes, amountTokens, supplyAPE));
// Get system parameters
SirStructs.SystemParameters memory systemParams = VAULT.systemParams();
// Get collateral withdrawn
amountCollateral = _feeAPE(collateralOut, systemParams.baseFee.fee, vaultParams.leverageTier);
} else {
// Get supply of TEA
uint256 supplyTEA = VAULT.totalSupply(vaultState.vaultId);
// Get amount of collateral that would be withdrawn
amountCollateral = uint144(FullMath.mulDiv(reserves.reserveLPers, amountTokens, supplyTEA));
}
}
/*////////////////////////////////////////////////////////////////
PRIVATE FUNCTIONS
////////////////////////////////////////////////////////////////*/
function _feeAPE(
uint144 collateralDepositedOrOut,
uint16 baseFee,
int256 leverageTier
) private pure returns (uint144 collateralInOrWithdrawn) {
unchecked {
uint256 feeNum;
uint256 feeDen;
if (leverageTier >= 0) {
feeNum = 10000; // baseFee is uint16, leverageTier is int8, so feeNum does not require more than 24 bits
feeDen = 10000 + (uint256(baseFee) << uint256(leverageTier));
} else {
uint256 temp = 10000 << uint256(-leverageTier);
feeNum = temp;
feeDen = temp + uint256(baseFee);
}
collateralInOrWithdrawn = uint144((uint256(collateralDepositedOrOut) * feeNum) / feeDen);
}
}
function _feeMintTEA(uint144 collateralDeposited, uint16 lpFee) private pure returns (uint144 collateralIn) {
unchecked {
uint256 feeNum = 10000;
uint256 feeDen = 10000 + uint256(lpFee);
collateralIn = uint144((uint256(collateralDeposited) * feeNum) / feeDen);
}
}
function _checkFeeTierExists(
SirStructs.VaultParameters calldata vaultParams,
uint24 feeTier
) private view returns (bool) {
return
UniswapPoolAddress
.computeAddress(
UNISWAPV3_FACTORY,
UniswapPoolAddress.getPoolKey(vaultParams.collateralToken, vaultParams.debtToken, feeTier)
)
.code
.length != 0;
}
function _amountFirstMint(address collateral, uint144 collateralDeposited) private view returns (uint256 amount) {
uint256 collateralTotalSupply = IERC20(collateral).totalSupply();
amount = collateralTotalSupply > SystemConstants.TEA_MAX_SUPPLY / 1e6
? FullMath.mulDiv(SystemConstants.TEA_MAX_SUPPLY, collateralDeposited, collateralTotalSupply)
: collateralDeposited * 1e6;
}
}
"
},
"src/interfaces/IQuoter.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >0.7.6;
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 IQuoter {
/// @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 number of initialized ticks loaded
function quoteExactInput(
bytes memory path,
uint256 amountIn
)
external
view
returns (
uint256 amountOut,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
struct QuoteExactInputSingleWithPoolParams {
address tokenIn;
address tokenOut;
uint256 amountIn;
address pool;
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 `quoteExactInputSingleWithPool`
/// tokenIn The token being swapped in
/// amountIn The desired input amount
/// tokenOut The token being swapped out
/// fee The fee of the pool to consider for the pair
/// pool The address of the pool to consider for the pair
/// 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 loaded
function quoteExactInputSingleWithPool(
QuoteExactInputSingleWithPoolParams memory params
)
external
view
returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, 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
/// amountIn The desired input amount
/// tokenOut The token being swapped out
/// fee The fee of the token pool to consider for the pair
/// 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 loaded
function quoteExactInputSingle(
QuoteExactInputSingleParams memory params
)
external
view
returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate);
struct QuoteExactOutputSingleWithPoolParams {
address tokenIn;
address tokenOut;
uint256 amount;
uint24 fee;
address pool;
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 `QuoteExactOutputSingleWithPoolParams`
/// tokenIn The token being swapped in
/// tokenOut The token being swapped out
/// amount The desired output amount
/// fee The fee of the token pool to consider for the pair
/// pool The address of the pool to consider for the pair
/// 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 loaded
function quoteExactOutputSingleWithPool(
QuoteExactOutputSingleWithPoolParams memory params
)
external
view
returns (uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, 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
/// amountOut The desired output amount
/// fee The fee of the token pool to consider for the pair
/// 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 loaded
function quoteExactOutputSingle(
QuoteExactOutputSingleParams memory params
)
external
view
returns (uint256 amountIn, 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
function quoteExactOutput(
bytes memory path,
uint256 amountOut
)
external
view
returns (
uint256 amountIn,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
}
"
},
"lib/Core/src/interfaces/IVault.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import {SirStructs} from "../libraries/SirStructs.sol";
interface IVault {
error AmountTooLow();
error DeadlineExceeded();
error ExcessiveDeposit();
error InsufficientCollateralReceivedFromUniswap();
error InsufficientDeposit();
error LengthMismatch();
error LeverageTierOutOfRange();
error Locked();
error NotAWETHVault();
error NotAuthorized();
error StringsInsufficientHexLength(uint256 value, uint256 length);
error TEAMaxSupplyExceeded();
error TransferToZeroAddress();
error UnsafeRecipient();
error VaultAlreadyInitialized();
error VaultDoesNotExist();
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event ReservesChanged(uint48 indexed vaultId, bool isAPE, bool isMint, uint144 reserveLPers, uint144 reserveApes);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] vaultIds,
uint256[] amounts
);
event TransferSingle(
address indexed operator,
address indexed from,
address indexed to,
uint256 id,
uint256 amount
);
event URI(string value, uint256 indexed id);
event VaultInitialized(
address indexed debtToken,
address indexed collateralToken,
int8 indexed leverageTier,
uint256 vaultId,
address ape
);
event VaultNewTax(uint48 indexed vault, uint8 tax, uint16 cumulativeTax);
function APE_IMPLEMENTATION() external view returns (address);
function ORACLE() external view returns (address);
function SIR() external view returns (address);
function SYSTEM_CONTROL() external view returns (address);
function TIMESTAMP_ISSUANCE_START() external view returns (uint40);
function balanceOf(address account, uint256 vaultId) external view returns (uint256);
function balanceOfBatch(
address[] memory owners,
uint256[] memory vaultIds
) external view returns (uint256[] memory balances_);
function burn(
bool isAPE,
SirStructs.VaultParameters memory vaultParams,
uint256 amount,
uint40 deadline
) external returns (uint144);
function claimSIR(uint256 vaultId, address lper) external returns (uint80);
function cumulativeSIRPerTEA(uint256 vaultId) external view returns (uint176 cumulativeSIRPerTEAx96);
function getReserves(
SirStructs.VaultParameters memory vaultParams
) external view returns (SirStructs.Reserves memory);
function initialize(SirStructs.VaultParameters memory vaultParams) external;
function isApprovedForAll(address, address) external view returns (bool);
function mint(
bool isAPE,
SirStructs.VaultParameters memory vaultParams,
uint256 amountToDeposit,
uint144 collateralToDepositMin,
uint40 deadline
) external payable returns (uint256 amount);
function numberOfVaults() external view returns (uint48);
function paramsById(uint48 vaultId) external view returns (SirStructs.VaultParameters memory);
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory vaultIds,
uint256[] memory amounts,
bytes memory data
) external;
function safeTransferFrom(address from, address to, uint256 vaultId, uint256 amount, bytes memory data) external;
function setApprovalForAll(address operator, bool approved) external;
function supportsInterface(bytes4 interfaceId) external pure returns (bool);
function systemParams() external view returns (SirStructs.SystemParameters memory systemParams_);
function totalReserves(address collateral) external view returns (uint256);
function totalSupply(uint256 vaultId) external view returns (uint256);
function unclaimedRewards(uint256 vaultId, address lper) external view returns (uint80);
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes memory data) external;
function updateSystemState(uint16 baseFee, uint16 lpFee, bool mintingStopped) external;
function updateVaults(
uint48[] memory oldVaults,
uint48[] memory newVaults,
uint8[] memory newTaxes,
uint16 cumulativeTax
) external;
function uri(uint256 vaultId) external view returns (string memory);
function vaultStates(
SirStructs.VaultParameters memory vaultParams
) external view returns (SirStructs.VaultState memory);
function vaultTax(uint48 vaultId) external view returns (uint8);
function withdrawFees(address token) external returns (uint256 totalFeesToStakers);
function withdrawToSaveSystem(address[] memory tokens, address to) external returns (uint256[] memory amounts);
}
"
},
"lib/Core/src/interfaces/IOracle.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import {SirStructs} from "../libraries/SirStructs.sol";
interface IOracle {
error NoUniswapPool();
error OracleNotInitialized();
error UniswapFeeTierIndexOutOfBounds();
event OracleFeeTierChanged(uint24 feeTierPrevious, uint24 feeTierSelected);
event OracleInitialized(
address indexed token0,
address indexed token1,
uint24 feeTierSelected,
uint136 avLiquidity,
uint40 period
);
event PriceUpdated(address indexed token0, address indexed token1, bool priceTruncated, int64 priceTickX42);
event UniswapFeeTierAdded(uint24 fee);
event UniswapOracleProbed(uint24 fee, uint136 avLiquidity, uint40 period, uint16 cardinalityToIncrease);
function TWAP_DURATION() external view returns (uint40);
function getPrice(address collateralToken, address debtToken) external view returns (int64);
function getUniswapFeeTiers() external view returns (SirStructs.UniswapFeeTier[] memory uniswapFeeTiers);
function initialize(address tokenA, address tokenB) external;
function newUniswapFeeTier(uint24 fee) external;
function state(address token0, address token1) external view returns (SirStructs.OracleState memory);
function uniswapFeeTierAddressOf(address tokenA, address tokenB) external view returns (address);
function uniswapFeeTierOf(address tokenA, address tokenB) external view returns (uint24);
function updateOracleState(
address collateralToken,
address debtToken
) external returns (int64 tickPriceX42, address uniswapPoolAddress);
}
"
},
"lib/Core/lib/v3-core/contracts/interfaces/IUniswapV3Pool.sol": {
"content": "// 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
{
}
"
},
"lib/Core/src/libraries/SirStructs.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SirStructs {
struct VaultIssuanceParams {
uint8 tax; // (tax / type(uint8).max * 10%) of its fee revenue is directed to the Treasury.
uint40 timestampLastUpdate; // timestamp of the last time cumulativeSIRPerTEAx96 was updated. 0 => use systemParams.timestampIssuanceStart instead
uint176 cumulativeSIRPerTEAx96; // Q104.96, cumulative SIR minted by the vaultId per unit of TEA.
}
struct VaultParameters {
address debtToken;
address collateralToken;
int8 leverageTier;
}
struct FeeStructure {
uint16 fee; // Fee in basis points.
uint16 feeNew; // New fee to replace fee if current time exceeds FEE_CHANGE_DELAY since timestampUpdate
uint40 timestampUpdate; // Timestamp fee change was made. If 0, feeNew is not used.
}
struct SystemParameters {
FeeStructure baseFee;
FeeStructure lpFee;
bool mintingStopped; // If true, no minting of TEA/APE
/** Aggregated taxes for all vaults. Choice of uint16 type.
For vault i, (tax_i / type(uint8).max)*10% is charged, where tax_i is of type uint8.
They must satisfy the condition
Σ_i (tax_i / type(uint8).max)^2 ≤ 0.1^2
Under this constraint, cumulativeTax = Σ_i tax_i is maximized when all taxes are equal (tax_i = tax for all i) and
tax = type(uint8).max / sqrt(Nvaults)
Since the lowest non-zero value is tax=1, the maximum number of vaults with non-zero tax is
Nvaults = type(uint8).max^2 < type(uint16).max
*/
uint16 cumulativeTax;
}
/** Collateral owned by the apes and LPers in a vault
*/
struct Reserves {
uint144 reserveApes;
uint144 reserveLPers;
int64 tickPriceX42;
}
/** Data needed for recoverying the amount of collateral owned by the apes and LPers in a vault
*/
struct VaultState {
uint144 reserve; // reserve = reserveApes + reserveLPers
/** Price at the border of the power and saturation zone.
Q21.42 - Fixed point number with 42 bits of precision after the comma.
type(int64).max and type(int64).min are used to represent +∞ and -∞ respectively.
*/
int64 tickPriceSatX42; // Saturation price in Q21.42 fixed point
uint48 vaultId; // Allows the creation of approximately 281 trillion vaults
}
/** The sum of all amounts in Fees are equal to the amounts deposited by the user (in the case of a mint)
or taken out by the user (in the case of a burn).
collateralInOrWithdrawn: Amount of collateral deposited by the user (in the case of a mint) or taken out by the user (in the case of a burn).
collateralFeeToStakers: Amount of collateral paid to the stakers.
collateralFeeToLPers: Amount of collateral paid to the gentlemen.
collateralFeeToProtocol: Amount of collateral paid to the protocol.
*/
struct Fees {
uint144 collateralInOrWithdrawn;
uint144 collateralFeeToStakers;
uint144 collateralFeeToLPers; // Sometimes all LPers and sometimes only protocol owned liquidity
}
struct StakingParams {
uint80 stake; // Amount of staked SIR
uint176 cumulativeETHPerSIRx80; // Cumulative ETH per SIR * 2^80
}
struct StakerParams {
uint80 stake; // Total amount of staked SIR by the staker
uint176 cumulativeETHPerSIRx80; // Cumulative ETH per SIR * 2^80 last time the user updated his balance of ETH dividends
uint80 lockedStake; // Amount of stake that was locked at time 'tsLastUpdate'
uint40 tsLastUpdate; // Timestamp of the last time the user staked or unstaked
}
struct Auction {
address bidder; // Address of the bidder
uint96 bid; // Amount of the bid
uint40 startTime; // Auction start time
}
struct OracleState {
int64 tickPriceX42; // Last stored price. Q21.42
uint40 timeStampPrice; // Timestamp of the last stored price
uint8 indexFeeTier; // Uniswap v3 fee tier currently being used as oracle
uint8 indexFeeTierProbeNext; // Uniswap v3 fee tier to probe next
uint40 timeStampFeeTier; // Timestamp of the last probed fee tier
bool initialized; // Whether the oracle has been initialized
UniswapFeeTier uniswapFeeTier; // Uniswap v3 fee tier currently being used as oracle
}
/**
* Parameters of a Uniswap v3 tier.
*/
struct UniswapFeeTier {
uint24 fee;
int24 tickSpacing;
}
}
"
},
"lib/Core/src/libraries/SystemConstants.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SystemConstants {
uint8 internal constant SIR_DECIMALS = 12;
/** SIR Token Issuance Rate
If we want to issue 2,015,000,000 SIR per year, this implies an issuance rate of 63.9 SIR/s.
*/
uint72 internal constant ISSUANCE = uint72(2015e6 * 10 ** SIR_DECIMALS - 1) / 365 days + 1; // [sir/s]
/** During the first 3 years, 30%-to-33% of the emissions are diverged to contributors.
- 10% to pre-mainnet contributors
- 10%-13% to fundraising contributors
- 10% to a treasury for post-mainnet stuff
*/
uint72 internal constant LP_ISSUANCE_FIRST_3_YEARS = uint72((uint256(56048532400000000) * ISSUANCE) / 1e17);
uint128 internal constant TEA_MAX_SUPPLY = (uint128(LP_ISSUANCE_FIRST_3_YEARS) << 96) / type(uint16).max; // Must fit in uint128
uint40 internal constant THREE_YEARS = 3 * 365 days;
int64 internal constant MAX_TICK_X42 = 1951133415219145403; // log_1.0001(x)*2^42 where x is the max possible Q64.64 value, i.e., 2^64 - 2^-64
// Approximately 10 days. We did not choose 10 days precisely to avoid auctions always ending on the same day and time of the week.
uint40 internal constant AUCTION_COOLDOWN = 247 hours; // 247h & 240h have no common factors
// Duration of an auction
uint40 internal constant AUCTION_DURATION = 24 hours;
// Time it takes for a change of LP or base fee to take effect
uint256 internal constant FEE_CHANGE_DELAY = 10 days;
uint40 internal constant SHUTDOWN_WITHDRAWAL_DELAY = 20 days;
int8 internal constant MAX_LEVERAGE_TIER = 2;
int8 internal constant MIN_LEVERAGE_TIER = -4;
uint256 internal constant HALVING_PERIOD = 30 days; // Every 30 days, half of the locked stake is unlocked
}
"
},
"lib/Core/src/libraries/FullMath.sol": {
"content": "// 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
/// @dev Modified from https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/FullMath.sol so that it can compile on Solidity 8
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) {
// 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.
unchecked {
uint256 twos = (type(uint256).max - denominator + 1) & 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;
}
}
function tryMulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (bool success, uint256 result) {
// 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) {
if (denominator == 0) return (false, 0);
assembly {
result := div(prod0, denominator)
}
return (true, result);
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
if (denominator <= prod1) return (false, 0);
///////////////////////////////////////////////
// 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.
unchecked {
uint256 twos = (type(uint256).max - denominator + 1) & 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 (true, 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) {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
function tryMulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (bool success, uint256 result) {
(success, result) = tryMulDiv(a, b, denominator);
if (success && mulmod(a, b, denominator) > 0) {
if (result == type(uint256).max) return (false, 0);
result++;
}
}
}
"
},
"lib/Core/src/interfaces/IWETH9.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title Interface for WETH9
interface IWETH9 is IERC20 {
/// @notice Deposit ether to get wrapped ether
function deposit() external payable;
/// @notice Withdraw wrapped ether to get ether
function withdraw(uint256) external;
}
"
},
"lib/Core/src/libraries/UniswapPoolAddress.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee
/// @notice Modified from https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol
library UniswapPoolAddress {
bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
/// @notice The identifying key of the pool
struct PoolKey {
address token0;
address token1;
uint24 fee;
}
/// @notice Returns PoolKey: the ordered tokens with the matched fee levels
/// @param tokenA The first token of a pool, unsorted
/// @param tokenB The second token of a pool, unsorted
/// @param fee The fee level of the pool
/// @return Poolkey The pool details with ordered token0 and token1 assignments
function getPoolKey(address tokenA, address tokenB, uint24 fee) internal pure returns (PoolKey memory) {
if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);
return PoolKey({token0: tokenA, token1: tokenB, fee: fee});
}
/// @notice Deterministically computes the pool address given the factory and PoolKey
/// @param factory The Uniswap V3 factory contract address
/// @param key The PoolKey
/// @return pool The contract address of the V3 pool
function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {
require(key.token0 < key.token1);
pool = address(
uint160(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
factory,
keccak256(abi.encode(key.token0, key.token1, key.fee)),
POOL_INIT_CODE_HASH
)
)
)
)
);
}
}
"
},
"lib/Core/src/libraries/AddressClone.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library AddressClone {
/// @dev Hash of the `_CREATE3_PROXY_BYTECODE`.
/// Equivalent to `keccak256(abi.encodePacked(hex"67363d3d37363d34f03d5260086018f3"))`.
bytes32 private constant _CREATE3_PROXY_BYTECODE_HASH =
0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f;
function getAddress(address deployer, uint256 vaultId) internal pure returns (address clone) {
/// @solidity memory-safe-assembly
// solhint-disable-next-line no-inline-assembly
assembly {
// Cache the free memory pointer.
let m := mload(0x40)
// Store `address(this)`.
mstore(0x00, deployer)
// Store the prefix.
mstore8(0x0b, 0xff)
// Store the salt.
mstore(0x20, vaultId)
// Store the bytecode hash.
mstore(0x40, _CREATE3_PROXY_BYTECODE_HASH)
// Store the proxy's address.
mstore(0x14, keccak256(0x0b, 0x55))
// Restore the free memory pointer.
mstore(0x40, m)
// 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01).
// 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex).
mstore(0x00, 0xd694)
// Nonce of the proxy contract (1).
mstore8(0x34, 0x01)
clone := and(keccak256(0x1e, 0x17), 0xffffffffffffffffffffffffffffffffffffffff)
}
}
}
"
},
"lib/forge-std/src/console.sol": {
"content": "// 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(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", 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, int256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,int256)", 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
Submitted on: 2025-10-03 11:22:25
Comments
Log in to comment.
No comments yet.