Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 4,949 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Redeem | 60860377 | 3 days ago | IN | 0 S | 0.00427284 | ||||
| Approve | 60624265 | 6 days ago | IN | 0 S | 0.0014427 | ||||
| Approve | 59995282 | 15 days ago | IN | 0 S | 0.0014427 | ||||
| Approve | 59679231 | 18 days ago | IN | 0 S | 0.0014427 | ||||
| Request Redeem | 59599341 | 20 days ago | IN | 0 S | 0.00636262 | ||||
| Approve | 59599332 | 20 days ago | IN | 0 S | 0.00269005 | ||||
| Approve | 59131642 | 26 days ago | IN | 0 S | 0.0014427 | ||||
| Approve | 59108201 | 27 days ago | IN | 0 S | 0.0014427 | ||||
| Permit | 58149379 | 38 days ago | IN | 0 S | 0.00274485 | ||||
| Approve | 57919780 | 41 days ago | IN | 0 S | 0.0014427 | ||||
| Request Redeem | 57574140 | 45 days ago | IN | 0 S | 0.00578485 | ||||
| Approve | 57574126 | 45 days ago | IN | 0 S | 0.0024455 | ||||
| Request Redeem | 57510554 | 46 days ago | IN | 0 S | 0.00636262 | ||||
| Approve | 57510545 | 46 days ago | IN | 0 S | 0.00273896 | ||||
| Redeem | 57066300 | 52 days ago | IN | 0 S | 0.00285645 | ||||
| Approve | 56987392 | 52 days ago | IN | 0 S | 0.00145713 | ||||
| Approve | 56692883 | 56 days ago | IN | 0 S | 0.0014427 | ||||
| Approve | 56585445 | 57 days ago | IN | 0 S | 0.0014427 | ||||
| Request Redeem | 56495263 | 59 days ago | IN | 0 S | 0.0063619 | ||||
| Approve | 56495237 | 59 days ago | IN | 0 S | 0.00269005 | ||||
| Approve | 55679262 | 67 days ago | IN | 0 S | 0.0014163 | ||||
| Request Redeem | 55457195 | 69 days ago | IN | 0 S | 0.00633622 | ||||
| Approve | 55457142 | 69 days ago | IN | 0 S | 0.00269005 | ||||
| Request Redeem | 55102261 | 72 days ago | IN | 0 S | 0.00553225 | ||||
| Approve | 55102191 | 72 days ago | IN | 0 S | 0.0023523 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 20874975 | 281 days ago | Contract Creation | 0 S |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
CommonPool
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 10 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ERC4626} from "solmate/tokens/ERC4626.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {BytesLib} from "./libraries/BytesLib.sol";
import {MathLite} from "./libraries/MathLite.sol";
import {RedeemVault} from "./RedeemVault.sol";
import {ICommonPool} from "./interfaces/ICommonPool.sol";
import {IRelativeRouter} from "./interfaces/IRelativeRouter.sol";
import {ISwapModule} from "./interfaces/ISwapModule.sol";
import {IMarketToken} from "./interfaces/IMarketToken.sol";
import {IMarketUtils} from "./interfaces/IMarketUtils.sol";
import {IErrors} from "./interfaces/IErrors.sol";
import {IOracle} from "./interfaces/IOracle.sol";
import {IHelper} from "./interfaces/IHelper.sol";
import "forge-std/console.sol";
// Gdai proxy: 0xd85E038593d7A098614721EaE955EC2022B9B91B
// Gdai impl: 0xBBDa8719A932b3cE5B7C56f427d97Fe4A8e305Fa
contract CommonPool is ICommonPool, ERC4626, AccessControl {
using EnumerableSet for EnumerableSet.AddressSet;
using SafeTransferLib for ERC20;
// Array to store the redeem requests
// New requests are pushed to the end and fulfilled requests(claimable or claimed) are cleared to reclaim storage gas
RedeemRequestItem[] redeemRequestsQueue;
// Requests are processed in increasing order, so all `redeemRequestsQueue[i]` where i < `pendingRequestIndex` would be claimable
uint256 pendingRequestIndex;
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant FUND_MANAGER_ROLE = keccak256("FUND_MANAGER_ROLE");
uint256 public constant PRECISION = 1e30;
EnumerableSet.AddressSet private activeMarkets;
uint256 public navStored;
uint256 navEquivalentAsset;
// Live ratio of (total Assets)/(total Shares) along with a `PRECISION` multiplier
uint256 public shareToAssetPrice;
IRelativeRouter public router;
IHelper public helper;
address public routerSender;
address public depositVault;
address public withdrawVault;
ISwapModule public swapModule;
// Amount of shares(by controller) that were requested to be redeemed and still pending
mapping(address => uint256) public pendingRedeem;
uint256 public totalPendingRedeem;
// Amount of shares(by controller) that were requested to be redeemed and are claimable
mapping(address => uint256) public claimableRedeem;
uint256 public totalClaimableRedeem;
// Amount of assets(by controller) that are claimable through `redeem()`/`mint()`
// When multiple requests are claimable, the asset values add up so that the final redeemable shares get an aggregated price
mapping(address => uint256) public claimableRedeemAssets;
uint256 totalClaimableRedeemAssets;
// Claimable assets are stored safely in `redeemVault`. This ensures they can't be used in allocations and won't count towards NAV computation
address public immutable redeemVault;
mapping(address controller => mapping(address operator => bool)) public isOperator;
// Only approved addresses will be given allowance permission for performing swaps
mapping(address => bool) public approvedExternalAddr;
// Only approved markets can be used in allocations
mapping(address => bool) public approvedMarkets;
// Temporary mappings that used and cleared within a function
mapping(address => uint256) requiredAllowances;
// @dev sets oracle prices, perform any additional tasks required,
// and clear the oracle prices after
//
// care should be taken to avoid re-entrancy while using this call
// since re-entrancy could allow functions to be called with prices
// meant for a different type of transaction
// the tokensWithPrices.length check in oracle.setPrices should help
// mitigate this
//
// @param oracle Oracle
// @param params OracleUtils.SetPricesParams
modifier withOraclePrices(IOracle.SetPricesParams memory params) {
helper.oracle().setPrices{value: msg.value}(
params
);
_;
helper.oracle().clearAllPrices();
}
constructor(
ERC20 _asset,
string memory _name,
string memory _symbol,
address _router,
address _routerSender,
address _depositVault,
address _withdrawVault,
address _helper,
address _swapModule
) ERC4626(_asset, _name, _symbol) {
if (_router == address(0)) revert IErrors.InvalidAddress();
if (_routerSender == address(0)) revert IErrors.InvalidAddress();
if (_depositVault == address(0)) revert IErrors.InvalidAddress();
if (_withdrawVault == address(0)) revert IErrors.InvalidAddress();
if (_helper == address(0)) revert IErrors.InvalidAddress();
if (_swapModule == address(0)) revert IErrors.InvalidAddress();
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
router = IRelativeRouter(_router);
routerSender = _routerSender;
depositVault = _depositVault;
withdrawVault = _withdrawVault;
helper = IHelper(_helper);
swapModule = ISwapModule(_swapModule);
shareToAssetPrice = PRECISION;
RedeemVault _redeemVault = new RedeemVault(asset);
redeemVault = address(_redeemVault);
}
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
return
interfaceId == 0xe3bc4e65 || // ERC165 Interface ID for ERC7540
interfaceId == 0x2f0a18c5 || // ERC165 Interface ID for ERC7575
interfaceId == 0x620ee8e4 || // ERC165 Interface ID for Async redeem vaults
super.supportsInterface(interfaceId);
}
/*//////////////////////////////////////////////////////////////
ERC7575 LOGIC
//////////////////////////////////////////////////////////////*/
function share() public view returns (address) {
return address(this);
}
/// @notice Approve or disapprove a series of addresses
/// @dev Only owner can call this function
/// @param _addr The pool addresses to approve or disapprove
/// @param _status The status of the pool
function updateApprovedExternalAddr(
address[] calldata _addr,
bool[] calldata _status
) external onlyRole(ADMIN_ROLE) {
if (_addr.length != _status.length) revert IErrors.InvalidLength();
for (uint256 i; i < _addr.length;) {
if(_addr[i] == address(0)) revert IErrors.InvalidAddress();
approvedExternalAddr[_addr[i]] = _status[i];
unchecked {
i++;
}
}
emit ApprovedExternalAddrUpdated(_addr, _status);
}
/// @notice Approve or disapprove a series of addresses
/// @dev Only owner can call this function
/// @param _addr The markert addresses to approve or disapprove
/// @param _status The status of the market
function updateApprovedMarkets(
address[] calldata _addr,
bool[] calldata _status
) external onlyRole(ADMIN_ROLE) {
if (_addr.length != _status.length) revert IErrors.InvalidLength();
for (uint256 i; i < _addr.length; i++) {
if(_addr[i] == address(0)) revert IErrors.InvalidAddress();
approvedMarkets[_addr[i]] = _status[i];
}
emit ApprovedMarketsUpdated(_addr, _status);
}
/// @notice Update the swap module for the pool
function updateSwapModule(address _newModule) external onlyRole(ADMIN_ROLE) {
if (_newModule == address(0)) revert IErrors.InvalidAddress();
swapModule = ISwapModule(_newModule);
emit SwapModuleUpdated(_newModule);
}
function updateRouter(address _newRouter) external onlyRole(ADMIN_ROLE) {
if (_newRouter == address(0)) revert IErrors.InvalidAddress();
router = IRelativeRouter(_newRouter);
emit RouterUpdated(_newRouter);
}
function updateRouterSender(address _newSender) external onlyRole(ADMIN_ROLE) {
if (_newSender == address(0)) revert IErrors.InvalidAddress();
routerSender = _newSender;
emit RouterSenderUpdated(_newSender);
}
function updateDepositVault(address _newDepositVault) external onlyRole(ADMIN_ROLE) {
if (_newDepositVault == address(0)) revert IErrors.InvalidAddress();
depositVault = _newDepositVault;
emit DepositVaultUpdated(_newDepositVault);
}
function updateWithdrawVault(address _newWithdrawVault) external onlyRole(ADMIN_ROLE) {
if (_newWithdrawVault == address(0)) revert IErrors.InvalidAddress();
withdrawVault = _newWithdrawVault;
emit WithdrawVaultUpdated(_newWithdrawVault);
}
function updateHelper(address _newHelper) external onlyRole(ADMIN_ROLE) {
if (_newHelper == address(0)) revert IErrors.InvalidAddress();
helper = IHelper(_newHelper);
emit HelperUpdated(_newHelper);
}
/////////////////////////////// Vault Functions ///////////////////////////////////////
/// @notice Allocate funds to the markets
function allocateFunds(WithdrawMulticall[] calldata _withdraws, DepositMulticall[] calldata _deposits) external payable onlyRole(FUND_MANAGER_ROLE) returns (bytes[] memory results) {
_validateAllocation(_withdraws, _deposits);
(bytes[] memory _data, address[] memory _markets) = helper
.buildTransactionData(_withdraws, _deposits);
// Approving funds being sent via SendTokens
_approveAllocation(_withdraws, _deposits);
// Updating enumerable set with the new markets
_addMarkets(_markets);
// Send transaction data to the router
results = router.multicall{value: msg.value}(_data);
}
/// @notice Perform swap to convert between tokens & wnt
function performSwap(
bytes[] calldata _swapInput,
SendTokenParams[] calldata _requiredAllowance
) public payable onlyRole(FUND_MANAGER_ROLE) returns (bytes[] memory results) {
// Approving the required tokens
_approveSpending(_requiredAllowance);
// Swapping via the swapModule
// The swap module should make sure exact amount of `msg.value` is provided
results = swapModule.swap{value: msg.value}(_swapInput);
}
/// @notice Finalize the reallocation and recalculate NAV
/// @dev As the reallocation is a request we have no view of the final state (atomically)
/// we need to ensure that the new NAV is recalculated once the reallocation is complete
function recalculateNAV(
IOracle.SetPricesParams memory _oracleParams
) public payable onlyRole(FUND_MANAGER_ROLE) withOraclePrices(_oracleParams) {
(
uint256 _navValue,
uint256 assetEquivalent,
address[] memory markets,
uint256[] memory marketBalances
) = _currentNAV();
// Removing empty markets
_removeMarkets(markets, marketBalances);
// Updating the stored navValue and distributing NAV per share
navStored = _navValue;
navEquivalentAsset = assetEquivalent;
shareToAssetPrice = (navEquivalentAsset * PRECISION) / totalSupply;
emit RecalculatedNAV(navStored, shareToAssetPrice);
}
// Serve the redeem requests in the queue upto `maxAssets`
function fulfillRequests(uint256 maxAssets) external onlyRole(FUND_MANAGER_ROLE) returns (uint256 claimableShares, uint256 claimableAssets) {
(claimableShares, claimableAssets) = _fulfillRequests(maxAssets);
}
/////////////////////////////// LP Functions ///////////////////////////////////////
function deposit(
uint256 assets,
address receiver
) public override returns (uint256 shares) {
shares = previewDeposit(assets);
_scaleVariables(shares, assets, true);
// Need to transfer before minting or ERC777s could reenter.
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
}
function requestRedeem(uint256 shares, address controller, address owner) public returns (uint256 requestId) {
// Request ID is always 0
requestId = 0;
require(shares != 0);
if(owner != msg.sender && !isOperator[owner][msg.sender]) {
// sender is neither `owner` nor their operator. Need to request from their allowance
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
// TOASK: also need to emit `Approve()` with remaining allowance value? How does subgraph keep track? msg.sender?
}
// Move the shares into custody of pool. They will be burned later during final redeem
_transfer(owner, address(this), shares);
redeemRequestsQueue.push(RedeemRequestItem({controller: controller, shares: shares}));
emit RedeemRequest(controller, owner, requestId, msg.sender, shares);
pendingRedeem[controller] += shares;
totalPendingRedeem += shares;
}
function pendingRedeemRequest(uint256 requestId, address controller) public view returns (uint256 shares) {
if (requestId != 0) {
// Only request ID 0 is supported
return 0;
}
return pendingRedeem[controller];
}
function claimableRedeemRequest(uint256 requestId, address controller) public view returns (uint256 shares) {
if (requestId != 0) {
// Only request ID 0 is supported
return 0;
}
return claimableRedeem[controller];
}
function withdraw(
uint256 assets,
address receiver,
address controller
) public override returns (uint256 shares) {
require(assets != 0);
require(controller == msg.sender || isOperator[controller][msg.sender]);
if (assets > maxWithdraw(controller)) revert IErrors.LimitExceeded();
uint256 claimableShares = claimableRedeem[controller];
uint256 claimableAssets = claimableRedeemAssets[controller];
// NOTE: the rounding up might result in a state with 0 claimable shares and non-zero claimable assets
// This is fine becasue `withdraw()` can be called again to get the remaining assets at cost of 0 shares
shares = MathLite.mulDivUp(assets, claimableShares, claimableAssets);
claimableRedeem[controller] -= shares;
totalClaimableRedeem -= shares;
claimableRedeemAssets[controller] -= assets;
totalClaimableRedeemAssets -= assets;
asset.safeTransferFrom(redeemVault, receiver, assets);
emit Withdraw(msg.sender, receiver, controller, assets, shares);
}
function mint(
uint256 shares,
address receiver
) public override returns (uint256 assets) {
assets = previewMint(shares);
_scaleVariables(shares, assets, true);
// Need to transfer before minting or ERC777s could reenter.
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
}
function redeem(
uint256 shares,
address receiver,
address controller
) public override returns (uint256 assets) {
require(shares != 0);
require(controller == msg.sender || isOperator[controller][msg.sender]);
if (shares > maxRedeem(controller)) revert IErrors.LimitExceeded();
uint256 claimableShares = claimableRedeem[controller];
uint256 claimableAssets = claimableRedeemAssets[controller];
assets = MathLite.mulDiv(shares, claimableAssets, claimableShares);
claimableRedeem[controller] -= shares;
totalClaimableRedeem -= shares;
claimableRedeemAssets[controller] -= assets;
totalClaimableRedeemAssets -= assets;
asset.safeTransferFrom(redeemVault, receiver, assets);
emit Withdraw(msg.sender, receiver, controller, assets, shares);
}
function convertToShares(
uint256 assets
) public view override returns (uint256 shares) {
return MathLite.mulDiv(assets, PRECISION, shareToAssetPrice);
}
function convertToAssets(
uint256 shares
) public view override returns (uint256 assets) {
return MathLite.mulDiv(shares, shareToAssetPrice, PRECISION);
}
function previewMint(uint256 shares) public view override returns (uint256) {
return MathLite.mulDivUp(shares, shareToAssetPrice, PRECISION);
}
function maxRedeem(address controller) public view override returns (uint256) {
return claimableRedeem[controller];
}
function maxWithdraw(address controller) public view override returns (uint256) {
return claimableRedeemAssets[controller];
}
function setOperator(address operator, bool approved) public returns (bool) {
isOperator[msg.sender][operator] = approved;
emit OperatorSet(msg.sender, operator, approved);
return true;
}
/// @dev According to EIP-7540, for asynchronous redeem vaults "previewRedeem and previewWithdraw MUST revert for all callers and inputs"
function previewRedeem(uint256 /*shares*/) public pure override returns (uint256) {
revert IErrors.NotAllowed();
}
function previewWithdraw(uint256 /*assets*/) public pure override returns (uint256) {
revert IErrors.NotAllowed();
}
/////////////////////////////// Vault Data Functions ///////////////////////////////////////
/// @notice Fetches the total assets theoretically in the pool i.e. total deposited + total liability
/// @dev This will return the value of the vault in the depositAsset
function totalAssets() public view override returns (uint256) {
return navEquivalentAsset;
}
/// @notice Fetches the list of markets deployed to and their allocation amount
/// @dev Allocation will be market token balance across markets instead of USD
function currentAllocation()
public
view
returns (address[] memory _markets, uint256[] memory _balances)
{
_markets = activeMarkets.values();
_balances = new uint256[](_markets.length);
for (uint256 i; i < _markets.length; ) {
_balances[i] = IERC20(_markets[i]).balanceOf(address(this));
unchecked {
i++;
}
}
}
/////////////////////////////// Internal Functions ///////////////////////////////////////
function _fulfillRequests(uint256 maxAssets) internal returns (uint256 claimableShares, uint256 claimableAssets) {
while (pendingRequestIndex < redeemRequestsQueue.length) {
RedeemRequestItem storage request = redeemRequestsQueue[pendingRequestIndex];
uint256 requiredAssets = convertToAssets(request.shares);
if (claimableAssets + requiredAssets > maxAssets) {
// Cannot fulfill the request completely, so leave it at pending
break;
}
claimableAssets += requiredAssets;
claimableShares += request.shares;
// fulfill the request moving it to claimable
pendingRedeem[request.controller] -= request.shares;
totalPendingRedeem -= request.shares;
claimableRedeem[request.controller] += request.shares;
totalClaimableRedeem += request.shares;
claimableRedeemAssets[request.controller] += requiredAssets;
totalClaimableRedeemAssets += requiredAssets;
// Clear storage for gas refunds
delete redeemRequestsQueue[pendingRequestIndex];
pendingRequestIndex++;
}
// No request was fulfilled. Just return
if (claimableShares == 0) return (claimableShares, claimableAssets);
// Some requests were successfully fulfilled. Need to update books and reserve funds
_scaleVariables(claimableShares, claimableAssets, false);
asset.safeTransfer(redeemVault, claimableAssets);
// Shares were already transferred to `this` during `requestRedeem()`. Time to burn them
_burn(address(this), claimableShares);
emit FulfilledRedeemRequests(claimableShares, claimableAssets);
}
/// @notice Values the allocation assets and pools assets in USD
function _currentNAV()
internal
view
returns (uint256 usdValue, uint256 assetEquivalent, address[] memory markets, uint256[] memory marketBalances)
{
(usdValue, assetEquivalent, markets, marketBalances) = helper.calculateNAV(
address(asset),
activeMarkets.values(),
address(this)
);
}
function _validateAllocation(
WithdrawMulticall[] calldata _withdraws,
DepositMulticall[] calldata _deposits
) internal view {
// Make sure market is approved and receivers are correct
for (uint256 i; i < _withdraws.length; i++) {
WithdrawMulticall calldata _withdraw = _withdraws[i];
if (!approvedMarkets[_withdraw.position.market]) {
revert IErrors.InvalidMarket(_withdraw.position.market);
}
if (_withdraw.position.receiver != address(this)) {
revert IErrors.InvalidReceiver(_withdraw.position.receiver);
}
if (_withdraw.sendWnt.amount > 0 && _withdraw.sendWnt.receiver != withdrawVault) {
revert IErrors.InvalidReceiver(_withdraw.sendWnt.receiver);
}
for (uint256 j; j < _withdraw.sendTokens.length; j++) {
if (_withdraw.sendTokens[j].receiver != withdrawVault) {
revert IErrors.InvalidReceiver(_withdraw.sendTokens[j].receiver);
}
}
}
for (uint256 i; i < _deposits.length; i++) {
DepositMulticall calldata _deposit = _deposits[i];
if (!approvedMarkets[_deposit.position.market]) {
revert IErrors.InvalidMarket(_deposit.position.market);
}
if (_deposit.position.receiver != address(this)) {
revert IErrors.InvalidReceiver(_deposit.position.receiver);
}
if (_deposit.sendWnt.amount > 0 && _deposit.sendWnt.receiver != depositVault) {
revert IErrors.InvalidReceiver(_deposit.sendWnt.receiver);
}
for (uint256 j; j < _deposit.sendTokens.length; j++) {
if (_deposit.sendTokens[j].receiver != depositVault) {
revert IErrors.InvalidReceiver(_deposit.sendTokens[j].receiver);
}
}
}
}
function _approveAllocation(
WithdrawMulticall[] calldata _withdraws,
DepositMulticall[] calldata _deposits
) internal {
// Aggregating the spending from withdrawTx
for (uint256 i; i < _withdraws.length; i++) {
for (uint256 j; j < _withdraws[i].sendTokens.length; j++) {
requiredAllowances[_withdraws[i].sendTokens[j].token] += _withdraws[i].sendTokens[j].amount;
}
}
// Aggregating the spending from depositTx
for (uint256 i; i < _deposits.length; i++) {
for (uint256 j; j < _deposits[i].sendTokens.length; j++) {
requiredAllowances[_deposits[i].sendTokens[j].token] += _deposits[i].sendTokens[j].amount;
}
}
// Approving the spending from withdrawTx
for (uint256 i; i < _withdraws.length; i++) {
for (uint256 j; j < _withdraws[i].sendTokens.length; j++) {
address token = _withdraws[i].sendTokens[j].token;
if(requiredAllowances[token] == 0) continue;
IERC20(token).approve(
routerSender,
requiredAllowances[token]
);
requiredAllowances[token] = 0;
}
}
// Approving the spending from depositTx
for (uint256 i; i < _deposits.length; i++) {
for (uint256 j; j < _deposits[i].sendTokens.length; j++) {
address token = _deposits[i].sendTokens[j].token;
if(requiredAllowances[token] == 0) continue;
IERC20(token).approve(
routerSender,
requiredAllowances[token]
);
requiredAllowances[token] = 0;
}
}
}
/// @notice Add markets to the active markets list
function _addMarkets(address[] memory _markets) internal {
for (uint256 i; i < _markets.length; ) {
activeMarkets.add(_markets[i]);
unchecked {
i++;
}
}
}
function _removeMarkets(
address[] memory _markets,
uint256[] memory _marketBalances
) internal {
for (uint256 i; i < _markets.length; ) {
if (_marketBalances[i] == 0) {
activeMarkets.remove(_markets[i]);
}
unchecked {
i++;
}
}
}
/// @notice Fetches swap contract to approve for spending
function _approveSpending(
SendTokenParams[] calldata _requiredAllowance
) internal {
for (uint256 i; i < _requiredAllowance.length; i++) {
SendTokenParams calldata send = _requiredAllowance[i];
// We just approve the allowance for swap instead of send it to contract
address spender = send.receiver;
// Checking the spender address is approved by the admin
if (!approvedExternalAddr[spender]) revert IErrors.InvalidSpender(spender);
IERC20(send.token).approve(spender, send.amount);
}
}
/// @dev Called on deposit/withdraw/redeem/mint to scale visible price
// NOTE: Should be internal for tests and private for prod (contract size)
function _scaleVariables(
uint256 shares,
uint256 assetAmount,
bool isDeposit
) internal {
// Update the navEquivalentAsset, which in turn affects `totalAssets()`
navEquivalentAsset = isDeposit ? navEquivalentAsset + assetAmount : navEquivalentAsset - assetAmount;
uint256 currentSupply = totalSupply;
uint256 finalSupply = isDeposit ? currentSupply + shares : currentSupply - shares;
if (finalSupply == 0) {
// Reset price when the pool is emptied
shareToAssetPrice = PRECISION;
return;
}
// This the current value of assets along with a precision multiplier
uint256 currentTotalAssets = shareToAssetPrice * currentSupply;
uint256 scaledAssetAmount = assetAmount * PRECISION;
uint256 updatedTotalAssets = isDeposit
? currentTotalAssets + scaledAssetAmount
: currentTotalAssets - scaledAssetAmount;
shareToAssetPrice = updatedTotalAssets / finalSupply;
}
/// @dev Private implementation of transfer functions to reduce bytecode
function _transfer(
address _from,
address _to,
uint256 _amount
) private returns (bool) {
balanceOf[_from] -= _amount;
balanceOf[_to] += _amount;
emit Transfer(_from, _to, _amount);
return true;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)
pragma solidity ^0.8.20;
interface IERC5267 {
/**
* @dev MAY be emitted to signal that the domain could have changed.
*/
event EIP712DomainChanged();
/**
* @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
* signature.
*/
function eip712Domain()
external
view
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @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 value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/
error ECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/
error ECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError, bytes32) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol)
pragma solidity ^0.8.20;
import {MessageHashUtils} from "./MessageHashUtils.sol";
import {ShortStrings, ShortString} from "../ShortStrings.sol";
import {IERC5267} from "../../interfaces/IERC5267.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
* encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract
* does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to
* produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
* separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the
* separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
*
* @custom:oz-upgrades-unsafe-allow state-variable-immutable
*/
abstract contract EIP712 is IERC5267 {
using ShortStrings for *;
bytes32 private constant TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _cachedDomainSeparator;
uint256 private immutable _cachedChainId;
address private immutable _cachedThis;
bytes32 private immutable _hashedName;
bytes32 private immutable _hashedVersion;
ShortString private immutable _name;
ShortString private immutable _version;
string private _nameFallback;
string private _versionFallback;
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
constructor(string memory name, string memory version) {
_name = name.toShortStringWithFallback(_nameFallback);
_version = version.toShortStringWithFallback(_versionFallback);
_hashedName = keccak256(bytes(name));
_hashedVersion = keccak256(bytes(version));
_cachedChainId = block.chainid;
_cachedDomainSeparator = _buildDomainSeparator();
_cachedThis = address(this);
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
return _cachedDomainSeparator;
} else {
return _buildDomainSeparator();
}
}
function _buildDomainSeparator() private view returns (bytes32) {
return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/**
* @dev See {IERC-5267}.
*/
function eip712Domain()
public
view
virtual
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
return (
hex"0f", // 01111
_EIP712Name(),
_EIP712Version(),
block.chainid,
address(this),
bytes32(0),
new uint256[](0)
);
}
/**
* @dev The name parameter for the EIP712 domain.
*
* NOTE: By default this function reads _name which is an immutable value.
* It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
*/
// solhint-disable-next-line func-name-mixedcase
function _EIP712Name() internal view returns (string memory) {
return _name.toStringWithFallback(_nameFallback);
}
/**
* @dev The version parameter for the EIP712 domain.
*
* NOTE: By default this function reads _version which is an immutable value.
* It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
*/
// solhint-disable-next-line func-name-mixedcase
function _EIP712Version() internal view returns (string memory) {
return _version.toStringWithFallback(_versionFallback);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)
pragma solidity ^0.8.20;
import {Strings} from "../Strings.sol";
/**
* @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
*
* The library provides methods for generating a hash of a message that conforms to the
* https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
* specifications.
*/
library MessageHashUtils {
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing a bytes32 `messageHash` with
* `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
* hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
*
* NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
* keccak256, although any bytes32 value can be safely used because the final digest will
* be re-hashed.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
}
}
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing an arbitrary `message` with
* `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
* hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
return
keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
}
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x00` (data with intended validator).
*
* The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
* `validator` address. Then hashing the result.
*
* See {ECDSA-recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(hex"19_00", validator, data));
}
/**
* @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).
*
* The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
* `\x19\x01` and hashing the result. It corresponds to the hash signed by the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
*
* See {ECDSA-recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, hex"19_01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
digest := keccak256(ptr, 0x42)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// 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 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
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 for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the 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.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // 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 preconditions 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 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol)
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
// | length | 0x BB |
type ShortString is bytes32;
/**
* @dev This library provides functions to convert short memory strings
* into a `ShortString` type that can be used as an immutable variable.
*
* Strings of arbitrary length can be optimized using this library if
* they are short enough (up to 31 bytes) by packing them with their
* length (1 byte) in a single EVM word (32 bytes). Additionally, a
* fallback mechanism can be used for every other case.
*
* Usage example:
*
* ```solidity
* contract Named {
* using ShortStrings for *;
*
* ShortString private immutable _name;
* string private _nameFallback;
*
* constructor(string memory contractName) {
* _name = contractName.toShortStringWithFallback(_nameFallback);
* }
*
* function name() external view returns (string memory) {
* return _name.toStringWithFallback(_nameFallback);
* }
* }
* ```
*/
library ShortStrings {
// Used as an identifier for strings longer than 31 bytes.
bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;
error StringTooLong(string str);
error InvalidShortString();
/**
* @dev Encode a string of at most 31 chars into a `ShortString`.
*
* This will trigger a `StringTooLong` error is the input string is too long.
*/
function toShortString(string memory str) internal pure returns (ShortString) {
bytes memory bstr = bytes(str);
if (bstr.length > 31) {
revert StringTooLong(str);
}
return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
}
/**
* @dev Decode a `ShortString` back to a "normal" string.
*/
function toString(ShortString sstr) internal pure returns (string memory) {
uint256 len = byteLength(sstr);
// using `new string(len)` would work locally but is not memory safe.
string memory str = new string(32);
/// @solidity memory-safe-assembly
assembly {
mstore(str, len)
mstore(add(str, 0x20), sstr)
}
return str;
}
/**
* @dev Return the length of a `ShortString`.
*/
function byteLength(ShortString sstr) internal pure returns (uint256) {
uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
if (result > 31) {
revert InvalidShortString();
}
return result;
}
/**
* @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
*/
function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
if (bytes(value).length < 32) {
return toShortString(value);
} else {
StorageSlot.getStringSlot(store).value = value;
return ShortString.wrap(FALLBACK_SENTINEL);
}
}
/**
* @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
*/
function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
return toString(value);
} else {
return store;
}
}
/**
* @dev Return the length of a string that was encoded to `ShortString` or written to storage using
* {setWithFallback}.
*
* WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
* actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
*/
function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
return byteLength(value);
} else {
return bytes(store).length;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.20;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 value => uint256) _positions;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {IRelativeRouter} from "./IRelativeRouter.sol";
interface ICommonPool {
struct WithdrawMulticall {
SendWntParams sendWnt;
SendTokenParams[] sendTokens;
IRelativeRouter.CreateWithdrawalParams position;
}
struct DepositMulticall {
SendWntParams sendWnt;
SendTokenParams[] sendTokens;
IRelativeRouter.CreateDepositParams position;
}
struct MarketProps {
address marketToken;
address indexToken;
address longToken;
address shortToken;
}
struct PriceProps {
uint256 min;
uint256 max;
}
struct SendWntParams {
address receiver;
uint256 amount;
}
struct SendTokenParams {
address token;
address receiver;
uint256 amount;
}
struct RedeemRequestItem {
// The controller for the request who gets access to the resulting assets
address controller;
// Amount of shares redeemed
uint256 shares;
}
event OperatorSet(address indexed controller, address indexed operator, bool approved);
event RedeemRequest(address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 shares);
event ApprovedExternalAddrUpdated(address[] market, bool[] status);
event ApprovedMarketsUpdated(address[] markets, bool[] status);
event SwapModuleUpdated(address newModule);
event RouterUpdated(address newRouter);
event RouterSenderUpdated(address newRouterSender);
event DepositVaultUpdated(address newDepositVault);
event WithdrawVaultUpdated(address newWithdrawVault);
event HelperUpdated(address newHelper);
event MarketUtilsUpdated(address newModule);
event RecalculatedNAV(uint256 navValue, uint256 shareToAssetPrice);
event FulfilledRedeemRequests(uint256 shares, uint256 assets);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IErrors {
// Generic Errors //
error InvalidLength();
error InvalidAddress();
error InvalidCaller();
// CommonPool Errors //
error NotAllowed();
error InvalidAmount(uint256 expected, uint256 actual);
error LimitExceeded();
error InvalidMarket(address market);
error InvalidReceiver(address receiver);
// SwapModule & Swapper Errors //
error InvalidSpender(address spender);
error ReceiverNotCaller();
error InvalidMinOut(uint256 amountOut);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ICommonPool} from "./ICommonPool.sol";
import {IOracle} from "./IOracle.sol";
interface IHelper {
function oracle() external view returns (IOracle);
function buildTransactionData(
ICommonPool.WithdrawMulticall[] calldata _withdraws,
ICommonPool.DepositMulticall[] calldata _deposits
) external pure returns (bytes[] memory, address[] memory);
function calculateNAV(
address _asset,
address[] memory _markets,
address poolAddress
) external view returns (uint256, uint256, address[] memory, uint256[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IMarketToken {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
// @dev interface with MarketUtils and function call used on Reader
interface IMarketUtils {
// @param min the min price
// @param max the max price
struct PriceProps {
uint256 min;
uint256 max;
}
// @param marketToken address of the market token for the market
// @param indexToken address of the index token for the market
// @param longToken address of the long token for the market
// @param shortToken address of the short token for the market
// @param data for any additional data
struct MarketProps {
address marketToken;
address indexToken;
address longToken;
address shortToken;
}
// @dev struct to store the prices of tokens of a market
// @param indexTokenPrice price of the market's index token
// @param longTokenPrice price of the market's long token
// @param shortTokenPrice price of the market's short token
struct MarketPrices {
PriceProps indexTokenPrice;
PriceProps longTokenPrice;
PriceProps shortTokenPrice;
}
// @dev struct to avoid stack too deep errors for the getPoolValue call
// @param value the pool value
// @param longTokenAmount the amount of long token in the pool
// @param shortTokenAmount the amount of short token in the pool
// @param longTokenUsd the USD value of the long tokens in the pool
// @param shortTokenUsd the USD value of the short tokens in the pool
// @param totalBorrowingFees the total pending borrowing fees for the market
// @param borrowingFeePoolFactor the pool factor for borrowing fees
// @param impactPoolAmount the amount of tokens in the impact pool
// @param longPnl the pending pnl of long positions
// @param shortPnl the pending pnl of short positions
// @param netPnl the net pnl of long and short positions
struct PoolValueProps {
int256 poolValue;
int256 longPnl;
int256 shortPnl;
int256 netPnl;
uint256 longTokenAmount;
uint256 shortTokenAmount;
uint256 longTokenUsd;
uint256 shortTokenUsd;
uint256 totalBorrowingFees;
uint256 borrowingFeePoolFactor;
uint256 impactPoolAmount;
}
// @dev get the market token's price
// @param dataStore DataStore
// @param market the market to check
// @param longTokenPrice the price of the long token
// @param shortTokenPrice the price of the short token
// @param indexTokenPrice the price of the index token
// @param maximize whether to maximize or minimize the market token price
// @return returns (the market token's price, MarketPoolValueInfo.Props)
function getMarketTokenPrice(
address dataStore,
MarketProps memory market,
PriceProps memory indexTokenPrice,
PriceProps memory longTokenPrice,
PriceProps memory shortTokenPrice,
bytes32 pnlFactorType,
bool maximize
) external view returns (int256, PoolValueProps memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {IMarketUtils} from "./IMarketUtils.sol";
interface IOracle {
struct SetPricesParams {
address[] tokens;
address[] providers;
bytes[] data;
}
function getPrimaryPrice(address token) external view returns (IMarketUtils.PriceProps memory);
function setPrices(SetPricesParams memory params) external payable;
function clearAllPrices() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ICommonPool} from "./ICommonPool.sol";
// Structs and interface from `ExchangeRouter.sol` of rfx contracts
interface IRelativeRouter {
/**
* @param receiver The address that will receive the withdrawal tokens.
* @param callbackContract The contract that will be called back.
* @param market The market on which the withdrawal will be executed.
* @param minLongTokenAmount The minimum amount of long tokens that must be withdrawn.
* @param minShortTokenAmount The minimum amount of short tokens that must be withdrawn.
* @param shouldUnwrapNativeToken Whether the native token should be unwrapped when executing the withdrawal.
* @param executionFee The execution fee for the withdrawal.
* @param callbackGasLimit The gas limit for calling the callback contract.
*/
struct CreateWithdrawalParams {
address receiver;
address callbackContract;
address uiFeeReceiver;
address market;
address[] longTokenSwapPath;
address[] shortTokenSwapPath;
uint256 minLongTokenAmount;
uint256 minShortTokenAmount;
bool shouldUnwrapNativeToken;
uint256 executionFee;
uint256 callbackGasLimit;
}
// @dev CreateDepositParams struct used in createDeposit to avoid stack
// too deep errors
//
// @param receiver the address to send the market tokens to
// @param callbackContract the callback contract
// @param uiFeeReceiver the ui fee receiver
// @param market the market to deposit into
// @param minMarketTokens the minimum acceptable number of liquidity tokens
// @param shouldUnwrapNativeToken whether to unwrap the native token when
// sending funds back to the user in case the deposit gets cancelled
// @param executionFee the execution fee for keepers
// @param callbackGasLimit the gas limit for the callbackContract
struct CreateDepositParams {
address receiver;
address callbackContract;
address uiFeeReceiver;
address market;
address initialLongToken;
address initialShortToken;
address[] longTokenSwapPath;
address[] shortTokenSwapPath;
uint256 minMarketTokens;
bool shouldUnwrapNativeToken;
uint256 executionFee;
uint256 callbackGasLimit;
}
// @dev CreateOrderParams struct used in createOrder to avoid stack
// too deep errors
//
// @param addresses address values
// @param numbers number values
// @param orderType for order.orderType
// @param decreasePositionSwapType for order.decreasePositionSwapType
// @param isLong for order.isLong
// @param shouldUnwrapNativeToken for order.shouldUnwrapNativeToken
struct CreateOrderParams {
CreateOrderParamsAddresses addresses;
CreateOrderParamsNumbers numbers;
OrderType orderType;
DecreasePositionSwapType decreasePositionSwapType;
bool isLong;
bool shouldUnwrapNativeToken;
bool autoCancel;
bytes32 referralCode;
}
// @param receiver for order.receiver
// @param callbackContract for order.callbackContract
// @param market for order.market
// @param initialCollateralToken for order.initialCollateralToken
// @param swapPath for order.swapPath
struct CreateOrderParamsAddresses {
address receiver;
address cancellationReceiver;
address callbackContract;
address uiFeeReceiver;
address market;
address initialCollateralToken;
address[] swapPath;
}
// @param sizeDeltaUsd for order.sizeDeltaUsd
// @param triggerPrice for order.triggerPrice
// @param acceptablePrice for order.acceptablePrice
// @param executionFee for order.executionFee
// @param callbackGasLimit for order.callbackGasLimit
// @param minOutputAmount for order.minOutputAmount
struct CreateOrderParamsNumbers {
uint256 sizeDeltaUsd;
uint256 initialCollateralDeltaAmount;
uint256 triggerPrice;
uint256 acceptablePrice;
uint256 executionFee;
uint256 callbackGasLimit;
uint256 minOutputAmount;
}
enum OrderType {
// @dev MarketSwap: swap token A to token B at the current market price
// the order will be cancelled if the minOutputAmount cannot be fulfilled
MarketSwap,
// @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled
LimitSwap,
// @dev MarketIncrease: increase position at the current market price
// the order will be cancelled if the position cannot be increased at the acceptablePrice
MarketIncrease,
// @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled
LimitIncrease,
// @dev MarketDecrease: decrease position at the current market price
// the order will be cancelled if the position cannot be decreased at the acceptablePrice
MarketDecrease,
// @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled
LimitDecrease,
// @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled
StopLossDecrease,
// @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met
Liquidation
}
enum DecreasePositionSwapType {
NoSwap,
SwapPnlTokenToCollateralToken,
SwapCollateralTokenToPnlToken
}
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
// @dev Wraps the specified amount of native tokens into WNT then sends the WNT to the specified address
function sendWnt(address receiver, uint256 amount) external payable;
// @dev Sends the given amount of tokens to the given address
function sendTokens(address token, address receiver, uint256 amount) external payable;
function createWithdrawal(
CreateWithdrawalParams calldata params
) external payable returns (bytes32);
function createDeposit(
CreateDepositParams calldata params
) external payable returns (bytes32);
/**
* @dev Creates a new order with the given amount, order parameters. The order is
* created by transferring the specified amount of collateral tokens from the caller's account to the
* order store, and then calling the `createOrder()` function on the order handler contract. The
* referral code is also set on the caller's account using the referral storage contract.
*/
function createOrder(CreateOrderParams calldata _params) external payable returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ICommonPool} from "./ICommonPool.sol";
import {IRelativeRouter} from "./IRelativeRouter.sol";
interface ISwapModule {
event ModuleAddressUpdated(uint256[] moduleIds, address[] moduleAddresses);
event ApprovedCallerUpdated(address[] callers, bool[] status);
function swap(bytes[] calldata _input) external payable returns (bytes[] memory);
}// SPDX-License-Identifier: MIT
/// @title Library for Bytes Manipulation
pragma solidity ^0.8.9;
library BytesLib {
function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address tempAddress) {
assembly {
tempAddress := mload(add(add(_bytes, 0x14), _start))
}
}
function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24 amount) {
assembly {
amount := mload(add(add(_bytes, 0x3), _start))
}
}
/// @param _bytes The bytes input
/// @param _start The start index of the slice
/// @param _length The length of the slice
function sliceBytes(bytes memory _bytes, uint256 _start, uint256 _length)
internal
pure
returns (bytes memory slicedBytes)
{
assembly {
slicedBytes := mload(0x40)
let lengthmod := and(_length, 31)
let mc := add(add(slicedBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)
for { let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} { mstore(mc, mload(cc)) }
mstore(slicedBytes, _length)
mstore(0x40, and(add(mc, 31), not(31)))
}
return slicedBytes;
}
function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {
bytes memory tempBytes;
assembly {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// Store the length of the first bytes array at the beginning of
// the memory for tempBytes.
let length := mload(_preBytes)
mstore(tempBytes, length)
// Maintain a memory counter for the current write location in the
// temp bytes array by adding the 32 bytes for the array length to
// the starting location.
let mc := add(tempBytes, 0x20)
// Stop copying when the memory counter reaches the length of the
// first bytes array.
let end := add(mc, length)
for {
// Initialize a copy counter to the start of the _preBytes data,
// 32 bytes into its memory.
let cc := add(_preBytes, 0x20)
} lt(mc, end) {
// Increase both counters by 32 bytes each iteration.
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
// Write the _preBytes data into the tempBytes memory 32 bytes
// at a time.
mstore(mc, mload(cc))
}
// Add the length of _postBytes to the current length of tempBytes
// and store it as the new length in the first 32 bytes of the
// tempBytes memory.
length := mload(_postBytes)
mstore(tempBytes, add(length, mload(tempBytes)))
// Move the memory counter back from a multiple of 0x20 to the
// actual end of the _preBytes data.
mc := end
// Stop copying when the memory counter reaches the new combined
// length of the arrays.
end := add(mc, length)
for { let cc := add(_postBytes, 0x20) } lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} { mstore(mc, mload(cc)) }
// Update the free-memory pointer by padding our last write location
// to 32 bytes: add 31 bytes to the end of tempBytes to move to the
// next 32 byte block, then round down to the nearest multiple of
// 32. If the sum of the length of the two arrays is zero then add
// one before rounding down to leave a blank 32 bytes (the length block with 0).
mstore(
0x40,
and(
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
not(31) // Round down to the nearest 32 bytes.
)
)
}
return tempBytes;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathLite {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// 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 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
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 for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the 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.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // 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 preconditions 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 * inverse;
return result;
}
}
/**
* @notice Calculates ceil(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Modified version of OpenZeppelin `mulDiv` to perform the round up. Based on Uniswap `mulDivRoundingUp()`
*/
function mulDivUp(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
result = mulDiv(x, y, denominator);
if (mulmod(x, y, denominator) > 0) {
result++;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {IErrors} from "./interfaces/IErrors.sol";
// The common pool needs to set aside some `asset` exclusively to serve redeem requests
// Having the asset sitting in the pool would interfere with NAV calculations and swaps
// Storing them in this separate contract instead should keep the funds locked and safe
contract RedeemVault {
using SafeTransferLib for ERC20;
address public immutable owner;
ERC20 public immutable asset;
constructor (ERC20 asset_) {
if (address(asset_) == address(0)) revert IErrors.InvalidAddress();
asset = asset_;
owner = msg.sender;
// Give max approval to start with
asset.safeApprove(owner, type(uint256).max);
}
// Not all tokens would treat uint max as infinite approval(as defined in eip-6909)
// Allow to reset the approval value again if it ever gets exhausted
function resetApproval() external returns (bool) {
asset.safeApprove(owner, type(uint256).max);
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _sendLogPayload(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal view {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
}
function logUint(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
}
function logString(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
}
function log(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
}
function log(uint p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
}
function log(uint p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
}
function log(uint p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
}
function log(string memory p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
}
function log(string memory p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
}
function log(bool p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
}
function log(address p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
}
function log(uint p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
}
function log(uint p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
}
function log(uint p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
}
function log(uint p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
}
function log(uint p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
}
function log(uint p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
}
function log(uint p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
}
function log(uint p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
}
function log(uint p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
}
function log(uint p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
}
function log(uint p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
}
function log(uint p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
}
function log(uint p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
}
function log(uint p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
}
function log(uint p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
}
function log(string memory p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
}
function log(string memory p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
}
function log(string memory p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
}
function log(string memory p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
}
function log(bool p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
}
function log(bool p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
}
function log(bool p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
}
function log(address p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
}
function log(address p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
}
function log(address p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol";
/// @notice Minimal ERC4626 tokenized Vault implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC4626.sol)
abstract contract ERC4626 is ERC20 {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed caller,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/*//////////////////////////////////////////////////////////////
IMMUTABLES
//////////////////////////////////////////////////////////////*/
ERC20 public immutable asset;
constructor(
ERC20 _asset,
string memory _name,
string memory _symbol
) ERC20(_name, _symbol, _asset.decimals()) {
asset = _asset;
}
/*//////////////////////////////////////////////////////////////
DEPOSIT/WITHDRAWAL LOGIC
//////////////////////////////////////////////////////////////*/
function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) {
// Check for rounding error since we round down in previewDeposit.
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
// Need to transfer before minting or ERC777s could reenter.
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) {
assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up.
// Need to transfer before minting or ERC777s could reenter.
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function withdraw(
uint256 assets,
address receiver,
address owner
) public virtual returns (uint256 shares) {
shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up.
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
function redeem(
uint256 shares,
address receiver,
address owner
) public virtual returns (uint256 assets) {
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
// Check for rounding error since we round down in previewRedeem.
require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS");
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
/*//////////////////////////////////////////////////////////////
ACCOUNTING LOGIC
//////////////////////////////////////////////////////////////*/
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}
function convertToAssets(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
}
function previewDeposit(uint256 assets) public view virtual returns (uint256) {
return convertToShares(assets);
}
function previewMint(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply);
}
function previewWithdraw(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets());
}
function previewRedeem(uint256 shares) public view virtual returns (uint256) {
return convertToAssets(shares);
}
/*//////////////////////////////////////////////////////////////
DEPOSIT/WITHDRAWAL LIMIT LOGIC
//////////////////////////////////////////////////////////////*/
function maxDeposit(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxMint(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxWithdraw(address owner) public view virtual returns (uint256) {
return convertToAssets(balanceOf[owner]);
}
function maxRedeem(address owner) public view virtual returns (uint256) {
return balanceOf[owner];
}
/*//////////////////////////////////////////////////////////////
INTERNAL HOOKS LOGIC
//////////////////////////////////////////////////////////////*/
function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {}
function afterDeposit(uint256 assets, uint256 shares) internal virtual {}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
/*//////////////////////////////////////////////////////////////
SIMPLIFIED FIXED POINT OPERATIONS
//////////////////////////////////////////////////////////////*/
uint256 internal constant MAX_UINT256 = 2**256 - 1;
uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.
function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
}
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
}
function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
}
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
}
/*//////////////////////////////////////////////////////////////
LOW LEVEL FIXED POINT OPERATIONS
//////////////////////////////////////////////////////////////*/
function mulDivDown(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
// Divide x * y by the denominator.
z := div(mul(x, y), denominator)
}
}
function mulDivUp(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
// If x * y modulo the denominator is strictly greater than 0,
// 1 is added to round up the division of x * y by the denominator.
z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
}
}
function rpow(
uint256 x,
uint256 n,
uint256 scalar
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
switch x
case 0 {
switch n
case 0 {
// 0 ** 0 = 1
z := scalar
}
default {
// 0 ** n = 0
z := 0
}
}
default {
switch mod(n, 2)
case 0 {
// If n is even, store scalar in z for now.
z := scalar
}
default {
// If n is odd, store x in z for now.
z := x
}
// Shifting right by 1 is like dividing by 2.
let half := shr(1, scalar)
for {
// Shift n right by 1 before looping to halve it.
n := shr(1, n)
} n {
// Shift n right by 1 each iteration to halve it.
n := shr(1, n)
} {
// Revert immediately if x ** 2 would overflow.
// Equivalent to iszero(eq(div(xx, x), x)) here.
if shr(128, x) {
revert(0, 0)
}
// Store x squared.
let xx := mul(x, x)
// Round to the nearest number.
let xxRound := add(xx, half)
// Revert if xx + half overflowed.
if lt(xxRound, xx) {
revert(0, 0)
}
// Set x to scaled xxRound.
x := div(xxRound, scalar)
// If n is even:
if mod(n, 2) {
// Compute z * x.
let zx := mul(z, x)
// If z * x overflowed:
if iszero(eq(div(zx, x), z)) {
// Revert if x is non-zero.
if iszero(iszero(x)) {
revert(0, 0)
}
}
// Round to the nearest number.
let zxRound := add(zx, half)
// Revert if zx + half overflowed.
if lt(zxRound, zx) {
revert(0, 0)
}
// Return properly scaled zxRound.
z := div(zxRound, scalar)
}
}
}
}
}
/*//////////////////////////////////////////////////////////////
GENERAL NUMBER UTILITIES
//////////////////////////////////////////////////////////////*/
function sqrt(uint256 x) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
let y := x // We start y at x, which will help us make our initial estimate.
z := 181 // The "correct" value is 1, but this saves a multiplication later.
// This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
// start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.
// We check y >= 2^(k + 8) but shift right by k bits
// each branch to ensure that if x >= 256, then y >= 256.
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
// Goal was to get z*z*y within a small factor of x. More iterations could
// get y in a tighter range. Currently, we will have y in [256, 256*2^16).
// We ensured y >= 256 so that the relative difference between y and y+1 is small.
// That's not possible if x < 256 but we can just verify those cases exhaustively.
// Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
// Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
// Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.
// For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
// (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.
// Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
// sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.
// There is no overflow risk here since y < 2^136 after the first branch above.
z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.
// Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
// If x+1 is a perfect square, the Babylonian method cycles between
// floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
// See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
// Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
// If you don't care whether the floor or ceil square root is returned, you can remove this statement.
z := sub(z, lt(div(x, z), z))
}
}
function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Mod x by y. Note this will return
// 0 instead of reverting if y is zero.
z := mod(x, y)
}
}
function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
// Divide x by y. Note this will return
// 0 instead of reverting if y is zero.
r := div(x, y)
}
}
function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Add 1 to x * y if x % y > 0. Note this will
// return 0 instead of reverting if y is zero.
z := add(gt(mod(x, y), 0), div(x, y))
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}{
"optimizer": {
"enabled": true,
"runs": 10,
"details": {
"constantOptimizer": true
}
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ERC20","name":"_asset","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_routerSender","type":"address"},{"internalType":"address","name":"_depositVault","type":"address"},{"internalType":"address","name":"_withdrawVault","type":"address"},{"internalType":"address","name":"_helper","type":"address"},{"internalType":"address","name":"_swapModule","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"InvalidMarket","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"InvalidSpender","type":"error"},{"inputs":[],"name":"LimitExceeded","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[],"name":"NotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"market","type":"address[]"},{"indexed":false,"internalType":"bool[]","name":"status","type":"bool[]"}],"name":"ApprovedExternalAddrUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"markets","type":"address[]"},{"indexed":false,"internalType":"bool[]","name":"status","type":"bool[]"}],"name":"ApprovedMarketsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newDepositVault","type":"address"}],"name":"DepositVaultUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"FulfilledRedeemRequests","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newHelper","type":"address"}],"name":"HelperUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"MarketUtilsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"OperatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"navValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareToAssetPrice","type":"uint256"}],"name":"RecalculatedNAV","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"RedeemRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newRouterSender","type":"address"}],"name":"RouterSenderUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newRouter","type":"address"}],"name":"RouterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"SwapModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newWithdrawVault","type":"address"}],"name":"WithdrawVaultUpdated","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FUND_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ICommonPool.SendWntParams","name":"sendWnt","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ICommonPool.SendTokenParams[]","name":"sendTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"address","name":"uiFeeReceiver","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address[]","name":"longTokenSwapPath","type":"address[]"},{"internalType":"address[]","name":"shortTokenSwapPath","type":"address[]"},{"internalType":"uint256","name":"minLongTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minShortTokenAmount","type":"uint256"},{"internalType":"bool","name":"shouldUnwrapNativeToken","type":"bool"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"}],"internalType":"struct IRelativeRouter.CreateWithdrawalParams","name":"position","type":"tuple"}],"internalType":"struct ICommonPool.WithdrawMulticall[]","name":"_withdraws","type":"tuple[]"},{"components":[{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ICommonPool.SendWntParams","name":"sendWnt","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ICommonPool.SendTokenParams[]","name":"sendTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"address","name":"uiFeeReceiver","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"initialLongToken","type":"address"},{"internalType":"address","name":"initialShortToken","type":"address"},{"internalType":"address[]","name":"longTokenSwapPath","type":"address[]"},{"internalType":"address[]","name":"shortTokenSwapPath","type":"address[]"},{"internalType":"uint256","name":"minMarketTokens","type":"uint256"},{"internalType":"bool","name":"shouldUnwrapNativeToken","type":"bool"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"}],"internalType":"struct IRelativeRouter.CreateDepositParams","name":"position","type":"tuple"}],"internalType":"struct ICommonPool.DepositMulticall[]","name":"_deposits","type":"tuple[]"}],"name":"allocateFunds","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedExternalAddr","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedMarkets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimableRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimableRedeemAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"claimableRedeemRequest","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentAllocation","outputs":[{"internalType":"address[]","name":"_markets","type":"address[]"},{"internalType":"uint256[]","name":"_balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxAssets","type":"uint256"}],"name":"fulfillRequests","outputs":[{"internalType":"uint256","name":"claimableShares","type":"uint256"},{"internalType":"uint256","name":"claimableAssets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"helper","outputs":[{"internalType":"contract IHelper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"navStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"pendingRedeemRequest","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_swapInput","type":"bytes[]"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ICommonPool.SendTokenParams[]","name":"_requiredAllowance","type":"tuple[]"}],"name":"performSwap","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address[]","name":"providers","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"internalType":"struct IOracle.SetPricesParams","name":"_oracleParams","type":"tuple"}],"name":"recalculateNAV","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"controller","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"requestRedeem","outputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IRelativeRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"routerSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"share","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shareToAssetPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapModule","outputs":[{"internalType":"contract ISwapModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalClaimableRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPendingRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addr","type":"address[]"},{"internalType":"bool[]","name":"_status","type":"bool[]"}],"name":"updateApprovedExternalAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addr","type":"address[]"},{"internalType":"bool[]","name":"_status","type":"bool[]"}],"name":"updateApprovedMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newDepositVault","type":"address"}],"name":"updateDepositVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newHelper","type":"address"}],"name":"updateHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newRouter","type":"address"}],"name":"updateRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newSender","type":"address"}],"name":"updateRouterSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newModule","type":"address"}],"name":"updateSwapModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newWithdrawVault","type":"address"}],"name":"updateWithdrawVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101206040523480156200001257600080fd5b5060405162005ce938038062005ce98339810160408190526200003591620004ff565b8888888181846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000079573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009f9190620005f1565b6000620000ad8482620006ac565b506001620000bc8382620006ac565b5060ff81166080524660a052620000d2620002b2565b60c0525050506001600160a01b0392831660e05250508616620001085760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b038516620001305760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b038416620001585760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b038316620001805760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b038216620001a85760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b038116620001d05760405163e6c4247b60e01b815260040160405180910390fd5b620001dd6000336200034e565b50600e80546001600160a01b03199081166001600160a01b0389811691909117909255601080548216888416179055601180548216878416179055601280548216868416179055600f80548216858416179055601380549091169183169190911790556c0c9f2c9cd04674edea40000000600d5560e05160405160009190620002669062000401565b6001600160a01b039091168152602001604051809103906000f08015801562000293573d6000803e3d6000fd5b506001600160a01b03166101005250620007f698505050505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051620002e6919062000778565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60008281526006602090815260408083206001600160a01b038516845290915281205460ff16620003f75760008381526006602090815260408083206001600160a01b03861684529091529020805460ff19166001179055620003ae3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620003fb565b5060005b92915050565b61034e806200599b83390190565b6001600160a01b03811681146200042557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200045057600080fd5b81516001600160401b03808211156200046d576200046d62000428565b604051601f8301601f19908116603f0116810190828211818310171562000498576200049862000428565b81604052838152602092508683858801011115620004b557600080fd5b600091505b83821015620004d95785820183015181830184015290820190620004ba565b600093810190920192909252949350505050565b8051620004fa816200040f565b919050565b60008060008060008060008060006101208a8c0312156200051f57600080fd5b89516200052c816200040f565b60208b01519099506001600160401b03808211156200054a57600080fd5b620005588d838e016200043e565b995060408c01519150808211156200056f57600080fd5b506200057e8c828d016200043e565b97505060608a015162000591816200040f565b9550620005a160808b01620004ed565b9450620005b160a08b01620004ed565b9350620005c160c08b01620004ed565b9250620005d160e08b01620004ed565b9150620005e26101008b01620004ed565b90509295985092959850929598565b6000602082840312156200060457600080fd5b815160ff811681146200061657600080fd5b9392505050565b600181811c908216806200063257607f821691505b6020821081036200065357634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620006a757600081815260208120601f850160051c81016020861015620006825750805b601f850160051c820191505b81811015620006a3578281556001016200068e565b5050505b505050565b81516001600160401b03811115620006c857620006c862000428565b620006e081620006d984546200061d565b8462000659565b602080601f831160018114620007185760008415620006ff5750858301515b600019600386901b1c1916600185901b178555620006a3565b600085815260208120601f198616915b82811015620007495788860151825594840194600190910190840162000728565b5085821015620007685787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600080835462000788816200061d565b60018281168015620007a35760018114620007b957620007ea565b60ff1984168752821515830287019450620007ea565b8760005260208060002060005b85811015620007e15781548a820152908401908201620007c6565b50505082870194505b50929695505050505050565b60805160a05160c05160e051610100516151216200087a600039600081816106ab01528181611bc001528181611e2a01526129360152600081816106280152818161158b0152818161196101528181611b9e01528181611e080152818161291401526138ca01526000611175015260006111400152600061057401526151216000f3fe6080604052600436106103465760003560e01c806374c0fddb116101b957806374c0fddb1461084757806375b238fc146108745780637d41c86e146108965780637ecebe00146108b65780637f164991146108e357806381e4cb65146108f95780638bcc41661461090c57806391d148541461092c57806394bf804d1461094c57806395d89b411461096c578063a217fddf14610981578063a8d5fd6514610996578063a9059cbb146109a9578063aaf5eb68146109c9578063b3d7f6b9146109e9578063b460af9414610a09578063b6363cf214610a29578063b87fa6b614610a64578063ba08765214610a84578063bb2d60a714610aa4578063c63d75b61461064a578063c6e6f59214610ab7578063c851cc3214610ad7578063ce96cb7714610af7578063d0d0ed0514610b17578063d505accf14610b37578063d547741f14610b57578063d7cd394914610b77578063d905777e14610b97578063dd62ed3e14610bb7578063eaed1d0714610bef578063ef8b30f714610c0f578063f28b9fb114610c2f578063f5a23d8d14610c4f578063f887ea4014610c6f578063fa716b3f14610c8f578063facda49114610caf57600080fd5b806301e1d1141461034b57806301ffc9a71461036f578063021076ed1461039f57806306fdde03146103b557806307a2d13a146103d7578063095ea7b3146103f75780630a28a4771461041757806318160ddd14610437578063199c28611461044d57806323b872dd1461047b578063248a9ca31461049b57806325bb3361146104bb5780632615b7a9146104d15780632c6886cb146104f35780632f2ff15d146105205780632f83a6bc14610540578063313ce56714610562578063345210dd146105a85780633644e515146105cb57806336568abe146105e057806336c8c73a1461060057806338d52e0f14610616578063402d267d1461064a57806340bc782e1461066c5780634388b8fe146106995780634cdad5061461041757806350423dbe146106cd578063558a7297146106ed5780635924b65b1461070d5780635d6584901461072d57806363b0e66a1461075a5780636513b4361461077a5780636e48b832146107aa5780636e553f65146107ca57806370a08231146107ea57806371dfdd9f14610817575b600080fd5b34801561035757600080fd5b50600c545b6040519081526020015b60405180910390f35b34801561037b57600080fd5b5061038f61038a366004613c97565b610ccf565b6040519015158152602001610366565b3480156103ab57600080fd5b5061035c600d5481565b3480156103c157600080fd5b506103ca610d30565b6040516103669190613d11565b3480156103e357600080fd5b5061035c6103f2366004613d24565b610dbe565b34801561040357600080fd5b5061038f610412366004613d62565b610dd9565b34801561042357600080fd5b5061035c610432366004613d24565b610e33565b34801561044357600080fd5b5061035c60025481565b34801561045957600080fd5b5061046d610468366004613d24565b610e4e565b604051610366929190613d8e565b34801561048757600080fd5b5061038f610496366004613d9c565b610e7d565b3480156104a757600080fd5b5061035c6104b6366004613d24565b610f5f565b3480156104c757600080fd5b5061035c60155481565b3480156104dd57600080fd5b506104f16104ec366004613ddd565b610f74565b005b3480156104ff57600080fd5b50601054610513906001600160a01b031681565b6040516103669190613e07565b34801561052c57600080fd5b506104f161053b366004613e1b565b61100a565b34801561054c57600080fd5b5061035c60008051602061504c83398151915281565b34801561056e57600080fd5b506105967f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610366565b3480156105b457600080fd5b506105bd61102c565b604051610366929190613e8f565b3480156105d757600080fd5b5061035c61113c565b3480156105ec57600080fd5b506104f16105fb366004613e1b565b611197565b34801561060c57600080fd5b5061035c60175481565b34801561062257600080fd5b506105137f000000000000000000000000000000000000000000000000000000000000000081565b34801561065657600080fd5b5061035c610665366004613ddd565b5060001990565b34801561067857600080fd5b5061035c610687366004613ddd565b60146020526000908152604090205481565b3480156106a557600080fd5b506105137f000000000000000000000000000000000000000000000000000000000000000081565b3480156106d957600080fd5b506104f16106e8366004613ddd565b6111cf565b3480156106f957600080fd5b5061038f610708366004613eff565b611259565b61072061071b366004613f78565b6112bd565b6040516103669190614038565b34801561073957600080fd5b5061035c610748366004613ddd565b60186020526000908152604090205481565b34801561076657600080fd5b50600f54610513906001600160a01b031681565b34801561078657600080fd5b5061038f610795366004613ddd565b601c6020526000908152604090205460ff1681565b3480156107b657600080fd5b506104f16107c5366004613f78565b611401565b3480156107d657600080fd5b5061035c6107e5366004613e1b565b611565565b3480156107f657600080fd5b5061035c610805366004613ddd565b60036020526000908152604090205481565b34801561082357600080fd5b5061038f610832366004613ddd565b601b6020526000908152604090205460ff1681565b34801561085357600080fd5b5061035c610862366004613ddd565b60166020526000908152604090205481565b34801561088057600080fd5b5061035c6000805160206150ac83398151915281565b3480156108a257600080fd5b5061035c6108b136600461404b565b6115fe565b3480156108c257600080fd5b5061035c6108d1366004613ddd565b60056020526000908152604090205481565b3480156108ef57600080fd5b5061035c600b5481565b61072061090736600461408d565b6117dd565b34801561091857600080fd5b506104f1610927366004613ddd565b611886565b34801561093857600080fd5b5061038f610947366004613e1b565b611910565b34801561095857600080fd5b5061035c610967366004613e1b565b61193b565b34801561097857600080fd5b506103ca6119c6565b34801561098d57600080fd5b5061035c600081565b3480156109a257600080fd5b5030610513565b3480156109b557600080fd5b5061038f6109c4366004613d62565b6119d3565b3480156109d557600080fd5b5061035c68327cb2734119d3b7a9601e1b81565b3480156109f557600080fd5b5061035c610a04366004613d24565b611a39565b348015610a1557600080fd5b5061035c610a2436600461404b565b611a54565b348015610a3557600080fd5b5061038f610a44366004614126565b601a60209081526000928352604080842090915290825290205460ff1681565b348015610a7057600080fd5b506104f1610a7f366004613ddd565b611c34565b348015610a9057600080fd5b5061035c610a9f36600461404b565b611cbe565b6104f1610ab2366004614280565b611e8d565b348015610ac357600080fd5b5061035c610ad2366004613d24565b6120cd565b348015610ae357600080fd5b506104f1610af2366004613ddd565b6120e8565b348015610b0357600080fd5b5061035c610b12366004613ddd565b612172565b348015610b2357600080fd5b50601254610513906001600160a01b031681565b348015610b4357600080fd5b506104f1610b523660046143e4565b61218d565b348015610b6357600080fd5b506104f1610b72366004613e1b565b6123be565b348015610b8357600080fd5b50601154610513906001600160a01b031681565b348015610ba357600080fd5b5061035c610bb2366004613ddd565b6123da565b348015610bc357600080fd5b5061035c610bd2366004614126565b600460209081526000928352604080842090915290825290205481565b348015610bfb57600080fd5b5061035c610c0a366004613e1b565b6123f5565b348015610c1b57600080fd5b5061035c610c2a366004613d24565b612423565b348015610c3b57600080fd5b506104f1610c4a366004613ddd565b61242e565b348015610c5b57600080fd5b5061035c610c6a366004613e1b565b6124b8565b348015610c7b57600080fd5b50600e54610513906001600160a01b031681565b348015610c9b57600080fd5b50601354610513906001600160a01b031681565b348015610cbb57600080fd5b506104f1610cca366004613f78565b6124e6565b600063e3bc4e6560e01b6001600160e01b031983161480610d005750632f0a18c560e01b6001600160e01b03198316145b80610d1b5750631883ba3960e21b6001600160e01b03198316145b80610d2a5750610d2a82612631565b92915050565b60008054610d3d9061445b565b80601f0160208091040260200160405190810160405280929190818152602001828054610d699061445b565b8015610db65780601f10610d8b57610100808354040283529160200191610db6565b820191906000526020600020905b815481529060010190602001808311610d9957829003601f168201915b505050505081565b6000610d2a82600d5468327cb2734119d3b7a9601e1b612666565b3360008181526004602090815260408083206001600160a01b0387168085529252808320859055519192909160008051602061508c83398151915290610e229086815260200190565b60405180910390a350600192915050565b6000604051631eb49d6d60e11b815260040160405180910390fd5b60008060008051602061504c833981519152610e698161272a565b610e7284612737565b909590945092505050565b6001600160a01b03831660009081526004602090815260408083203384529091528120546000198114610ed957610eb483826144ab565b6001600160a01b03861660009081526004602090815260408083203384529091529020555b6001600160a01b03851660009081526003602052604081208054859290610f019084906144ab565b90915550506001600160a01b038085166000818152600360205260409081902080548701905551909187169060008051602061506c83398151915290610f4a9087815260200190565b60405180910390a360019150505b9392505050565b60009081526006602052604090206001015490565b6000805160206150ac833981519152610f8c8161272a565b6001600160a01b038216610fb35760405163e6c4247b60e01b815260040160405180910390fd5b601080546001600160a01b0319166001600160a01b0384161790556040517f61eeccc62b2fff98fea77f70c98b615ae0494ebd8e140b43bbeb9cdaca2e5a5990610ffe908490613e07565b60405180910390a15050565b61101382610f5f565b61101c8161272a565b61102683836129a3565b50505050565b6060806110396009612a37565b915081516001600160401b0381111561105457611054614154565b60405190808252806020026020018201604052801561107d578160200160208202803683370190505b50905060005b82518110156111375782818151811061109e5761109e6144be565b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016110d19190613e07565b602060405180830381865afa1580156110ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111291906144d4565b828281518110611124576111246144be565b6020908102919091010152600101611083565b509091565b60007f000000000000000000000000000000000000000000000000000000000000000046146111725761116d612a44565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b03811633146111c05760405163334bd91960e11b815260040160405180910390fd5b6111ca8282612ade565b505050565b6000805160206150ac8339815191526111e78161272a565b6001600160a01b03821661120e5760405163e6c4247b60e01b815260040160405180910390fd5b601280546001600160a01b0319166001600160a01b0384161790556040517f0e0ed07b314aa8a9a2104b2333805db1f23505037c1e8a163f6e0ce8d482bb7d90610ffe908490613e07565b336000818152601a602090815260408083206001600160a01b038716808552908352818420805460ff191687151590811790915591519182529293917fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa2679101610e22565b606060008051602061504c8339815191526112d78161272a565b6112e386868686612b4b565b600f54604051637923351b60e11b815260009182916001600160a01b039091169063f2466a369061131e908b908b908b908b9060040161481f565b600060405180830381865afa15801561133b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113639190810190614ae8565b9150915061137388888888612f01565b61137c816134b8565b600e54604051631592ca1b60e31b81526001600160a01b039091169063ac9650d89034906113ae908690600401614038565b60006040518083038185885af11580156113cc573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526113f59190810190614b4b565b98975050505050505050565b6000805160206150ac8339815191526114198161272a565b8382146114395760405163251f56a160e21b815260040160405180910390fd5b60005b84811015611520576000868683818110611458576114586144be565b905060200201602081019061146d9190613ddd565b6001600160a01b0316036114945760405163e6c4247b60e01b815260040160405180910390fd5b8383828181106114a6576114a66144be565b90506020020160208101906114bb9190614b87565b601c60008888858181106114d1576114d16144be565b90506020020160208101906114e69190613ddd565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558061151881614ba4565b91505061143c565b507fa3476bdc214fa6a8f0c8ad026e0a9e8c05484ec623d62f903054e9525ca8e1bf858585856040516115569493929190614bbd565b60405180910390a15050505050565b600061157083612423565b905061157e818460016134fe565b6115b36001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330866135d0565b6115bd8282613665565b816001600160a01b0316336001600160a01b03166000805160206150cc83398151915285846040516115f0929190613d8e565b60405180910390a392915050565b60008360000361160d57600080fd5b6001600160a01b038216331480159061164a57506001600160a01b0382166000908152601a6020908152604080832033845290915290205460ff16155b156116ad576001600160a01b038216600090815260046020908152604080832033845290915290205460001981146116ab5761168685826144ab565b6001600160a01b03841660009081526004602090815260408083203384529091529020555b505b6116b88230866136bf565b506040805180820182526001600160a01b03858116808352602083018881526007805460018101825560009190915293517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600290950294850180546001600160a01b031916918516919091179055517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6899093019290925591518392851691907f1fdc681a13d8c5da54e301c7ce6542dcde4581e4725043fdab2db12ddc574506906117879033908a90614c1b565b60405180910390a46001600160a01b038316600090815260146020526040812080548692906117b7908490614c34565b9250508190555083601560008282546117d09190614c34565b9091555090949350505050565b606060008051602061504c8339815191526117f78161272a565b6118018484613762565b6013546040516309d902f160e21b81526001600160a01b03909116906327640bc4903490611835908a908a90600401614c70565b60006040518083038185885af1158015611853573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405261187c9190810190614b4b565b9695505050505050565b6000805160206150ac83398151915261189e8161272a565b6001600160a01b0382166118c55760405163e6c4247b60e01b815260040160405180910390fd5b600f80546001600160a01b0319166001600160a01b0384161790556040517f20e752df2d1d9e69c7eb8f9e96973ff9b6f881a03503a3b5cac668cafb9a1ac890610ffe908490613e07565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b600061194683611a39565b9050611954838260016134fe565b6119896001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330846135d0565b6119938284613665565b816001600160a01b0316336001600160a01b03166000805160206150cc83398151915283866040516115f0929190613d8e565b60018054610d3d9061445b565b336000908152600360205260408120805483919083906119f49084906144ab565b90915550506001600160a01b0383166000818152600360205260409081902080548501905551339060008051602061506c83398151915290610e229086815260200190565b6000610d2a82600d5468327cb2734119d3b7a9601e1b613872565b600083600003611a6357600080fd5b6001600160a01b038216331480611a9d57506001600160a01b0382166000908152601a6020908152604080832033845290915290205460ff165b611aa657600080fd5b611aaf82612172565b841115611acf57604051631930e3c960e11b815260040160405180910390fd5b6001600160a01b038216600090815260166020908152604080832054601890925290912054611aff868383613872565b6001600160a01b038516600090815260166020526040812080549295508592909190611b2c9084906144ab565b925050819055508260176000828254611b4591906144ab565b90915550506001600160a01b03841660009081526018602052604081208054889290611b729084906144ab565b925050819055508560196000828254611b8b91906144ab565b90915550611be690506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000087896135d0565b836001600160a01b0316856001600160a01b0316336001600160a01b031660008051602061502c8339815191528987604051611c23929190613d8e565b60405180910390a450509392505050565b6000805160206150ac833981519152611c4c8161272a565b6001600160a01b038216611c735760405163e6c4247b60e01b815260040160405180910390fd5b601180546001600160a01b0319166001600160a01b0384161790556040517ff1f4d3d6c666f9a8405868563a53355305afc3d7a918e905a2a08481f439592090610ffe908490613e07565b600083600003611ccd57600080fd5b6001600160a01b038216331480611d0757506001600160a01b0382166000908152601a6020908152604080832033845290915290205460ff165b611d1057600080fd5b611d19826123da565b841115611d3957604051631930e3c960e11b815260040160405180910390fd5b6001600160a01b038216600090815260166020908152604080832054601890925290912054611d69868284612666565b6001600160a01b038516600090815260166020526040812080549295508892909190611d969084906144ab565b925050819055508560176000828254611daf91906144ab565b90915550506001600160a01b03841660009081526018602052604081208054859290611ddc9084906144ab565b925050819055508260196000828254611df591906144ab565b90915550611e5090506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000087866135d0565b836001600160a01b0316856001600160a01b0316336001600160a01b031660008051602061502c833981519152868a604051611c23929190613d8e565b60008051602061504c833981519152611ea58161272a565b600f54604080516307dc0d1d60e41b8152905184926001600160a01b031691637dc0d1d09160048083019260209291908290030181865afa158015611eee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f129190614cfe565b6001600160a01b0316633d333c8534836040518363ffffffff1660e01b8152600401611f3e9190614d1b565b6000604051808303818588803b158015611f5757600080fd5b505af1158015611f6b573d6000803e3d6000fd5b5050505050600080600080611f7e6138ad565b9350935093509350611f908282613965565b600b849055600c839055600254611fb368327cb2734119d3b7a9601e1b85614d73565b611fbd9190614da0565b600d819055600b546040517ffba84dda7abcc3f95f3c4d1ffa85ff2a568c9a02ca6181f14305b0005fa7336f92611ff49291613d8e565b60405180910390a150505050600f60009054906101000a90046001600160a01b03166001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120779190614cfe565b6001600160a01b031662ccf1556040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120b057600080fd5b505af11580156120c4573d6000803e3d6000fd5b50505050505050565b6000610d2a8268327cb2734119d3b7a9601e1b600d54612666565b6000805160206150ac8339815191526121008161272a565b6001600160a01b0382166121275760405163e6c4247b60e01b815260040160405180910390fd5b600e80546001600160a01b0319166001600160a01b0384161790556040517f7aed1d3e8155a07ccf395e44ea3109a0e2d6c9b29bbbe9f142d9790596f4dc8090610ffe908490613e07565b6001600160a01b031660009081526018602052604090205490565b428410156121dc5760405162461bcd60e51b815260206004820152601760248201527614115493525517d11150511312539157d1561412549151604a1b60448201526064015b60405180910390fd5b600060016121e861113c565b6001600160a01b038a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156122f4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061232a5750876001600160a01b0316816001600160a01b0316145b6123675760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b60448201526064016121d3565b6001600160a01b0390811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a169160008051602061508c833981519152910160405180910390a350505050505050565b6123c782610f5f565b6123d08161272a565b6110268383612ade565b6001600160a01b031660009081526016602052604090205490565b6000821561240557506000610d2a565b506001600160a01b0316600090815260166020526040902054919050565b6000610d2a826120cd565b6000805160206150ac8339815191526124468161272a565b6001600160a01b03821661246d5760405163e6c4247b60e01b815260040160405180910390fd5b601380546001600160a01b0319166001600160a01b0384161790556040517faf6cd135c2ebef948aa7b21587e2c9af90e943077ddce2329e3562ff4343853b90610ffe908490613e07565b600082156124c857506000610d2a565b506001600160a01b0316600090815260146020526040902054919050565b6000805160206150ac8339815191526124fe8161272a565b83821461251e5760405163251f56a160e21b815260040160405180910390fd5b60005b848110156125fb57600086868381811061253d5761253d6144be565b90506020020160208101906125529190613ddd565b6001600160a01b0316036125795760405163e6c4247b60e01b815260040160405180910390fd5b83838281811061258b5761258b6144be565b90506020020160208101906125a09190614b87565b601b60008888858181106125b6576125b66144be565b90506020020160208101906125cb9190613ddd565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101612521565b507f8e76b36c7816a433d72c7df0b85914261ff3471c309e999cd40d66c61028a067858585856040516115569493929190614bbd565b60006001600160e01b03198216637965db0b60e01b1480610d2a57506301ffc9a760e01b6001600160e01b0319831614610d2a565b600083830281600019858709828110838203039150508060000361269d5783828161269357612693614d8a565b0492505050610f58565b8084116126bd5760405163227bc15360e01b815260040160405180910390fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b61273481336139c9565b50565b6000805b60075460085410156128ee57600060076008548154811061275e5761275e6144be565b90600052602060002090600202019050600061277d8260010154610dbe565b90508461278a8285614c34565b11156127975750506128ee565b6127a18184614c34565b92508160010154846127b39190614c34565b600183015483546001600160a01b03166000908152601460205260408120805493975091926127e39084906144ab565b90915550506001820154601580546000906127ff9084906144ab565b9091555050600182015482546001600160a01b031660009081526016602052604081208054909190612832908490614c34565b909155505060018201546017805460009061284e908490614c34565b909155505081546001600160a01b03166000908152601860205260408120805483929061287c908490614c34565b9250508190555080601960008282546128959190614c34565b925050819055506007600854815481106128b1576128b16144be565b60009182526020822060029091020180546001600160a01b031916815560010181905560088054916128e283614ba4565b9190505550505061273b565b816000036128fb57915091565b612907828260006134fe565b61295b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000836139f4565b6129653083613a75565b7f4f1ca23eae8569319445ac7ba753a438cc3fdb97f1ac4db7f9016999f1850ef58282604051612996929190613d8e565b60405180910390a1915091565b60006129af8383611910565b612a2f5760008381526006602090815260408083206001600160a01b03861684529091529020805460ff191660011790556129e73390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610d2a565b506000610d2a565b60606000610f5883613ad7565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051612a769190614dc2565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6000612aea8383611910565b15612a2f5760008381526006602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610d2a565b60005b83811015612d5f5736858583818110612b6957612b696144be565b9050602002810190612b7b9190614e61565b9050601c6000612b8e6060840184614e81565b612b9f906080810190606001613ddd565b6001600160a01b0316815260208101919091526040016000205460ff16612bf757612bcd6060820182614e81565b612bde906080810190606001613ddd565b604051623aae9360e61b81526004016121d39190613e07565b30612c056060830183614e81565b612c13906020810190613ddd565b6001600160a01b031614612c5657612c2e6060820182614e81565b612c3c906020810190613ddd565b604051639cfea58360e01b81526004016121d39190613e07565b602081013515801590612c8957506012546001600160a01b0316612c7d6020830183613ddd565b6001600160a01b031614155b15612c9b57612c3c6020820182613ddd565b60005b612cab6040830183614e98565b9050811015612d4a576012546001600160a01b0316612ccd6040840184614e98565b83818110612cdd57612cdd6144be565b9050606002016020016020810190612cf59190613ddd565b6001600160a01b031614612d3857612d106040830183614e98565b82818110612d2057612d206144be565b9050606002016020016020810190612c3c9190613ddd565b80612d4281614ba4565b915050612c9e565b50508080612d5790614ba4565b915050612b4e565b5060005b81811015612efa5736838383818110612d7e57612d7e6144be565b9050602002810190612d909190614e61565b9050601c6000612da36060840184614ee0565b612db4906080810190606001613ddd565b6001600160a01b0316815260208101919091526040016000205460ff16612de257612bcd6060820182614ee0565b30612df06060830183614ee0565b612dfe906020810190613ddd565b6001600160a01b031614612e1957612c2e6060820182614ee0565b602081013515801590612e4c57506011546001600160a01b0316612e406020830183613ddd565b6001600160a01b031614155b15612e5e57612c3c6020820182613ddd565b60005b612e6e6040830183614e98565b9050811015612ee5576011546001600160a01b0316612e906040840184614e98565b83818110612ea057612ea06144be565b9050606002016020016020810190612eb89190613ddd565b6001600160a01b031614612ed357612d106040830183614e98565b80612edd81614ba4565b915050612e61565b50508080612ef290614ba4565b915050612d63565b5050505050565b60005b8381101561304c5760005b858583818110612f2157612f216144be565b9050602002810190612f339190614e61565b612f41906040810190614e98565b905081101561303957858583818110612f5c57612f5c6144be565b9050602002810190612f6e9190614e61565b612f7c906040810190614e98565b82818110612f8c57612f8c6144be565b90506060020160400135601d6000888886818110612fac57612fac6144be565b9050602002810190612fbe9190614e61565b612fcc906040810190614e98565b85818110612fdc57612fdc6144be565b612ff29260206060909202019081019150613ddd565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546130219190614c34565b9091555081905061303181614ba4565b915050612f0f565b508061304481614ba4565b915050612f04565b5060005b818110156131985760005b83838381811061306d5761306d6144be565b905060200281019061307f9190614e61565b61308d906040810190614e98565b9050811015613185578383838181106130a8576130a86144be565b90506020028101906130ba9190614e61565b6130c8906040810190614e98565b828181106130d8576130d86144be565b90506060020160400135601d60008686868181106130f8576130f86144be565b905060200281019061310a9190614e61565b613118906040810190614e98565b85818110613128576131286144be565b61313e9260206060909202019081019150613ddd565b6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461316d9190614c34565b9091555081905061317d81614ba4565b91505061305b565b508061319081614ba4565b915050613050565b5060005b838110156133285760005b8585838181106131b9576131b96144be565b90506020028101906131cb9190614e61565b6131d9906040810190614e98565b90508110156133155760008686848181106131f6576131f66144be565b90506020028101906132089190614e61565b613216906040810190614e98565b83818110613226576132266144be565b61323c9260206060909202019081019150613ddd565b6001600160a01b0381166000908152601d6020526040812054919250036132635750613303565b6010546001600160a01b038083166000818152601d60205260409081902054905163095ea7b360e01b8152919363095ea7b3936132a69391169190600401614c1b565b6020604051808303816000875af11580156132c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132e99190614ef7565b506001600160a01b03166000908152601d60205260408120555b8061330d81614ba4565b9150506131a7565b508061332081614ba4565b91505061319c565b5060005b81811015612efa5760005b838383818110613349576133496144be565b905060200281019061335b9190614e61565b613369906040810190614e98565b90508110156134a5576000848484818110613386576133866144be565b90506020028101906133989190614e61565b6133a6906040810190614e98565b838181106133b6576133b66144be565b6133cc9260206060909202019081019150613ddd565b6001600160a01b0381166000908152601d6020526040812054919250036133f35750613493565b6010546001600160a01b038083166000818152601d60205260409081902054905163095ea7b360e01b8152919363095ea7b3936134369391169190600401614c1b565b6020604051808303816000875af1158015613455573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134799190614ef7565b506001600160a01b03166000908152601d60205260408120555b8061349d81614ba4565b915050613337565b50806134b081614ba4565b91505061332c565b60005b81518110156134fa576134f18282815181106134d9576134d96144be565b60200260200101516009613b3390919063ffffffff16565b506001016134bb565b5050565b806135165781600c5461351191906144ab565b613524565b81600c546135249190614c34565b600c556002546000826135405761353b85836144ab565b61354a565b61354a8583614c34565b90508060000361356b57505068327cb2734119d3b7a9601e1b600d55505050565b600082600d5461357b9190614d73565b9050600061359568327cb2734119d3b7a9601e1b87614d73565b90506000856135ad576135a882846144ab565b6135b7565b6135b78284614c34565b90506135c38482614da0565b600d555050505050505050565b60006040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b03841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080612efa5760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064016121d3565b80600260008282546136779190614c34565b90915550506001600160a01b03821660008181526003602090815260408083208054860190555184815260008051602061506c83398151915291015b60405180910390a35050565b6001600160a01b0383166000908152600360205260408120805483919083906136e99084906144ab565b90915550506001600160a01b03831660009081526003602052604081208054849290613716908490614c34565b92505081905550826001600160a01b0316846001600160a01b031660008051602061506c8339815191528460405161375091815260200190565b60405180910390a35060019392505050565b60005b818110156111ca5736838383818110613780576137806144be565b9050606002019050600081602001602081019061379d9190613ddd565b6001600160a01b0381166000908152601b602052604090205490915060ff166137db578060405163270af7ed60e11b81526004016121d39190613e07565b6137e86020830183613ddd565b6001600160a01b031663095ea7b38284604001356040518363ffffffff1660e01b8152600401613819929190614c1b565b6020604051808303816000875af1158015613838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385c9190614ef7565b505050808061386a90614ba4565b915050613765565b600061387f848484612666565b90506000828061389157613891614d8a565b8486091115610f5857806138a481614ba4565b95945050505050565b600f54600090819060609081906001600160a01b031663f01e23577f00000000000000000000000000000000000000000000000000000000000000006138f36009612a37565b306040518463ffffffff1660e01b815260040161391293929190614f14565b600060405180830381865afa15801561392f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139579190810190614f49565b929791965094509092509050565b60005b82518110156111ca57818181518110613983576139836144be565b60200260200101516000036139c1576139bf8382815181106139a7576139a76144be565b60200260200101516009613b4890919063ffffffff16565b505b600101613968565b6139d38282611910565b6134fa57808260405163e2517d3f60e01b81526004016121d3929190614c1b565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806110265760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016121d3565b6001600160a01b03821660009081526003602052604081208054839290613a9d9084906144ab565b90915550506002805482900390556040518181526000906001600160a01b0384169060008051602061506c833981519152906020016136b3565b606081600001805480602002602001604051908101604052809291908181526020018280548015613b2757602002820191906000526020600020905b815481526020019060010190808311613b13575b50505050509050919050565b6000610f58836001600160a01b038416613b5d565b6000610f58836001600160a01b038416613ba4565b6000818152600183016020526040812054612a2f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d2a565b60008181526001830160205260408120548015613c8d576000613bc86001836144ab565b8554909150600090613bdc906001906144ab565b9050808214613c41576000866000018281548110613bfc57613bfc6144be565b9060005260206000200154905080876000018481548110613c1f57613c1f6144be565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613c5257613c52615015565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d2a565b6000915050610d2a565b600060208284031215613ca957600080fd5b81356001600160e01b031981168114610f5857600080fd5b60005b83811015613cdc578181015183820152602001613cc4565b50506000910152565b60008151808452613cfd816020860160208601613cc1565b601f01601f19169290920160200192915050565b602081526000610f586020830184613ce5565b600060208284031215613d3657600080fd5b5035919050565b6001600160a01b038116811461273457600080fd5b8035613d5d81613d3d565b919050565b60008060408385031215613d7557600080fd5b8235613d8081613d3d565b946020939093013593505050565b918252602082015260400190565b600080600060608486031215613db157600080fd5b8335613dbc81613d3d565b92506020840135613dcc81613d3d565b929592945050506040919091013590565b600060208284031215613def57600080fd5b8135610f5881613d3d565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b60008060408385031215613e2e57600080fd5b823591506020830135613e4081613d3d565b809150509250929050565b600081518084526020808501945080840160005b83811015613e845781516001600160a01b031687529582019590820190600101613e5f565b509495945050505050565b604081526000613ea26040830185613e4b565b82810360208481019190915284518083528582019282019060005b81811015613ed957845183529383019391830191600101613ebd565b5090979650505050505050565b801515811461273457600080fd5b8035613d5d81613ee6565b60008060408385031215613f1257600080fd5b8235613f1d81613d3d565b91506020830135613e4081613ee6565b60008083601f840112613f3f57600080fd5b5081356001600160401b03811115613f5657600080fd5b6020830191508360208260051b8501011115613f7157600080fd5b9250929050565b60008060008060408587031215613f8e57600080fd5b84356001600160401b0380821115613fa557600080fd5b613fb188838901613f2d565b90965094506020870135915080821115613fca57600080fd5b50613fd787828801613f2d565b95989497509550505050565b600081518084526020808501808196508360051b8101915082860160005b8581101561402b578284038952614019848351613ce5565b98850198935090840190600101614001565b5091979650505050505050565b602081526000610f586020830184613fe3565b60008060006060848603121561406057600080fd5b83359250602084013561407281613d3d565b9150604084013561408281613d3d565b809150509250925092565b600080600080604085870312156140a357600080fd5b84356001600160401b03808211156140ba57600080fd5b6140c688838901613f2d565b909650945060208701359150808211156140df57600080fd5b818701915087601f8301126140f357600080fd5b81358181111561410257600080fd5b88602060608302850101111561411757600080fd5b95989497505060200194505050565b6000806040838503121561413957600080fd5b823561414481613d3d565b91506020830135613e4081613d3d565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561418c5761418c614154565b60405290565b604051601f8201601f191681016001600160401b03811182821017156141ba576141ba614154565b604052919050565b60006001600160401b038211156141db576141db614154565b5060051b60200190565b600082601f8301126141f657600080fd5b8135602061420b614206836141c2565b614192565b82815260059290921b8401810191818101908684111561422a57600080fd5b8286015b8481101561424e57803561424181613d3d565b835291830191830161422e565b509695505050505050565b60006001600160401b0382111561427257614272614154565b50601f01601f191660200190565b6000602080838503121561429357600080fd5b82356001600160401b03808211156142aa57600080fd5b90840190606082870312156142be57600080fd5b6142c661416a565b8235828111156142d557600080fd5b6142e1888286016141e5565b82525083830135828111156142f557600080fd5b614301888286016141e5565b85830152506040808401358381111561431957600080fd5b80850194505087601f85011261432e57600080fd5b833561433c614206826141c2565b81815260059190911b8501860190868101908a83111561435b57600080fd5b8787015b838110156143cf578035878111156143775760008081fd5b8801603f81018d136143895760008081fd5b8981013561439961420682614259565b8181528e888385010111156143ae5760008081fd5b818884018d83013760009181018c019190915284525091880191880161435f565b50928401929092525090979650505050505050565b600080600080600080600060e0888a0312156143ff57600080fd5b873561440a81613d3d565b9650602088013561441a81613d3d565b95506040880135945060608801359350608088013560ff8116811461443e57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600181811c9082168061446f57607f821691505b60208210810361448f57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d2a57610d2a614495565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156144e657600080fd5b5051919050565b80356144f881613d3d565b6001600160a01b03168252602090810135910152565b6000808335601e1984360301811261452557600080fd5b83016020810192503590506001600160401b0381111561454457600080fd5b606081023603821315613f7157600080fd5b8183526000602080850194508260005b85811015613e8457813561457981613d3d565b6001600160a01b039081168852828401359061459482613d3d565b16878401526040828101359088015260609687019690910190600101614566565b6000808335601e198436030181126145cc57600080fd5b83016020810192503590506001600160401b038111156145eb57600080fd5b8060051b3603821315613f7157600080fd5b8183526000602080850194508260005b85811015613e8457813561462081613d3d565b6001600160a01b03168752958201959082019060010161460d565b60008235607e1983360301811261465157600080fd5b90910192915050565b81835260006020808501808196508560051b81019150846000805b88811015614811578385038a5261468c838961463b565b608061469887836144ed565b60406146a68184018461450e565b83838b01526146b8848b018284614556565b91505060608085013561017e198636030181126146d3578788fd5b8a8303828c0152909401936101806146f3836146ee88613d52565b613dfa565b6146fe8c8701613d52565b61470a8d850182613dfa565b50614716848701613d52565b61472285850182613dfa565b5061472e828701613d52565b935061473c82840185613dfa565b614747858701613d52565b935061475585840185613dfa565b60a09450614764858701613d52565b935061477285840185613dfa565b60c09450614782858701876145b5565b94509150808584015261479881840185846145fd565b9450505060e091506147ac828501856145b5565b828503848401526147be8582846145fd565b6101008781013590850152945061012093506147de915050828501613ef4565b80151582840152506101408481013590820152610160938401359301929092529a87019a95505091850191600101614675565b509298975050505050505050565b60408082528181018590526000906060808401600588901b850182018985805b8b8110156149a557888403605f1901855261485a838e61463b565b608061486686836144ed565b6148728983018361450e565b828b8901526148848389018284614556565b9150508883013561015e1984360301811261489d578586fd5b8782038a890152909201916101606148b8826146ee86613d52565b60206148c5818601613d52565b6148d182850182613dfa565b506148dd8c8601613d52565b6148e98d850182613dfa565b506148f58b8601613d52565b6149018c850182613dfa565b5061490e848601866145b5565b838686015261492084860182846145fd565b9550505060a09150614934828601866145b5565b848603848601526149468682846145fd565b60c0888101359087015260e080890135908701529550610100935061496f915050828601613ef4565b1515918301919091526101208481013590830152610140938401359390910192909252958101959450929092019160010161483f565b50505085810360208701526149bb81888a61465a565b9a9950505050505050505050565b600082601f8301126149da57600080fd5b815160206149ea614206836141c2565b82815260059290921b84018101918181019086841115614a0957600080fd5b8286015b8481101561424e5780516001600160401b03811115614a2c5760008081fd5b8701603f81018913614a3e5760008081fd5b848101516040614a5061420683614259565b8281528b82848601011115614a655760008081fd5b614a7483898301848701613cc1565b8652505050918301918301614a0d565b600082601f830112614a9557600080fd5b81516020614aa5614206836141c2565b82815260059290921b84018101918181019086841115614ac457600080fd5b8286015b8481101561424e578051614adb81613d3d565b8352918301918301614ac8565b60008060408385031215614afb57600080fd5b82516001600160401b0380821115614b1257600080fd5b614b1e868387016149c9565b93506020850151915080821115614b3457600080fd5b50614b4185828601614a84565b9150509250929050565b600060208284031215614b5d57600080fd5b81516001600160401b03811115614b7357600080fd5b614b7f848285016149c9565b949350505050565b600060208284031215614b9957600080fd5b8135610f5881613ee6565b600060018201614bb657614bb6614495565b5060010190565b604081526000614bd16040830186886145fd565b8281036020848101919091528482528591810160005b86811015614c0e578335614bfa81613ee6565b151582529282019290820190600101614be7565b5098975050505050505050565b6001600160a01b03929092168252602082015260400190565b80820180821115610d2a57610d2a614495565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040600585901b8401810190840186845b8781101561402b57868403603f190183528135368a9003601e19018112614cb557600080fd5b890185810190356001600160401b03811115614cd057600080fd5b803603821315614cdf57600080fd5b614cea868284614c47565b955050509184019190840190600101614c8f565b600060208284031215614d1057600080fd5b8151610f5881613d3d565b602081526000825160606020840152614d376080840182613e4b565b90506020840151601f1980858403016040860152614d558383613e4b565b92506040860151915080858403016060860152506138a48282613fe3565b8082028115828204841417610d2a57610d2a614495565b634e487b7160e01b600052601260045260246000fd5b600082614dbd57634e487b7160e01b600052601260045260246000fd5b500490565b600080835481600182811c915080831680614dde57607f831692505b60208084108203614dfd57634e487b7160e01b86526022600452602486fd5b818015614e115760018114614e2657614e53565b60ff1986168952841515850289019650614e53565b60008a81526020902060005b86811015614e4b5781548b820152908501908301614e32565b505084890196505b509498975050505050505050565b60008235607e19833603018112614e7757600080fd5b9190910192915050565b6000823561015e19833603018112614e7757600080fd5b6000808335601e19843603018112614eaf57600080fd5b8301803591506001600160401b03821115614ec957600080fd5b6020019150606081023603821315613f7157600080fd5b6000823561017e19833603018112614e7757600080fd5b600060208284031215614f0957600080fd5b8151610f5881613ee6565b600060018060a01b03808616835260606020840152614f366060840186613e4b565b9150808416604084015250949350505050565b60008060008060808587031215614f5f57600080fd5b845160208087015160408801519296509450906001600160401b0380821115614f8757600080fd5b614f9389838a01614a84565b94506060880151915080821115614fa957600080fd5b508601601f81018813614fbb57600080fd5b8051614fc9614206826141c2565b81815260059190911b8201830190838101908a831115614fe857600080fd5b928401925b8284101561500657835182529284019290840190614fed565b979a9699509497505050505050565b634e487b7160e01b600052603160045260246000fdfefbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db0b84ee281e5cf521a9ad54a86fafe78946b157177e231bd8ae785af4d3b3620fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775dcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7a264697066735822122061e763bff663a466db4c8663414660479722dc6acdd03a0528e19e5258f699f664736f6c6343000814003360c060405234801561001057600080fd5b5060405161034e38038061034e83398101604081905261002f91610108565b6001600160a01b0381166100565760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b03811660a0819052336080819052610078919060001961007e565b50610138565b600060405163095ea7b360e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806101025760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b604482015260640160405180910390fd5b50505050565b60006020828403121561011a57600080fd5b81516001600160a01b038116811461013157600080fd5b9392505050565b60805160a0516101e7610167600039600081816068015260d801526000818160a7015260fa01526101e76000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063330b8b711461004657806338d52e0f146100635780638da5cb5b146100a2575b600080fd5b61004e6100c9565b60405190151581526020015b60405180910390f35b61008a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161005a565b61008a7f000000000000000000000000000000000000000000000000000000000000000081565b60006101216001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000600019610127565b50600190565b600060405163095ea7b360e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806101ab5760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b604482015260640160405180910390fd5b5050505056fea264697066735822122087ad503f44a06fc0188db6b619bc63d683b0a0ee5783c38cda2d7adda819fd0a64736f6c63430008140033000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad3800000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000e48acbd0179a36c59bd6c0553e8ce022b73541a70000000000000000000000008516221732ca346224fe4231fa51adad370d4f680000000000000000000000001b76028f3a036f1896a4ee888f9bd972e401564d0000000000000000000000003b52709be829343bceb8a15f3b1c1cf675a777e200000000000000000000000078cf89062bca42ccb62ddbceedc665e5e58eb890000000000000000000000000c945b5c646bfe9efca3f3c77597cd2b1befba269000000000000000000000000000000000000000000000000000000000000001d52465820775320536861726564204c6971756964697479205661756c740000000000000000000000000000000000000000000000000000000000000000000006534c562077530000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106103465760003560e01c806374c0fddb116101b957806374c0fddb1461084757806375b238fc146108745780637d41c86e146108965780637ecebe00146108b65780637f164991146108e357806381e4cb65146108f95780638bcc41661461090c57806391d148541461092c57806394bf804d1461094c57806395d89b411461096c578063a217fddf14610981578063a8d5fd6514610996578063a9059cbb146109a9578063aaf5eb68146109c9578063b3d7f6b9146109e9578063b460af9414610a09578063b6363cf214610a29578063b87fa6b614610a64578063ba08765214610a84578063bb2d60a714610aa4578063c63d75b61461064a578063c6e6f59214610ab7578063c851cc3214610ad7578063ce96cb7714610af7578063d0d0ed0514610b17578063d505accf14610b37578063d547741f14610b57578063d7cd394914610b77578063d905777e14610b97578063dd62ed3e14610bb7578063eaed1d0714610bef578063ef8b30f714610c0f578063f28b9fb114610c2f578063f5a23d8d14610c4f578063f887ea4014610c6f578063fa716b3f14610c8f578063facda49114610caf57600080fd5b806301e1d1141461034b57806301ffc9a71461036f578063021076ed1461039f57806306fdde03146103b557806307a2d13a146103d7578063095ea7b3146103f75780630a28a4771461041757806318160ddd14610437578063199c28611461044d57806323b872dd1461047b578063248a9ca31461049b57806325bb3361146104bb5780632615b7a9146104d15780632c6886cb146104f35780632f2ff15d146105205780632f83a6bc14610540578063313ce56714610562578063345210dd146105a85780633644e515146105cb57806336568abe146105e057806336c8c73a1461060057806338d52e0f14610616578063402d267d1461064a57806340bc782e1461066c5780634388b8fe146106995780634cdad5061461041757806350423dbe146106cd578063558a7297146106ed5780635924b65b1461070d5780635d6584901461072d57806363b0e66a1461075a5780636513b4361461077a5780636e48b832146107aa5780636e553f65146107ca57806370a08231146107ea57806371dfdd9f14610817575b600080fd5b34801561035757600080fd5b50600c545b6040519081526020015b60405180910390f35b34801561037b57600080fd5b5061038f61038a366004613c97565b610ccf565b6040519015158152602001610366565b3480156103ab57600080fd5b5061035c600d5481565b3480156103c157600080fd5b506103ca610d30565b6040516103669190613d11565b3480156103e357600080fd5b5061035c6103f2366004613d24565b610dbe565b34801561040357600080fd5b5061038f610412366004613d62565b610dd9565b34801561042357600080fd5b5061035c610432366004613d24565b610e33565b34801561044357600080fd5b5061035c60025481565b34801561045957600080fd5b5061046d610468366004613d24565b610e4e565b604051610366929190613d8e565b34801561048757600080fd5b5061038f610496366004613d9c565b610e7d565b3480156104a757600080fd5b5061035c6104b6366004613d24565b610f5f565b3480156104c757600080fd5b5061035c60155481565b3480156104dd57600080fd5b506104f16104ec366004613ddd565b610f74565b005b3480156104ff57600080fd5b50601054610513906001600160a01b031681565b6040516103669190613e07565b34801561052c57600080fd5b506104f161053b366004613e1b565b61100a565b34801561054c57600080fd5b5061035c60008051602061504c83398151915281565b34801561056e57600080fd5b506105967f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff9091168152602001610366565b3480156105b457600080fd5b506105bd61102c565b604051610366929190613e8f565b3480156105d757600080fd5b5061035c61113c565b3480156105ec57600080fd5b506104f16105fb366004613e1b565b611197565b34801561060c57600080fd5b5061035c60175481565b34801561062257600080fd5b506105137f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad3881565b34801561065657600080fd5b5061035c610665366004613ddd565b5060001990565b34801561067857600080fd5b5061035c610687366004613ddd565b60146020526000908152604090205481565b3480156106a557600080fd5b506105137f000000000000000000000000bd03a854ba7f6176db4e76cddfa719baf64617de81565b3480156106d957600080fd5b506104f16106e8366004613ddd565b6111cf565b3480156106f957600080fd5b5061038f610708366004613eff565b611259565b61072061071b366004613f78565b6112bd565b6040516103669190614038565b34801561073957600080fd5b5061035c610748366004613ddd565b60186020526000908152604090205481565b34801561076657600080fd5b50600f54610513906001600160a01b031681565b34801561078657600080fd5b5061038f610795366004613ddd565b601c6020526000908152604090205460ff1681565b3480156107b657600080fd5b506104f16107c5366004613f78565b611401565b3480156107d657600080fd5b5061035c6107e5366004613e1b565b611565565b3480156107f657600080fd5b5061035c610805366004613ddd565b60036020526000908152604090205481565b34801561082357600080fd5b5061038f610832366004613ddd565b601b6020526000908152604090205460ff1681565b34801561085357600080fd5b5061035c610862366004613ddd565b60166020526000908152604090205481565b34801561088057600080fd5b5061035c6000805160206150ac83398151915281565b3480156108a257600080fd5b5061035c6108b136600461404b565b6115fe565b3480156108c257600080fd5b5061035c6108d1366004613ddd565b60056020526000908152604090205481565b3480156108ef57600080fd5b5061035c600b5481565b61072061090736600461408d565b6117dd565b34801561091857600080fd5b506104f1610927366004613ddd565b611886565b34801561093857600080fd5b5061038f610947366004613e1b565b611910565b34801561095857600080fd5b5061035c610967366004613e1b565b61193b565b34801561097857600080fd5b506103ca6119c6565b34801561098d57600080fd5b5061035c600081565b3480156109a257600080fd5b5030610513565b3480156109b557600080fd5b5061038f6109c4366004613d62565b6119d3565b3480156109d557600080fd5b5061035c68327cb2734119d3b7a9601e1b81565b3480156109f557600080fd5b5061035c610a04366004613d24565b611a39565b348015610a1557600080fd5b5061035c610a2436600461404b565b611a54565b348015610a3557600080fd5b5061038f610a44366004614126565b601a60209081526000928352604080842090915290825290205460ff1681565b348015610a7057600080fd5b506104f1610a7f366004613ddd565b611c34565b348015610a9057600080fd5b5061035c610a9f36600461404b565b611cbe565b6104f1610ab2366004614280565b611e8d565b348015610ac357600080fd5b5061035c610ad2366004613d24565b6120cd565b348015610ae357600080fd5b506104f1610af2366004613ddd565b6120e8565b348015610b0357600080fd5b5061035c610b12366004613ddd565b612172565b348015610b2357600080fd5b50601254610513906001600160a01b031681565b348015610b4357600080fd5b506104f1610b523660046143e4565b61218d565b348015610b6357600080fd5b506104f1610b72366004613e1b565b6123be565b348015610b8357600080fd5b50601154610513906001600160a01b031681565b348015610ba357600080fd5b5061035c610bb2366004613ddd565b6123da565b348015610bc357600080fd5b5061035c610bd2366004614126565b600460209081526000928352604080842090915290825290205481565b348015610bfb57600080fd5b5061035c610c0a366004613e1b565b6123f5565b348015610c1b57600080fd5b5061035c610c2a366004613d24565b612423565b348015610c3b57600080fd5b506104f1610c4a366004613ddd565b61242e565b348015610c5b57600080fd5b5061035c610c6a366004613e1b565b6124b8565b348015610c7b57600080fd5b50600e54610513906001600160a01b031681565b348015610c9b57600080fd5b50601354610513906001600160a01b031681565b348015610cbb57600080fd5b506104f1610cca366004613f78565b6124e6565b600063e3bc4e6560e01b6001600160e01b031983161480610d005750632f0a18c560e01b6001600160e01b03198316145b80610d1b5750631883ba3960e21b6001600160e01b03198316145b80610d2a5750610d2a82612631565b92915050565b60008054610d3d9061445b565b80601f0160208091040260200160405190810160405280929190818152602001828054610d699061445b565b8015610db65780601f10610d8b57610100808354040283529160200191610db6565b820191906000526020600020905b815481529060010190602001808311610d9957829003601f168201915b505050505081565b6000610d2a82600d5468327cb2734119d3b7a9601e1b612666565b3360008181526004602090815260408083206001600160a01b0387168085529252808320859055519192909160008051602061508c83398151915290610e229086815260200190565b60405180910390a350600192915050565b6000604051631eb49d6d60e11b815260040160405180910390fd5b60008060008051602061504c833981519152610e698161272a565b610e7284612737565b909590945092505050565b6001600160a01b03831660009081526004602090815260408083203384529091528120546000198114610ed957610eb483826144ab565b6001600160a01b03861660009081526004602090815260408083203384529091529020555b6001600160a01b03851660009081526003602052604081208054859290610f019084906144ab565b90915550506001600160a01b038085166000818152600360205260409081902080548701905551909187169060008051602061506c83398151915290610f4a9087815260200190565b60405180910390a360019150505b9392505050565b60009081526006602052604090206001015490565b6000805160206150ac833981519152610f8c8161272a565b6001600160a01b038216610fb35760405163e6c4247b60e01b815260040160405180910390fd5b601080546001600160a01b0319166001600160a01b0384161790556040517f61eeccc62b2fff98fea77f70c98b615ae0494ebd8e140b43bbeb9cdaca2e5a5990610ffe908490613e07565b60405180910390a15050565b61101382610f5f565b61101c8161272a565b61102683836129a3565b50505050565b6060806110396009612a37565b915081516001600160401b0381111561105457611054614154565b60405190808252806020026020018201604052801561107d578160200160208202803683370190505b50905060005b82518110156111375782818151811061109e5761109e6144be565b60200260200101516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016110d19190613e07565b602060405180830381865afa1580156110ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111291906144d4565b828281518110611124576111246144be565b6020908102919091010152600101611083565b509091565b60007f000000000000000000000000000000000000000000000000000000000000009246146111725761116d612a44565b905090565b507ff4f06b2eb5d53a76a00fced6ff257c6cbb89d9ed000fa7d6c05a4cdb2b29ad2790565b6001600160a01b03811633146111c05760405163334bd91960e11b815260040160405180910390fd5b6111ca8282612ade565b505050565b6000805160206150ac8339815191526111e78161272a565b6001600160a01b03821661120e5760405163e6c4247b60e01b815260040160405180910390fd5b601280546001600160a01b0319166001600160a01b0384161790556040517f0e0ed07b314aa8a9a2104b2333805db1f23505037c1e8a163f6e0ce8d482bb7d90610ffe908490613e07565b336000818152601a602090815260408083206001600160a01b038716808552908352818420805460ff191687151590811790915591519182529293917fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa2679101610e22565b606060008051602061504c8339815191526112d78161272a565b6112e386868686612b4b565b600f54604051637923351b60e11b815260009182916001600160a01b039091169063f2466a369061131e908b908b908b908b9060040161481f565b600060405180830381865afa15801561133b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113639190810190614ae8565b9150915061137388888888612f01565b61137c816134b8565b600e54604051631592ca1b60e31b81526001600160a01b039091169063ac9650d89034906113ae908690600401614038565b60006040518083038185885af11580156113cc573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526113f59190810190614b4b565b98975050505050505050565b6000805160206150ac8339815191526114198161272a565b8382146114395760405163251f56a160e21b815260040160405180910390fd5b60005b84811015611520576000868683818110611458576114586144be565b905060200201602081019061146d9190613ddd565b6001600160a01b0316036114945760405163e6c4247b60e01b815260040160405180910390fd5b8383828181106114a6576114a66144be565b90506020020160208101906114bb9190614b87565b601c60008888858181106114d1576114d16144be565b90506020020160208101906114e69190613ddd565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558061151881614ba4565b91505061143c565b507fa3476bdc214fa6a8f0c8ad026e0a9e8c05484ec623d62f903054e9525ca8e1bf858585856040516115569493929190614bbd565b60405180910390a15050505050565b600061157083612423565b905061157e818460016134fe565b6115b36001600160a01b037f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38163330866135d0565b6115bd8282613665565b816001600160a01b0316336001600160a01b03166000805160206150cc83398151915285846040516115f0929190613d8e565b60405180910390a392915050565b60008360000361160d57600080fd5b6001600160a01b038216331480159061164a57506001600160a01b0382166000908152601a6020908152604080832033845290915290205460ff16155b156116ad576001600160a01b038216600090815260046020908152604080832033845290915290205460001981146116ab5761168685826144ab565b6001600160a01b03841660009081526004602090815260408083203384529091529020555b505b6116b88230866136bf565b506040805180820182526001600160a01b03858116808352602083018881526007805460018101825560009190915293517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600290950294850180546001600160a01b031916918516919091179055517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6899093019290925591518392851691907f1fdc681a13d8c5da54e301c7ce6542dcde4581e4725043fdab2db12ddc574506906117879033908a90614c1b565b60405180910390a46001600160a01b038316600090815260146020526040812080548692906117b7908490614c34565b9250508190555083601560008282546117d09190614c34565b9091555090949350505050565b606060008051602061504c8339815191526117f78161272a565b6118018484613762565b6013546040516309d902f160e21b81526001600160a01b03909116906327640bc4903490611835908a908a90600401614c70565b60006040518083038185885af1158015611853573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405261187c9190810190614b4b565b9695505050505050565b6000805160206150ac83398151915261189e8161272a565b6001600160a01b0382166118c55760405163e6c4247b60e01b815260040160405180910390fd5b600f80546001600160a01b0319166001600160a01b0384161790556040517f20e752df2d1d9e69c7eb8f9e96973ff9b6f881a03503a3b5cac668cafb9a1ac890610ffe908490613e07565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b600061194683611a39565b9050611954838260016134fe565b6119896001600160a01b037f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38163330846135d0565b6119938284613665565b816001600160a01b0316336001600160a01b03166000805160206150cc83398151915283866040516115f0929190613d8e565b60018054610d3d9061445b565b336000908152600360205260408120805483919083906119f49084906144ab565b90915550506001600160a01b0383166000818152600360205260409081902080548501905551339060008051602061506c83398151915290610e229086815260200190565b6000610d2a82600d5468327cb2734119d3b7a9601e1b613872565b600083600003611a6357600080fd5b6001600160a01b038216331480611a9d57506001600160a01b0382166000908152601a6020908152604080832033845290915290205460ff165b611aa657600080fd5b611aaf82612172565b841115611acf57604051631930e3c960e11b815260040160405180910390fd5b6001600160a01b038216600090815260166020908152604080832054601890925290912054611aff868383613872565b6001600160a01b038516600090815260166020526040812080549295508592909190611b2c9084906144ab565b925050819055508260176000828254611b4591906144ab565b90915550506001600160a01b03841660009081526018602052604081208054889290611b729084906144ab565b925050819055508560196000828254611b8b91906144ab565b90915550611be690506001600160a01b037f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38167f000000000000000000000000bd03a854ba7f6176db4e76cddfa719baf64617de87896135d0565b836001600160a01b0316856001600160a01b0316336001600160a01b031660008051602061502c8339815191528987604051611c23929190613d8e565b60405180910390a450509392505050565b6000805160206150ac833981519152611c4c8161272a565b6001600160a01b038216611c735760405163e6c4247b60e01b815260040160405180910390fd5b601180546001600160a01b0319166001600160a01b0384161790556040517ff1f4d3d6c666f9a8405868563a53355305afc3d7a918e905a2a08481f439592090610ffe908490613e07565b600083600003611ccd57600080fd5b6001600160a01b038216331480611d0757506001600160a01b0382166000908152601a6020908152604080832033845290915290205460ff165b611d1057600080fd5b611d19826123da565b841115611d3957604051631930e3c960e11b815260040160405180910390fd5b6001600160a01b038216600090815260166020908152604080832054601890925290912054611d69868284612666565b6001600160a01b038516600090815260166020526040812080549295508892909190611d969084906144ab565b925050819055508560176000828254611daf91906144ab565b90915550506001600160a01b03841660009081526018602052604081208054859290611ddc9084906144ab565b925050819055508260196000828254611df591906144ab565b90915550611e5090506001600160a01b037f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38167f000000000000000000000000bd03a854ba7f6176db4e76cddfa719baf64617de87866135d0565b836001600160a01b0316856001600160a01b0316336001600160a01b031660008051602061502c833981519152868a604051611c23929190613d8e565b60008051602061504c833981519152611ea58161272a565b600f54604080516307dc0d1d60e41b8152905184926001600160a01b031691637dc0d1d09160048083019260209291908290030181865afa158015611eee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f129190614cfe565b6001600160a01b0316633d333c8534836040518363ffffffff1660e01b8152600401611f3e9190614d1b565b6000604051808303818588803b158015611f5757600080fd5b505af1158015611f6b573d6000803e3d6000fd5b5050505050600080600080611f7e6138ad565b9350935093509350611f908282613965565b600b849055600c839055600254611fb368327cb2734119d3b7a9601e1b85614d73565b611fbd9190614da0565b600d819055600b546040517ffba84dda7abcc3f95f3c4d1ffa85ff2a568c9a02ca6181f14305b0005fa7336f92611ff49291613d8e565b60405180910390a150505050600f60009054906101000a90046001600160a01b03166001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120779190614cfe565b6001600160a01b031662ccf1556040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120b057600080fd5b505af11580156120c4573d6000803e3d6000fd5b50505050505050565b6000610d2a8268327cb2734119d3b7a9601e1b600d54612666565b6000805160206150ac8339815191526121008161272a565b6001600160a01b0382166121275760405163e6c4247b60e01b815260040160405180910390fd5b600e80546001600160a01b0319166001600160a01b0384161790556040517f7aed1d3e8155a07ccf395e44ea3109a0e2d6c9b29bbbe9f142d9790596f4dc8090610ffe908490613e07565b6001600160a01b031660009081526018602052604090205490565b428410156121dc5760405162461bcd60e51b815260206004820152601760248201527614115493525517d11150511312539157d1561412549151604a1b60448201526064015b60405180910390fd5b600060016121e861113c565b6001600160a01b038a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156122f4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061232a5750876001600160a01b0316816001600160a01b0316145b6123675760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b60448201526064016121d3565b6001600160a01b0390811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a169160008051602061508c833981519152910160405180910390a350505050505050565b6123c782610f5f565b6123d08161272a565b6110268383612ade565b6001600160a01b031660009081526016602052604090205490565b6000821561240557506000610d2a565b506001600160a01b0316600090815260166020526040902054919050565b6000610d2a826120cd565b6000805160206150ac8339815191526124468161272a565b6001600160a01b03821661246d5760405163e6c4247b60e01b815260040160405180910390fd5b601380546001600160a01b0319166001600160a01b0384161790556040517faf6cd135c2ebef948aa7b21587e2c9af90e943077ddce2329e3562ff4343853b90610ffe908490613e07565b600082156124c857506000610d2a565b506001600160a01b0316600090815260146020526040902054919050565b6000805160206150ac8339815191526124fe8161272a565b83821461251e5760405163251f56a160e21b815260040160405180910390fd5b60005b848110156125fb57600086868381811061253d5761253d6144be565b90506020020160208101906125529190613ddd565b6001600160a01b0316036125795760405163e6c4247b60e01b815260040160405180910390fd5b83838281811061258b5761258b6144be565b90506020020160208101906125a09190614b87565b601b60008888858181106125b6576125b66144be565b90506020020160208101906125cb9190613ddd565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101612521565b507f8e76b36c7816a433d72c7df0b85914261ff3471c309e999cd40d66c61028a067858585856040516115569493929190614bbd565b60006001600160e01b03198216637965db0b60e01b1480610d2a57506301ffc9a760e01b6001600160e01b0319831614610d2a565b600083830281600019858709828110838203039150508060000361269d5783828161269357612693614d8a565b0492505050610f58565b8084116126bd5760405163227bc15360e01b815260040160405180910390fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b61273481336139c9565b50565b6000805b60075460085410156128ee57600060076008548154811061275e5761275e6144be565b90600052602060002090600202019050600061277d8260010154610dbe565b90508461278a8285614c34565b11156127975750506128ee565b6127a18184614c34565b92508160010154846127b39190614c34565b600183015483546001600160a01b03166000908152601460205260408120805493975091926127e39084906144ab565b90915550506001820154601580546000906127ff9084906144ab565b9091555050600182015482546001600160a01b031660009081526016602052604081208054909190612832908490614c34565b909155505060018201546017805460009061284e908490614c34565b909155505081546001600160a01b03166000908152601860205260408120805483929061287c908490614c34565b9250508190555080601960008282546128959190614c34565b925050819055506007600854815481106128b1576128b16144be565b60009182526020822060029091020180546001600160a01b031916815560010181905560088054916128e283614ba4565b9190505550505061273b565b816000036128fb57915091565b612907828260006134fe565b61295b6001600160a01b037f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38167f000000000000000000000000bd03a854ba7f6176db4e76cddfa719baf64617de836139f4565b6129653083613a75565b7f4f1ca23eae8569319445ac7ba753a438cc3fdb97f1ac4db7f9016999f1850ef58282604051612996929190613d8e565b60405180910390a1915091565b60006129af8383611910565b612a2f5760008381526006602090815260408083206001600160a01b03861684529091529020805460ff191660011790556129e73390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610d2a565b506000610d2a565b60606000610f5883613ad7565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051612a769190614dc2565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6000612aea8383611910565b15612a2f5760008381526006602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610d2a565b60005b83811015612d5f5736858583818110612b6957612b696144be565b9050602002810190612b7b9190614e61565b9050601c6000612b8e6060840184614e81565b612b9f906080810190606001613ddd565b6001600160a01b0316815260208101919091526040016000205460ff16612bf757612bcd6060820182614e81565b612bde906080810190606001613ddd565b604051623aae9360e61b81526004016121d39190613e07565b30612c056060830183614e81565b612c13906020810190613ddd565b6001600160a01b031614612c5657612c2e6060820182614e81565b612c3c906020810190613ddd565b604051639cfea58360e01b81526004016121d39190613e07565b602081013515801590612c8957506012546001600160a01b0316612c7d6020830183613ddd565b6001600160a01b031614155b15612c9b57612c3c6020820182613ddd565b60005b612cab6040830183614e98565b9050811015612d4a576012546001600160a01b0316612ccd6040840184614e98565b83818110612cdd57612cdd6144be565b9050606002016020016020810190612cf59190613ddd565b6001600160a01b031614612d3857612d106040830183614e98565b82818110612d2057612d206144be565b9050606002016020016020810190612c3c9190613ddd565b80612d4281614ba4565b915050612c9e565b50508080612d5790614ba4565b915050612b4e565b5060005b81811015612efa5736838383818110612d7e57612d7e6144be565b9050602002810190612d909190614e61565b9050601c6000612da36060840184614ee0565b612db4906080810190606001613ddd565b6001600160a01b0316815260208101919091526040016000205460ff16612de257612bcd6060820182614ee0565b30612df06060830183614ee0565b612dfe906020810190613ddd565b6001600160a01b031614612e1957612c2e6060820182614ee0565b602081013515801590612e4c57506011546001600160a01b0316612e406020830183613ddd565b6001600160a01b031614155b15612e5e57612c3c6020820182613ddd565b60005b612e6e6040830183614e98565b9050811015612ee5576011546001600160a01b0316612e906040840184614e98565b83818110612ea057612ea06144be565b9050606002016020016020810190612eb89190613ddd565b6001600160a01b031614612ed357612d106040830183614e98565b80612edd81614ba4565b915050612e61565b50508080612ef290614ba4565b915050612d63565b5050505050565b60005b8381101561304c5760005b858583818110612f2157612f216144be565b9050602002810190612f339190614e61565b612f41906040810190614e98565b905081101561303957858583818110612f5c57612f5c6144be565b9050602002810190612f6e9190614e61565b612f7c906040810190614e98565b82818110612f8c57612f8c6144be565b90506060020160400135601d6000888886818110612fac57612fac6144be565b9050602002810190612fbe9190614e61565b612fcc906040810190614e98565b85818110612fdc57612fdc6144be565b612ff29260206060909202019081019150613ddd565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546130219190614c34565b9091555081905061303181614ba4565b915050612f0f565b508061304481614ba4565b915050612f04565b5060005b818110156131985760005b83838381811061306d5761306d6144be565b905060200281019061307f9190614e61565b61308d906040810190614e98565b9050811015613185578383838181106130a8576130a86144be565b90506020028101906130ba9190614e61565b6130c8906040810190614e98565b828181106130d8576130d86144be565b90506060020160400135601d60008686868181106130f8576130f86144be565b905060200281019061310a9190614e61565b613118906040810190614e98565b85818110613128576131286144be565b61313e9260206060909202019081019150613ddd565b6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461316d9190614c34565b9091555081905061317d81614ba4565b91505061305b565b508061319081614ba4565b915050613050565b5060005b838110156133285760005b8585838181106131b9576131b96144be565b90506020028101906131cb9190614e61565b6131d9906040810190614e98565b90508110156133155760008686848181106131f6576131f66144be565b90506020028101906132089190614e61565b613216906040810190614e98565b83818110613226576132266144be565b61323c9260206060909202019081019150613ddd565b6001600160a01b0381166000908152601d6020526040812054919250036132635750613303565b6010546001600160a01b038083166000818152601d60205260409081902054905163095ea7b360e01b8152919363095ea7b3936132a69391169190600401614c1b565b6020604051808303816000875af11580156132c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132e99190614ef7565b506001600160a01b03166000908152601d60205260408120555b8061330d81614ba4565b9150506131a7565b508061332081614ba4565b91505061319c565b5060005b81811015612efa5760005b838383818110613349576133496144be565b905060200281019061335b9190614e61565b613369906040810190614e98565b90508110156134a5576000848484818110613386576133866144be565b90506020028101906133989190614e61565b6133a6906040810190614e98565b838181106133b6576133b66144be565b6133cc9260206060909202019081019150613ddd565b6001600160a01b0381166000908152601d6020526040812054919250036133f35750613493565b6010546001600160a01b038083166000818152601d60205260409081902054905163095ea7b360e01b8152919363095ea7b3936134369391169190600401614c1b565b6020604051808303816000875af1158015613455573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134799190614ef7565b506001600160a01b03166000908152601d60205260408120555b8061349d81614ba4565b915050613337565b50806134b081614ba4565b91505061332c565b60005b81518110156134fa576134f18282815181106134d9576134d96144be565b60200260200101516009613b3390919063ffffffff16565b506001016134bb565b5050565b806135165781600c5461351191906144ab565b613524565b81600c546135249190614c34565b600c556002546000826135405761353b85836144ab565b61354a565b61354a8583614c34565b90508060000361356b57505068327cb2734119d3b7a9601e1b600d55505050565b600082600d5461357b9190614d73565b9050600061359568327cb2734119d3b7a9601e1b87614d73565b90506000856135ad576135a882846144ab565b6135b7565b6135b78284614c34565b90506135c38482614da0565b600d555050505050505050565b60006040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b03841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080612efa5760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064016121d3565b80600260008282546136779190614c34565b90915550506001600160a01b03821660008181526003602090815260408083208054860190555184815260008051602061506c83398151915291015b60405180910390a35050565b6001600160a01b0383166000908152600360205260408120805483919083906136e99084906144ab565b90915550506001600160a01b03831660009081526003602052604081208054849290613716908490614c34565b92505081905550826001600160a01b0316846001600160a01b031660008051602061506c8339815191528460405161375091815260200190565b60405180910390a35060019392505050565b60005b818110156111ca5736838383818110613780576137806144be565b9050606002019050600081602001602081019061379d9190613ddd565b6001600160a01b0381166000908152601b602052604090205490915060ff166137db578060405163270af7ed60e11b81526004016121d39190613e07565b6137e86020830183613ddd565b6001600160a01b031663095ea7b38284604001356040518363ffffffff1660e01b8152600401613819929190614c1b565b6020604051808303816000875af1158015613838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385c9190614ef7565b505050808061386a90614ba4565b915050613765565b600061387f848484612666565b90506000828061389157613891614d8a565b8486091115610f5857806138a481614ba4565b95945050505050565b600f54600090819060609081906001600160a01b031663f01e23577f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad386138f36009612a37565b306040518463ffffffff1660e01b815260040161391293929190614f14565b600060405180830381865afa15801561392f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139579190810190614f49565b929791965094509092509050565b60005b82518110156111ca57818181518110613983576139836144be565b60200260200101516000036139c1576139bf8382815181106139a7576139a76144be565b60200260200101516009613b4890919063ffffffff16565b505b600101613968565b6139d38282611910565b6134fa57808260405163e2517d3f60e01b81526004016121d3929190614c1b565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806110265760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016121d3565b6001600160a01b03821660009081526003602052604081208054839290613a9d9084906144ab565b90915550506002805482900390556040518181526000906001600160a01b0384169060008051602061506c833981519152906020016136b3565b606081600001805480602002602001604051908101604052809291908181526020018280548015613b2757602002820191906000526020600020905b815481526020019060010190808311613b13575b50505050509050919050565b6000610f58836001600160a01b038416613b5d565b6000610f58836001600160a01b038416613ba4565b6000818152600183016020526040812054612a2f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d2a565b60008181526001830160205260408120548015613c8d576000613bc86001836144ab565b8554909150600090613bdc906001906144ab565b9050808214613c41576000866000018281548110613bfc57613bfc6144be565b9060005260206000200154905080876000018481548110613c1f57613c1f6144be565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613c5257613c52615015565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d2a565b6000915050610d2a565b600060208284031215613ca957600080fd5b81356001600160e01b031981168114610f5857600080fd5b60005b83811015613cdc578181015183820152602001613cc4565b50506000910152565b60008151808452613cfd816020860160208601613cc1565b601f01601f19169290920160200192915050565b602081526000610f586020830184613ce5565b600060208284031215613d3657600080fd5b5035919050565b6001600160a01b038116811461273457600080fd5b8035613d5d81613d3d565b919050565b60008060408385031215613d7557600080fd5b8235613d8081613d3d565b946020939093013593505050565b918252602082015260400190565b600080600060608486031215613db157600080fd5b8335613dbc81613d3d565b92506020840135613dcc81613d3d565b929592945050506040919091013590565b600060208284031215613def57600080fd5b8135610f5881613d3d565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b60008060408385031215613e2e57600080fd5b823591506020830135613e4081613d3d565b809150509250929050565b600081518084526020808501945080840160005b83811015613e845781516001600160a01b031687529582019590820190600101613e5f565b509495945050505050565b604081526000613ea26040830185613e4b565b82810360208481019190915284518083528582019282019060005b81811015613ed957845183529383019391830191600101613ebd565b5090979650505050505050565b801515811461273457600080fd5b8035613d5d81613ee6565b60008060408385031215613f1257600080fd5b8235613f1d81613d3d565b91506020830135613e4081613ee6565b60008083601f840112613f3f57600080fd5b5081356001600160401b03811115613f5657600080fd5b6020830191508360208260051b8501011115613f7157600080fd5b9250929050565b60008060008060408587031215613f8e57600080fd5b84356001600160401b0380821115613fa557600080fd5b613fb188838901613f2d565b90965094506020870135915080821115613fca57600080fd5b50613fd787828801613f2d565b95989497509550505050565b600081518084526020808501808196508360051b8101915082860160005b8581101561402b578284038952614019848351613ce5565b98850198935090840190600101614001565b5091979650505050505050565b602081526000610f586020830184613fe3565b60008060006060848603121561406057600080fd5b83359250602084013561407281613d3d565b9150604084013561408281613d3d565b809150509250925092565b600080600080604085870312156140a357600080fd5b84356001600160401b03808211156140ba57600080fd5b6140c688838901613f2d565b909650945060208701359150808211156140df57600080fd5b818701915087601f8301126140f357600080fd5b81358181111561410257600080fd5b88602060608302850101111561411757600080fd5b95989497505060200194505050565b6000806040838503121561413957600080fd5b823561414481613d3d565b91506020830135613e4081613d3d565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561418c5761418c614154565b60405290565b604051601f8201601f191681016001600160401b03811182821017156141ba576141ba614154565b604052919050565b60006001600160401b038211156141db576141db614154565b5060051b60200190565b600082601f8301126141f657600080fd5b8135602061420b614206836141c2565b614192565b82815260059290921b8401810191818101908684111561422a57600080fd5b8286015b8481101561424e57803561424181613d3d565b835291830191830161422e565b509695505050505050565b60006001600160401b0382111561427257614272614154565b50601f01601f191660200190565b6000602080838503121561429357600080fd5b82356001600160401b03808211156142aa57600080fd5b90840190606082870312156142be57600080fd5b6142c661416a565b8235828111156142d557600080fd5b6142e1888286016141e5565b82525083830135828111156142f557600080fd5b614301888286016141e5565b85830152506040808401358381111561431957600080fd5b80850194505087601f85011261432e57600080fd5b833561433c614206826141c2565b81815260059190911b8501860190868101908a83111561435b57600080fd5b8787015b838110156143cf578035878111156143775760008081fd5b8801603f81018d136143895760008081fd5b8981013561439961420682614259565b8181528e888385010111156143ae5760008081fd5b818884018d83013760009181018c019190915284525091880191880161435f565b50928401929092525090979650505050505050565b600080600080600080600060e0888a0312156143ff57600080fd5b873561440a81613d3d565b9650602088013561441a81613d3d565b95506040880135945060608801359350608088013560ff8116811461443e57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600181811c9082168061446f57607f821691505b60208210810361448f57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d2a57610d2a614495565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156144e657600080fd5b5051919050565b80356144f881613d3d565b6001600160a01b03168252602090810135910152565b6000808335601e1984360301811261452557600080fd5b83016020810192503590506001600160401b0381111561454457600080fd5b606081023603821315613f7157600080fd5b8183526000602080850194508260005b85811015613e8457813561457981613d3d565b6001600160a01b039081168852828401359061459482613d3d565b16878401526040828101359088015260609687019690910190600101614566565b6000808335601e198436030181126145cc57600080fd5b83016020810192503590506001600160401b038111156145eb57600080fd5b8060051b3603821315613f7157600080fd5b8183526000602080850194508260005b85811015613e8457813561462081613d3d565b6001600160a01b03168752958201959082019060010161460d565b60008235607e1983360301811261465157600080fd5b90910192915050565b81835260006020808501808196508560051b81019150846000805b88811015614811578385038a5261468c838961463b565b608061469887836144ed565b60406146a68184018461450e565b83838b01526146b8848b018284614556565b91505060608085013561017e198636030181126146d3578788fd5b8a8303828c0152909401936101806146f3836146ee88613d52565b613dfa565b6146fe8c8701613d52565b61470a8d850182613dfa565b50614716848701613d52565b61472285850182613dfa565b5061472e828701613d52565b935061473c82840185613dfa565b614747858701613d52565b935061475585840185613dfa565b60a09450614764858701613d52565b935061477285840185613dfa565b60c09450614782858701876145b5565b94509150808584015261479881840185846145fd565b9450505060e091506147ac828501856145b5565b828503848401526147be8582846145fd565b6101008781013590850152945061012093506147de915050828501613ef4565b80151582840152506101408481013590820152610160938401359301929092529a87019a95505091850191600101614675565b509298975050505050505050565b60408082528181018590526000906060808401600588901b850182018985805b8b8110156149a557888403605f1901855261485a838e61463b565b608061486686836144ed565b6148728983018361450e565b828b8901526148848389018284614556565b9150508883013561015e1984360301811261489d578586fd5b8782038a890152909201916101606148b8826146ee86613d52565b60206148c5818601613d52565b6148d182850182613dfa565b506148dd8c8601613d52565b6148e98d850182613dfa565b506148f58b8601613d52565b6149018c850182613dfa565b5061490e848601866145b5565b838686015261492084860182846145fd565b9550505060a09150614934828601866145b5565b848603848601526149468682846145fd565b60c0888101359087015260e080890135908701529550610100935061496f915050828601613ef4565b1515918301919091526101208481013590830152610140938401359390910192909252958101959450929092019160010161483f565b50505085810360208701526149bb81888a61465a565b9a9950505050505050505050565b600082601f8301126149da57600080fd5b815160206149ea614206836141c2565b82815260059290921b84018101918181019086841115614a0957600080fd5b8286015b8481101561424e5780516001600160401b03811115614a2c5760008081fd5b8701603f81018913614a3e5760008081fd5b848101516040614a5061420683614259565b8281528b82848601011115614a655760008081fd5b614a7483898301848701613cc1565b8652505050918301918301614a0d565b600082601f830112614a9557600080fd5b81516020614aa5614206836141c2565b82815260059290921b84018101918181019086841115614ac457600080fd5b8286015b8481101561424e578051614adb81613d3d565b8352918301918301614ac8565b60008060408385031215614afb57600080fd5b82516001600160401b0380821115614b1257600080fd5b614b1e868387016149c9565b93506020850151915080821115614b3457600080fd5b50614b4185828601614a84565b9150509250929050565b600060208284031215614b5d57600080fd5b81516001600160401b03811115614b7357600080fd5b614b7f848285016149c9565b949350505050565b600060208284031215614b9957600080fd5b8135610f5881613ee6565b600060018201614bb657614bb6614495565b5060010190565b604081526000614bd16040830186886145fd565b8281036020848101919091528482528591810160005b86811015614c0e578335614bfa81613ee6565b151582529282019290820190600101614be7565b5098975050505050505050565b6001600160a01b03929092168252602082015260400190565b80820180821115610d2a57610d2a614495565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040600585901b8401810190840186845b8781101561402b57868403603f190183528135368a9003601e19018112614cb557600080fd5b890185810190356001600160401b03811115614cd057600080fd5b803603821315614cdf57600080fd5b614cea868284614c47565b955050509184019190840190600101614c8f565b600060208284031215614d1057600080fd5b8151610f5881613d3d565b602081526000825160606020840152614d376080840182613e4b565b90506020840151601f1980858403016040860152614d558383613e4b565b92506040860151915080858403016060860152506138a48282613fe3565b8082028115828204841417610d2a57610d2a614495565b634e487b7160e01b600052601260045260246000fd5b600082614dbd57634e487b7160e01b600052601260045260246000fd5b500490565b600080835481600182811c915080831680614dde57607f831692505b60208084108203614dfd57634e487b7160e01b86526022600452602486fd5b818015614e115760018114614e2657614e53565b60ff1986168952841515850289019650614e53565b60008a81526020902060005b86811015614e4b5781548b820152908501908301614e32565b505084890196505b509498975050505050505050565b60008235607e19833603018112614e7757600080fd5b9190910192915050565b6000823561015e19833603018112614e7757600080fd5b6000808335601e19843603018112614eaf57600080fd5b8301803591506001600160401b03821115614ec957600080fd5b6020019150606081023603821315613f7157600080fd5b6000823561017e19833603018112614e7757600080fd5b600060208284031215614f0957600080fd5b8151610f5881613ee6565b600060018060a01b03808616835260606020840152614f366060840186613e4b565b9150808416604084015250949350505050565b60008060008060808587031215614f5f57600080fd5b845160208087015160408801519296509450906001600160401b0380821115614f8757600080fd5b614f9389838a01614a84565b94506060880151915080821115614fa957600080fd5b508601601f81018813614fbb57600080fd5b8051614fc9614206826141c2565b81815260059190911b8201830190838101908a831115614fe857600080fd5b928401925b8284101561500657835182529284019290840190614fed565b979a9699509497505050505050565b634e487b7160e01b600052603160045260246000fdfefbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db0b84ee281e5cf521a9ad54a86fafe78946b157177e231bd8ae785af4d3b3620fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775dcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7a264697066735822122061e763bff663a466db4c8663414660479722dc6acdd03a0528e19e5258f699f664736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad3800000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000e48acbd0179a36c59bd6c0553e8ce022b73541a70000000000000000000000008516221732ca346224fe4231fa51adad370d4f680000000000000000000000001b76028f3a036f1896a4ee888f9bd972e401564d0000000000000000000000003b52709be829343bceb8a15f3b1c1cf675a777e200000000000000000000000078cf89062bca42ccb62ddbceedc665e5e58eb890000000000000000000000000c945b5c646bfe9efca3f3c77597cd2b1befba269000000000000000000000000000000000000000000000000000000000000001d52465820775320536861726564204c6971756964697479205661756c740000000000000000000000000000000000000000000000000000000000000000000006534c562077530000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _asset (address): 0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38
Arg [1] : _name (string): RFX wS Shared Liquidity Vault
Arg [2] : _symbol (string): SLV wS
Arg [3] : _router (address): 0xe48AcBD0179a36c59BD6C0553e8CE022b73541A7
Arg [4] : _routerSender (address): 0x8516221732cA346224FE4231FA51adAd370D4f68
Arg [5] : _depositVault (address): 0x1b76028F3A036F1896a4ee888F9bd972e401564D
Arg [6] : _withdrawVault (address): 0x3B52709BE829343bCeB8A15F3b1c1cF675a777e2
Arg [7] : _helper (address): 0x78Cf89062BcA42CcB62dDbcEEdC665e5E58eB890
Arg [8] : _swapModule (address): 0xC945b5C646bFE9eFcA3f3C77597cd2b1bEFBa269
-----Encoded View---------------
13 Constructor Arguments found :
Arg [0] : 000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [3] : 000000000000000000000000e48acbd0179a36c59bd6c0553e8ce022b73541a7
Arg [4] : 0000000000000000000000008516221732ca346224fe4231fa51adad370d4f68
Arg [5] : 0000000000000000000000001b76028f3a036f1896a4ee888f9bd972e401564d
Arg [6] : 0000000000000000000000003b52709be829343bceb8a15f3b1c1cf675a777e2
Arg [7] : 00000000000000000000000078cf89062bca42ccb62ddbceedc665e5e58eb890
Arg [8] : 000000000000000000000000c945b5c646bfe9efca3f3c77597cd2b1befba269
Arg [9] : 000000000000000000000000000000000000000000000000000000000000001d
Arg [10] : 52465820775320536861726564204c6971756964697479205661756c74000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [12] : 534c562077530000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.